1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef LIBPANDAFILE_FILE_ITEMS_H
17 #define LIBPANDAFILE_FILE_ITEMS_H
18 
19 #include "file.h"
20 #include "file_writer.h"
21 #include "macros.h"
22 #include "modifiers.h"
23 #include "type.h"
24 #include "file_format_version.h"
25 #include "source_lang_enum.h"
26 
27 #include <cstddef>
28 #include <cstdint>
29 
30 #include <algorithm>
31 #include <memory>
32 #include <string>
33 #include <variant>
34 #include <vector>
35 #include <list>
36 #include <set>
37 
38 namespace panda::panda_file {
39 
40 enum class ClassTag : uint8_t {
41     NOTHING = 0x00,
42     INTERFACES = 0x01,
43     SOURCE_LANG = 0x02,
44     RUNTIME_ANNOTATION = 0x03,
45     ANNOTATION = 0x04,
46     RUNTIME_TYPE_ANNOTATION = 0x05,
47     TYPE_ANNOTATION = 0x06,
48     SOURCE_FILE = 0x07
49 };
50 
51 enum class MethodTag : uint8_t {
52     NOTHING = 0x00,
53     CODE = 0x01,
54     SOURCE_LANG = 0x02,
55     RUNTIME_ANNOTATION = 0x03,
56     RUNTIME_PARAM_ANNOTATION = 0x04,
57     DEBUG_INFO = 0x05,
58     ANNOTATION = 0x06,
59     PARAM_ANNOTATION = 0x07,
60     TYPE_ANNOTATION = 0x08,
61     RUNTIME_TYPE_ANNOTATION = 0x09
62 };
63 
64 enum class FieldTag : uint8_t {
65     NOTHING = 0x00,
66     INT_VALUE = 0x01,
67     VALUE = 0x02,
68     RUNTIME_ANNOTATION = 0x03,
69     ANNOTATION = 0x04,
70     RUNTIME_TYPE_ANNOTATION = 0x05,
71     TYPE_ANNOTATION = 0x06
72 };
73 
74 enum class FunctionKind : uint8_t {
75     NONE = 0x0,
76     FUNCTION = 0x1,
77     NC_FUNCTION = 0x2,
78     GENERATOR_FUNCTION = 0x3,
79     ASYNC_FUNCTION = 0x4,
80     ASYNC_GENERATOR_FUNCTION = 0x5,
81     ASYNC_NC_FUNCTION = 0x6,
82     CONCURRENT_FUNCTION = 0x7,
83     // Use bit operation to support both sendable function and async sendable function
84     SENDABLE_FUNCTION = 1 << 3
85 };
86 
87 enum class ItemRank : uint8_t {
88     DEFAULT_RANK = 0x0,
89     STRING_ITEM_RANK = 0x1,
90     CLASS_ITEM_RANK = 0x2
91 };
92 
93 enum class ItemTypes {
94     ANNOTATION_ITEM,
95     CATCH_BLOCK_ITEM,
96     CLASS_INDEX_ITEM,
97     CLASS_ITEM,
98     CODE_ITEM,
99     DEBUG_INFO_ITEM,
100     END_ITEM,
101     FIELD_INDEX_ITEM,
102     FIELD_ITEM,
103     FOREIGN_CLASS_ITEM,
104     FOREIGN_FIELD_ITEM,
105     FOREIGN_METHOD_ITEM,
106     INDEX_HEADER,
107     INDEX_SECTION,
108     LINE_NUMBER_PROGRAM_INDEX_ITEM,
109     LINE_NUMBER_PROGRAM_ITEM,
110     LITERAL_ARRAY_ITEM,
111     LITERAL_ITEM,
112     METHOD_HANDLE_ITEM,
113     METHOD_INDEX_ITEM,
114     METHOD_ITEM,
115     PARAM_ANNOTATIONS_ITEM,
116     PRIMITIVE_TYPE_ITEM,
117     PROTO_INDEX_ITEM,
118     PROTO_ITEM,
119     STRING_ITEM,
120     TRY_BLOCK_ITEM,
121     VALUE_ITEM
122 };
123 
124 bool IsDynamicLanguage(panda::panda_file::SourceLang lang);
125 std::optional<panda::panda_file::SourceLang> LanguageFromString(const std::string_view &lang);
126 const char *LanguageToString(panda::panda_file::SourceLang lang);
127 const char *GetCtorName(panda::panda_file::SourceLang lang);
128 const char *GetCctorName(panda::panda_file::SourceLang lang);
129 const char *GetStringClassDescriptor(panda::panda_file::SourceLang lang);
130 std::string ItemTypeToString(ItemTypes type);
131 
132 static constexpr size_t ID_SIZE = File::EntityId::GetSize();
133 static constexpr size_t IDX_SIZE = sizeof(uint16_t);
134 static constexpr size_t TAG_SIZE = 1;
135 static constexpr uint32_t INVALID_OFFSET = std::numeric_limits<uint32_t>::max();
136 static constexpr uint32_t INVALID_INDEX = std::numeric_limits<uint32_t>::max();
137 static constexpr uint32_t MAX_INDEX_32 = std::numeric_limits<uint32_t>::max();
138 static constexpr uint32_t FLAG_WIDTH = 8;
139 static constexpr uint32_t FUNTION_KIND_WIDTH = 8;
140 static constexpr uint32_t FUNCTION_KIND_MASK = 0xFF00;
141 static constexpr uint32_t FLAG_MASK = 0xFF;
142 
143 constexpr uint16_t INVALID_INDEX_16 = std::numeric_limits<uint16_t>::max();
144 constexpr uint32_t MAX_INDEX_16 = std::numeric_limits<uint16_t>::max() - 1;
145 
146 constexpr uint32_t PGO_STRING_DEFAULT_COUNT = 5;
147 constexpr uint32_t PGO_CLASS_DEFAULT_COUNT = 3;
148 constexpr uint32_t PGO_CODE_DEFAULT_COUNT = 1;
149 
150 constexpr std::string_view STRING_ITEM = "string_item";
151 constexpr std::string_view CLASS_ITEM = "class_item";
152 constexpr std::string_view CODE_ITEM = "code_item";
153 
154 enum class IndexType {
155     // 16-bit indexes
156     CLASS = 0x0,
157     METHOD_STRING_LITERAL = 0x1,
158     FIELD = 0x2,
159     PROTO = 0x3,
160     LAST_16 = PROTO,
161     // 32-bit indexes
162     LINE_NUMBER_PROG = 0x04,
163     LAST_32 = LINE_NUMBER_PROG,
164 
165     NONE
166 };
167 
168 static constexpr size_t INDEX_COUNT_16 = static_cast<size_t>(IndexType::LAST_16) + 1;
169 
170 class IndexedItem;
171 class ItemContainer;
172 
173 class BaseItem {
174 public:
175     using VisitorCallBack = std::function<bool(BaseItem *)>;
176 
177     BaseItem() = default;
178     virtual ~BaseItem() = default;
179 
180     DEFAULT_COPY_SEMANTIC(BaseItem);
181     DEFAULT_MOVE_SEMANTIC(BaseItem);
182 
GetSize() const183     size_t GetSize() const
184     {
185         return CalculateSize();
186     }
187 
188     virtual size_t CalculateSize() const = 0;
189 
ComputeLayout()190     virtual void ComputeLayout() {}
191 
Alignment()192     virtual size_t Alignment()
193     {
194         return 1;
195     }
196 
IsForeign() const197     virtual bool IsForeign() const
198     {
199         return false;
200     }
201 
GetOffset() const202     uint32_t GetOffset() const
203     {
204         return offset_;
205     }
206 
GetFileId() const207     panda_file::File::EntityId GetFileId() const
208     {
209         return panda_file::File::EntityId(offset_);
210     }
211 
SetOffset(uint32_t offset)212     void SetOffset(uint32_t offset)
213     {
214         offset_ = offset;
215     }
216 
NeedsEmit() const217     bool NeedsEmit() const
218     {
219         return needs_emit_;
220     }
221 
SetNeedsEmit(bool needs_emit)222     void SetNeedsEmit(bool needs_emit)
223     {
224         needs_emit_ = needs_emit;
225     }
226 
GetIndexDependencies() const227     const std::list<IndexedItem *> &GetIndexDependencies() const
228     {
229         return index_deps_;
230     }
231 
AddIndexDependency(IndexedItem *item)232     void AddIndexDependency(IndexedItem *item)
233     {
234         ASSERT(item != nullptr);
235         index_deps_.push_back(item);
236     }
237 
SetOrderIndex(uint32_t order)238     void SetOrderIndex(uint32_t order)
239     {
240         order_ = order;
241     }
242 
GetOrderIndex() const243     uint32_t GetOrderIndex() const
244     {
245         return order_;
246     }
247 
HasOrderIndex() const248     bool HasOrderIndex() const
249     {
250         return order_ != INVALID_INDEX;
251     }
252 
253     virtual bool Write(Writer *writer) = 0;
254 
255     std::string GetName() const;
256 
257     virtual ItemTypes GetItemType() const = 0;
258 
Dump([[maybe_unused]] std::ostream &os) const259     virtual void Dump([[maybe_unused]] std::ostream &os) const {}
260 
Visit([[maybe_unused]] const VisitorCallBack &cb)261     virtual void Visit([[maybe_unused]] const VisitorCallBack &cb) {}
262 
SetPGORank(uint32_t rank)263     void SetPGORank(uint32_t rank)
264     {
265         pgo_rank_ = rank;
266     }
267 
GetPGORank() const268     uint32_t GetPGORank() const
269     {
270         return pgo_rank_;
271     }
272 
SetOriginalRank(uint32_t rank)273     void SetOriginalRank(uint32_t rank)
274     {
275         original_rank_ = rank;
276     }
277 
GetOriginalRank() const278     uint32_t GetOriginalRank() const
279     {
280         return original_rank_;
281     }
282 
SetReLayoutRank(ItemRank rank)283     void SetReLayoutRank(ItemRank rank)
284     {
285         re_layout_rank_ = rank;
286     }
287 
GetReLayoutRank() const288     ItemRank GetReLayoutRank() const
289     {
290         return re_layout_rank_;
291     }
292 
293 private:
294     bool needs_emit_ {true};
295     uint32_t offset_ {0};
296     uint32_t order_ {INVALID_INDEX};
297     std::list<IndexedItem *> index_deps_;
298     uint32_t pgo_rank_ {0};
299     uint32_t original_rank_ {0};
300     ItemRank re_layout_rank_ {ItemRank::DEFAULT_RANK};
301 };
302 
303 class IndexedItem : public BaseItem {
304 public:
305     explicit IndexedItem(ItemContainer *container);
306 
GetIndex(const BaseItem *item) const307     uint32_t GetIndex(const BaseItem *item) const
308     {
309         auto *idx = FindIndex(item);
310         ASSERT(idx != nullptr);
311         return idx->index;
312     }
313 
HasIndex(const BaseItem *item) const314     bool HasIndex(const BaseItem *item) const
315     {
316         return FindIndex(item) != nullptr;
317     }
318 
SetIndex(const BaseItem *start, const BaseItem *end, uint32_t index)319     void SetIndex(const BaseItem *start, const BaseItem *end, uint32_t index)
320     {
321         ASSERT(FindIndex(start, end) == nullptr);
322         indexes_.push_back({start, end, index});
323     }
324 
ClearIndexes()325     void ClearIndexes()
326     {
327         indexes_.clear();
328     }
329 
IncRefCount()330     void IncRefCount()
331     {
332         ++ref_count_;
333     }
334 
DecRefCount()335     void DecRefCount()
336     {
337         ASSERT(ref_count_ != 0);
338         --ref_count_;
339     }
340 
GetRefCount() const341     size_t GetRefCount() const
342     {
343         return ref_count_;
344     }
345 
GetIndexType() const346     virtual IndexType GetIndexType() const
347     {
348         return IndexType::NONE;
349     }
350 
GetIndexedItemCount() const351     size_t GetIndexedItemCount() const
352     {
353         return item_global_index_;
354     }
355 
356 private:
357     struct Index {
358         const BaseItem *start;
359         const BaseItem *end;
360         uint32_t index;
361     };
362 
FindIndex(const BaseItem *start, const BaseItem *end) const363     const Index *FindIndex(const BaseItem *start, const BaseItem *end) const
364     {
365         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(),
366                                [start, end](const Index &idx) { return idx.start == start && idx.end == end; });
367 
368         return it != indexes_.cend() ? &*it : nullptr;
369     }
370 
FindIndex(const BaseItem *item) const371     const Index *FindIndex(const BaseItem *item) const
372     {
373         ASSERT(item->HasOrderIndex());
374         auto order_idx = item->GetOrderIndex();
375 
376         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(), [order_idx](const Index &idx) {
377             if (idx.start == nullptr && idx.end == nullptr) {
378                 return true;
379             }
380 
381             if (idx.start == nullptr || idx.end == nullptr) {
382                 return false;
383             }
384 
385             ASSERT(idx.start->HasOrderIndex());
386             ASSERT(idx.end->HasOrderIndex());
387             return idx.start->GetOrderIndex() <= order_idx && order_idx < idx.end->GetOrderIndex();
388         });
389 
390         return it != indexes_.cend() ? &*it : nullptr;
391     }
392 
393     std::vector<Index> indexes_;
394     size_t ref_count_ {1};
395     size_t item_global_index_ {0};
396 };
397 
398 class TypeItem : public IndexedItem {
399 public:
TypeItem(Type type, ItemContainer *container)400     explicit TypeItem(Type type, ItemContainer *container) : IndexedItem(container), type_(type) {}
401 
TypeItem(Type::TypeId type_id, ItemContainer *container)402     explicit TypeItem(Type::TypeId type_id, ItemContainer *container) : IndexedItem(container), type_(type_id) {}
403 
404     ~TypeItem() override = default;
405 
GetType() const406     Type GetType() const
407     {
408         return type_;
409     }
410 
411     IndexType GetIndexType() const override
412     {
413         return IndexType::CLASS;
414     }
415 
416     DEFAULT_MOVE_SEMANTIC(TypeItem);
417     DEFAULT_COPY_SEMANTIC(TypeItem);
418 
419 private:
420     Type type_;
421 };
422 
423 class PrimitiveTypeItem : public TypeItem {
424 public:
PrimitiveTypeItem(Type type, ItemContainer *container)425     explicit PrimitiveTypeItem(Type type, ItemContainer *container) : PrimitiveTypeItem(type.GetId(), container) {}
426 
PrimitiveTypeItem(Type::TypeId type_id, ItemContainer *container)427     explicit PrimitiveTypeItem(Type::TypeId type_id, ItemContainer *container) : TypeItem(type_id, container)
428     {
429         ASSERT(GetType().IsPrimitive());
430         SetNeedsEmit(false);
431         SetOffset(GetType().GetFieldEncoding());
432     }
433 
434     ~PrimitiveTypeItem() override = default;
435 
436     size_t CalculateSize() const override
437     {
438         return 0;
439     }
440 
441     bool Write([[maybe_unused]] Writer *writer) override
442     {
443         return true;
444     }
445 
446     ItemTypes GetItemType() const override
447     {
448         return ItemTypes::PRIMITIVE_TYPE_ITEM;
449     }
450 
451     DEFAULT_MOVE_SEMANTIC(PrimitiveTypeItem);
452     DEFAULT_COPY_SEMANTIC(PrimitiveTypeItem);
453 };
454 
455 class StringItem : public IndexedItem {
456 public:
457     explicit StringItem(std::string str, ItemContainer *container);
458 
459     explicit StringItem(File::StringData data, ItemContainer *container);
460 
461     ~StringItem() override = default;
462 
463     size_t CalculateSize() const override;
464 
465     bool Write(Writer *writer) override;
466 
467     ItemTypes GetItemType() const override
468     {
469         return ItemTypes::STRING_ITEM;
470     }
471 
GetData() const472     const std::string &GetData() const
473     {
474         return str_;
475     }
476 
GetUtf16Len() const477     size_t GetUtf16Len() const
478     {
479         return utf16_length_;
480     }
481 
482     IndexType GetIndexType() const override
483     {
484         return IndexType::METHOD_STRING_LITERAL;
485     }
486 
487     DEFAULT_MOVE_SEMANTIC(StringItem);
488     DEFAULT_COPY_SEMANTIC(StringItem);
489 
490 private:
491     std::string str_;
492     size_t utf16_length_;
493     size_t is_ascii_ = 0;
494 };
495 
496 class AnnotationItem;
497 class BaseClassItem;
498 class ClassItem;
499 class ForeignClassItem;
500 class ValueItem;
501 
502 class BaseFieldItem : public IndexedItem {
503 public:
504     IndexType GetIndexType() const override
505     {
506         return IndexType::FIELD;
507     }
508 
GetNameItem() const509     StringItem *GetNameItem() const
510     {
511         return name_;
512     }
513 
514     ~BaseFieldItem() override = default;
515 
516     DEFAULT_MOVE_SEMANTIC(BaseFieldItem);
517     DEFAULT_COPY_SEMANTIC(BaseFieldItem);
518 
519 protected:
520     BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, ItemContainer *container);
521 
522     size_t CalculateSize() const override;
523 
524     bool Write(Writer *writer) override;
525 
526 private:
527     BaseClassItem *class_;
528     StringItem *name_;
529     TypeItem *type_;
530 };
531 
532 class FieldItem : public BaseFieldItem {
533 public:
534     FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t access_flags, ItemContainer *container);
535 
536     ~FieldItem() override = default;
537 
538     void SetValue(ValueItem *value);
539 
GetValue() const540     ValueItem *GetValue() const
541     {
542         return value_;
543     }
544 
AddRuntimeAnnotation(AnnotationItem *runtime_annotation)545     void AddRuntimeAnnotation(AnnotationItem *runtime_annotation)
546     {
547         runtime_annotations_.push_back(runtime_annotation);
548     }
549 
AddAnnotation(AnnotationItem *annotation)550     void AddAnnotation(AnnotationItem *annotation)
551     {
552         annotations_.push_back(annotation);
553     }
554 
AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)555     void AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)
556     {
557         runtime_type_annotations_.push_back(runtime_type_annotation);
558     }
559 
AddTypeAnnotation(AnnotationItem *type_annotation)560     void AddTypeAnnotation(AnnotationItem *type_annotation)
561     {
562         type_annotations_.push_back(type_annotation);
563     }
564 
565     size_t CalculateSize() const override;
566 
567     bool Write(Writer *writer) override;
568 
569     ItemTypes GetItemType() const override
570     {
571         return ItemTypes::FIELD_ITEM;
572     }
573 
GetRuntimeAnnotations()574     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
575     {
576         return &runtime_annotations_;
577     }
578 
GetAnnotations()579     std::vector<AnnotationItem *> *GetAnnotations()
580     {
581         return &annotations_;
582     }
583 
GetTypeAnnotations()584     std::vector<AnnotationItem *> *GetTypeAnnotations()
585     {
586         return &type_annotations_;
587     }
588 
GetRuntimeTypeAnnotations()589     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
590     {
591         return &runtime_type_annotations_;
592     }
593 
594     DEFAULT_MOVE_SEMANTIC(FieldItem);
595     DEFAULT_COPY_SEMANTIC(FieldItem);
596 
597 private:
598     bool WriteValue(Writer *writer);
599 
600     bool WriteAnnotations(Writer *writer);
601 
602     bool WriteTaggedData(Writer *writer);
603 
604     uint32_t access_flags_;
605     ValueItem *value_;
606     std::vector<AnnotationItem *> runtime_annotations_;
607     std::vector<AnnotationItem *> annotations_;
608     std::vector<AnnotationItem *> type_annotations_;
609     std::vector<AnnotationItem *> runtime_type_annotations_;
610 };
611 
612 class ProtoItem;
613 class CodeItem;
614 
615 class LineNumberProgramItem : public IndexedItem {
616 public:
617     enum class Opcode : uint8_t {
618         END_SEQUENCE = 0x00,
619         ADVANCE_PC = 0x01,
620         ADVANCE_LINE = 0x02,
621         START_LOCAL = 0x03,
622         START_LOCAL_EXTENDED = 0x04,
623         END_LOCAL = 0x05,
624         RESTART_LOCAL = 0x06,
625         SET_PROLOGUE_END = 0x07,
626         SET_EPILOGUE_BEGIN = 0x08,
627         SET_FILE = 0x09,
628         SET_SOURCE_CODE = 0x0a,
629         SET_COLUMN = 0X0b,
630         LAST
631     };
632 
633     static constexpr uint8_t OPCODE_BASE = static_cast<uint8_t>(Opcode::LAST);
634     static constexpr int32_t LINE_RANGE = 15;
635     static constexpr int32_t LINE_BASE = -4;
636 
LineNumberProgramItem(ItemContainer *container)637     explicit LineNumberProgramItem(ItemContainer *container) : IndexedItem(container) {}
638 
639     void EmitEnd();
640 
641     void EmitAdvancePc(std::vector<uint8_t> *constant_pool, uint32_t value);
642 
643     void EmitAdvanceLine(std::vector<uint8_t> *constant_pool, int32_t value);
644 
645     void EmitColumn(std::vector<uint8_t> *constant_pool, uint32_t pc_inc, uint32_t column);
646 
647     void EmitStartLocal(std::vector<uint8_t> *constant_pool, int32_t register_number, StringItem *name,
648                         StringItem *type);
649 
650     void EmitStartLocalExtended(std::vector<uint8_t> *constant_pool, int32_t register_number, StringItem *name,
651                                 StringItem *type, StringItem *type_signature);
652 
653     void EmitEndLocal(int32_t register_number);
654 
655     void EmitRestartLocal(int32_t register_number);
656 
657     bool EmitSpecialOpcode(uint32_t pc_inc, int32_t line_inc);
658 
659     void EmitPrologEnd();
660 
661     void EmitEpilogBegin();
662 
663     void EmitSetFile(std::vector<uint8_t> *constant_pool, StringItem *source_file);
664 
665     void EmitSetSourceCode(std::vector<uint8_t> *constant_pool, StringItem *source_code);
666 
667     bool Write(Writer *writer) override;
668 
669     size_t CalculateSize() const override;
670 
671     ItemTypes GetItemType() const override
672     {
673         return ItemTypes::LINE_NUMBER_PROGRAM_ITEM;
674     }
675 
GetData() const676     const std::vector<uint8_t> &GetData() const
677     {
678         return data_;
679     }
680 
681     IndexType GetIndexType() const override
682     {
683         return IndexType::LINE_NUMBER_PROG;
684     }
685 
686     void SetData(std::vector<uint8_t> &&data);
687 
688 private:
689     void EmitOpcode(Opcode opcode);
690     void EmitRegister(int32_t register_number);
691 
692     static void EmitUleb128(std::vector<uint8_t> *data, uint32_t value);
693 
694     static void EmitSleb128(std::vector<uint8_t> *data, int32_t value);
695 
696     std::vector<uint8_t> data_;
697 };
698 
699 class DebugInfoItem : public BaseItem {
700 public:
DebugInfoItem(LineNumberProgramItem *item)701     explicit DebugInfoItem(LineNumberProgramItem *item) : program_(item) {}
702 
703     ~DebugInfoItem() override = default;
704 
705     DEFAULT_MOVE_SEMANTIC(DebugInfoItem);
706     DEFAULT_COPY_SEMANTIC(DebugInfoItem);
707 
GetLineNumber() const708     size_t GetLineNumber() const
709     {
710         return line_num_;
711     }
712 
SetLineNumber(size_t line_num)713     void SetLineNumber(size_t line_num)
714     {
715         line_num_ = line_num;
716     }
717 
GetLineNumberProgram() const718     LineNumberProgramItem *GetLineNumberProgram() const
719     {
720         return program_;
721     }
722 
SetLineNumberProgram(LineNumberProgramItem *program)723     void SetLineNumberProgram(LineNumberProgramItem *program)
724     {
725         ASSERT(program->GetOffset() != 0);
726         program_ = program;
727     }
728 
AddParameter(StringItem *name)729     void AddParameter(StringItem *name)
730     {
731         parameters_.push_back(name);
732     }
733 
GetConstantPool()734     std::vector<uint8_t> *GetConstantPool()
735     {
736         return &constant_pool_;
737     }
738 
739     size_t CalculateSize() const override;
740 
741     bool Write(Writer *writer) override;
742 
743     ItemTypes GetItemType() const override
744     {
745         return ItemTypes::DEBUG_INFO_ITEM;
746     }
747 
748     void Dump(std::ostream &os) const override;
749 
750 private:
751     size_t line_num_ {0};
752     LineNumberProgramItem *program_;
753     std::vector<uint8_t> constant_pool_;
754     std::vector<StringItem *> parameters_;
755 };
756 
757 class BaseMethodItem : public IndexedItem {
758 public:
GetProto() const759     ProtoItem *GetProto() const
760     {
761         return proto_;
762     }
763 
IsStatic() const764     bool IsStatic() const
765     {
766         return (access_flags_ & ACC_STATIC) != 0;
767     }
768 
769     IndexType GetIndexType() const override
770     {
771         return IndexType::METHOD_STRING_LITERAL;
772     }
773 
GetNameItem() const774     StringItem *GetNameItem() const
775     {
776         return name_;
777     }
778 
GetClassItem() const779     BaseClassItem *GetClassItem() const
780     {
781         return class_;
782     }
783 
SetFunctionKind(FunctionKind kind)784     void SetFunctionKind(FunctionKind kind)
785     {
786         access_flags_ &= (~FUNCTION_KIND_MASK);
787         access_flags_ |= (static_cast<uint32_t>(kind) << FLAG_WIDTH);
788     }
789 
SetHeaderIndex(uint16_t idx)790     void SetHeaderIndex(uint16_t idx)
791     {
792         access_flags_ &= (FUNCTION_KIND_MASK | FLAG_MASK);
793         access_flags_ |= (static_cast<uint32_t>(idx) << (FUNTION_KIND_WIDTH + FLAG_WIDTH));
794     }
795 
796     ~BaseMethodItem() override = default;
797 
798     DEFAULT_MOVE_SEMANTIC(BaseMethodItem);
799     DEFAULT_COPY_SEMANTIC(BaseMethodItem);
800 
801 protected:
802     BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
803         ItemContainer *container);
804 
805     size_t CalculateSize() const override;
806 
807     bool Write(Writer *writer) override;
808 
809 private:
810     BaseClassItem *class_;
811     StringItem *name_;
812     ProtoItem *proto_;
813     uint32_t access_flags_;  // layout: |<- 16-bit header index ->|<- 8-bit FunctionKind ->|<- 8-bit flag ->|
814 };
815 
816 class MethodParamItem {
817 public:
MethodParamItem(TypeItem *type)818     explicit MethodParamItem(TypeItem *type) : type_(type) {}
819 
820     ~MethodParamItem() = default;
821 
822     DEFAULT_MOVE_SEMANTIC(MethodParamItem);
823     DEFAULT_COPY_SEMANTIC(MethodParamItem);
824 
AddRuntimeAnnotation(AnnotationItem *runtime_annotation)825     void AddRuntimeAnnotation(AnnotationItem *runtime_annotation)
826     {
827         runtime_annotations_.push_back(runtime_annotation);
828     }
829 
AddAnnotation(AnnotationItem *annotation)830     void AddAnnotation(AnnotationItem *annotation)
831     {
832         annotations_.push_back(annotation);
833     }
834 
AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)835     void AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)
836     {
837         runtime_type_annotations_.push_back(runtime_type_annotation);
838     }
839 
AddTypeAnnotation(AnnotationItem *type_annotation)840     void AddTypeAnnotation(AnnotationItem *type_annotation)
841     {
842         type_annotations_.push_back(type_annotation);
843     }
844 
GetType() const845     TypeItem *GetType() const
846     {
847         return type_;
848     }
849 
GetRuntimeAnnotations() const850     const std::vector<AnnotationItem *> &GetRuntimeAnnotations() const
851     {
852         return runtime_annotations_;
853     }
854 
GetAnnotations() const855     const std::vector<AnnotationItem *> &GetAnnotations() const
856     {
857         return annotations_;
858     }
859 
HasAnnotations() const860     bool HasAnnotations() const
861     {
862         return !annotations_.empty();
863     }
864 
HasRuntimeAnnotations() const865     bool HasRuntimeAnnotations() const
866     {
867         return !runtime_annotations_.empty();
868     }
869 
870 private:
871     TypeItem *type_;
872     std::vector<AnnotationItem *> runtime_annotations_;
873     std::vector<AnnotationItem *> annotations_;
874     std::vector<AnnotationItem *> type_annotations_;
875     std::vector<AnnotationItem *> runtime_type_annotations_;
876 };
877 
878 class ParamAnnotationsItem;
879 class BaseClassItem;
880 
881 class MethodItem : public BaseMethodItem {
882 public:
883     MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
884                std::vector<MethodParamItem> params, ItemContainer *container);
885 
886     ~MethodItem() override = default;
887 
888     DEFAULT_MOVE_SEMANTIC(MethodItem);
889     DEFAULT_COPY_SEMANTIC(MethodItem);
890 
SetSourceLang(SourceLang lang)891     void SetSourceLang(SourceLang lang)
892     {
893         source_lang_ = lang;
894     }
895 
SetCode(CodeItem *code)896     void SetCode(CodeItem *code)
897     {
898         code_ = code;
899     }
900 
SetDebugInfo(DebugInfoItem *debug_info)901     void SetDebugInfo(DebugInfoItem *debug_info)
902     {
903         debug_info_ = debug_info;
904     }
905 
AddRuntimeAnnotation(AnnotationItem *runtime_annotation)906     void AddRuntimeAnnotation(AnnotationItem *runtime_annotation)
907     {
908         runtime_annotations_.push_back(runtime_annotation);
909     }
910 
AddAnnotation(AnnotationItem *annotation)911     void AddAnnotation(AnnotationItem *annotation)
912     {
913         annotations_.push_back(annotation);
914     }
915 
AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)916     void AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)
917     {
918         runtime_type_annotations_.push_back(runtime_type_annotation);
919     }
920 
AddTypeAnnotation(AnnotationItem *type_annotation)921     void AddTypeAnnotation(AnnotationItem *type_annotation)
922     {
923         type_annotations_.push_back(type_annotation);
924     }
925 
SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations)926     void SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations)
927     {
928         runtime_param_annotations_ = annotations;
929     }
930 
SetParamAnnotationItem(ParamAnnotationsItem *annotations)931     void SetParamAnnotationItem(ParamAnnotationsItem *annotations)
932     {
933         param_annotations_ = annotations;
934     }
935 
HasRuntimeParamAnnotations() const936     bool HasRuntimeParamAnnotations() const
937     {
938         return std::any_of(params_.cbegin(), params_.cend(),
939                            [](const MethodParamItem &item) { return item.HasRuntimeAnnotations(); });
940     }
941 
HasParamAnnotations() const942     bool HasParamAnnotations() const
943     {
944         return std::any_of(params_.cbegin(), params_.cend(),
945                            [](const MethodParamItem &item) { return item.HasAnnotations(); });
946     }
947 
GetCode() const948     CodeItem *GetCode() const
949     {
950         return code_;
951     }
952 
GetDebugInfo() const953     DebugInfoItem *GetDebugInfo() const
954     {
955         return debug_info_;
956     }
957 
958     size_t CalculateSize() const override;
959 
960     bool Write(Writer *writer) override;
961 
962     ItemTypes GetItemType() const override
963     {
964         return ItemTypes::METHOD_ITEM;
965     }
966 
GetParams()967     std::vector<MethodParamItem> &GetParams()
968     {
969         return params_;
970     }
971 
GetRuntimeAnnotations()972     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
973     {
974         return &runtime_annotations_;
975     }
976 
GetAnnotations()977     std::vector<AnnotationItem *> *GetAnnotations()
978     {
979         return &annotations_;
980     }
981 
GetTypeAnnotations()982     std::vector<AnnotationItem *> *GetTypeAnnotations()
983     {
984         return &type_annotations_;
985     }
986 
GetRuntimeTypeAnnotations()987     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
988     {
989         return &runtime_type_annotations_;
990     }
991 
992 private:
993     bool WriteRuntimeAnnotations(Writer *writer);
994 
995     bool WriteTypeAnnotations(Writer *writer);
996 
997     bool WriteTaggedData(Writer *writer);
998 
999     std::vector<MethodParamItem> params_;
1000 
1001     SourceLang source_lang_;
1002     CodeItem *code_;
1003     DebugInfoItem *debug_info_;
1004     std::vector<AnnotationItem *> runtime_annotations_;
1005     std::vector<AnnotationItem *> annotations_;
1006     std::vector<AnnotationItem *> type_annotations_;
1007     std::vector<AnnotationItem *> runtime_type_annotations_;
1008     ParamAnnotationsItem *runtime_param_annotations_ {nullptr};
1009     ParamAnnotationsItem *param_annotations_ {nullptr};
1010 };
1011 
1012 class BaseClassItem : public TypeItem {
1013 public:
GetNameItem()1014     StringItem *GetNameItem()
1015     {
1016         return &name_;
1017     }
1018 
1019 protected:
BaseClassItem(const std::string &name, ItemContainer *container)1020     explicit BaseClassItem(const std::string &name, ItemContainer *container)
1021         : TypeItem(Type::TypeId::REFERENCE, container), name_(name, container) {}
1022 
1023     ~BaseClassItem() override = default;
1024 
1025     size_t CalculateSize() const override;
1026 
1027     void ComputeLayout() override;
1028 
1029     bool Write(Writer *writer) override;
1030 
1031     DEFAULT_MOVE_SEMANTIC(BaseClassItem);
1032     DEFAULT_COPY_SEMANTIC(BaseClassItem);
1033 
1034 private:
1035     StringItem name_;
1036 };
1037 
1038 class ClassItem : public BaseClassItem {
1039 public:
ClassItem(const std::string &name, ItemContainer *container)1040     explicit ClassItem(const std::string &name, ItemContainer *container)
1041         : BaseClassItem(name, container),
1042           super_class_(nullptr),
1043           access_flags_(0),
1044           source_lang_(SourceLang::PANDA_ASSEMBLY),
1045           source_file_(nullptr),
1046           container_(container)
1047     {
1048     }
1049 
1050     ~ClassItem() override = default;
1051 
SetAccessFlags(uint32_t access_flags)1052     void SetAccessFlags(uint32_t access_flags)
1053     {
1054         access_flags_ = access_flags;
1055     }
1056 
SetSourceLang(SourceLang lang)1057     void SetSourceLang(SourceLang lang)
1058     {
1059         source_lang_ = lang;
1060     }
1061 
SetSuperClass(BaseClassItem *super_class)1062     void SetSuperClass(BaseClassItem *super_class)
1063     {
1064         super_class_ = super_class;
1065     }
1066 
AddInterface(BaseClassItem *iface)1067     void AddInterface(BaseClassItem *iface)
1068     {
1069         AddIndexDependency(iface);
1070         ifaces_.push_back(iface);
1071     }
1072 
AddRuntimeAnnotation(AnnotationItem *runtime_annotation)1073     void AddRuntimeAnnotation(AnnotationItem *runtime_annotation)
1074     {
1075         runtime_annotations_.push_back(runtime_annotation);
1076     }
1077 
AddAnnotation(AnnotationItem *annotation)1078     void AddAnnotation(AnnotationItem *annotation)
1079     {
1080         annotations_.push_back(annotation);
1081     }
1082 
AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)1083     void AddRuntimeTypeAnnotation(AnnotationItem *runtime_type_annotation)
1084     {
1085         runtime_type_annotations_.push_back(runtime_type_annotation);
1086     }
1087 
AddTypeAnnotation(AnnotationItem *type_annotation)1088     void AddTypeAnnotation(AnnotationItem *type_annotation)
1089     {
1090         type_annotations_.push_back(type_annotation);
1091     }
1092 
1093     template <class... Args>
AddField(Args.... args)1094     FieldItem *AddField(Args... args)
1095     {
1096         fields_.emplace_back(std::make_unique<FieldItem>(this, std::forward<Args>(args)..., container_));
1097         return fields_.back().get();
1098     }
1099 
1100     template <class... Args>
AddMethod(Args.... args)1101     MethodItem *AddMethod(Args... args)
1102     {
1103         // insert new method to set ordered by method name
1104         return methods_.insert(std::make_unique<MethodItem>(this, std::forward<Args>(args)..., container_))->get();
1105     }
1106 
SetSourceFile(StringItem *item)1107     void SetSourceFile(StringItem *item)
1108     {
1109         source_file_ = item;
1110     }
1111 
1112     size_t CalculateSizeWithoutFieldsAndMethods() const;
1113 
1114     size_t CalculateSize() const override;
1115 
1116     void ComputeLayout() override;
1117 
1118     bool Write(Writer *writer) override;
1119 
1120     ItemTypes GetItemType() const override
1121     {
1122         return ItemTypes::CLASS_ITEM;
1123     }
1124 
VisitFields(const VisitorCallBack &cb)1125     void VisitFields(const VisitorCallBack &cb)
1126     {
1127         for (auto &field : fields_) {
1128             if (!cb(field.get())) {
1129                 break;
1130             }
1131         }
1132     }
1133 
VisitMethods(const VisitorCallBack &cb)1134     void VisitMethods(const VisitorCallBack &cb)
1135     {
1136         for (auto &method : methods_) {
1137             if (!cb(method.get())) {
1138                 break;
1139             }
1140         }
1141     }
1142 
1143     void Visit(const VisitorCallBack &cb) override
1144     {
1145         VisitFields(cb);
1146         VisitMethods(cb);
1147     }
1148 
GetRuntimeAnnotations()1149     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
1150     {
1151         return &runtime_annotations_;
1152     }
1153 
GetAnnotations()1154     std::vector<AnnotationItem *> *GetAnnotations()
1155     {
1156         return &annotations_;
1157     }
1158 
GetTypeAnnotations()1159     std::vector<AnnotationItem *> *GetTypeAnnotations()
1160     {
1161         return &type_annotations_;
1162     }
1163 
GetRuntimeTypeAnnotations()1164     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
1165     {
1166         return &runtime_type_annotations_;
1167     }
1168 
1169     DEFAULT_MOVE_SEMANTIC(ClassItem);
1170     DEFAULT_COPY_SEMANTIC(ClassItem);
1171 
1172 private:
1173     struct MethodCompByName {
operator ()panda::panda_file::ClassTag::MethodTag::FieldTag::ClassItem::MethodCompByName1174         bool operator()(const std::unique_ptr<MethodItem> &m1, const std::unique_ptr<MethodItem> &m2) const
1175         {
1176             auto *str1 = m1->GetNameItem();
1177             auto *str2 = m2->GetNameItem();
1178             if (str1->GetUtf16Len() == str2->GetUtf16Len()) {
1179                 return str1->GetData() < str2->GetData();
1180             }
1181             return str1->GetUtf16Len() < str2->GetUtf16Len();
1182         }
1183     };
1184 
1185     bool WriteIfaces(Writer *writer);
1186 
1187     bool WriteAnnotations(Writer *writer);
1188 
1189     bool WriteTaggedData(Writer *writer);
1190 
1191     BaseClassItem *super_class_;
1192     uint32_t access_flags_;
1193     SourceLang source_lang_;
1194     std::vector<BaseClassItem *> ifaces_;
1195     std::vector<AnnotationItem *> runtime_annotations_;
1196     std::vector<AnnotationItem *> annotations_;
1197     std::vector<AnnotationItem *> type_annotations_;
1198     std::vector<AnnotationItem *> runtime_type_annotations_;
1199     StringItem *source_file_;
1200     std::vector<std::unique_ptr<FieldItem>> fields_;
1201     std::multiset<std::unique_ptr<MethodItem>, MethodCompByName> methods_;
1202     ItemContainer *container_;
1203 };
1204 
1205 class ForeignClassItem : public BaseClassItem {
1206 public:
ForeignClassItem(const std::string &name, ItemContainer *container)1207     explicit ForeignClassItem(const std::string &name, ItemContainer *container) : BaseClassItem(name, container) {}
1208 
1209     ~ForeignClassItem() override = default;
1210 
1211     bool IsForeign() const override
1212     {
1213         return true;
1214     }
1215 
1216     ItemTypes GetItemType() const override
1217     {
1218         return ItemTypes::FOREIGN_CLASS_ITEM;
1219     }
1220 
1221     DEFAULT_MOVE_SEMANTIC(ForeignClassItem);
1222     DEFAULT_COPY_SEMANTIC(ForeignClassItem);
1223 };
1224 
1225 class ForeignFieldItem : public BaseFieldItem {
1226 public:
ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, ItemContainer *container)1227     ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, ItemContainer *container)
1228         : BaseFieldItem(cls, name, type, container) {}
1229 
1230     ~ForeignFieldItem() override = default;
1231 
1232     bool IsForeign() const override
1233     {
1234         return true;
1235     }
1236 
1237     ItemTypes GetItemType() const override
1238     {
1239         return ItemTypes::FOREIGN_FIELD_ITEM;
1240     }
1241 
1242     DEFAULT_MOVE_SEMANTIC(ForeignFieldItem);
1243     DEFAULT_COPY_SEMANTIC(ForeignFieldItem);
1244 };
1245 
1246 class ForeignMethodItem : public BaseMethodItem {
1247 public:
ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags, ItemContainer *container)1248     ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t access_flags,
1249         ItemContainer *container) : BaseMethodItem(cls, name, proto, access_flags, container)
1250     {
1251     }
1252 
1253     ~ForeignMethodItem() override = default;
1254 
1255     bool IsForeign() const override
1256     {
1257         return true;
1258     }
1259 
1260     ItemTypes GetItemType() const override
1261     {
1262         return ItemTypes::FOREIGN_METHOD_ITEM;
1263     }
1264 
1265     DEFAULT_MOVE_SEMANTIC(ForeignMethodItem);
1266     DEFAULT_COPY_SEMANTIC(ForeignMethodItem);
1267 };
1268 
1269 class ProtoItem;
1270 
1271 class ParamAnnotationsItem : public BaseItem {
1272 public:
1273     ParamAnnotationsItem(MethodItem *method, bool is_runtime_annotations);
1274 
1275     ~ParamAnnotationsItem() override = default;
1276 
1277     ItemTypes GetItemType() const override
1278     {
1279         return ItemTypes::PARAM_ANNOTATIONS_ITEM;
1280     }
1281 
1282     size_t CalculateSize() const override;
1283 
1284     bool Write(Writer *writer) override;
1285 
1286     DEFAULT_MOVE_SEMANTIC(ParamAnnotationsItem);
1287     DEFAULT_COPY_SEMANTIC(ParamAnnotationsItem);
1288 
1289 private:
1290     std::vector<std::vector<AnnotationItem *>> annotations_;
1291 };
1292 
1293 class ProtoItem : public IndexedItem {
1294 public:
1295     ProtoItem(TypeItem *ret_type, const std::vector<MethodParamItem> &params, ItemContainer *itemContainer);
1296 
1297     ~ProtoItem() override = default;
1298 
1299     DEFAULT_MOVE_SEMANTIC(ProtoItem);
1300     DEFAULT_COPY_SEMANTIC(ProtoItem);
1301 
1302     size_t CalculateSize() const override
1303     {
1304         size_t size = shorty_.size() * sizeof(uint16_t);
1305         size += reference_types_.size() * IDX_SIZE;
1306         return size;
1307     }
1308 
1309     bool Write(Writer *writer) override;
1310 
1311     ItemTypes GetItemType() const override
1312     {
1313         return ItemTypes::PROTO_ITEM;
1314     }
1315 
1316     IndexType GetIndexType() const override
1317     {
1318         return IndexType::PROTO;
1319     }
1320 
1321     size_t Alignment() override
1322     {
1323         return sizeof(uint16_t);
1324     }
1325 
1326 private:
1327     static constexpr size_t SHORTY_ELEM_SIZE = 4;
1328 
1329     void AddType(TypeItem *type, size_t *n);
1330 
1331     std::vector<uint16_t> shorty_;
1332     std::vector<TypeItem *> reference_types_;
1333 };
1334 
1335 class CodeItem : public BaseItem {
1336 public:
1337     class CatchBlock : public BaseItem {
1338     public:
CatchBlock(MethodItem *method, BaseClassItem *type, size_t handler_pc, size_t code_size = 0)1339         CatchBlock(MethodItem *method, BaseClassItem *type, size_t handler_pc, size_t code_size = 0)
1340             : method_(method), type_(type), handler_pc_(handler_pc), code_size_(code_size)
1341         {
1342         }
1343 
1344         ~CatchBlock() override = default;
1345 
1346         DEFAULT_MOVE_SEMANTIC(CatchBlock);
1347         DEFAULT_COPY_SEMANTIC(CatchBlock);
1348 
1349         size_t CalculateSize() const override;
1350 
1351         bool Write(Writer *writer) override;
1352 
1353         ItemTypes GetItemType() const override
1354         {
1355             return ItemTypes::CATCH_BLOCK_ITEM;
1356         }
1357 
1358     private:
1359         MethodItem *method_;
1360         BaseClassItem *type_;
1361         size_t handler_pc_;
1362         size_t code_size_;
1363     };
1364 
1365     class TryBlock : public BaseItem {
1366     public:
TryBlock(size_t start_pc, size_t length, std::vector<CatchBlock> catch_blocks)1367         TryBlock(size_t start_pc, size_t length, std::vector<CatchBlock> catch_blocks)
1368             : start_pc_(start_pc), length_(length), catch_blocks_(std::move(catch_blocks))
1369         {
1370         }
1371 
1372         ~TryBlock() override = default;
1373 
1374         DEFAULT_MOVE_SEMANTIC(TryBlock);
1375         DEFAULT_COPY_SEMANTIC(TryBlock);
1376 
1377         size_t CalculateSizeWithoutCatchBlocks() const;
1378 
1379         void ComputeLayout() override;
1380 
1381         size_t CalculateSize() const override;
1382 
1383         bool Write(Writer *writer) override;
1384 
1385         ItemTypes GetItemType() const override
1386         {
1387             return ItemTypes::TRY_BLOCK_ITEM;
1388         }
1389 
1390     private:
1391         size_t start_pc_;
1392         size_t length_;
1393         std::vector<CatchBlock> catch_blocks_;
1394     };
1395 
CodeItem(size_t num_vregs, size_t num_args, std::vector<uint8_t> instructions)1396     CodeItem(size_t num_vregs, size_t num_args, std::vector<uint8_t> instructions)
1397         : num_vregs_(num_vregs), num_args_(num_args), instructions_(std::move(instructions))
1398     {
1399     }
1400 
1401     CodeItem() = default;
1402 
1403     ~CodeItem() override = default;
1404 
SetNumVregs(size_t num_vregs)1405     void SetNumVregs(size_t num_vregs)
1406     {
1407         num_vregs_ = num_vregs;
1408     }
1409 
SetNumArgs(size_t num_args)1410     void SetNumArgs(size_t num_args)
1411     {
1412         num_args_ = num_args;
1413     }
1414 
GetInstructions()1415     std::vector<uint8_t> *GetInstructions()
1416     {
1417         return &instructions_;
1418     }
1419 
SetNumInstructions(size_t num_ins)1420     void SetNumInstructions(size_t num_ins)
1421     {
1422         num_ins_ = num_ins;
1423     }
1424 
GetNumInstructions() const1425     size_t GetNumInstructions() const
1426     {
1427         return num_ins_;
1428     }
1429 
AddTryBlock(const TryBlock &try_block)1430     void AddTryBlock(const TryBlock &try_block)
1431     {
1432         try_blocks_.push_back(try_block);
1433     }
1434 
1435     size_t CalculateSizeWithoutTryBlocks() const;
1436 
1437     void ComputeLayout() override;
1438 
1439     size_t CalculateSize() const override;
1440 
1441     size_t GetCodeSize() const;
1442 
1443     bool Write(Writer *writer) override;
1444 
1445     ItemTypes GetItemType() const override
1446     {
1447         return ItemTypes::CODE_ITEM;
1448     }
1449 
AddMethod(BaseMethodItem *method)1450     void AddMethod(BaseMethodItem *method)
1451     {
1452         methods_.emplace_back(method);
1453     }
1454 
GetMethodNames() const1455     std::vector<std::string> GetMethodNames() const
1456     {
1457         std::vector<std::string> names;
1458         for (const auto *method : methods_) {
1459             if (method == nullptr) {
1460                 continue;
1461             }
1462             std::string class_name;
1463             if (method->GetClassItem() != nullptr) {
1464                 class_name = method->GetClassItem()->GetNameItem()->GetData();
1465                 class_name.pop_back();          // remove '\0'
1466                 ASSERT(class_name.size() > 2);  // 2 - L and ;
1467                 class_name.erase(0, 1);
1468                 class_name.pop_back();
1469                 class_name.append("::");
1470             }
1471             class_name.append(method->GetNameItem()->GetData());
1472             class_name.pop_back();  // remove '\0'
1473             names.emplace_back(class_name);
1474         }
1475         return names;
1476     }
1477 
1478     DEFAULT_MOVE_SEMANTIC(CodeItem);
1479     DEFAULT_COPY_SEMANTIC(CodeItem);
1480 
1481 private:
1482     size_t num_vregs_ {0};
1483     size_t num_args_ {0};
1484     size_t num_ins_ {0};
1485     std::vector<uint8_t> instructions_;
1486     std::vector<TryBlock> try_blocks_;
1487     std::vector<BaseMethodItem *> methods_;
1488 };
1489 
1490 class ScalarValueItem;
1491 class ArrayValueItem;
1492 
1493 class ValueItem : public IndexedItem {
1494 public:
1495     enum class Type { INTEGER, LONG, FLOAT, DOUBLE, ID, ARRAY };
1496 
ValueItem(Type type, ItemContainer *container)1497     explicit ValueItem(Type type, ItemContainer *container) : IndexedItem(container), type_(type) {}
1498 
1499     ~ValueItem() override = default;
1500 
1501     DEFAULT_MOVE_SEMANTIC(ValueItem);
1502     DEFAULT_COPY_SEMANTIC(ValueItem);
1503 
GetType() const1504     Type GetType() const
1505     {
1506         return type_;
1507     }
1508 
IsArray() const1509     bool IsArray() const
1510     {
1511         return type_ == Type::ARRAY;
1512     }
1513 
Is32bit() const1514     bool Is32bit() const
1515     {
1516         return type_ == Type::INTEGER || type_ == Type::FLOAT || type_ == Type::ID;
1517     }
1518 
1519     ItemTypes GetItemType() const override
1520     {
1521         return ItemTypes::VALUE_ITEM;
1522     }
1523 
1524     ScalarValueItem *GetAsScalar();
1525 
1526     ArrayValueItem *GetAsArray();
1527 
1528 private:
1529     Type type_;
1530 };
1531 
1532 class ScalarValueItem : public ValueItem {
1533 public:
ScalarValueItem(uint32_t v, ItemContainer *container)1534     explicit ScalarValueItem(uint32_t v, ItemContainer *container) : ValueItem(Type::INTEGER, container), value_(v) {}
1535 
ScalarValueItem(uint64_t v, ItemContainer *container)1536     explicit ScalarValueItem(uint64_t v, ItemContainer *container) : ValueItem(Type::LONG, container), value_(v) {}
1537 
ScalarValueItem(float v, ItemContainer *container)1538     explicit ScalarValueItem(float v, ItemContainer *container) : ValueItem(Type::FLOAT, container), value_(v) {}
1539 
ScalarValueItem(double v, ItemContainer *container)1540     explicit ScalarValueItem(double v, ItemContainer *container) : ValueItem(Type::DOUBLE, container), value_(v) {}
1541 
ScalarValueItem(BaseItem *v, ItemContainer *container)1542     explicit ScalarValueItem(BaseItem *v, ItemContainer *container) : ValueItem(Type::ID, container), value_(v) {}
1543 
1544     ~ScalarValueItem() override = default;
1545 
1546     DEFAULT_MOVE_SEMANTIC(ScalarValueItem);
1547     DEFAULT_COPY_SEMANTIC(ScalarValueItem);
1548 
1549     template <class T>
GetValue() const1550     T GetValue() const
1551     {
1552         return std::get<T>(value_);
1553     }
1554 
GetId() const1555     File::EntityId GetId() const
1556     {
1557         return File::EntityId(GetValue<BaseItem *>()->GetOffset());
1558     }
1559 
1560     size_t GetULeb128EncodedSize();
1561 
1562     size_t GetSLeb128EncodedSize();
1563 
1564     size_t CalculateSize() const override;
1565 
1566     size_t Alignment() override;
1567 
1568     bool Write(Writer *writer) override;
1569 
1570     bool WriteAsUleb128(Writer *writer);
1571 
1572 private:
1573     std::variant<uint32_t, uint64_t, float, double, BaseItem *> value_;
1574 };
1575 
1576 class ArrayValueItem : public ValueItem {
1577 public:
ArrayValueItem(panda_file::Type component_type, std::vector<ScalarValueItem> items, ItemContainer *container)1578     ArrayValueItem(panda_file::Type component_type, std::vector<ScalarValueItem> items, ItemContainer *container)
1579         : ValueItem(Type::ARRAY, container), component_type_(component_type), items_(std::move(items))
1580     {
1581     }
1582 
1583     ~ArrayValueItem() override = default;
1584 
1585     DEFAULT_MOVE_SEMANTIC(ArrayValueItem);
1586     DEFAULT_COPY_SEMANTIC(ArrayValueItem);
1587 
1588     size_t CalculateSize() const override;
1589 
1590     void ComputeLayout() override;
1591 
1592     bool Write(Writer *writer) override;
1593 
1594 private:
1595     size_t GetComponentSize() const;
1596 
1597     panda_file::Type component_type_;
1598     std::vector<ScalarValueItem> items_;
1599 };
1600 
1601 class LiteralItem;
1602 class LiteralArrayItem;
1603 
1604 class LiteralItem : public BaseItem {
1605 public:
1606     enum class Type { B1, B2, B4, B8, STRING, METHOD, LITERALARRAY };
1607 
LiteralItem(uint8_t v)1608     explicit LiteralItem(uint8_t v) : type_(Type::B1), value_(v) {}
1609 
LiteralItem(uint16_t v)1610     explicit LiteralItem(uint16_t v) : type_(Type::B2), value_(v) {}
1611 
LiteralItem(uint32_t v)1612     explicit LiteralItem(uint32_t v) : type_(Type::B4), value_(v) {}
1613 
LiteralItem(uint64_t v)1614     explicit LiteralItem(uint64_t v) : type_(Type::B8), value_(v) {}
1615 
LiteralItem(StringItem *v)1616     explicit LiteralItem(StringItem *v) : type_(Type::STRING), value_(v) {}
1617 
LiteralItem(MethodItem *v)1618     explicit LiteralItem(MethodItem *v) : type_(Type::METHOD), value_(v) {}
1619 
LiteralItem(LiteralArrayItem *v)1620     explicit LiteralItem(LiteralArrayItem *v) : type_(Type::LITERALARRAY), value_(v) {}
1621 
1622     ~LiteralItem() override = default;
1623 
1624     DEFAULT_MOVE_SEMANTIC(LiteralItem);
1625     DEFAULT_COPY_SEMANTIC(LiteralItem);
1626 
GetType() const1627     Type GetType() const
1628     {
1629         return type_;
1630     }
1631 
1632     ItemTypes GetItemType() const override
1633     {
1634         return ItemTypes::LITERAL_ITEM;
1635     }
1636 
1637     template <class T>
GetValue() const1638     T GetValue() const
1639     {
1640         return std::get<T>(value_);
1641     }
1642 
1643     size_t CalculateSize() const override;
1644 
1645     size_t Alignment() override;
1646 
GetId() const1647     File::EntityId GetId() const
1648     {
1649         return File::EntityId(GetValue<StringItem *>()->GetOffset());
1650     }
1651 
1652     File::EntityId GetLiteralArrayFileId() const;
1653 
GetMethodId() const1654     File::EntityId GetMethodId() const
1655     {
1656         return File::EntityId(GetValue<MethodItem *>()->GetFileId());
1657     }
1658 
1659     bool Write(Writer *writer) override;
1660 
1661 private:
1662     Type type_;
1663     std::variant<uint8_t, uint16_t, uint32_t, uint64_t, StringItem *, MethodItem *, LiteralArrayItem *> value_;
1664 };
1665 
1666 class LiteralArrayItem : public ValueItem {
1667 public:
LiteralArrayItem(ItemContainer *container)1668     explicit LiteralArrayItem(ItemContainer *container) : ValueItem(Type::ARRAY, container) {}
1669 
1670     ~LiteralArrayItem() override = default;
1671 
1672     DEFAULT_MOVE_SEMANTIC(LiteralArrayItem);
1673     DEFAULT_COPY_SEMANTIC(LiteralArrayItem);
1674 
1675     void AddItems(const std::vector<LiteralItem> &item);
1676 
1677     size_t CalculateSize() const override;
1678 
1679     void ComputeLayout() override;
1680 
1681     bool Write(Writer *writer) override;
1682 
1683     IndexType GetIndexType() const override
1684     {
1685         return IndexType::METHOD_STRING_LITERAL;
1686     }
1687 
1688     ItemTypes GetItemType() const override
1689     {
1690         return ItemTypes::LITERAL_ARRAY_ITEM;
1691     }
1692 
1693 private:
1694     std::vector<LiteralItem> items_;
1695 };
1696 
1697 class AnnotationItem : public BaseItem {
1698 public:
1699     class Elem {
1700     public:
Elem(StringItem *name, ValueItem *value)1701         Elem(StringItem *name, ValueItem *value) : name_(name), value_(value)
1702         {
1703             value_->SetNeedsEmit(!value_->Is32bit());
1704         }
1705 
1706         ~Elem() = default;
1707 
1708         DEFAULT_MOVE_SEMANTIC(Elem);
1709         DEFAULT_COPY_SEMANTIC(Elem);
1710 
GetName()1711         const StringItem *GetName()
1712         {
1713             return name_;
1714         }
1715 
GetValue()1716         ValueItem *GetValue()
1717         {
1718             return value_;
1719         }
1720 
SetValue(ValueItem *item)1721         void SetValue(ValueItem *item)
1722         {
1723             value_ = item;
1724         }
1725 
1726     private:
1727         StringItem *name_;
1728         ValueItem *value_;
1729     };
1730 
1731     class Tag {
1732     public:
Tag(char item)1733         explicit Tag(char item) : item_(item) {}
1734 
1735         ~Tag() = default;
1736 
1737         DEFAULT_MOVE_SEMANTIC(Tag);
1738         DEFAULT_COPY_SEMANTIC(Tag);
1739 
GetItem() const1740         uint8_t GetItem() const
1741         {
1742             return item_;
1743         }
1744 
1745     private:
1746         uint8_t item_;
1747     };
1748 
AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags)1749     AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags)
1750         : class_(cls), elements_(std::move(elements)), tags_(std::move(tags))
1751     {
1752         AddIndexDependency(cls);
1753     }
1754 
1755     ~AnnotationItem() override = default;
1756 
1757     DEFAULT_MOVE_SEMANTIC(AnnotationItem);
1758     DEFAULT_COPY_SEMANTIC(AnnotationItem);
1759 
1760     size_t CalculateSize() const override;
1761 
1762     bool Write(Writer *writer) override;
1763 
1764     ItemTypes GetItemType() const override
1765     {
1766         return ItemTypes::ANNOTATION_ITEM;
1767     }
1768 
GetElements()1769     std::vector<Elem> *GetElements()
1770     {
1771         return &elements_;
1772     }
1773 
SetElements(std::vector<Elem> &&elements)1774     void SetElements(std::vector<Elem> &&elements)
1775     {
1776         elements_ = std::move(elements);
1777     }
1778 
GetTags() const1779     const std::vector<Tag> &GetTags() const
1780     {
1781         return tags_;
1782     }
1783 
SetTags(std::vector<Tag> &&tags)1784     void SetTags(std::vector<Tag> &&tags)
1785     {
1786         tags_ = std::move(tags);
1787     }
1788 
1789 private:
1790     BaseClassItem *class_;
1791     std::vector<Elem> elements_;
1792     std::vector<Tag> tags_;
1793 };
1794 
1795 enum class MethodHandleType : uint8_t {
1796     PUT_STATIC = 0x00,
1797     GET_STATIC = 0x01,
1798     PUT_INSTANCE = 0x02,
1799     GET_INSTANCE = 0x03,
1800     INVOKE_STATIC = 0x04,
1801     INVOKE_INSTANCE = 0x05,
1802     INVOKE_CONSTRUCTOR = 0x06,
1803     INVOKE_DIRECT = 0x07,
1804     INVOKE_INTERFACE = 0x08
1805 };
1806 
1807 class MethodHandleItem : public BaseItem {
1808 public:
MethodHandleItem(MethodHandleType type, BaseItem *entity)1809     MethodHandleItem(MethodHandleType type, BaseItem *entity) : type_(type), entity_(entity) {}
1810 
1811     ~MethodHandleItem() override = default;
1812 
1813     DEFAULT_MOVE_SEMANTIC(MethodHandleItem);
1814     DEFAULT_COPY_SEMANTIC(MethodHandleItem);
1815 
1816     size_t CalculateSize() const override
1817     {
1818         return sizeof(uint8_t) + leb128::UnsignedEncodingSize(entity_->GetOffset());
1819     }
1820 
1821     bool Write(Writer *writer) override;
1822 
1823     ItemTypes GetItemType() const override
1824     {
1825         return ItemTypes::METHOD_HANDLE_ITEM;
1826     }
1827 
GetType() const1828     MethodHandleType GetType() const
1829     {
1830         return type_;
1831     }
1832 
1833 private:
1834     MethodHandleType type_;
1835     BaseItem *entity_;
1836 };
1837 
1838 enum class ArgumentType : uint8_t {
1839     INTEGER = 0x00,
1840     LONG = 0x01,
1841     FLOAT = 0x02,
1842     DOUBLE = 0x03,
1843     STRING = 0x04,
1844     CLASS = 0x05,
1845     METHOD_HANDLE = 0x06,
1846     METHOD_TYPE = 0x07
1847 };
1848 
1849 }  // namespace panda::panda_file
1850 
1851 #endif  // LIBPANDAFILE_FILE_ITEMS_H
1852