• 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 PANDA_CODE_INFO_BUILDER_H
17 #define PANDA_CODE_INFO_BUILDER_H
18 
19 #include "code_info.h"
20 #include "utils/arena_containers.h"
21 #include "utils/bit_vector.h"
22 
23 namespace panda::compiler {
24 
25 class CodeInfoBuilder {
26 public:
CodeInfoBuilder(Arch arch,ArenaAllocator * allocator)27     CodeInfoBuilder(Arch arch, ArenaAllocator *allocator)
28         : arch_(arch),
29           stack_maps_(allocator),
30           inline_infos_(allocator),
31           roots_reg_masks_(allocator),
32           roots_stack_masks_(allocator),
33           method_ids_(allocator),
34           vregs_catalogue_(allocator),
35           vregs_map_(allocator),
36           vreg_masks_(allocator),
37           implicit_nullchecks_(allocator),
38           constant_table_(allocator),
39           current_vregs_(allocator->Adapter()),
40           last_vregs_(allocator->Adapter()),
41           vregs_last_change_(allocator->Adapter()),
42           inline_info_stack_(allocator->Adapter()),
43           vregs_map_storage_(allocator->Adapter()),
44           vregs_mask_storage_(allocator)
45     {
46     }
47 
48     NO_COPY_SEMANTIC(CodeInfoBuilder);
49     NO_MOVE_SEMANTIC(CodeInfoBuilder);
50     ~CodeInfoBuilder() = default;
51 
52     void BeginMethod(uint32_t frame_size, uint32_t vregs_count);
53 
54     void EndMethod();
55 
56     void BeginStackMap(uint32_t bpc, uint32_t npc, ArenaBitVector *stack_roots, uint32_t regs_roots,
57                        bool require_vreg_map, bool is_osr);
58 
59     void EndStackMap();
60 
61     void BeginInlineInfo(void *method, uint32_t method_id, uint32_t bpc, uint32_t vregs_count);
62 
63     void EndInlineInfo();
64 
AddVReg(VRegInfo reg)65     void AddVReg(VRegInfo reg)
66     {
67         // Constant should be added via `AddConstant` method
68         ASSERT(reg.GetLocation() != VRegInfo::Location::CONSTANT);
69         current_vregs_.push_back(reg);
70     }
71 
72     void AddConstant(uint64_t value, VRegInfo::Type type, bool is_acc);
73 
SetFrameSize(uint32_t size)74     void SetFrameSize(uint32_t size)
75     {
76         header_.SetFrameSize(size);
77     }
78 
79     void Encode(ArenaVector<uint8_t> *stream, size_t offset = 0);
80 
SetSavedCalleeRegsMask(uint32_t mask,uint32_t vmask)81     void SetSavedCalleeRegsMask(uint32_t mask, uint32_t vmask)
82     {
83         header_.SetCalleeRegMask(mask);
84         header_.SetCalleeFpRegMask(vmask);
85     }
86 
AddImplicitNullCheck(uint32_t instruction_native_pc,uint32_t offset)87     void AddImplicitNullCheck(uint32_t instruction_native_pc, uint32_t offset)
88     {
89         implicit_nullchecks_.Add({instruction_native_pc, offset});
90     }
91 
SetHasFloatRegs(bool has)92     void SetHasFloatRegs(bool has)
93     {
94         header_.SetHasFloatRegs(has);
95     }
96 
97     template <typename Func>
EnumerateTables(Func func)98     constexpr void EnumerateTables(Func func)
99     {
100         size_t index = 0;
101         func(index++, &stack_maps_);
102         func(index++, &inline_infos_);
103         func(index++, &roots_reg_masks_);
104         func(index++, &roots_stack_masks_);
105         func(index++, &method_ids_);
106         func(index++, &vreg_masks_);
107         func(index++, &vregs_map_);
108         func(index++, &vregs_catalogue_);
109         func(index++, &implicit_nullchecks_);
110         func(index++, &constant_table_);
111         ASSERT(index == CodeInfo::TABLES_COUNT);
112     }
113 
114     void DumpCurrentStackMap(std::ostream &stream) const;
115 
116 private:
117     void EmitVRegs();
118 
119 private:
120     Arch arch_;
121     uint32_t vregs_count_ {0};
122     uint32_t current_vregs_count_ {0};
123 
124     CodeInfoHeader header_ {};
125 
126     // Tables
127     BitTableBuilder<StackMap> stack_maps_;
128     BitTableBuilder<InlineInfo> inline_infos_;
129     BitTableBuilder<RegisterMask> roots_reg_masks_;
130     BitmapTableBuilder roots_stack_masks_;
131     BitTableBuilder<MethodId> method_ids_;
132     BitTableBuilder<VRegisterInfo> vregs_catalogue_;
133     BitTableBuilder<VRegisterCatalogueIndex> vregs_map_;
134     BitmapTableBuilder vreg_masks_;
135     BitTableBuilder<ImplicitNullChecks> implicit_nullchecks_;
136     BitTableBuilder<ConstantTable> constant_table_;
137 
138     // Auxiliary containers
139     BitTableBuilder<StackMap>::Entry current_stack_map_;
140     ArenaVector<VRegInfo> current_vregs_;
141     ArenaVector<VRegInfo> last_vregs_;
142     ArenaVector<uint32_t> vregs_last_change_;
143     ArenaVector<BitTableBuilder<InlineInfo>::Entry> inline_info_stack_;
144     ArenaVector<BitTableBuilder<VRegisterCatalogueIndex>::Entry> vregs_map_storage_;
145     ArenaBitVector vregs_mask_storage_;
146 
147 #ifndef NDEBUG
148     bool was_method_begin_ {false};
149     bool was_stack_map_begin_ {false};
150     bool was_inline_info_begin_ {false};
151 #endif
152 
153     static constexpr size_t MAX_VREG_LIVE_DISTANCE = 32;
154 };
155 
156 }  // namespace panda::compiler
157 
158 #endif  // PANDA_CODE_INFO_BUILDER_H
159