• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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_INST_BUILDER_H
17 #define PANDA_INST_BUILDER_H
18 
19 #include "compiler_options.h"
20 #include "optimizer/ir/graph.h"
21 #include "optimizer/ir/basicblock.h"
22 #include "optimizer/analysis/loop_analyzer.h"
23 #include "code_info/vreg_info.h"
24 #include "code_data_accessor.h"
25 #include "file_items.h"
26 #include "compiler_logger.h"
27 
28 #include "bytecode_instruction.h"
29 
30 namespace panda::compiler {
31 constexpr int64_t INVALID_OFFSET = std::numeric_limits<int64_t>::max();
32 
33 class InstBuilder {
34 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
35 #define ENV_IDX(ENV_TYPE) \
36     static constexpr uint8_t ENV_TYPE##_IDX = VRegInfo::VRegType::ENV_TYPE - VRegInfo::VRegType::ENV_BEGIN;
VREGS_ENV_TYPE_DEFS(ENV_IDX)37     VREGS_ENV_TYPE_DEFS(ENV_IDX)
38 #undef ENV_IDX
39 public:
40     InstBuilder(Graph *graph, RuntimeInterface::MethodPtr method, CallInst *callerInst, uint32_t inliningDepth)
41         : graph_(graph),
42           runtime_(graph->GetRuntime()),
43           defs_(graph->GetLocalAllocator()->Adapter()),
44           method_(method),
45           vregsAndArgsCount_(graph->GetRuntime()->GetMethodRegistersCount(method) +
46                              graph->GetRuntime()->GetMethodTotalArgumentsCount(method)),
47           instructionsBuf_(GetGraph()->GetRuntime()->GetMethodCode(GetGraph()->GetMethod())),
48           callerInst_(callerInst),
49           inliningDepth_(inliningDepth),
50           classId_ {runtime_->GetClassIdForMethod(method_)}
51     {
52         noTypeMarker_ = GetGraph()->NewMarker();
53         visitedBlockMarker_ = GetGraph()->NewMarker();
54 
55         defs_.resize(graph_->GetVectorBlocks().size(), InstVector(graph->GetLocalAllocator()->Adapter()));
56         for (auto &v : defs_) {
57             v.resize(GetVRegsCount());
58         }
59 
60         for (auto bb : graph->GetBlocksRPO()) {
61             if (bb->IsCatchBegin()) {
62                 for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) {
63                     auto catchPhi = GetGraph()->CreateInstCatchPhi(DataType::NO_TYPE, bb->GetGuestPc());
64                     catchPhi->SetMarker(GetNoTypeMarker());
65                     bb->AppendInst(catchPhi);
66                     COMPILER_LOG(DEBUG, IR_BUILDER)
67                         << "Creat catchphi " << catchPhi->GetId() << " for bb(" << bb->GetId() << ")";
68                     if (vreg == vregsAndArgsCount_) {
69                         catchPhi->SetIsAcc();
70                     } else if (vreg > vregsAndArgsCount_) {
71                         catchPhi->SetType(DataType::ANY);
72                     }
73                 }
74             }
75         }
76     }
77 
78     NO_COPY_SEMANTIC(InstBuilder);
79     NO_MOVE_SEMANTIC(InstBuilder);
~InstBuilder()80     ~InstBuilder()
81     {
82         GetGraph()->EraseMarker(noTypeMarker_);
83         GetGraph()->EraseMarker(visitedBlockMarker_);
84     }
85 
86     /**
87      * Content of this function is auto generated from inst_builder.erb and is located in inst_builder_gen.cpp file
88      * @param instruction Pointer to bytecode instruction
89      */
90     void BuildInstruction(const BytecodeInstruction *instruction);
91 
InitEnv(BasicBlock * bb)92     void InitEnv(BasicBlock *bb)
93     {
94         auto thisFunc = GetGraph()->FindParameter(0);
95         auto cp = GetGraph()->CreateInstLoadConstantPool(DataType::ANY, INVALID_PC, thisFunc);
96         bb->AppendInst(cp);
97 
98         auto lexEnv = GetGraph()->CreateInstLoadLexicalEnv(DataType::ANY, INVALID_PC, thisFunc);
99         bb->AppendInst(lexEnv);
100 
101         defs_[bb->GetId()][vregsAndArgsCount_ + 1 + THIS_FUNC_IDX] = thisFunc;
102         defs_[bb->GetId()][vregsAndArgsCount_ + 1 + CONST_POOL_IDX] = cp;
103         defs_[bb->GetId()][vregsAndArgsCount_ + 1 + LEX_ENV_IDX] = lexEnv;
104         COMPILER_LOG(DEBUG, IR_BUILDER) << "Init environment this_func = " << thisFunc->GetId()
105                                         << ", const_pool = " << cp->GetId() << ", lex_env = " << lexEnv->GetId();
106     }
107 
IsFailed()108     bool IsFailed() const
109     {
110         return failed_;
111     }
112 
113     /// Return jump offset for instruction `inst`, 0 if it is not jump instruction.
114     static int64_t GetInstructionJumpOffset(const BytecodeInstruction *inst);
115 
SetCurrentBlock(BasicBlock * bb)116     void SetCurrentBlock(BasicBlock *bb)
117     {
118         if (GetGraph()->IsDynamicMethod() && !GetGraph()->IsBytecodeOptimizer() &&
119             currentBb_ != GetGraph()->GetStartBlock() && currentDefs_ != nullptr) {
120             ASSERT((*currentDefs_)[vregsAndArgsCount_ + 1 + THIS_FUNC_IDX] != nullptr);
121             ASSERT((*currentDefs_)[vregsAndArgsCount_ + 1 + CONST_POOL_IDX] != nullptr);
122             ASSERT((*currentDefs_)[vregsAndArgsCount_ + 1 + LEX_ENV_IDX] != nullptr);
123         }
124         currentBb_ = bb;
125         currentDefs_ = &defs_[bb->GetId()];
126     }
127 
GetCurrentBlock()128     BasicBlock *GetCurrentBlock() const
129     {
130         return currentBb_;
131     }
132 
133     void Prepare(bool isInlinedGraph);
134 
135     void FixInstructions();
136     void ResolveConstants();
137     void SplitConstant(ConstantInst *constInst);
138 
139     static void RemoveNotDominateInputs(SaveStateInst *saveState);
140 
141     size_t GetPc(const uint8_t *instPtr) const;
142 
CreateSafePoint(BasicBlock * bb)143     auto CreateSafePoint(BasicBlock *bb)
144     {
145         return CreateSaveState(Opcode::SafePoint, bb->GetGuestPc());
146     }
147 
CreateSaveStateOsr(BasicBlock * bb)148     auto CreateSaveStateOsr(BasicBlock *bb)
149     {
150         return CreateSaveState(Opcode::SaveStateOsr, bb->GetGuestPc());
151     }
152 
CreateSaveStateDeoptimize(uint32_t pc)153     auto CreateSaveStateDeoptimize(uint32_t pc)
154     {
155         return CreateSaveState(Opcode::SaveStateDeoptimize, pc);
156     }
157 
158     void UpdateDefs();
159     bool UpdateDefsForPreds(size_t vreg, std::optional<Inst *> &value);
160 
GetCurrentDefs()161     const auto &GetCurrentDefs()
162     {
163         ASSERT(currentDefs_ != nullptr);
164         return *currentDefs_;
165     }
166 
167     void AddCatchPhiInputs(const ArenaUnorderedSet<BasicBlock *> &catchHandlers, const InstVector &defs,
168                            Inst *throwableInst);
169 
170     SaveStateInst *CreateSaveState(Opcode opc, size_t pc);
171 
172     static void SetParamSpillFill(Graph *graph, ParameterInst *paramInst, size_t numArgs, size_t i,
173                                   DataType::Type type);
174 
175 private:
176     void SyncWithGraph();
177 
178     void UpdateDefsForCatch();
179     void UpdateDefsForLoopHead();
180 
GetVRegsCount()181     size_t GetVRegsCount() const
182     {
183         return vregsAndArgsCount_ + 1 + GetGraph()->GetEnvCount();
184     }
185 
186     template <typename T>
AddInstruction(T inst)187     void AddInstruction(T inst)
188     {
189         ASSERT(currentBb_);
190         currentBb_->AppendInst(inst);
191 
192 #ifdef PANDA_COMPILER_DEBUG_INFO
193         if (inst->GetPc() != INVALID_PC) {
194             inst->SetCurrentMethod(method_);
195         }
196 #endif
197         COMPILER_LOG(DEBUG, IR_BUILDER) << *inst;
198     }
199 
200     template <typename T, typename... Ts>
AddInstruction(T inst,Ts...insts)201     void AddInstruction(T inst, Ts... insts)
202     {
203         AddInstruction(inst);
204         AddInstruction(insts...);
205     }
206 
UpdateDefinition(size_t vreg,Inst * inst)207     void UpdateDefinition(size_t vreg, Inst *inst)
208     {
209         ASSERT(vreg < currentDefs_->size());
210         COMPILER_LOG(DEBUG, IR_BUILDER) << "update def for r" << vreg << " from "
211                                         << ((*currentDefs_)[vreg] != nullptr
212                                                 ? std::to_string((*currentDefs_)[vreg]->GetId())
213                                                 : "null")
214                                         << " to " << inst->GetId();
215         (*currentDefs_)[vreg] = inst;
216     }
217 
UpdateDefinitionAcc(Inst * inst)218     void UpdateDefinitionAcc(Inst *inst)
219     {
220         if (inst == nullptr) {
221             COMPILER_LOG(DEBUG, IR_BUILDER) << "reset accumulator definition";
222         } else {
223             COMPILER_LOG(DEBUG, IR_BUILDER) << "update accumulator from "
224                                             << ((*currentDefs_)[vregsAndArgsCount_] != nullptr
225                                                     ? std::to_string((*currentDefs_)[vregsAndArgsCount_]->GetId())
226                                                     : "null")
227                                             << " to " << inst->GetId();
228         }
229         (*currentDefs_)[vregsAndArgsCount_] = inst;
230     }
231 
UpdateDefinitionLexEnv(Inst * inst)232     void UpdateDefinitionLexEnv(Inst *inst)
233     {
234         ASSERT(inst != nullptr);
235         ASSERT((*currentDefs_)[vregsAndArgsCount_ + 1 + LEX_ENV_IDX] != nullptr);
236         COMPILER_LOG(DEBUG, IR_BUILDER) << "update lexical environment from "
237                                         << std::to_string(
238                                                (*currentDefs_)[vregsAndArgsCount_ + 1 + LEX_ENV_IDX]->GetId())
239                                         << " to " << inst->GetId();
240         (*currentDefs_)[vregsAndArgsCount_ + 1 + LEX_ENV_IDX] = inst;
241     }
242 
GetDefinition(size_t vreg)243     Inst *GetDefinition(size_t vreg)
244     {
245         ASSERT(vreg < currentDefs_->size());
246         ASSERT((*currentDefs_)[vreg] != nullptr);
247 
248         if (vreg >= currentDefs_->size() || (*currentDefs_)[vreg] == nullptr) {
249             failed_ = true;
250             COMPILER_LOG(ERROR, IR_BUILDER) << "GetDefinition failed for verg " << vreg;
251             return nullptr;
252         }
253         return (*currentDefs_)[vreg];
254     }
255 
GetDefinitionAcc()256     Inst *GetDefinitionAcc()
257     {
258         auto *accInst = (*currentDefs_)[vregsAndArgsCount_];
259         ASSERT(accInst != nullptr);
260 
261         if (accInst == nullptr) {
262             failed_ = true;
263             COMPILER_LOG(ERROR, IR_BUILDER) << "GetDefinitionAcc failed";
264         }
265         return accInst;
266     }
267 
GetEnvDefinition(uint8_t envIdx)268     Inst *GetEnvDefinition(uint8_t envIdx)
269     {
270         auto *inst = (*currentDefs_)[vregsAndArgsCount_ + 1 + envIdx];
271         ASSERT(inst != nullptr);
272 
273         if (inst == nullptr) {
274             failed_ = true;
275         }
276         return inst;
277     }
278 
FindOrCreate32BitConstant(uint32_t value)279     auto FindOrCreate32BitConstant(uint32_t value)
280     {
281         auto inst = GetGraph()->FindOrCreateConstant<uint32_t>(value);
282         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
283             COMPILER_LOG(DEBUG, IR_BUILDER) << "create new constant: value=" << value << ", inst=" << inst->GetId();
284         }
285         return inst;
286     }
287 
FindOrCreateConstant(uint64_t value)288     auto FindOrCreateConstant(uint64_t value)
289     {
290         auto inst = GetGraph()->FindOrCreateConstant<uint64_t>(value);
291         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
292             COMPILER_LOG(DEBUG, IR_BUILDER) << "create new constant: value=" << value << ", inst=" << inst->GetId();
293         }
294         return inst;
295     }
296 
FindOrCreateAnyConstant(DataType::Any value)297     auto FindOrCreateAnyConstant(DataType::Any value)
298     {
299         auto inst = GetGraph()->FindOrCreateConstant(value);
300         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
301             COMPILER_LOG(DEBUG, IR_BUILDER)
302                 << "create new constant: value=" << value.Raw() << ", inst=" << inst->GetId();
303         }
304         return inst;
305     }
306 
FindOrCreateDoubleConstant(double value)307     auto FindOrCreateDoubleConstant(double value)
308     {
309         auto inst = GetGraph()->FindOrCreateConstant<double>(value);
310         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
311             COMPILER_LOG(DEBUG, IR_BUILDER) << "create new constant: value=" << value << ", inst=" << inst->GetId();
312         }
313         return inst;
314     }
315 
FindOrCreateFloatConstant(float value)316     auto FindOrCreateFloatConstant(float value)
317     {
318         auto inst = GetGraph()->FindOrCreateConstant<float>(value);
319         if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) {
320             COMPILER_LOG(DEBUG, IR_BUILDER) << "create new constant: value=" << value << ", inst=" << inst->GetId();
321         }
322         return inst;
323     }
324 
325     enum SaveStateType {
326         CHECK = 0,  // side_exit = true,  move_to_side_exit = true
327         CALL,       // side_exit = false,  move_to_side_exit = false
328         VIRT_CALL   // side_exit = true,  move_to_side_exit = false
329     };
330 
331     ClassInst *CreateLoadAndInitClassGeneric(uint32_t classId, size_t pc);
332 
CreateCast(Inst * input,DataType::Type type,DataType::Type operandsType,size_t pc)333     Inst *CreateCast(Inst *input, DataType::Type type, DataType::Type operandsType, size_t pc)
334     {
335         auto cast = GetGraph()->CreateInstCast(type, pc, input, operandsType);
336         if (!input->HasType()) {
337             input->SetType(operandsType);
338         }
339         return cast;
340     }
341 
CreateNewObjectInst(size_t pc,uint32_t typeId,SaveStateInst * saveState,Inst * initClass)342     NewObjectInst *CreateNewObjectInst(size_t pc, uint32_t typeId, SaveStateInst *saveState, Inst *initClass)
343     {
344         auto newObj =
345             graph_->CreateInstNewObject(DataType::REFERENCE, pc, initClass, saveState, typeId, graph_->GetMethod());
346         return newObj;
347     }
348 
349     template <Opcode OPCODE>
350     void BuildCall(const BytecodeInstruction *bcInst, bool isRange, bool accRead, Inst *additionalInput = nullptr);
351     template <Opcode OPCODE>
352     CallInst *BuildCallInst(RuntimeInterface::MethodPtr method, uint32_t methodId, size_t pc, Inst **resolver,
353                             uint32_t classId);
354     template <Opcode OPCODE>
355     CallInst *BuildCallStaticInst(RuntimeInterface::MethodPtr method, uint32_t methodId, size_t pc, Inst **resolver,
356                                   [[maybe_unused]] uint32_t classId);
357     template <Opcode OPCODE>
358     CallInst *BuildCallVirtualInst(RuntimeInterface::MethodPtr method, uint32_t methodId, size_t pc, Inst **resolver);
359     void BuildInitClassInstForCallStatic(RuntimeInterface::MethodPtr method, uint32_t classId, size_t pc,
360                                          Inst *saveState);
361     template <typename T>
362     void SetCallArgs(const BytecodeInstruction *bcInst, bool isRange, bool accRead, Inst *resolver, T *call,
363                      Inst *nullCheck, SaveStateInst *saveState, bool hasImplicitArg, uint32_t methodId,
364                      Inst *additionalInput = nullptr);
365     Inst *GetArgDefinition(const BytecodeInstruction *bcInst, size_t idx, bool accRead, bool isRange = false);
366     Inst *GetArgDefinitionRange(const BytecodeInstruction *bcInst, size_t idx);
367     template <bool IS_VIRTUAL>
368     void AddArgNullcheckIfNeeded(RuntimeInterface::IntrinsicId intrinsic, Inst *inst, Inst *saveState, size_t bcAddr);
369     void BuildMonitor(const BytecodeInstruction *bcInst, Inst *def, bool isEnter);
370     Inst *BuildFloatInst(const BytecodeInstruction *bcInst);
371     void BuildIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead);
372     void BuildDefaultIntrinsic(bool isVirtual, const BytecodeInstruction *bcInst, bool isRange, bool accRead);
373     void BuildStaticCallIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead);
374     void BuildAbsIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
375     template <Opcode OPCODE>
376     void BuildBinaryOperationIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
377     void BuildSqrtIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
378     void BuildIsNanIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
379     void BuildStringLengthIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
380     void BuildStringIsEmptyIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
381     void BuildCharIsUpperCaseIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
382     void BuildCharToUpperCaseIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
383     void BuildCharIsLowerCaseIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
384     void BuildCharToLowerCaseIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
385     void BuildMonitorIntrinsic(const BytecodeInstruction *bcInst, bool isEnter, bool accRead);
386     void BuildDefaultStaticIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead);
387     void BuildDefaultVirtualCallIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead);
388     void BuildVirtualCallIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead);
389     void BuildThrow(const BytecodeInstruction *bcInst);
390     void BuildLenArray(const BytecodeInstruction *bcInst);
391     void BuildNewArray(const BytecodeInstruction *bcInst);
392     void BuildNewObject(const BytecodeInstruction *bcInst);
393     void BuildLoadConstArray(const BytecodeInstruction *bcInst);
394     void BuildLoadConstStringArray(const BytecodeInstruction *bcInst);
395     template <typename T>
396     void BuildUnfoldLoadConstArray(const BytecodeInstruction *bcInst, DataType::Type type,
397                                    const pandasm::LiteralArray &litArray);
398     template <typename T>
399     void BuildUnfoldLoadConstStringArray(const BytecodeInstruction *bcInst, DataType::Type type,
400                                          const pandasm::LiteralArray &litArray, NewArrayInst *arrayInst);
401     void BuildInitString(const BytecodeInstruction *bcInst);
402     void BuildInitObject(const BytecodeInstruction *bcInst, bool isRange);
403     CallInst *BuildCallStaticForInitObject(const BytecodeInstruction *bcInst, uint32_t methodId, Inst **resolver);
404     void BuildMultiDimensionalArrayObject(const BytecodeInstruction *bcInst, bool isRange);
405     void BuildInitObjectMultiDimensionalArray(const BytecodeInstruction *bcInst, bool isRange);
406     template <bool IS_ACC_WRITE>
407     void BuildLoadObject(const BytecodeInstruction *bcInst, DataType::Type type);
408     template <bool IS_ACC_READ>
409     void BuildStoreObject(const BytecodeInstruction *bcInst, DataType::Type type);
410     Inst *BuildStoreObjectInst(const BytecodeInstruction *bcInst, DataType::Type type, RuntimeInterface::FieldPtr field,
411                                size_t fieldId, Inst **resolveInst);
412     void BuildLoadStatic(const BytecodeInstruction *bcInst, DataType::Type type);
413     Inst *BuildLoadStaticInst(const BytecodeInstruction *bcInst, DataType::Type type, size_t typeId, Inst *saveState);
414     void BuildStoreStatic(const BytecodeInstruction *bcInst, DataType::Type type);
415     Inst *BuildStoreStaticInst(const BytecodeInstruction *bcInst, DataType::Type type, size_t typeId, Inst *storeInput,
416                                Inst *saveState);
417     void BuildCheckCast(const BytecodeInstruction *bcInst);
418     void BuildIsInstance(const BytecodeInstruction *bcInst);
419     Inst *BuildLoadClass(RuntimeInterface::IdType typeId, size_t pc, Inst *saveState);
420     void BuildLoadArray(const BytecodeInstruction *bcInst, DataType::Type type);
421     void BuildStoreArray(const BytecodeInstruction *bcInst, DataType::Type type);
422     template <bool CREATE_REF_CHECK>
423     void BuildStoreArrayInst(const BytecodeInstruction *bcInst, DataType::Type type, Inst *arrayRef, Inst *index,
424                              Inst *value);
425     void BuildChecksBeforeArray(size_t pc, Inst *arrayRef, Inst **ss, Inst **nc, Inst **al, Inst **bc,
426                                 bool withNullcheck = true);
427     template <Opcode OPCODE>
428     void BuildLoadFromPool(const BytecodeInstruction *bcInst);
429     void BuildCastToAnyString(const BytecodeInstruction *bcInst);
430     void BuildCastToAnyNumber(const BytecodeInstruction *bcInst);
431     Inst *BuildAnyTypeCheckInst(size_t bcAddr, Inst *input, Inst *saveState,
432                                 AnyBaseType type = AnyBaseType::UNDEFINED_TYPE, bool typeWasProfiled = false,
433                                 profiling::AnyInputType allowedInputType = {});
434     bool TryBuildStringCharAtIntrinsic(const BytecodeInstruction *bcInst, bool accRead);
435 #include "inst_builder_extensions.inl.h"
436 
GetGraph()437     Graph *GetGraph()
438     {
439         return graph_;
440     }
441 
GetGraph()442     const Graph *GetGraph() const
443     {
444         return graph_;
445     }
446 
GetRuntime()447     const RuntimeInterface *GetRuntime() const
448     {
449         return runtime_;
450     }
451 
GetRuntime()452     RuntimeInterface *GetRuntime()
453     {
454         return runtime_;
455     }
456 
GetMethod()457     auto GetMethod() const
458     {
459         return method_;
460     }
461 
GetClassId()462     auto GetClassId() const
463     {
464         return classId_;
465     }
466 
GetNoTypeMarker()467     Marker GetNoTypeMarker() const
468     {
469         return noTypeMarker_;
470     }
471 
GetVisitedBlockMarker()472     Marker GetVisitedBlockMarker() const
473     {
474         return visitedBlockMarker_;
475     }
476 
ForceUnresolved()477     bool ForceUnresolved() const
478     {
479 #ifndef NDEBUG
480         return g_options.IsCompilerForceUnresolved() && !graph_->IsBytecodeOptimizer();
481 #else
482         return false;
483 #endif
484     }
485 
486     void SetTypeRec(Inst *inst, DataType::Type type);
487 
488     /// Convert Panda bytecode type to COMPILER IR type
489     static DataType::Type ConvertPbcType(panda_file::Type type);
490 
491     /// Get return type of the method specified by id
492     DataType::Type GetMethodReturnType(uintptr_t id) const;
493     /// Get type of argument of the method specified by id
494     DataType::Type GetMethodArgumentType(uintptr_t id, size_t index) const;
495     /// Get count of arguments for the method specified by id
496     size_t GetMethodArgumentsCount(uintptr_t id) const;
497     /// Get return type of currently compiling method
498     DataType::Type GetCurrentMethodReturnType() const;
499     /// Get type of argument of currently compiling method
500     DataType::Type GetCurrentMethodArgumentType(size_t index) const;
501     /// Get count of arguments of currently compiling method
502     size_t GetCurrentMethodArgumentsCount() const;
503 
504 #ifndef PANDA_ETS_INTEROP_JS
TryBuildInteropCall(const BytecodeInstruction * bcInst,bool isRange,bool accRead)505     bool TryBuildInteropCall([[maybe_unused]] const BytecodeInstruction *bcInst, [[maybe_unused]] bool isRange,
506                              [[maybe_unused]] bool accRead)
507     {
508         return false;
509     }
510 #endif
511 
512 private:
513     static constexpr size_t ONE_FOR_OBJECT = 1;
514     static constexpr size_t ONE_FOR_SSTATE = 1;
515 
516     Graph *graph_ {nullptr};
517     RuntimeInterface *runtime_ {nullptr};
518     BasicBlock *currentBb_ {nullptr};
519 
520     RuntimeInterface::MethodProfile methodProfile_ {};
521 
522     // Definitions vector of currently processed basic block
523     InstVector *currentDefs_ {nullptr};
524     // Result of LoadFromConstantPool which will be added to SaveState inputs
525     Inst *additionalDef_ {nullptr};
526     // Contains definitions of the virtual registers in all basic blocks
527     ArenaVector<InstVector> defs_;
528 
529     RuntimeInterface::MethodPtr method_ {nullptr};
530     // Set to true if builder failed to build IR
531     bool failed_ {false};
532     // Number of virtual registers and method arguments
533     const size_t vregsAndArgsCount_;
534     // Marker for instructions with undefined type in the building phase
535     Marker noTypeMarker_;
536     Marker visitedBlockMarker_;
537 
538     // Pointer to start position of bytecode instructions buffer
539     const uint8_t *instructionsBuf_ {nullptr};
540 
541     CallInst *callerInst_ {nullptr};
542     uint32_t inliningDepth_ {0};
543     size_t classId_;
544 #include "intrinsics_ir_build.inl.h"
545 };
546 }  // namespace panda::compiler
547 
548 #endif  // PANDA_INST_BUILDER_H
549