• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H
17 #define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H
18 
19 #include "static_core/compiler/optimizer/ir/graph.h"
20 #include "static_core/compiler/optimizer/ir/basicblock.h"
21 #include "static_core/compiler/optimizer/analysis/loop_analyzer.h"
22 
23 #include "libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h"
24 #include "libabckit/src/irbuilder_dynamic/bytecode_inst.h"
25 
26 namespace libabckit {
27 
28 constexpr int64_t INVALID_OFFSET = std::numeric_limits<int64_t>::max();
29 using ark::BytecodeInstruction;
30 
31 class InstBuilder {
32 public:
InstBuilder(ark::compiler::Graph * graph,AbckitRuntimeAdapterDynamic::MethodPtr method)33     InstBuilder(ark::compiler::Graph *graph, AbckitRuntimeAdapterDynamic::MethodPtr method)
34         : graph_(graph),
35           runtime_(graph->GetRuntime()),
36           defs_(graph->GetLocalAllocator()->Adapter()),
37           method_(method),
38           vregsAndArgsCount_(graph->GetRuntime()->GetMethodRegistersCount(method) +
39                              graph->GetRuntime()->GetMethodTotalArgumentsCount(method)),
40           instructionsBuf_(GetGraph()->GetRuntime()->GetMethodCode(GetGraph()->GetMethod())),
41           classId_ {runtime_->GetClassIdForMethod(method_)}
42     {
43         noTypeMarker_ = GetGraph()->NewMarker();
44         visitedBlockMarker_ = GetGraph()->NewMarker();
45 
46         defs_.resize(graph_->GetVectorBlocks().size(),
47                      ark::compiler::InstVector(graph->GetLocalAllocator()->Adapter()));
48         for (auto &v : defs_) {
49             v.resize(vregsAndArgsCount_ + 1);
50         }
51 
52         for (auto bb : graph->GetBlocksRPO()) {
53             if (bb->IsCatchBegin()) {
54                 for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) {
55                     auto catchPhi = GetGraph()->CreateInstCatchPhi();
56                     catchPhi->SetPc(bb->GetGuestPc());
57                     catchPhi->SetMarker(GetNoTypeMarker());
58                     bb->AppendInst(catchPhi);
59                     if (vreg == vregsAndArgsCount_) {
60                         catchPhi->SetIsAcc();
61                     }
62                 }
63             }
64         }
65     }
66 
67     NO_COPY_SEMANTIC(InstBuilder);
68     NO_MOVE_SEMANTIC(InstBuilder);
~InstBuilder()69     ~InstBuilder()
70     {
71         GetGraph()->EraseMarker(noTypeMarker_);
72         GetGraph()->EraseMarker(visitedBlockMarker_);
73     }
74 
75     /**
76      * Content of this function is auto generated from inst_builder.erb and is located in inst_builder_gen.cpp file
77      * @param instruction Pointer to bytecode instruction
78      */
79     void BuildInstruction(const BytecodeInst *instruction);
80 
IsFailed()81     bool IsFailed() const
82     {
83         return failed_;
84     }
85 
86     /**
87      * Return jump offset for instruction `inst`, 0 if it is not jump instruction.
88      */
89     static int64_t GetInstructionJumpOffset(const BytecodeInst *inst);
90 
SetCurrentBlock(ark::compiler::BasicBlock * bb)91     void SetCurrentBlock(ark::compiler::BasicBlock *bb)
92     {
93         currentBb_ = bb;
94         currentDefs_ = &defs_[bb->GetId()];
95     }
96 
97     void Prepare();
98 
99     void UpdatePreds(ark::compiler::BasicBlock *bb, ark::compiler::Inst *inst);
100     void SetType(ark::compiler::Inst *inst);
101     void FixInstructions();
102     void CheckInstructions(ark::compiler::Inst *inst);
103     void ResolveConstants();
104     void SplitConstant(ark::compiler::ConstantInst *constInst);
105     void CleanupInst(ark::compiler::BasicBlock *block, ark::compiler::Inst *inst);
106     void CleanupCatchPhis();
107     void AddPhiToDifferent();
108 
109     static void RemoveNotDominateInputs(ark::compiler::SaveStateInst *saveState);
110 
111     size_t GetPc(const uint8_t *instPtr) const;
112 
113     void UpdateDefs();
114 
GetCurrentDefs()115     const auto &GetCurrentDefs()
116     {
117         ASSERT(currentDefs_ != nullptr);
118         return *currentDefs_;
119     }
120 
121     void AddCatchPhiInputs(const ark::ArenaUnorderedSet<ark::compiler::BasicBlock *> &catchHandlers,
122                            const ark::compiler::InstVector &defs, ark::compiler::Inst *throwableInst);
123 
124     ark::compiler::SaveStateInst *CreateSaveState(ark::compiler::Opcode opc, size_t pc);
125 
126     static void SetParamSpillFill(ark::compiler::Graph *graph, ark::compiler::ParameterInst *paramInst, size_t numArgs,
127                                   size_t i, ark::compiler::DataType::Type type);
128 
129 private:
130     void UpdateDefsForCatch();
131     void UpdateDefsForLoopHead();
132 
GetVRegsCount()133     size_t GetVRegsCount() const
134     {
135         return vregsAndArgsCount_ + 1;
136     }
137 
AddInstruction(ark::compiler::Inst * inst)138     void AddInstruction(ark::compiler::Inst *inst)
139     {
140         ASSERT(currentBb_);
141         currentBb_->AppendInst(inst);
142         LIBABCKIT_LOG(DEBUG) << *inst << std::endl;
143     }
144 
UpdateDefinition(size_t vreg,ark::compiler::Inst * inst)145     void UpdateDefinition(size_t vreg, ark::compiler::Inst *inst)
146     {
147         ASSERT(vreg < currentDefs_->size());
148         (*currentDefs_)[vreg] = inst;
149     }
150 
UpdateDefinitionAcc(ark::compiler::Inst * inst)151     void UpdateDefinitionAcc(ark::compiler::Inst *inst)
152     {
153         (*currentDefs_)[vregsAndArgsCount_] = inst;
154     }
155 
GetDefinition(size_t vreg)156     ark::compiler::Inst *GetDefinition(size_t vreg)
157     {
158         ASSERT(vreg < currentDefs_->size());
159         ASSERT((*currentDefs_)[vreg] != nullptr);
160 
161         if (vreg >= currentDefs_->size() || (*currentDefs_)[vreg] == nullptr) {
162             failed_ = true;
163             LIBABCKIT_LOG(DEBUG) << "GetDefinition failed for verg " << vreg << std::endl;
164             return nullptr;
165         }
166         return (*currentDefs_)[vreg];
167     }
168 
GetDefinitionAcc()169     ark::compiler::Inst *GetDefinitionAcc()
170     {
171         auto *accInst = (*currentDefs_)[vregsAndArgsCount_];
172         ASSERT(accInst != nullptr);
173 
174         if (accInst == nullptr) {
175             failed_ = true;
176             LIBABCKIT_LOG(DEBUG) << "GetDefinitionAcc failed\n";
177         }
178         return accInst;
179     }
180 
FindOrCreate32BitConstant(uint32_t value)181     auto FindOrCreate32BitConstant(uint32_t value)
182     {
183         auto inst = GetGraph()->FindOrCreateConstant<uint32_t>(value);
184         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
185             LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl;
186         }
187         return inst;
188     }
189 
FindOrCreateConstant(uint64_t value)190     auto FindOrCreateConstant(uint64_t value)
191     {
192         auto inst = GetGraph()->FindOrCreateConstant<uint64_t>(value);
193         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
194             LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl;
195         }
196         return inst;
197     }
198 
FindOrCreateDoubleConstant(double value)199     auto FindOrCreateDoubleConstant(double value)
200     {
201         auto inst = GetGraph()->FindOrCreateConstant<double>(value);
202         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
203             LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl;
204         }
205         return inst;
206     }
207 
208     void BuildEcma([[maybe_unused]] const BytecodeInst *bcInst);
209     template <bool WITH_SPECULATIVE = false>
210     void BuildEcmaAsIntrinsics([[maybe_unused]] const BytecodeInst *bcInst);
211     void BuildAbcKitLoadStringIntrinsic(const BytecodeInst *bcInst);
212 
213     template <ark::compiler::Opcode OPCODE>
214     void BuildLoadFromPool(const BytecodeInst *bcInst);
215 
GetGraph()216     ark::compiler::Graph *GetGraph()
217     {
218         return graph_;
219     }
220 
GetGraph()221     const ark::compiler::Graph *GetGraph() const
222     {
223         return graph_;
224     }
225 
GetRuntime()226     const ark::compiler::RuntimeInterface *GetRuntime() const
227     {
228         return runtime_;
229     }
230 
GetRuntime()231     ark::compiler::RuntimeInterface *GetRuntime()
232     {
233         return runtime_;
234     }
235 
GetMethod()236     auto GetMethod() const
237     {
238         return method_;
239     }
240 
GetClassId()241     auto GetClassId() const
242     {
243         return classId_;
244     }
245 
GetNoTypeMarker()246     ark::compiler::Marker GetNoTypeMarker() const
247     {
248         return noTypeMarker_;
249     }
250 
GetVisitedBlockMarker()251     ark::compiler::Marker GetVisitedBlockMarker() const
252     {
253         return visitedBlockMarker_;
254     }
255 
256     void SetTypeRec(ark::compiler::Inst *inst, ark::compiler::DataType::Type type);
257 
258     size_t GetMethodArgumentsCount(uintptr_t id) const;
259 
260 private:
261     static constexpr size_t INPUT_2 = 2;
262     static constexpr size_t INPUT_3 = 3;
263     static constexpr size_t TWO_INPUTS = 2;
264 
265     ark::compiler::Graph *graph_ {nullptr};
266     ark::compiler::RuntimeInterface *runtime_ {nullptr};
267     ark::compiler::BasicBlock *currentBb_ {nullptr};
268 
269     // Definitions vector of currently processed basic block
270     ark::compiler::InstVector *currentDefs_ {nullptr};
271     // Contains definitions of the virtual registers in all basic blocks
272     ark::ArenaVector<ark::compiler::InstVector> defs_;
273 
274     AbckitRuntimeAdapterDynamic::MethodPtr method_ {nullptr};
275     // Set to true if builder failed to build IR
276     bool failed_ {false};
277     // Number of virtual registers and method arguments
278     const size_t vregsAndArgsCount_;
279     // Marker for instructions with undefined type in the building phase
280     ark::compiler::Marker noTypeMarker_;
281     ark::compiler::Marker visitedBlockMarker_;
282 
283     // Pointer to start position of bytecode instructions buffer
284     const uint8_t *instructionsBuf_ {nullptr};
285 
286     size_t classId_;
287 
288 #include "intrinsics_ir_build.inl.h"
289 };
290 
291 }  // namespace libabckit
292 
293 #endif  // LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H
294