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