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