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