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