• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 <type_traits>
34 #include <variant>
35 #include <vector>
36 #include <list>
37 #include <set>
38 
39 namespace ark::panda_file {
40 
41 enum class ClassTag : uint8_t {
42     NOTHING = 0x00,
43     INTERFACES = 0x01,
44     SOURCE_LANG = 0x02,
45     RUNTIME_ANNOTATION = 0x03,
46     ANNOTATION = 0x04,
47     RUNTIME_TYPE_ANNOTATION = 0x05,
48     TYPE_ANNOTATION = 0x06,
49     SOURCE_FILE = 0x07
50 };
51 
52 enum class MethodTag : uint8_t {
53     NOTHING = 0x00,
54     CODE = 0x01,
55     SOURCE_LANG = 0x02,
56     RUNTIME_ANNOTATION = 0x03,
57     RUNTIME_PARAM_ANNOTATION = 0x04,
58     DEBUG_INFO = 0x05,
59     ANNOTATION = 0x06,
60     PARAM_ANNOTATION = 0x07,
61     TYPE_ANNOTATION = 0x08,
62     RUNTIME_TYPE_ANNOTATION = 0x09,
63     PROFILE_INFO = 0x0a
64 };
65 
66 enum class FieldTag : uint8_t {
67     NOTHING = 0x00,
68     INT_VALUE = 0x01,
69     VALUE = 0x02,
70     RUNTIME_ANNOTATION = 0x03,
71     ANNOTATION = 0x04,
72     RUNTIME_TYPE_ANNOTATION = 0x05,
73     TYPE_ANNOTATION = 0x06
74 };
75 
76 PANDA_PUBLIC_API bool IsDynamicLanguage(ark::panda_file::SourceLang lang);
77 PANDA_PUBLIC_API std::optional<ark::panda_file::SourceLang> LanguageFromString(std::string_view lang);
78 const char *LanguageToString(ark::panda_file::SourceLang lang);
79 PANDA_PUBLIC_API const char *GetCtorName(ark::panda_file::SourceLang lang);
80 PANDA_PUBLIC_API const char *GetCctorName(ark::panda_file::SourceLang lang);
81 PANDA_PUBLIC_API const char *GetStringClassDescriptor(ark::panda_file::SourceLang lang);
82 
83 constexpr size_t ID_SIZE = File::EntityId::GetSize();
84 constexpr size_t IDX_SIZE = sizeof(uint16_t);
85 constexpr size_t TAG_SIZE = 1;
86 constexpr uint32_t INVALID_OFFSET = std::numeric_limits<uint32_t>::max();
87 constexpr uint32_t INVALID_INDEX = std::numeric_limits<uint32_t>::max();
88 constexpr uint32_t MAX_INDEX_16 = std::numeric_limits<uint16_t>::max();
89 constexpr uint32_t MAX_INDEX_32 = std::numeric_limits<uint32_t>::max();
90 
91 constexpr uint32_t PGO_STRING_DEFAULT_COUNT = 5;
92 constexpr uint32_t PGO_CLASS_DEFAULT_COUNT = 3;
93 constexpr uint32_t PGO_CODE_DEFAULT_COUNT = 1;
94 
95 enum class ItemTypes {
96     ANNOTATION_ITEM,
97     CATCH_BLOCK_ITEM,
98     CLASS_INDEX_ITEM,
99     CLASS_ITEM,
100     CODE_ITEM,
101     DEBUG_INFO_ITEM,
102     END_ITEM,
103     FIELD_INDEX_ITEM,
104     FIELD_ITEM,
105     FOREIGN_CLASS_ITEM,
106     FOREIGN_FIELD_ITEM,
107     FOREIGN_METHOD_ITEM,
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     REGION_HEADER,
120     REGION_SECTION,
121     STRING_ITEM,
122     TRY_BLOCK_ITEM,
123     VALUE_ITEM
124 };
125 
126 std::string ItemTypeToString(ItemTypes type);
127 constexpr std::string_view STRING_ITEM = "string_item";
128 constexpr std::string_view CLASS_ITEM = "class_item";
129 constexpr std::string_view CODE_ITEM = "code_item";
130 
131 enum class IndexType {
132     // 16-bit indexes
133     CLASS = 0x0,
134     METHOD = 0x1,
135     FIELD = 0x2,
136     PROTO = 0x3,
137     LAST_16 = PROTO,
138 
139     // 32-bit indexes
140     LINE_NUMBER_PROG = 0x04,
141     LAST_32 = LINE_NUMBER_PROG,
142 
143     NONE
144 };
145 
146 constexpr size_t INDEX_COUNT_16 = static_cast<size_t>(IndexType::LAST_16) + 1;
147 
148 class IndexedItem;
149 
150 class BaseItem {
151 public:
152     using VisitorCallBack = std::function<bool(BaseItem *)>;
153 
154     BaseItem() = default;
155     virtual ~BaseItem() = default;
156 
157     DEFAULT_COPY_SEMANTIC(BaseItem);
158     DEFAULT_MOVE_SEMANTIC(BaseItem);
159 
GetSize()160     size_t GetSize() const
161     {
162         return CalculateSize();
163     }
164 
165     virtual size_t CalculateSize() const = 0;
166 
ComputeLayout()167     virtual void ComputeLayout() {}
168 
Alignment()169     virtual size_t Alignment()
170     {
171         return 1;
172     }
173 
IsForeign()174     virtual bool IsForeign() const
175     {
176         return false;
177     }
178 
GetOffset()179     uint32_t GetOffset() const
180     {
181         return offset_;
182     }
183 
GetFileId()184     panda_file::File::EntityId GetFileId() const
185     {
186         return panda_file::File::EntityId(offset_);
187     }
188 
SetOffset(uint32_t offset)189     void SetOffset(uint32_t offset)
190     {
191         offset_ = offset;
192     }
193 
NeedsEmit()194     bool NeedsEmit() const
195     {
196         return needsEmit_;
197     }
198 
SetNeedsEmit(bool needsEmit)199     void SetNeedsEmit(bool needsEmit)
200     {
201         needsEmit_ = needsEmit;
202     }
203 
GetIndexDependencies()204     const std::list<IndexedItem *> &GetIndexDependencies() const
205     {
206         return indexDeps_;
207     }
208 
AddIndexDependency(IndexedItem * item)209     void AddIndexDependency(IndexedItem *item)
210     {
211         ASSERT(item != nullptr);
212         indexDeps_.push_back(item);
213     }
214 
SetOrderIndex(uint32_t order)215     void SetOrderIndex(uint32_t order)
216     {
217         order_ = order;
218     }
219 
GetOrderIndex()220     uint32_t GetOrderIndex() const
221     {
222         return order_;
223     }
224 
HasOrderIndex()225     bool HasOrderIndex() const
226     {
227         return order_ != INVALID_INDEX;
228     }
229 
230     virtual bool Write(Writer *writer) = 0;
231 
232     std::string GetName() const;
233 
234     virtual ItemTypes GetItemType() const = 0;
235 
Dump(std::ostream & os)236     virtual void Dump([[maybe_unused]] std::ostream &os) const {}
237 
Visit(const VisitorCallBack & cb)238     virtual void Visit([[maybe_unused]] const VisitorCallBack &cb) {}
239 
SetPGORank(uint32_t rank)240     void SetPGORank(uint32_t rank)
241     {
242         pgoRank_ = rank;
243     }
244 
GetPGORank()245     uint32_t GetPGORank() const
246     {
247         return pgoRank_;
248     }
249 
SetOriginalRank(uint32_t rank)250     void SetOriginalRank(uint32_t rank)
251     {
252         originalRank_ = rank;
253     }
254 
GetOriginalRank()255     uint32_t GetOriginalRank() const
256     {
257         return originalRank_;
258     }
259 
SetDependencyMark()260     virtual void SetDependencyMark()
261     {
262         dependencyMarked_ = true;
263     }
264 
GetDependencyMark()265     bool GetDependencyMark() const
266     {
267         return dependencyMarked_;
268     }
269 
GetBaseItemType()270     ItemTypes GetBaseItemType() const
271     {
272         return type_;
273     }
274 
SetBaseItemType(ItemTypes type)275     void SetBaseItemType(ItemTypes type)
276     {
277         type_ = type;
278     }
279 
280 private:
281     bool needsEmit_ {true};
282     bool dependencyMarked_ {false};
283     uint32_t offset_ {0};
284     uint32_t order_ {INVALID_INDEX};
285     std::list<IndexedItem *> indexDeps_;
286     uint32_t pgoRank_ {0};
287     uint32_t originalRank_ {0};
288     ItemTypes type_ = ItemTypes::ANNOTATION_ITEM;
289 };
290 
291 class IndexedItem : public BaseItem {
292 public:
IndexedItem()293     IndexedItem()
294     {
295         itemAllocId_ = itemAllocIdNext_++;
296     }
297 
GetIndex(const BaseItem * item)298     uint32_t GetIndex(const BaseItem *item) const
299     {
300         auto *idx = FindIndex(item);
301         ASSERT(idx != nullptr);
302         return idx->index;
303     }
304 
HasIndex(const BaseItem * item)305     bool HasIndex(const BaseItem *item) const
306     {
307         return FindIndex(item) != nullptr;
308     }
309 
SetIndex(const BaseItem * start,const BaseItem * end,uint32_t index)310     void SetIndex(const BaseItem *start, const BaseItem *end, uint32_t index)
311     {
312         ASSERT(FindIndex(start, end) == nullptr);
313         indexes_.push_back({start, end, index});
314     }
315 
ClearIndexes()316     void ClearIndexes()
317     {
318         indexes_.clear();
319     }
320 
IncRefCount()321     void IncRefCount()
322     {
323         ++refCount_;
324     }
325 
DecRefCount()326     void DecRefCount()
327     {
328         ASSERT(refCount_ != 0);
329         --refCount_;
330     }
331 
GetRefCount()332     size_t GetRefCount() const
333     {
334         return refCount_;
335     }
336 
GetIndexType()337     virtual IndexType GetIndexType() const
338     {
339         return IndexType::NONE;
340     }
341 
GetItemAllocId()342     size_t GetItemAllocId() const
343     {
344         return itemAllocId_;
345     }
346 
347 private:
348     struct Index {
349         const BaseItem *start;
350         const BaseItem *end;
351         uint32_t index;
352     };
353 
FindIndex(const BaseItem * start,const BaseItem * end)354     const Index *FindIndex(const BaseItem *start, const BaseItem *end) const
355     {
356         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(),
357                                [start, end](const Index &idx) { return idx.start == start && idx.end == end; });
358 
359         return it != indexes_.cend() ? &*it : nullptr;
360     }
361 
FindIndex(const BaseItem * item)362     const Index *FindIndex(const BaseItem *item) const
363     {
364         ASSERT(item);
365         ASSERT(item->HasOrderIndex());
366         auto orderIdx = item->GetOrderIndex();
367 
368         auto it = std::find_if(indexes_.cbegin(), indexes_.cend(), [orderIdx](const Index &idx) {
369             if (idx.start == nullptr && idx.end == nullptr) {
370                 return true;
371             }
372 
373             if (idx.start == nullptr || idx.end == nullptr) {
374                 return false;
375             }
376 
377             ASSERT(idx.start->HasOrderIndex());
378             ASSERT(idx.end->HasOrderIndex());
379             return idx.start->GetOrderIndex() <= orderIdx && orderIdx < idx.end->GetOrderIndex();
380         });
381 
382         return it != indexes_.cend() ? &*it : nullptr;
383     }
384 
385     std::vector<Index> indexes_;
386     size_t refCount_ {1};
387     size_t itemAllocId_ {0};
388 
389     // needed for keeping same layout of panda file after rebuilding it,
390     // even if same `IndexedItem` was allocated at different addresses
391     static size_t itemAllocIdNext_;
392 };
393 
394 class TypeItem : public IndexedItem {
395 public:
TypeItem(Type type)396     explicit TypeItem(Type type) : type_(type) {}
397 
TypeItem(Type::TypeId typeId)398     explicit TypeItem(Type::TypeId typeId) : type_(typeId) {}
399 
400     ~TypeItem() override = default;
401 
GetType()402     Type GetType() const
403     {
404         return type_;
405     }
406 
GetIndexType()407     IndexType GetIndexType() const override
408     {
409         return IndexType::CLASS;
410     }
411 
412     DEFAULT_MOVE_SEMANTIC(TypeItem);
413     DEFAULT_COPY_SEMANTIC(TypeItem);
414 
415 private:
416     Type type_;
417 };
418 
419 class PrimitiveTypeItem : public TypeItem {
420 public:
PrimitiveTypeItem(Type type)421     explicit PrimitiveTypeItem(Type type) : PrimitiveTypeItem(type.GetId()) {}
422 
PrimitiveTypeItem(Type::TypeId typeId)423     explicit PrimitiveTypeItem(Type::TypeId typeId) : TypeItem(typeId)
424     {
425         ASSERT(GetType().IsPrimitive());
426         SetNeedsEmit(false);
427         SetOffset(GetType().GetFieldEncoding());
428     }
429 
430     ~PrimitiveTypeItem() override = default;
431 
CalculateSize()432     size_t CalculateSize() const override
433     {
434         return 0;
435     }
436 
Write(Writer * writer)437     bool Write([[maybe_unused]] Writer *writer) override
438     {
439         return true;
440     }
441 
GetItemType()442     ItemTypes GetItemType() const override
443     {
444         return ItemTypes::PRIMITIVE_TYPE_ITEM;
445     }
446 
447     DEFAULT_MOVE_SEMANTIC(PrimitiveTypeItem);
448     DEFAULT_COPY_SEMANTIC(PrimitiveTypeItem);
449 };
450 
451 class StringItem : public BaseItem {
452 public:
453     explicit StringItem(std::string str);
454 
455     explicit StringItem(File::StringData data);
456 
457     ~StringItem() override = default;
458 
459     size_t CalculateSize() const override;
460 
461     bool Write(Writer *writer) override;
462 
GetItemType()463     ItemTypes GetItemType() const override
464     {
465         return ItemTypes::STRING_ITEM;
466     }
467 
GetData()468     const std::string &GetData() const
469     {
470         return str_;
471     }
472 
GetUtf16Len()473     size_t GetUtf16Len() const
474     {
475         return utf16Length_;
476     }
477 
478     DEFAULT_MOVE_SEMANTIC(StringItem);
479     DEFAULT_COPY_SEMANTIC(StringItem);
480 
481 private:
482     std::string str_;
483     size_t utf16Length_;
484     size_t isAscii_ = 0;
485 };
486 
487 class AnnotationItem;
488 class BaseClassItem;
489 class ClassItem;
490 class ForeignClassItem;
491 class ValueItem;
492 
493 class BaseFieldItem : public IndexedItem {
494 public:
GetIndexType()495     IndexType GetIndexType() const override
496     {
497         return IndexType::FIELD;
498     }
499 
GetNameItem()500     StringItem *GetNameItem() const
501     {
502         return name_;
503     }
504 
GetTypeItem()505     TypeItem *GetTypeItem() const
506     {
507         return type_;
508     }
509 
GetClassItem()510     BaseClassItem *GetClassItem() const
511     {
512         return class_;
513     }
514 
GetAccessFlags()515     uint32_t GetAccessFlags() const
516     {
517         return accessFlags_;
518     }
519 
IsStatic()520     bool IsStatic() const
521     {
522         return (accessFlags_ & ACC_STATIC) != 0;
523     }
524 
525     ~BaseFieldItem() override = default;
526 
527     DEFAULT_MOVE_SEMANTIC(BaseFieldItem);
528     DEFAULT_COPY_SEMANTIC(BaseFieldItem);
529 
530 protected:
531     PANDA_PUBLIC_API BaseFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags);
532 
533     PANDA_PUBLIC_API size_t CalculateSize() const override;
534 
535     PANDA_PUBLIC_API bool Write(Writer *writer) override;
536 
537     PANDA_PUBLIC_API void SetDependencyMark() override;
538 
539 private:
540     BaseClassItem *class_;
541     StringItem *name_;
542     TypeItem *type_;
543     uint32_t accessFlags_;
544 };
545 
546 class FieldItem : public BaseFieldItem {
547 public:
548     PANDA_PUBLIC_API FieldItem(ClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags);
549 
550     ~FieldItem() override = default;
551 
552     PANDA_PUBLIC_API void SetValue(ValueItem *value);
553 
GetValue()554     ValueItem *GetValue() const
555     {
556         return value_;
557     }
558 
AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)559     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
560     {
561         runtimeAnnotations_.push_back(runtimeAnnotation);
562     }
563 
AddAnnotation(AnnotationItem * annotation)564     void AddAnnotation(AnnotationItem *annotation)
565     {
566         annotations_.push_back(annotation);
567     }
568 
AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)569     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
570     {
571         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
572     }
573 
AddTypeAnnotation(AnnotationItem * typeAnnotation)574     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
575     {
576         typeAnnotations_.push_back(typeAnnotation);
577     }
578 
579     size_t CalculateSize() const override;
580 
581     bool Write(Writer *writer) override;
582 
GetItemType()583     ItemTypes GetItemType() const override
584     {
585         return ItemTypes::FIELD_ITEM;
586     }
587 
GetRuntimeAnnotations()588     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
589     {
590         return &runtimeAnnotations_;
591     }
592 
GetAnnotations()593     std::vector<AnnotationItem *> *GetAnnotations()
594     {
595         return &annotations_;
596     }
597 
GetTypeAnnotations()598     std::vector<AnnotationItem *> *GetTypeAnnotations()
599     {
600         return &typeAnnotations_;
601     }
602 
GetRuntimeTypeAnnotations()603     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
604     {
605         return &runtimeTypeAnnotations_;
606     }
607 
608     void SetDependencyMark() override;
609 
610     DEFAULT_MOVE_SEMANTIC(FieldItem);
611     DEFAULT_COPY_SEMANTIC(FieldItem);
612 
613 private:
614     bool WriteValue(Writer *writer);
615 
616     bool WriteAnnotations(Writer *writer);
617 
618     bool WriteTaggedData(Writer *writer);
619 
620     ValueItem *value_ {nullptr};
621     std::vector<AnnotationItem *> runtimeAnnotations_;
622     std::vector<AnnotationItem *> annotations_;
623     std::vector<AnnotationItem *> typeAnnotations_;
624     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
625 };
626 
627 class ProtoItem;
628 class CodeItem;
629 
630 /**
631  * @brief Base class of `LineNumberProgramItem`.
632  *
633  * Instances of this class might be used in order to fill constant pool of a shared `LineNumberProgram`.
634  * Implementations must override `Empty`, `EmitOpcode` and `EmitRegister`, which are left no-op.
635  */
636 class LineNumberProgramItemBase {
637 public:
638     enum class Opcode : uint8_t {
639         END_SEQUENCE = 0x00,
640         ADVANCE_PC = 0x01,
641         ADVANCE_LINE = 0x02,
642         START_LOCAL = 0x03,
643         START_LOCAL_EXTENDED = 0x04,
644         END_LOCAL = 0x05,
645         RESTART_LOCAL = 0x06,
646         SET_PROLOGUE_END = 0x07,
647         SET_EPILOGUE_BEGIN = 0x08,
648         SET_FILE = 0x09,
649         SET_SOURCE_CODE = 0x0a,
650         SET_COLUMN = 0X0b,
651         LAST
652     };
653 
654     static constexpr uint8_t OPCODE_BASE = static_cast<uint8_t>(Opcode::LAST);
655     static constexpr int32_t LINE_RANGE = 15;
656     static constexpr int32_t LINE_BASE = -4;
657 
658     PANDA_PUBLIC_API void EmitEnd();
659 
660     PANDA_PUBLIC_API void EmitAdvancePc(std::vector<uint8_t> *constantPool, uint32_t value);
661 
662     PANDA_PUBLIC_API void EmitAdvanceLine(std::vector<uint8_t> *constantPool, int32_t value);
663 
664     PANDA_PUBLIC_API void EmitColumn(std::vector<uint8_t> *constantPool, uint32_t pcInc, uint32_t column);
665 
666     PANDA_PUBLIC_API void EmitStartLocal(std::vector<uint8_t> *constantPool, int32_t registerNumber, StringItem *name,
667                                          StringItem *type);
668 
669     PANDA_PUBLIC_API void EmitStartLocalExtended(std::vector<uint8_t> *constantPool, int32_t registerNumber,
670                                                  StringItem *name, StringItem *type, StringItem *typeSignature);
671 
672     PANDA_PUBLIC_API void EmitEndLocal(int32_t registerNumber);
673 
674     void EmitRestartLocal(int32_t registerNumber);
675 
676     PANDA_PUBLIC_API bool EmitSpecialOpcode(uint32_t pcInc, int32_t lineInc);
677 
678     void EmitPrologueEnd();
679 
680     void EmitEpilogueBegin();
681 
682     PANDA_PUBLIC_API void EmitSetFile(std::vector<uint8_t> *constantPool, StringItem *sourceFile);
683 
684     PANDA_PUBLIC_API void EmitSetSourceCode(std::vector<uint8_t> *constantPool, StringItem *sourceCode);
685 
686     void EmitOpcode(Opcode opcode);
687 
Empty()688     virtual bool Empty() const
689     {
690         return true;
691     }
692 
693 protected:
EmitOpcode(uint8_t opcode)694     virtual void EmitOpcode([[maybe_unused]] uint8_t opcode) {}
EmitRegister(int32_t registerNumber)695     virtual void EmitRegister([[maybe_unused]] int32_t registerNumber) {}
696 
697     static void EmitUleb128(std::vector<uint8_t> *data, uint32_t value);
698 
699     static void EmitSleb128(std::vector<uint8_t> *data, int32_t value);
700 };
701 
702 // NOLINTNEXTLINE(fuchsia-multiple-inheritance)
703 class LineNumberProgramItem final : public IndexedItem, public LineNumberProgramItemBase {
704 public:
705     bool Write(Writer *writer) override;
706 
707     size_t CalculateSize() const override;
708 
GetItemType()709     ItemTypes GetItemType() const override
710     {
711         return ItemTypes::LINE_NUMBER_PROGRAM_ITEM;
712     }
713 
Empty()714     bool Empty() const override
715     {
716         return GetData().empty();
717     }
718 
GetData()719     const std::vector<uint8_t> &GetData() const
720     {
721         return data_;
722     }
723 
GetIndexType()724     IndexType GetIndexType() const override
725     {
726         return IndexType::LINE_NUMBER_PROG;
727     }
728 
729     void SetData(std::vector<uint8_t> &&data);
730 
731 private:
732     void EmitOpcode(uint8_t opcode) override;
733     void EmitRegister(int32_t registerNumber) override;
734 
735     std::vector<uint8_t> data_;
736 };
737 
738 class PANDA_PUBLIC_API DebugInfoItem : public BaseItem {
739 public:
DebugInfoItem(LineNumberProgramItem * item)740     explicit DebugInfoItem(LineNumberProgramItem *item) : program_(item) {}
741 
742     ~DebugInfoItem() override = default;
743 
744     DEFAULT_MOVE_SEMANTIC(DebugInfoItem);
745     DEFAULT_COPY_SEMANTIC(DebugInfoItem);
746 
GetLineNumber()747     size_t GetLineNumber() const
748     {
749         return lineNum_;
750     }
751 
SetLineNumber(size_t lineNum)752     void SetLineNumber(size_t lineNum)
753     {
754         lineNum_ = lineNum;
755     }
756 
GetLineNumberProgram()757     LineNumberProgramItem *GetLineNumberProgram() const
758     {
759         return program_;
760     }
761 
SetLineNumberProgram(LineNumberProgramItem * program)762     void SetLineNumberProgram(LineNumberProgramItem *program)
763     {
764         ASSERT(program->GetOffset() != 0);
765         program_ = program;
766     }
767 
AddParameter(StringItem * name)768     void AddParameter(StringItem *name)
769     {
770         parameters_.push_back(name);
771     }
772 
GetParameters()773     const std::vector<StringItem *> *GetParameters() const
774     {
775         return &parameters_;
776     }
777 
GetConstantPool()778     std::vector<uint8_t> *GetConstantPool()
779     {
780         return &constantPool_;
781     }
782 
783     size_t CalculateSize() const override;
784 
785     bool Write(Writer *writer) override;
786 
GetItemType()787     ItemTypes GetItemType() const override
788     {
789         return ItemTypes::DEBUG_INFO_ITEM;
790     }
791 
792     void Dump(std::ostream &os) const override;
793 
SetDependencyMark()794     void SetDependencyMark() override
795     {
796         BaseItem::SetDependencyMark();
797         if (program_ != nullptr) {
798             program_->SetDependencyMark();
799         }
800         for (auto &item : parameters_) {
801             item->SetDependencyMark();
802         }
803     }
804 
805 private:
806     size_t lineNum_ {0};
807     LineNumberProgramItem *program_;
808     std::vector<uint8_t> constantPool_;
809     std::vector<StringItem *> parameters_;
810 };
811 
812 class BaseMethodItem : public IndexedItem {
813 public:
GetProto()814     ProtoItem *GetProto() const
815     {
816         return proto_;
817     }
818 
IsStatic()819     bool IsStatic() const
820     {
821         return (accessFlags_ & ACC_STATIC) != 0;
822     }
823 
GetIndexType()824     IndexType GetIndexType() const override
825     {
826         return IndexType::METHOD;
827     }
828 
GetNameItem()829     StringItem *GetNameItem() const
830     {
831         return name_;
832     }
833 
GetClassItem()834     BaseClassItem *GetClassItem() const
835     {
836         return class_;
837     }
838 
GetAccessFlags()839     uint32_t GetAccessFlags() const
840     {
841         return accessFlags_;
842     }
843 
844     ~BaseMethodItem() override = default;
845 
846     DEFAULT_MOVE_SEMANTIC(BaseMethodItem);
847     DEFAULT_COPY_SEMANTIC(BaseMethodItem);
848 
849 protected:
850     PANDA_PUBLIC_API BaseMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags);
851 
852     PANDA_PUBLIC_API size_t CalculateSize() const override;
853 
854     PANDA_PUBLIC_API bool Write(Writer *writer) override;
855 
856     PANDA_PUBLIC_API void SetDependencyMark() override;
857 
858 private:
859     BaseClassItem *class_;
860     StringItem *name_;
861     ProtoItem *proto_;
862     uint32_t accessFlags_;
863 };
864 
865 class MethodParamItem {
866 public:
MethodParamItem(TypeItem * type)867     explicit MethodParamItem(TypeItem *type) : type_(type) {}
868 
869     ~MethodParamItem() = default;
870 
871     DEFAULT_MOVE_SEMANTIC(MethodParamItem);
872     DEFAULT_COPY_SEMANTIC(MethodParamItem);
873 
AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)874     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
875     {
876         runtimeAnnotations_.push_back(runtimeAnnotation);
877     }
878 
AddAnnotation(AnnotationItem * annotation)879     void AddAnnotation(AnnotationItem *annotation)
880     {
881         annotations_.push_back(annotation);
882     }
883 
AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)884     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
885     {
886         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
887     }
888 
AddTypeAnnotation(AnnotationItem * typeAnnotation)889     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
890     {
891         typeAnnotations_.push_back(typeAnnotation);
892     }
893 
GetType()894     TypeItem *GetType() const
895     {
896         return type_;
897     }
898 
GetRuntimeAnnotations()899     const std::vector<AnnotationItem *> &GetRuntimeAnnotations() const
900     {
901         return runtimeAnnotations_;
902     }
903 
GetAnnotations()904     const std::vector<AnnotationItem *> &GetAnnotations() const
905     {
906         return annotations_;
907     }
908 
GetRuntimeTypeAnnotations()909     const std::vector<AnnotationItem *> &GetRuntimeTypeAnnotations() const
910     {
911         return runtimeTypeAnnotations_;
912     }
913 
GetTypeAnnotations()914     const std::vector<AnnotationItem *> &GetTypeAnnotations() const
915     {
916         return typeAnnotations_;
917     }
918 
HasAnnotations()919     bool HasAnnotations() const
920     {
921         return !annotations_.empty();
922     }
923 
HasRuntimeAnnotations()924     bool HasRuntimeAnnotations() const
925     {
926         return !runtimeAnnotations_.empty();
927     }
928 
929 private:
930     TypeItem *type_;
931     std::vector<AnnotationItem *> runtimeAnnotations_;
932     std::vector<AnnotationItem *> annotations_;
933     std::vector<AnnotationItem *> typeAnnotations_;
934     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
935 };
936 
937 class ParamAnnotationsItem;
938 class BaseClassItem;
939 
940 class MethodItem : public BaseMethodItem {
941 public:
942     PANDA_PUBLIC_API MethodItem(ClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags,
943                                 std::vector<MethodParamItem> params);
944 
945     ~MethodItem() override = default;
946 
947     DEFAULT_MOVE_SEMANTIC(MethodItem);
948     DEFAULT_COPY_SEMANTIC(MethodItem);
949 
SetSourceLang(SourceLang lang)950     void SetSourceLang(SourceLang lang)
951     {
952         sourceLang_ = lang;
953     }
954 
SetCode(CodeItem * code)955     void SetCode(CodeItem *code)
956     {
957         code_ = code;
958     }
959 
SetDebugInfo(DebugInfoItem * debugInfo)960     void SetDebugInfo(DebugInfoItem *debugInfo)
961     {
962         debugInfo_ = debugInfo;
963     }
964 
GetDebugInfo()965     DebugInfoItem *GetDebugInfo()
966     {
967         return debugInfo_;
968     }
969 
AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)970     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
971     {
972         runtimeAnnotations_.push_back(runtimeAnnotation);
973     }
974 
AddAnnotation(AnnotationItem * annotation)975     void AddAnnotation(AnnotationItem *annotation)
976     {
977         annotations_.push_back(annotation);
978     }
979 
AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)980     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
981     {
982         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
983     }
984 
AddTypeAnnotation(AnnotationItem * typeAnnotation)985     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
986     {
987         typeAnnotations_.push_back(typeAnnotation);
988     }
989 
SetRuntimeParamAnnotationItem(ParamAnnotationsItem * annotations)990     void SetRuntimeParamAnnotationItem(ParamAnnotationsItem *annotations)
991     {
992         runtimeParamAnnotations_ = annotations;
993     }
994 
SetParamAnnotationItem(ParamAnnotationsItem * annotations)995     void SetParamAnnotationItem(ParamAnnotationsItem *annotations)
996     {
997         paramAnnotations_ = annotations;
998     }
999 
HasRuntimeParamAnnotations()1000     bool HasRuntimeParamAnnotations() const
1001     {
1002         return std::any_of(params_.cbegin(), params_.cend(),
1003                            [](const MethodParamItem &item) { return item.HasRuntimeAnnotations(); });
1004     }
1005 
HasParamAnnotations()1006     bool HasParamAnnotations() const
1007     {
1008         return std::any_of(params_.cbegin(), params_.cend(),
1009                            [](const MethodParamItem &item) { return item.HasAnnotations(); });
1010     }
1011 
GetCode()1012     CodeItem *GetCode() const
1013     {
1014         return code_;
1015     }
1016 
GetDebugInfo()1017     DebugInfoItem *GetDebugInfo() const
1018     {
1019         return debugInfo_;
1020     }
1021 
1022     size_t CalculateSize() const override;
1023 
1024     bool Write(Writer *writer) override;
1025 
GetItemType()1026     ItemTypes GetItemType() const override
1027     {
1028         return ItemTypes::METHOD_ITEM;
1029     }
1030 
GetParams()1031     std::vector<MethodParamItem> &GetParams()
1032     {
1033         return params_;
1034     }
1035 
GetRuntimeAnnotations()1036     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
1037     {
1038         return &runtimeAnnotations_;
1039     }
1040 
GetAnnotations()1041     std::vector<AnnotationItem *> *GetAnnotations()
1042     {
1043         return &annotations_;
1044     }
1045 
GetTypeAnnotations()1046     std::vector<AnnotationItem *> *GetTypeAnnotations()
1047     {
1048         return &typeAnnotations_;
1049     }
1050 
GetRuntimeTypeAnnotations()1051     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
1052     {
1053         return &runtimeTypeAnnotations_;
1054     }
1055 
SetProfileSize(size_t size)1056     void SetProfileSize(size_t size)
1057     {
1058         ASSERT(size <= MAX_PROFILE_SIZE);
1059         profileSize_ = size;
1060     }
1061 
GetProfileSize()1062     size_t GetProfileSize() const
1063     {
1064         return profileSize_;
1065     }
1066 
1067     void SetDependencyMark() override;
1068 
1069 private:
1070     bool WriteRuntimeAnnotations(Writer *writer);
1071 
1072     bool WriteTypeAnnotations(Writer *writer);
1073 
1074     bool WriteTaggedData(Writer *writer);
1075 
1076     std::vector<MethodParamItem> params_;
1077 
1078     SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY};
1079     CodeItem *code_ {nullptr};
1080     DebugInfoItem *debugInfo_ {nullptr};
1081     std::vector<AnnotationItem *> runtimeAnnotations_;
1082     std::vector<AnnotationItem *> annotations_;
1083     std::vector<AnnotationItem *> typeAnnotations_;
1084     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
1085     ParamAnnotationsItem *runtimeParamAnnotations_ {nullptr};
1086     ParamAnnotationsItem *paramAnnotations_ {nullptr};
1087     uint16_t profileSize_ {0};
1088 
1089 public:
1090     constexpr static auto MAX_PROFILE_SIZE = std::numeric_limits<decltype(profileSize_)>::max();
1091 };
1092 
1093 class BaseClassItem : public TypeItem {
1094 public:
GetNameItem()1095     StringItem *GetNameItem()
1096     {
1097         return &name_;
1098     }
1099 
GetNameItemData()1100     const std::string &GetNameItemData() const
1101     {
1102         return name_.GetData();
1103     }
1104 
1105 protected:
BaseClassItem(const std::string & name)1106     explicit BaseClassItem(const std::string &name) : TypeItem(Type::TypeId::REFERENCE), name_(name) {}
1107 
1108     ~BaseClassItem() override = default;
1109 
1110     size_t CalculateSize() const override;
1111 
1112     void ComputeLayout() override;
1113 
1114     bool Write(Writer *writer) override;
1115 
1116     DEFAULT_MOVE_SEMANTIC(BaseClassItem);
1117     DEFAULT_COPY_SEMANTIC(BaseClassItem);
1118 
1119 private:
1120     StringItem name_;
1121 };
1122 
1123 class ClassItem : public BaseClassItem {
1124 public:
ClassItem(const std::string & name)1125     explicit ClassItem(const std::string &name) : BaseClassItem(name) {}
1126 
1127     ~ClassItem() override = default;
1128 
SetAccessFlags(uint32_t accessFlags)1129     void SetAccessFlags(uint32_t accessFlags)
1130     {
1131         accessFlags_ = accessFlags;
1132     }
1133 
SetSourceLang(SourceLang lang)1134     void SetSourceLang(SourceLang lang)
1135     {
1136         sourceLang_ = lang;
1137     }
1138 
SetSuperClass(BaseClassItem * superClass)1139     void SetSuperClass(BaseClassItem *superClass)
1140     {
1141         superClass_ = superClass;
1142     }
1143 
AddInterface(BaseClassItem * iface)1144     void AddInterface(BaseClassItem *iface)
1145     {
1146         AddIndexDependency(iface);
1147         ifaces_.push_back(iface);
1148     }
1149 
AddRuntimeAnnotation(AnnotationItem * runtimeAnnotation)1150     void AddRuntimeAnnotation(AnnotationItem *runtimeAnnotation)
1151     {
1152         runtimeAnnotations_.push_back(runtimeAnnotation);
1153     }
1154 
AddAnnotation(AnnotationItem * annotation)1155     void AddAnnotation(AnnotationItem *annotation)
1156     {
1157         annotations_.push_back(annotation);
1158     }
1159 
AddRuntimeTypeAnnotation(AnnotationItem * runtimeTypeAnnotation)1160     void AddRuntimeTypeAnnotation(AnnotationItem *runtimeTypeAnnotation)
1161     {
1162         runtimeTypeAnnotations_.push_back(runtimeTypeAnnotation);
1163     }
1164 
AddTypeAnnotation(AnnotationItem * typeAnnotation)1165     void AddTypeAnnotation(AnnotationItem *typeAnnotation)
1166     {
1167         typeAnnotations_.push_back(typeAnnotation);
1168     }
1169 
1170     template <class... Args>
AddField(Args...args)1171     FieldItem *AddField(Args... args)
1172     {
1173         fields_.emplace_back(std::make_unique<FieldItem>(this, std::forward<Args>(args)...));
1174         return fields_.back().get();
1175     }
1176 
1177     template <class... Args>
AddMethod(Args...args)1178     MethodItem *AddMethod(Args... args)
1179     {
1180         // insert new method to set ordered by method name
1181         return methods_.insert(std::make_unique<MethodItem>(this, std::forward<Args>(args)...))->get();
1182     }
1183 
GetSourceFile()1184     StringItem *GetSourceFile() const
1185     {
1186         return sourceFile_;
1187     }
1188 
SetSourceFile(StringItem * item)1189     void SetSourceFile(StringItem *item)
1190     {
1191         sourceFile_ = item;
1192     }
1193 
1194     size_t CalculateSizeWithoutFieldsAndMethods() const;
1195 
1196     size_t CalculateSize() const override;
1197 
1198     void ComputeLayout() override;
1199 
1200     bool Write(Writer *writer) override;
1201 
GetItemType()1202     ItemTypes GetItemType() const override
1203     {
1204         return ItemTypes::CLASS_ITEM;
1205     }
1206 
VisitFields(const VisitorCallBack & cb)1207     void VisitFields(const VisitorCallBack &cb)
1208     {
1209         for (auto &field : fields_) {
1210             if (!cb(field.get())) {
1211                 break;
1212             }
1213         }
1214     }
1215 
VisitMethods(const VisitorCallBack & cb)1216     void VisitMethods(const VisitorCallBack &cb)
1217     {
1218         for (auto &method : methods_) {
1219             if (!cb(method.get())) {
1220                 break;
1221             }
1222         }
1223     }
1224 
Visit(const VisitorCallBack & cb)1225     void Visit(const VisitorCallBack &cb) override
1226     {
1227         VisitFields(cb);
1228         VisitMethods(cb);
1229     }
1230 
GetRuntimeAnnotations()1231     std::vector<AnnotationItem *> *GetRuntimeAnnotations()
1232     {
1233         return &runtimeAnnotations_;
1234     }
1235 
GetAnnotations()1236     std::vector<AnnotationItem *> *GetAnnotations()
1237     {
1238         return &annotations_;
1239     }
1240 
GetTypeAnnotations()1241     std::vector<AnnotationItem *> *GetTypeAnnotations()
1242     {
1243         return &typeAnnotations_;
1244     }
1245 
GetRuntimeTypeAnnotations()1246     std::vector<AnnotationItem *> *GetRuntimeTypeAnnotations()
1247     {
1248         return &runtimeTypeAnnotations_;
1249     }
1250 
GetSourceLang()1251     SourceLang GetSourceLang() const
1252     {
1253         return sourceLang_;
1254     }
1255 
GetAccessFlags()1256     uint32_t GetAccessFlags() const
1257     {
1258         return accessFlags_;
1259     }
1260 
GetSuperClass()1261     BaseClassItem *GetSuperClass() const
1262     {
1263         return superClass_;
1264     }
1265 
GetInterfaces()1266     const std::vector<BaseClassItem *> &GetInterfaces() const
1267     {
1268         return ifaces_;
1269     }
1270     void SetDependencyMark() override;
1271 
1272     DEFAULT_MOVE_SEMANTIC(ClassItem);
1273     DEFAULT_COPY_SEMANTIC(ClassItem);
1274 
1275 private:
1276     struct MethodCompByName {
1277         using is_transparent = std::true_type;  // NOLINT(readability-identifier-naming)
1278 
operatorMethodCompByName1279         bool operator()(const StringItem *str1, const StringItem *str2) const
1280         {
1281             if (str1->GetUtf16Len() == str2->GetUtf16Len()) {
1282                 return str1->GetData() < str2->GetData();
1283             }
1284             return str1->GetUtf16Len() < str2->GetUtf16Len();
1285         }
1286 
operatorMethodCompByName1287         bool operator()(const StringItem *m1, const std::unique_ptr<MethodItem> &m2) const
1288         {
1289             return (*this)(m1, m2->GetNameItem());
1290         }
1291 
operatorMethodCompByName1292         bool operator()(const std::unique_ptr<MethodItem> &m1, const StringItem *str2) const
1293         {
1294             return (*this)(m1->GetNameItem(), str2);
1295         }
1296 
operatorMethodCompByName1297         bool operator()(const std::unique_ptr<MethodItem> &m1, const std::unique_ptr<MethodItem> &m2) const
1298         {
1299             return (*this)(m1->GetNameItem(), m2->GetNameItem());
1300         }
1301     };
1302 
1303     bool WriteIfaces(Writer *writer);
1304 
1305     bool WriteAnnotations(Writer *writer);
1306 
1307     bool WriteTaggedData(Writer *writer);
1308 
1309     BaseClassItem *superClass_ {nullptr};
1310     uint32_t accessFlags_ {0};
1311     SourceLang sourceLang_ {SourceLang::PANDA_ASSEMBLY};
1312     std::vector<BaseClassItem *> ifaces_;
1313     std::vector<AnnotationItem *> runtimeAnnotations_;
1314     std::vector<AnnotationItem *> annotations_;
1315     std::vector<AnnotationItem *> typeAnnotations_;
1316     std::vector<AnnotationItem *> runtimeTypeAnnotations_;
1317     StringItem *sourceFile_ {nullptr};
1318     std::vector<std::unique_ptr<FieldItem>> fields_;
1319     std::multiset<std::unique_ptr<MethodItem>, MethodCompByName> methods_;
1320 
1321 public:
1322     using FindMethodIterator = typename std::multiset<std::unique_ptr<MethodItem>, MethodCompByName>::const_iterator;
1323 
FindMethod(StringItem * name)1324     std::pair<FindMethodIterator, FindMethodIterator> FindMethod(StringItem *name) const
1325     {
1326         return methods_.equal_range(name);
1327     }
1328 };
1329 
1330 class ForeignClassItem : public BaseClassItem {
1331 public:
ForeignClassItem(const std::string & name)1332     explicit ForeignClassItem(const std::string &name) : BaseClassItem(name) {}
1333 
1334     ~ForeignClassItem() override = default;
1335 
IsForeign()1336     bool IsForeign() const override
1337     {
1338         return true;
1339     }
1340 
GetItemType()1341     ItemTypes GetItemType() const override
1342     {
1343         return ItemTypes::FOREIGN_CLASS_ITEM;
1344     }
1345 
1346     DEFAULT_MOVE_SEMANTIC(ForeignClassItem);
1347     DEFAULT_COPY_SEMANTIC(ForeignClassItem);
1348 };
1349 
1350 class ForeignFieldItem : public BaseFieldItem {
1351 public:
ForeignFieldItem(BaseClassItem * cls,StringItem * name,TypeItem * type,uint32_t accessFlags)1352     ForeignFieldItem(BaseClassItem *cls, StringItem *name, TypeItem *type, uint32_t accessFlags)
1353         : BaseFieldItem(cls, name, type, accessFlags)
1354     {
1355     }
1356 
1357     ~ForeignFieldItem() override = default;
1358 
IsForeign()1359     bool IsForeign() const override
1360     {
1361         return true;
1362     }
1363 
GetItemType()1364     ItemTypes GetItemType() const override
1365     {
1366         return ItemTypes::FOREIGN_FIELD_ITEM;
1367     }
1368 
1369     DEFAULT_MOVE_SEMANTIC(ForeignFieldItem);
1370     DEFAULT_COPY_SEMANTIC(ForeignFieldItem);
1371 };
1372 
1373 class ForeignMethodItem : public BaseMethodItem {
1374 public:
ForeignMethodItem(BaseClassItem * cls,StringItem * name,ProtoItem * proto,uint32_t accessFlags)1375     ForeignMethodItem(BaseClassItem *cls, StringItem *name, ProtoItem *proto, uint32_t accessFlags)
1376         : BaseMethodItem(cls, name, proto, accessFlags)
1377     {
1378     }
1379 
1380     ~ForeignMethodItem() override = default;
1381 
IsForeign()1382     bool IsForeign() const override
1383     {
1384         return true;
1385     }
1386 
GetItemType()1387     ItemTypes GetItemType() const override
1388     {
1389         return ItemTypes::FOREIGN_METHOD_ITEM;
1390     }
1391 
1392     DEFAULT_MOVE_SEMANTIC(ForeignMethodItem);
1393     DEFAULT_COPY_SEMANTIC(ForeignMethodItem);
1394 };
1395 
1396 class ProtoItem;
1397 
1398 class ParamAnnotationsItem : public BaseItem {
1399 public:
1400     PANDA_PUBLIC_API ParamAnnotationsItem(MethodItem *method, bool isRuntimeAnnotations);
1401 
1402     ~ParamAnnotationsItem() override = default;
1403 
GetItemType()1404     ItemTypes GetItemType() const override
1405     {
1406         return ItemTypes::PARAM_ANNOTATIONS_ITEM;
1407     }
1408 
1409     size_t CalculateSize() const override;
1410 
1411     bool Write(Writer *writer) override;
1412 
1413     DEFAULT_MOVE_SEMANTIC(ParamAnnotationsItem);
1414     DEFAULT_COPY_SEMANTIC(ParamAnnotationsItem);
1415 
1416 private:
1417     std::vector<std::vector<AnnotationItem *>> annotations_;
1418 };
1419 
1420 class ProtoItem : public IndexedItem {
1421 public:
1422     ProtoItem(TypeItem *retType, const std::vector<MethodParamItem> &params);
1423 
1424     ~ProtoItem() override = default;
1425 
1426     DEFAULT_MOVE_SEMANTIC(ProtoItem);
1427     DEFAULT_COPY_SEMANTIC(ProtoItem);
1428 
CalculateSize()1429     size_t CalculateSize() const override
1430     {
1431         size_t size = shorty_.size() * sizeof(uint16_t);
1432         size += referenceTypes_.size() * IDX_SIZE;
1433         return size;
1434     }
1435 
1436     bool Write(Writer *writer) override;
1437 
GetItemType()1438     ItemTypes GetItemType() const override
1439     {
1440         return ItemTypes::PROTO_ITEM;
1441     }
1442 
GetIndexType()1443     IndexType GetIndexType() const override
1444     {
1445         return IndexType::PROTO;
1446     }
1447 
Alignment()1448     size_t Alignment() override
1449     {
1450         return sizeof(uint16_t);
1451     }
1452 
GetShorty()1453     const std::vector<uint16_t> &GetShorty() const
1454     {
1455         return shorty_;
1456     }
1457 
GetRefTypes()1458     const std::vector<TypeItem *> &GetRefTypes() const
1459     {
1460         return referenceTypes_;
1461     }
1462 
1463     void SetDependencyMark() override;
1464 
1465 private:
1466     static constexpr size_t SHORTY_ELEM_SIZE = 4;
1467 
1468     void AddType(TypeItem *type, size_t *n);
1469 
1470     std::vector<uint16_t> shorty_;
1471     std::vector<TypeItem *> referenceTypes_;
1472 };
1473 
1474 class PANDA_PUBLIC_API CodeItem : public BaseItem {
1475 public:
1476     class PANDA_PUBLIC_API CatchBlock : public BaseItem {
1477     public:
1478         CatchBlock(MethodItem *method, BaseClassItem *type, size_t handlerPc, size_t codeSize = 0)
method_(method)1479             : method_(method), type_(type), handlerPc_(handlerPc), codeSize_(codeSize)
1480         {
1481         }
1482 
1483         ~CatchBlock() override = default;
1484 
1485         DEFAULT_MOVE_SEMANTIC(CatchBlock);
1486         DEFAULT_COPY_SEMANTIC(CatchBlock);
1487 
GetMethod()1488         MethodItem *GetMethod() const
1489         {
1490             return method_;
1491         }
1492 
GetType()1493         BaseClassItem *GetType() const
1494         {
1495             return type_;
1496         }
1497 
GetHandlerPc()1498         size_t GetHandlerPc() const
1499         {
1500             return handlerPc_;
1501         }
1502 
GetCodeSize()1503         size_t GetCodeSize() const
1504         {
1505             return codeSize_;
1506         }
1507 
1508         size_t CalculateSize() const override;
1509 
1510         bool Write(Writer *writer) override;
1511 
GetItemType()1512         ItemTypes GetItemType() const override
1513         {
1514             return ItemTypes::CATCH_BLOCK_ITEM;
1515         }
1516 
1517     private:
1518         MethodItem *method_;
1519         BaseClassItem *type_;
1520         size_t handlerPc_;
1521         size_t codeSize_;
1522     };
1523 
1524     class PANDA_PUBLIC_API TryBlock : public BaseItem {
1525     public:
TryBlock(size_t startPc,size_t length,std::vector<CatchBlock> catchBlocks)1526         TryBlock(size_t startPc, size_t length, std::vector<CatchBlock> catchBlocks)
1527             : startPc_(startPc), length_(length), catchBlocks_(std::move(catchBlocks))
1528         {
1529         }
1530 
1531         ~TryBlock() override = default;
1532 
1533         DEFAULT_MOVE_SEMANTIC(TryBlock);
1534         DEFAULT_COPY_SEMANTIC(TryBlock);
1535 
GetStartPc()1536         size_t GetStartPc() const
1537         {
1538             return startPc_;
1539         }
1540 
GetLength()1541         size_t GetLength() const
1542         {
1543             return length_;
1544         }
1545 
GetCatchBlocks()1546         std::vector<CatchBlock> GetCatchBlocks() const
1547         {
1548             return catchBlocks_;
1549         }
1550 
1551         size_t CalculateSizeWithoutCatchBlocks() const;
1552 
1553         void ComputeLayout() override;
1554 
1555         size_t CalculateSize() const override;
1556 
1557         bool Write(Writer *writer) override;
1558 
GetItemType()1559         ItemTypes GetItemType() const override
1560         {
1561             return ItemTypes::TRY_BLOCK_ITEM;
1562         }
1563 
1564     private:
1565         size_t startPc_;
1566         size_t length_;
1567         std::vector<CatchBlock> catchBlocks_;
1568     };
1569 
CodeItem(size_t numVregs,size_t numArgs,std::vector<uint8_t> instructions)1570     CodeItem(size_t numVregs, size_t numArgs, std::vector<uint8_t> instructions)
1571         : numVregs_(numVregs), numArgs_(numArgs), instructions_(std::move(instructions))
1572     {
1573     }
1574 
1575     CodeItem() = default;
1576 
1577     ~CodeItem() override = default;
1578 
SetNumVregs(size_t numVregs)1579     void SetNumVregs(size_t numVregs)
1580     {
1581         numVregs_ = numVregs;
1582     }
1583 
SetNumArgs(size_t numArgs)1584     void SetNumArgs(size_t numArgs)
1585     {
1586         numArgs_ = numArgs;
1587     }
1588 
GetInstructions()1589     std::vector<uint8_t> *GetInstructions()
1590     {
1591         return &instructions_;
1592     }
1593 
SetNumInstructions(size_t numIns)1594     void SetNumInstructions(size_t numIns)
1595     {
1596         numIns_ = numIns;
1597     }
1598 
GetNumInstructions()1599     size_t GetNumInstructions() const
1600     {
1601         return numIns_;
1602     }
1603 
GetTryBlocks()1604     std::vector<TryBlock> GetTryBlocks()
1605     {
1606         return tryBlocks_;
1607     }
1608 
AddTryBlock(const TryBlock & tryBlock)1609     void AddTryBlock(const TryBlock &tryBlock)
1610     {
1611         tryBlocks_.push_back(tryBlock);
1612     }
1613 
1614     size_t CalculateSizeWithoutTryBlocks() const;
1615 
1616     void ComputeLayout() override;
1617 
1618     size_t CalculateSize() const override;
1619 
1620     size_t GetCodeSize() const;
1621 
1622     bool Write(Writer *writer) override;
1623 
GetItemType()1624     ItemTypes GetItemType() const override
1625     {
1626         return ItemTypes::CODE_ITEM;
1627     }
1628 
AddMethod(BaseMethodItem * method)1629     void AddMethod(BaseMethodItem *method)
1630     {
1631         methods_.emplace_back(method);
1632     }
1633 
GetMethodNames()1634     std::vector<std::string> GetMethodNames() const
1635     {
1636         std::vector<std::string> names;
1637         for (const auto *method : methods_) {
1638             if (method == nullptr) {
1639                 continue;
1640             }
1641             std::string className;
1642             if (method->GetClassItem() != nullptr) {
1643                 className = method->GetClassItem()->GetNameItem()->GetData();
1644                 className.pop_back();          // remove '\0'
1645                 ASSERT(className.size() > 2);  // 2 - L and ;
1646                 className.erase(0, 1);
1647                 className.pop_back();
1648                 className.append("::");
1649             }
1650             className.append(method->GetNameItem()->GetData());
1651             className.pop_back();  // remove '\0'
1652             names.emplace_back(className);
1653         }
1654         return names;
1655     }
1656 
GetNumVregs()1657     size_t GetNumVregs()
1658     {
1659         return numVregs_;
1660     }
1661 
GetNumArgs()1662     size_t GetNumArgs()
1663     {
1664         return numArgs_;
1665     }
1666 
1667     DEFAULT_MOVE_SEMANTIC(CodeItem);
1668     DEFAULT_COPY_SEMANTIC(CodeItem);
1669 
1670 private:
1671     size_t numVregs_ {0};
1672     size_t numArgs_ {0};
1673     size_t numIns_ {0};
1674     std::vector<uint8_t> instructions_;
1675     std::vector<TryBlock> tryBlocks_;
1676     std::vector<BaseMethodItem *> methods_;
1677 };
1678 
1679 class ScalarValueItem;
1680 class ArrayValueItem;
1681 
1682 class ValueItem : public BaseItem {
1683 public:
1684     enum class Type { INTEGER, LONG, FLOAT, DOUBLE, ID, ARRAY };
1685 
ValueItem(Type type)1686     explicit ValueItem(Type type) : type_(type) {}
1687 
1688     ~ValueItem() override = default;
1689 
1690     DEFAULT_MOVE_SEMANTIC(ValueItem);
1691     DEFAULT_COPY_SEMANTIC(ValueItem);
1692 
GetType()1693     Type GetType() const
1694     {
1695         return type_;
1696     }
1697 
IsArray()1698     bool IsArray() const
1699     {
1700         return type_ == Type::ARRAY;
1701     }
1702 
Is32bit()1703     bool Is32bit() const
1704     {
1705         return type_ == Type::INTEGER || type_ == Type::FLOAT || type_ == Type::ID;
1706     }
1707 
GetItemType()1708     ItemTypes GetItemType() const override
1709     {
1710         return ItemTypes::VALUE_ITEM;
1711     }
1712 
1713     ScalarValueItem *GetAsScalar();
1714 
1715     ArrayValueItem *GetAsArray();
1716 
1717 private:
1718     Type type_;
1719 };
1720 
1721 class PANDA_PUBLIC_API ScalarValueItem : public ValueItem {
1722 public:
ScalarValueItem(uint32_t v)1723     explicit ScalarValueItem(uint32_t v) : ValueItem(Type::INTEGER), value_(v) {}
1724 
ScalarValueItem(uint64_t v)1725     explicit ScalarValueItem(uint64_t v) : ValueItem(Type::LONG), value_(v) {}
1726 
ScalarValueItem(float v)1727     explicit ScalarValueItem(float v) : ValueItem(Type::FLOAT), value_(v) {}
1728 
ScalarValueItem(double v)1729     explicit ScalarValueItem(double v) : ValueItem(Type::DOUBLE), value_(v) {}
1730 
ScalarValueItem(BaseItem * v)1731     explicit ScalarValueItem(BaseItem *v) : ValueItem(Type::ID), value_(v) {}
1732 
1733     ~ScalarValueItem() override = default;
1734 
1735     DEFAULT_MOVE_SEMANTIC(ScalarValueItem);
1736     DEFAULT_COPY_SEMANTIC(ScalarValueItem);
1737 
1738     template <class T>
GetValue()1739     T GetValue() const
1740     {
1741         return std::get<T>(value_);
1742     }
1743 
1744     template <class T>
HasValue()1745     bool HasValue() const
1746     {
1747         return std::holds_alternative<T>(value_);
1748     }
1749 
GetId()1750     File::EntityId GetId() const
1751     {
1752         return File::EntityId(GetValue<BaseItem *>()->GetOffset());
1753     }
1754 
GetIdItem()1755     BaseItem *GetIdItem() const
1756     {
1757         return GetValue<BaseItem *>();
1758     }
1759 
1760     size_t GetULeb128EncodedSize();
1761 
1762     size_t GetSLeb128EncodedSize();
1763 
1764     size_t CalculateSize() const override;
1765 
1766     size_t Alignment() override;
1767 
1768     bool Write(Writer *writer) override;
1769 
1770     bool WriteAsUleb128(Writer *writer);
1771 
1772 private:
1773     std::variant<uint32_t, uint64_t, float, double, BaseItem *> value_;
1774 };
1775 
1776 class PANDA_PUBLIC_API ArrayValueItem : public ValueItem {
1777 public:
ArrayValueItem(panda_file::Type componentType,std::vector<ScalarValueItem> items)1778     ArrayValueItem(panda_file::Type componentType, std::vector<ScalarValueItem> items)
1779         : ValueItem(Type::ARRAY), componentType_(componentType), items_(std::move(items))
1780     {
1781     }
1782 
1783     ~ArrayValueItem() override = default;
1784 
1785     DEFAULT_MOVE_SEMANTIC(ArrayValueItem);
1786     DEFAULT_COPY_SEMANTIC(ArrayValueItem);
1787 
1788     size_t CalculateSize() const override;
1789 
1790     void ComputeLayout() override;
1791 
1792     bool Write(Writer *writer) override;
1793 
GetComponentType()1794     panda_file::Type GetComponentType() const
1795     {
1796         return componentType_;
1797     }
1798 
GetItems()1799     const std::vector<ScalarValueItem> &GetItems() const
1800     {
1801         return items_;
1802     }
1803 
GetMutableItems()1804     std::vector<ScalarValueItem> *GetMutableItems()
1805     {
1806         return &items_;
1807     }
1808 
1809 private:
1810     size_t GetComponentSize() const;
1811 
1812     panda_file::Type componentType_;
1813     std::vector<ScalarValueItem> items_;
1814 };
1815 
1816 class LiteralItem;
1817 class LiteralArrayItem;
1818 
1819 class PANDA_PUBLIC_API LiteralItem : public BaseItem {
1820 public:
1821     enum class Type { B1, B2, B4, B8, STRING, METHOD, LITERALARRAY };
1822 
LiteralItem(uint8_t v)1823     explicit LiteralItem(uint8_t v) : type_(Type::B1), value_(v) {}
1824 
LiteralItem(uint16_t v)1825     explicit LiteralItem(uint16_t v) : type_(Type::B2), value_(v) {}
1826 
LiteralItem(uint32_t v)1827     explicit LiteralItem(uint32_t v) : type_(Type::B4), value_(v) {}
1828 
LiteralItem(uint64_t v)1829     explicit LiteralItem(uint64_t v) : type_(Type::B8), value_(v) {}
1830 
LiteralItem(StringItem * v)1831     explicit LiteralItem(StringItem *v) : type_(Type::STRING), value_(v) {}
1832 
LiteralItem(MethodItem * v)1833     explicit LiteralItem(MethodItem *v) : type_(Type::METHOD), value_(v) {}
1834 
LiteralItem(LiteralArrayItem * v)1835     explicit LiteralItem(LiteralArrayItem *v) : type_(Type::LITERALARRAY), value_(v) {}
1836 
1837     ~LiteralItem() override = default;
1838 
1839     DEFAULT_MOVE_SEMANTIC(LiteralItem);
1840     DEFAULT_COPY_SEMANTIC(LiteralItem);
1841 
GetType()1842     Type GetType() const
1843     {
1844         return type_;
1845     }
1846 
GetItemType()1847     ItemTypes GetItemType() const override
1848     {
1849         return ItemTypes::LITERAL_ITEM;
1850     }
1851 
1852     template <class T>
GetValue()1853     T GetValue() const
1854     {
1855         return std::get<T>(value_);
1856     }
1857 
1858     // NOTE: fix in follow-up patch (#24481)
1859     template <class T>
SetValueUnsafe(T value)1860     void SetValueUnsafe(T value)
1861     {
1862         std::get<T>(value_) = value;
1863     }
1864 
1865     size_t CalculateSize() const override;
1866 
1867     size_t Alignment() override;
1868 
GetId()1869     File::EntityId GetId() const
1870     {
1871         return File::EntityId(GetValue<StringItem *>()->GetOffset());
1872     }
1873 
1874     File::EntityId GetLiteralArrayFileId() const;
1875 
GetMethodId()1876     File::EntityId GetMethodId() const
1877     {
1878         return File::EntityId(GetValue<MethodItem *>()->GetFileId());
1879     }
1880 
1881     bool Write(Writer *writer) override;
1882 
1883     void SetDependencyMark() override;
1884 
1885 private:
1886     Type type_;
1887     std::variant<uint8_t, uint16_t, uint32_t, uint64_t, StringItem *, MethodItem *, LiteralArrayItem *> value_;
1888 };
1889 
1890 class LiteralArrayItem : public ValueItem {
1891 public:
LiteralArrayItem()1892     explicit LiteralArrayItem() : ValueItem(Type::ARRAY) {}
1893 
1894     ~LiteralArrayItem() override = default;
1895 
1896     DEFAULT_MOVE_SEMANTIC(LiteralArrayItem);
1897     DEFAULT_COPY_SEMANTIC(LiteralArrayItem);
1898 
1899     PANDA_PUBLIC_API void AddItems(const std::vector<LiteralItem> &item);
1900 
GetItems()1901     const std::vector<LiteralItem> &GetItems() const
1902     {
1903         return items_;
1904     }
1905 
1906     // NOTE: fix in follow-up patch (#24481)
GetItemsUnsafe()1907     std::vector<LiteralItem> &GetItemsUnsafe()
1908     {
1909         return items_;
1910     }
1911 
1912     size_t CalculateSize() const override;
1913 
1914     void ComputeLayout() override;
1915 
1916     bool Write(Writer *writer) override;
1917 
GetItemType()1918     ItemTypes GetItemType() const override
1919     {
1920         return ItemTypes::LITERAL_ARRAY_ITEM;
1921     }
1922 
SetIndex(uint32_t index)1923     void SetIndex(uint32_t index)
1924     {
1925         index_ = index;
1926     }
1927 
GetIndex()1928     uint32_t GetIndex() const
1929     {
1930         return index_;
1931     }
1932 
1933     void SetDependencyMark() override;
1934 
1935 private:
1936     std::vector<LiteralItem> items_;
1937     uint32_t index_ {0};
1938 };
1939 
1940 class PANDA_PUBLIC_API AnnotationItem : public BaseItem {
1941 public:
1942     class Elem {
1943     public:
Elem(StringItem * name,ValueItem * value)1944         Elem(StringItem *name, ValueItem *value) : name_(name), value_(value)
1945         {
1946             value_->SetNeedsEmit(!value_->Is32bit());
1947         }
1948 
1949         ~Elem() = default;
1950 
1951         DEFAULT_MOVE_SEMANTIC(Elem);
1952         DEFAULT_COPY_SEMANTIC(Elem);
1953 
GetName()1954         const StringItem *GetName() const
1955         {
1956             return name_;
1957         }
1958 
GetValue()1959         ValueItem *GetValue() const
1960         {
1961             return value_;
1962         }
1963 
SetValue(ValueItem * item)1964         void SetValue(ValueItem *item)
1965         {
1966             value_ = item;
1967         }
1968 
SetDependencyMark()1969         void SetDependencyMark()
1970         {
1971             if (name_ != nullptr) {
1972                 name_->SetDependencyMark();
1973             }
1974             if (value_ != nullptr) {
1975                 value_->SetDependencyMark();
1976             }
1977         }
1978 
1979     private:
1980         StringItem *name_;
1981         ValueItem *value_;
1982     };
1983 
1984     class Tag {
1985     public:
Tag(char item)1986         explicit Tag(char item) : item_(item) {}
1987 
1988         ~Tag() = default;
1989 
1990         DEFAULT_MOVE_SEMANTIC(Tag);
1991         DEFAULT_COPY_SEMANTIC(Tag);
1992 
GetItem()1993         uint8_t GetItem() const
1994         {
1995             return item_;
1996         }
1997 
1998     private:
1999         uint8_t item_;
2000     };
2001 
AnnotationItem(BaseClassItem * cls,std::vector<Elem> elements,std::vector<Tag> tags)2002     AnnotationItem(BaseClassItem *cls, std::vector<Elem> elements, std::vector<Tag> tags)
2003         : class_(cls), elements_(std::move(elements)), tags_(std::move(tags))
2004     {
2005         AddIndexDependency(cls);
2006     }
2007 
2008     ~AnnotationItem() override = default;
2009 
2010     DEFAULT_MOVE_SEMANTIC(AnnotationItem);
2011     DEFAULT_COPY_SEMANTIC(AnnotationItem);
2012 
2013     size_t CalculateSize() const override;
2014 
2015     bool Write(Writer *writer) override;
2016 
GetItemType()2017     ItemTypes GetItemType() const override
2018     {
2019         return ItemTypes::ANNOTATION_ITEM;
2020     }
2021 
GetClassItem()2022     BaseClassItem *GetClassItem() const
2023     {
2024         return class_;
2025     }
2026 
GetElements()2027     std::vector<Elem> *GetElements()
2028     {
2029         return &elements_;
2030     }
2031 
GetElements()2032     const std::vector<Elem> *GetElements() const
2033     {
2034         return &elements_;
2035     }
2036 
SetElements(std::vector<Elem> && elements)2037     void SetElements(std::vector<Elem> &&elements)
2038     {
2039         elements_ = std::move(elements);
2040     }
2041 
GetTags()2042     const std::vector<Tag> &GetTags() const
2043     {
2044         return tags_;
2045     }
2046 
SetTags(std::vector<Tag> && tags)2047     void SetTags(std::vector<Tag> &&tags)
2048     {
2049         tags_ = std::move(tags);
2050     }
2051     void SetDependencyMark() override;
2052 
2053 private:
2054     BaseClassItem *class_;
2055     std::vector<Elem> elements_;
2056     std::vector<Tag> tags_;
2057 };
2058 
2059 enum class MethodHandleType : uint8_t {
2060     PUT_STATIC = 0x00,
2061     GET_STATIC = 0x01,
2062     PUT_INSTANCE = 0x02,
2063     GET_INSTANCE = 0x03,
2064     INVOKE_STATIC = 0x04,
2065     INVOKE_INSTANCE = 0x05,
2066     INVOKE_CONSTRUCTOR = 0x06,
2067     INVOKE_DIRECT = 0x07,
2068     INVOKE_INTERFACE = 0x08
2069 };
2070 
2071 class PANDA_PUBLIC_API MethodHandleItem : public BaseItem {
2072 public:
MethodHandleItem(MethodHandleType type,BaseItem * entity)2073     MethodHandleItem(MethodHandleType type, BaseItem *entity) : type_(type), entity_(entity) {}
2074 
2075     ~MethodHandleItem() override = default;
2076 
2077     DEFAULT_MOVE_SEMANTIC(MethodHandleItem);
2078     DEFAULT_COPY_SEMANTIC(MethodHandleItem);
2079 
CalculateSize()2080     size_t CalculateSize() const override
2081     {
2082         return sizeof(uint8_t) + leb128::UnsignedEncodingSize(entity_->GetOffset());
2083     }
2084 
2085     bool Write(Writer *writer) override;
2086 
GetItemType()2087     ItemTypes GetItemType() const override
2088     {
2089         return ItemTypes::METHOD_HANDLE_ITEM;
2090     }
2091 
GetType()2092     MethodHandleType GetType() const
2093     {
2094         return type_;
2095     }
2096 
2097 private:
2098     MethodHandleType type_;
2099     BaseItem *entity_;
2100 };
2101 
2102 enum class ArgumentType : uint8_t {
2103     INTEGER = 0x00,
2104     LONG = 0x01,
2105     FLOAT = 0x02,
2106     DOUBLE = 0x03,
2107     STRING = 0x04,
2108     CLASS = 0x05,
2109     METHOD_HANDLE = 0x06,
2110     METHOD_TYPE = 0x07
2111 };
2112 
2113 }  // namespace ark::panda_file
2114 
2115 #endif  // LIBPANDAFILE_FILE_ITEMS_H_
2116