1/* 2 * Copyright (c) 2021-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#include "ecmascript/compiler/codegen/maple/litecg_ir_builder.h" 17 18#include <cmath> 19#include <cstdint> 20 21#include "ecmascript/compiler/argument_accessor.h" 22#include "ecmascript/compiler/bc_call_signature.h" 23#include "ecmascript/compiler/baseline/baseline_call_signature.h" 24#include "ecmascript/compiler/circuit.h" 25#include "ecmascript/compiler/call_signature.h" 26#include "ecmascript/compiler/common_stub_csigns.h" 27#include "ecmascript/compiler/gate.h" 28#include "ecmascript/compiler/rt_call_signature.h" 29#include "ecmascript/deoptimizer/deoptimizer.h" 30#include "ecmascript/frames.h" 31#include "ecmascript/js_function.h" 32#include "ecmascript/js_thread.h" 33#include "ecmascript/method.h" 34#include "triple.h" 35#include "lmir_builder.h" 36 37namespace panda::ecmascript::kungfu { 38using FunctionBuilder = maple::litecg::LMIRBuilder::FunctionBuilder; 39using SwitchBuilder = maple::litecg::LMIRBuilder::SwitchBuilder; 40using Function = maple::litecg::Function; 41using LMIRBuilder = maple::litecg::LMIRBuilder; 42using BB = maple::litecg::BB; 43using Expr = maple::litecg::Expr; 44using Stmt = maple::litecg::Stmt; 45using Const = maple::litecg::Const; 46using LiteCGType = maple::litecg::Type; 47using IntCmpCondition = maple::litecg::IntCmpCondition; 48using FloatCmpCondition = maple::litecg::FloatCmpCondition; 49using Var = maple::litecg::Var; 50using PregIdx = maple::litecg::PregIdx; 51using IntrinsicId = maple::litecg::IntrinsicId; 52using maple::litecg::LiteCGValue; 53using maple::litecg::LiteCGValueKind; 54 55using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, Expr>; 56 57LiteCGIRBuilder::LiteCGIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit, 58 LMIRModule *module, const CompilationConfig *cfg, CallSignature::CallConv callConv, 59 bool enableLog, bool enableOptInlining, 60 const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, 61 const std::string &funcName) 62 : scheduledGates_(schedule), 63 circuit_(circuit), 64 lmirModule_(module), 65 compCfg_(cfg), 66 callConv_(callConv), 67 enableLog_(enableLog), 68 enableOptInlining_(enableOptInlining), 69 methodLiteral_(methodLiteral), 70 jsPandaFile_(jsPandaFile), 71 funcName_(funcName), 72 acc_(circuit), 73 cf_(*module->GetModule()) 74{ 75 lmirBuilder_ = new LMIRBuilder(*module->GetModule()); 76 maple::theMIRModule = module->GetModule(); 77 ASSERT(compCfg_->Is64Bit()); 78 slotSize_ = sizeof(uint64_t); 79 slotType_ = lmirBuilder_->i64Type; 80 InitializeHandlers(); 81 if (cfg != nullptr) { 82 maple::Triple::GetTriple().Init(cfg->IsAArch64()); 83 } 84} 85 86LiteCGIRBuilder::~LiteCGIRBuilder() 87{ 88 delete lmirBuilder_; 89} 90 91void LiteCGIRBuilder::BuildInstID2BBIDMap() 92{ 93 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) { 94 const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx); 95 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) { 96 GateId gateId = acc_.GetId(bb[instIdx - 1]); 97 instID2bbID_[gateId] = static_cast<int>(bbIdx); 98 } 99 } 100} 101 102BB &LiteCGIRBuilder::GetOrCreateBB(int bbID) 103{ 104 auto itr = bbID2BB_.find(bbID); 105 if (itr != bbID2BB_.end()) { 106 return *(itr->second); 107 } 108 BB &bb = lmirBuilder_->CreateBB(); 109 bbID2BB_[bbID] = &bb; 110 return bb; 111} 112 113BB &LiteCGIRBuilder::GetFirstBB() 114{ 115 // Obtain the first BB (i.e. the BB with id zero) for inserting prologue information 116 return GetOrCreateBB(0); 117} 118 119BB &LiteCGIRBuilder::CreateBB() 120{ 121 BB &bb = lmirBuilder_->CreateBB(false); 122 return bb; 123} 124 125LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromGate(GateRef gate, bool isSigned) const 126{ 127 if (acc_.IsGCRelated(gate)) { 128 return lmirBuilder_->i64RefType; 129 } 130 131 MachineType t = acc_.GetMachineType(gate); 132 switch (t) { 133 case MachineType::NOVALUE: 134 return lmirBuilder_->voidType; 135 case MachineType::I1: 136 return lmirBuilder_->u1Type; 137 case MachineType::I8: 138 return isSigned ? lmirBuilder_->i8Type : lmirBuilder_->u8Type; 139 case MachineType::I16: 140 return isSigned ? lmirBuilder_->i16Type : lmirBuilder_->u16Type; 141 case MachineType::I32: 142 return isSigned ? lmirBuilder_->i32Type : lmirBuilder_->u32Type; 143 case MachineType::I64: 144 return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type; 145 case MachineType::F32: 146 return lmirBuilder_->f32Type; 147 case MachineType::F64: 148 return lmirBuilder_->f64Type; 149 case MachineType::ARCH: 150 return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type; 151 default: 152 LOG_ECMA(FATAL) << "this branch is unreachable"; 153 UNREACHABLE(); 154 } 155} 156 157void LiteCGIRBuilder::AddFunc() 158{ 159 // setup function type 160 std::string funcName = lmirModule_->GetFuncName(methodLiteral_, jsPandaFile_); 161 FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName); 162 funcBuilder.Param(lmirBuilder_->i64Type, "glue"); 163 if (circuit_->IsOsr()) { 164 funcBuilder.Param(lmirBuilder_->i64PtrType, "interpSp"); 165 } else if (!methodLiteral_->IsFastCall()) { 166 funcBuilder.Param(lmirBuilder_->i64Type, "actualArgc") 167 .Param(lmirBuilder_->i64PtrType, "actualArgv") 168 .Param(lmirBuilder_->i64RefType, "func") 169 .Param(lmirBuilder_->i64RefType, "new_target") 170 .Param(lmirBuilder_->i64RefType, "this_object"); 171 for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) { 172 funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i)); 173 } 174 } else { 175 funcBuilder.Param(lmirBuilder_->i64RefType, "func").Param(lmirBuilder_->i64RefType, "this_object"); 176 for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) { 177 funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i)); 178 } 179 } 180 181 funcBuilder.CallConvAttribute(ConvertCallAttr(callConv_)); 182 Function &function = funcBuilder.Return(lmirBuilder_->i64RefType).Done(); 183 lmirBuilder_->SetCurFunc(function); 184 lmirBuilder_->RenameFormal2Preg(function); 185 GenPrologue(function); 186 auto offsetInPandaFile = methodLiteral_->GetMethodId().GetOffset(); 187 lmirModule_->SetFunction(offsetInPandaFile, funcName, methodLiteral_->IsFastCall()); 188} 189 190// deal with derived reference 191void LiteCGIRBuilder::CollectDerivedRefInfo() 192{ 193 auto GetPregFromGate = [&](GateRef gate)->PregIdx { 194 LiteCGValue value = gate2Expr_[gate]; 195 ASSERT(value.kind == LiteCGValueKind::kPregKind); 196 return std::get<PregIdx>(value.data); 197 }; 198 199 // collect base references for derived phi reference 200 for (auto &pair : bbID2basePhis_) { 201 for (auto &desc : pair.second) { 202 Expr expr = GetExprFromGate(desc.operand); 203 if (derivedPhiGate2BasePhiPreg_.find(desc.operand) != derivedPhiGate2BasePhiPreg_.end()) { 204 expr = lmirBuilder_->Regread(derivedPhiGate2BasePhiPreg_[desc.operand]); 205 } 206 Stmt &tmpPhiAssign = lmirBuilder_->Regassign(expr, desc.phi); 207 lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(desc.predBBId), tmpPhiAssign); 208 } 209 } 210 211 std::set<PregIdx> baseRefSet; 212 // set common derived reference 213 for (auto it : derivedGate2BaseGate_) { 214 if (GetExprFromGate(it.second).IsConstValue() || GetExprFromGate(it.first).IsConstValue()) { 215 continue; 216 } 217 ASSERT(!GetExprFromGate(it.second).IsDread()); 218 PregIdx derivedIdx = GetPregFromGate(it.first); 219 PregIdx baseIdx = GetPregFromGate(it.second); 220 baseRefSet.insert(baseIdx); 221 lmirBuilder_->SetFunctionDerived2BaseRef(derivedIdx, baseIdx); 222 } 223 224 // set phi derived reference 225 for (auto it : derivedPhiGate2BasePhiPreg_) { 226 PregIdx derivedIdx = GetPregFromGate(it.first); 227 PregIdx baseIdx = it.second; 228 if (baseRefSet.find(derivedIdx) != baseRefSet.end()) { 229 LOG_COMPILER(FATAL) << "shouldn't occur nested derived reference" << std::endl; 230 UNREACHABLE(); 231 } 232 lmirBuilder_->SetFunctionDerived2BaseRef(derivedIdx, baseIdx); 233 } 234 235 bbID2basePhis_.clear(); 236 derivedPhiGate2BasePhiPreg_.clear(); 237 derivedGate2BaseGate_.clear(); 238 derivedGateCache_.clear(); 239} 240 241void LiteCGIRBuilder::HandleBB(const std::vector<GateRef> &bb, std::unordered_set<OpCode> &usedOpcodeSet) 242{ 243 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) { 244 GateRef gate = bb[instIdx - 1]; 245 OpCode opcode = acc_.GetOpCode(gate); 246 if (IsLogEnabled()) { 247 lmirBuilder_->SetCurrentDebugComment(acc_.ToString(gate)); 248 } 249 switch (opcode) { 250 case OpCode::STATE_ENTRY: 251 HandleGoto(gate); 252 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::STATE_ENTRY); 253 break; 254 case OpCode::RETURN: 255 HandleReturn(gate); 256 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RETURN); 257 break; 258 case OpCode::RETURN_VOID: 259 HandleReturnVoid(gate); 260 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RETURN_VOID); 261 break; 262 case OpCode::IF_BRANCH: 263 HandleBranch(gate); 264 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_BRANCH); 265 break; 266 case OpCode::ORDINARY_BLOCK: 267 HandleGoto(gate); 268 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ORDINARY_BLOCK); 269 break; 270 case OpCode::IF_TRUE: 271 HandleGoto(gate); 272 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_TRUE); 273 break; 274 case OpCode::IF_FALSE: 275 HandleGoto(gate); 276 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_FALSE); 277 break; 278 case OpCode::SWITCH_BRANCH: 279 HandleSwitch(gate); 280 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SWITCH_BRANCH); 281 break; 282 case OpCode::SWITCH_CASE: 283 HandleGoto(gate); 284 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SWITCH_CASE); 285 break; 286 case OpCode::MERGE: 287 HandleGoto(gate); 288 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MERGE); 289 break; 290 case OpCode::DEFAULT_CASE: 291 HandleGoto(gate); 292 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DEFAULT_CASE); 293 break; 294 case OpCode::LOOP_BEGIN: 295 HandleGoto(gate); 296 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOOP_BACK); 297 break; 298 case OpCode::LOOP_BACK: 299 HandleGoto(gate); 300 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOOP_BEGIN); 301 break; 302 case OpCode::VALUE_SELECTOR: 303 HandlePhi(gate); 304 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::VALUE_SELECTOR); 305 break; 306 case OpCode::RUNTIME_CALL: 307 HandleRuntimeCall(gate); 308 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RUNTIME_CALL); 309 break; 310 case OpCode::RUNTIME_CALL_WITH_ARGV: 311 HandleRuntimeCallWithArgv(gate); 312 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RUNTIME_CALL_WITH_ARGV); 313 break; 314 case OpCode::NOGC_RUNTIME_CALL: 315 HandleCall(gate); 316 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::NOGC_RUNTIME_CALL); 317 break; 318 case OpCode::CALL_OPTIMIZED: 319 HandleCall(gate); 320 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CALL_OPTIMIZED); 321 break; 322 case OpCode::FAST_CALL_OPTIMIZED: 323 HandleCall(gate); 324 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FAST_CALL_OPTIMIZED); 325 break; 326 case OpCode::CALL: 327 HandleCall(gate); 328 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CALL); 329 break; 330 case OpCode::BASELINE_CALL: 331 HandleCall(gate); 332 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BASELINE_CALL); 333 break; 334 case OpCode::BUILTINS_CALL: 335 HandleCall(gate); 336 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BUILTINS_CALL); 337 break; 338 case OpCode::BUILTINS_CALL_WITH_ARGV: 339 HandleCall(gate); 340 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BUILTINS_CALL_WITH_ARGV); 341 break; 342 case OpCode::ARG: 343 HandleParameter(gate); 344 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ARG); 345 break; 346 case OpCode::CONSTANT: 347 HandleConstant(gate); 348 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CONSTANT); 349 break; 350 case OpCode::ZEXT: 351 HandleZExtInt(gate); 352 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ZEXT); 353 break; 354 case OpCode::SEXT: 355 HandleSExtInt(gate); 356 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SEXT); 357 break; 358 case OpCode::TRUNC: 359 HandleCastIntXToIntY(gate); 360 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC); 361 break; 362 case OpCode::FEXT: 363 HandleFPExt(gate); 364 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FEXT); 365 break; 366 case OpCode::FTRUNC: 367 HandleFPTrunc(gate); 368 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FTRUNC); 369 break; 370 case OpCode::REV: 371 HandleIntRev(gate); 372 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::REV); 373 break; 374 case OpCode::ADD: 375 HandleAdd(gate); 376 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ADD); 377 break; 378 case OpCode::SUB: 379 HandleSub(gate); 380 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SUB); 381 break; 382 case OpCode::MUL: 383 HandleMul(gate); 384 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MUL); 385 break; 386 case OpCode::FDIV: 387 HandleFloatDiv(gate); 388 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FDIV); 389 break; 390 case OpCode::SDIV: 391 HandleIntDiv(gate); 392 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SDIV); 393 break; 394 case OpCode::UDIV: 395 HandleUDiv(gate); 396 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::UDIV); 397 break; 398 case OpCode::AND: 399 HandleIntAnd(gate); 400 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::AND); 401 break; 402 case OpCode::OR: 403 HandleIntOr(gate); 404 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::OR); 405 break; 406 case OpCode::XOR: 407 HandleIntXor(gate); 408 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::XOR); 409 break; 410 case OpCode::LSR: 411 HandleIntLsr(gate); 412 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LSR); 413 break; 414 case OpCode::ASR: 415 HandleIntAsr(gate); 416 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ASR); 417 break; 418 case OpCode::ICMP: 419 HandleCmp(gate); 420 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ICMP); 421 break; 422 case OpCode::FCMP: 423 HandleCmp(gate); 424 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FCMP); 425 break; 426 case OpCode::LOAD: 427 HandleLoad(gate); 428 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOAD); 429 break; 430 case OpCode::STORE_WITHOUT_BARRIER: 431 HandleStore(gate); 432 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::STORE_WITHOUT_BARRIER); 433 break; 434 case OpCode::SIGNED_INT_TO_FLOAT: 435 HandleChangeInt32ToDouble(gate); 436 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SIGNED_INT_TO_FLOAT); 437 break; 438 case OpCode::UNSIGNED_INT_TO_FLOAT: 439 HandleChangeUInt32ToDouble(gate); 440 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::UNSIGNED_INT_TO_FLOAT); 441 break; 442 case OpCode::FLOAT_TO_SIGNED_INT: 443 HandleChangeDoubleToInt32(gate); 444 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FLOAT_TO_SIGNED_INT); 445 break; 446 case OpCode::TAGGED_TO_INT64: 447 HandleChangeTaggedPointerToInt64(gate); 448 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TAGGED_TO_INT64); 449 break; 450 case OpCode::INT64_TO_TAGGED: 451 HandleChangeInt64ToTagged(gate); 452 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::INT64_TO_TAGGED); 453 break; 454 case OpCode::BITCAST: 455 HandleBitCast(gate); 456 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BITCAST); 457 break; 458 case OpCode::LSL: 459 HandleIntLsl(gate); 460 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LSL); 461 break; 462 case OpCode::SMOD: 463 HandleMod(gate); 464 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SMOD); 465 break; 466 case OpCode::FMOD: 467 HandleMod(gate); 468 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FMOD); 469 break; 470 case OpCode::DEOPT_CHECK: 471 HandleDeoptCheck(gate); 472 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DEOPT_CHECK); 473 break; 474 case OpCode::TRUNC_FLOAT_TO_INT64: 475 HandleTruncFloatToInt(gate); 476 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC_FLOAT_TO_INT64); 477 break; 478 case OpCode::TRUNC_FLOAT_TO_INT32: 479 HandleTruncFloatToInt(gate); 480 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC_FLOAT_TO_INT32); 481 break; 482 case OpCode::ADD_WITH_OVERFLOW: 483 HandleAddWithOverflow(gate); 484 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ADD_WITH_OVERFLOW); 485 break; 486 case OpCode::SUB_WITH_OVERFLOW: 487 HandleSubWithOverflow(gate); 488 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SUB_WITH_OVERFLOW); 489 break; 490 case OpCode::MUL_WITH_OVERFLOW: 491 HandleMulWithOverflow(gate); 492 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MUL_WITH_OVERFLOW); 493 break; 494 case OpCode::EXP: 495 HandleExp(gate); 496 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::EXP); 497 break; 498 case OpCode::ABS: 499 HandleAbs(gate); 500 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ABS); 501 break; 502 case OpCode::MIN: 503 HandleMin(gate); 504 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MIN); 505 break; 506 case OpCode::MAX: 507 HandleMax(gate); 508 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MAX); 509 break; 510 case OpCode::CLZ32: 511 HandleClz32(gate); 512 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CLZ32); 513 break; 514 case OpCode::DOUBLE_TRUNC: 515 HandleDoubleTrunc(gate); 516 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DOUBLE_TRUNC); 517 break; 518 case OpCode::CEIL: 519 HandleCeil(gate); 520 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CEIL); 521 break; 522 case OpCode::FLOOR: 523 HandleFloor(gate); 524 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FLOOR); 525 break; 526 case OpCode::EXTRACT_VALUE: 527 HandleExtractValue(gate); 528 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::EXTRACT_VALUE); 529 break; 530 case OpCode::SQRT: 531 HandleSqrt(gate); 532 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SQRT); 533 break; 534 case OpCode::READSP: 535 HandleReadSp(gate); 536 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::READSP); 537 break; 538 case OpCode::FINISH_ALLOCATE: 539 HandleFinishAllocate(gate); 540 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FINISH_ALLOCATE); 541 break; 542 case OpCode::INITVREG: 543 HandleInitVreg(gate); 544 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::INITVREG); 545 break; 546 default: 547 if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) { 548 LOG_COMPILER(FATAL) << "can't process opcode: " << acc_.GetOpCode(gate) << std::endl; 549 } 550 } 551 if (IsLogEnabled()) { 552 lmirBuilder_->ClearCurrentDebugComment(); 553 } 554 } 555} 556void LiteCGIRBuilder::Build() 557{ 558 BuildInstID2BBIDMap(); 559 AddFunc(); 560 LOG_COMPILER(INFO) << "============== building litecg ir=======" << std::endl; 561 562 std::unordered_set<OpCode> usedOpcodeSet; 563 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) { 564 const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx); 565 HandleBB(bb, usedOpcodeSet); 566 } 567 568 if (enableLog_) { 569 for (auto &opcode : usedOpcodeSet) { 570 LOG_COMPILER(INFO) << "OPCODE: " << opcode << std::endl; 571 } 572 } 573 574 CollectDerivedRefInfo(); 575 576 std::map<int, std::vector<std::pair<PregIdx, PregIdx>>> bbID2phiAssign; 577 for (auto &pair : bbID2unmergedPhis_) { 578 for (auto &desc : pair.second) { 579 Expr value = GetExprFromGate(desc.operand); 580 PregIdx tmpPhiPregIdx = lmirBuilder_->CreatePreg(value.GetType()); 581 Stmt &tmpPhiAssign = lmirBuilder_->Regassign(value, tmpPhiPregIdx); 582 lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(desc.predBBId), tmpPhiAssign); 583 bbID2phiAssign[desc.predBBId].emplace_back(std::make_pair(tmpPhiPregIdx, desc.phi)); 584 } 585 } 586 587 for (auto &pair: bbID2phiAssign) { 588 for (auto &expr: pair.second) { 589 auto &stmt = lmirBuilder_->Regassign(lmirBuilder_->Regread(expr.first), expr.second); 590 lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(pair.first), stmt); 591 } 592 } 593 bbID2unmergedPhis_.clear(); 594 bbID2phiAssign.clear(); 595 596 lmirBuilder_->AppendBB(lmirBuilder_->GetLastPosBB()); 597} 598 599void LiteCGIRBuilder::AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType, 600 maple::litecg::Function &function) 601{ 602 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); 603 if (circuit_->IsOsr()) { 604 auto osrFrameType = methodLiteral_->IsFastCall() ? FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME : frameType; 605 SaveFrameTypeOnFrame(function, osrFrameType); 606 return; 607 } 608 auto ArgList = circuit_->GetArgRoot(); 609 auto uses = acc_.Uses(ArgList); 610 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { 611 int argth = static_cast<int>(acc_.TryGetValue(*useIt)); 612 Var &value = lmirBuilder_->GetParam(function, argth); 613 int funcIndex = 0; 614 if (methodLiteral_->IsFastCall()) { 615 frameType = FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 616 funcIndex = static_cast<int>(FastCallArgIdx::FUNC); 617 } else { 618 funcIndex = static_cast<int>(CommonArgIdx::FUNC); 619 } 620 if (argth == funcIndex) { 621 SaveByteCodePcOnOptJSFuncFrame(value); 622 SaveJSFuncOnOptJSFuncFrame(function, value, funcIndex); 623 SaveFrameTypeOnFrame(function, frameType); 624 } 625 } 626} 627 628void LiteCGIRBuilder::GenPrologue(maple::litecg::Function &function) 629{ 630 auto frameType = circuit_->GetFrameType(); 631 if (IsInterpreted() || IsBaselineBuiltin()) { 632 return; 633 } 634 lmirBuilder_->SetFuncFramePointer("all"); 635 size_t reservedSlotsSize = 0; 636 if (frameType == FrameType::OPTIMIZED_FRAME) { 637 reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); 638 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); 639 SaveFrameTypeOnFrame(function, frameType); 640 } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { 641 reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 642 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); 643 if (circuit_->IsOsr()) { 644 auto osrFrameType = methodLiteral_->IsFastCall() ? FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME 645 : frameType; 646 SaveFrameTypeOnFrame(function, osrFrameType); 647 return; 648 } 649 auto ArgList = circuit_->GetArgRoot(); 650 auto uses = acc_.Uses(ArgList); 651 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { 652 int argth = static_cast<int>(acc_.TryGetValue(*useIt)); 653 Var &value = lmirBuilder_->GetParam(function, argth); 654 int funcIndex = 0; 655 if (methodLiteral_->IsFastCall()) { 656 frameType = FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 657 funcIndex = static_cast<int>(FastCallArgIdx::FUNC); 658 } else { 659 funcIndex = static_cast<int>(CommonArgIdx::FUNC); 660 } 661 if (argth == funcIndex) { 662 SaveJSFuncOnOptJSFuncFrame(function, value, funcIndex); 663 SaveFrameTypeOnFrame(function, frameType); 664 } 665 } 666 } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) { 667 reservedSlotsSize = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_); 668 AssistGenPrologue(reservedSlotsSize, frameType, function); 669 } else { 670 LOG_COMPILER(FATAL) << "frameType interpret type error !"; 671 ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !"); 672 } 673} 674 675void LiteCGIRBuilder::SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value) 676{ 677 ASSERT(circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME); 678 // load method 679 Expr func = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value)); 680 Expr offsetMethod = lmirBuilder_->ConstVal( 681 lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, JSFunctionBase::METHOD_OFFSET)); 682 Expr addrMethod = lmirBuilder_->Add(lmirBuilder_->i64PtrType, func, offsetMethod); 683 Expr method = lmirBuilder_->Iread( 684 lmirBuilder_->i64PtrType, addrMethod, lmirBuilder_->CreatePtrType(lmirBuilder_->i64PtrType)); 685 // load byteCodePc 686 Expr offsetByteCodePc = lmirBuilder_->ConstVal( 687 lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET)); 688 Expr addrByteCodePc = lmirBuilder_->Add(lmirBuilder_->i64PtrType, method, offsetByteCodePc); 689 Expr byteCodePc = lmirBuilder_->Iread( 690 lmirBuilder_->i64PtrType, addrByteCodePc, lmirBuilder_->CreatePtrType(lmirBuilder_->i64PtrType)); 691 // push byteCodePc 692 Expr fpAddr = CallingFp(false); 693 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); 694 size_t reservedOffset = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_); 695 Expr frameByteCodePcSlotAddr = 696 lmirBuilder_->Sub(frameAddr.GetType(), frameAddr, 697 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset))); 698 Expr byteCodePcAddr = 699 lmirBuilder_->Cvt(frameByteCodePcSlotAddr.GetType(), 700 lmirBuilder_->CreatePtrType(slotType_), frameByteCodePcSlotAddr); 701 auto &stmt = lmirBuilder_->Iassign(byteCodePc, byteCodePcAddr, byteCodePcAddr.GetType()); 702 lmirBuilder_->AppendStmt(GetFirstBB(), stmt); 703} 704 705void LiteCGIRBuilder::SaveJSFuncOnOptJSFuncFrame(maple::litecg::Function &function, maple::litecg::Var &value, 706 int funcIndex) 707{ 708 ASSERT(IsOptimizedJSFunction()); 709 if (compCfg_->IsAArch64()) { 710 auto frameType = circuit_->GetFrameType(); 711 if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { 712 function.SetFuncInfo(OptimizedJSFunctionFrame::GetFunctionToFpDelta(), true, funcIndex); 713 } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) { 714 function.SetFuncInfo(FASTJITFunctionFrame::GetFunctionToFpDelta(), true, funcIndex); 715 } 716 } else { 717 Expr fpAddr = CallingFp(false); 718 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); 719 size_t reservedOffset = 0; 720 if (circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { 721 reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 722 } else { 723 reservedOffset = FASTJITFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 724 } 725 726 Expr frameJSFuncSlotAddr = 727 lmirBuilder_->Sub(frameAddr.GetType(), frameAddr, 728 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset))); 729 Expr jsFuncAddr = 730 lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), 731 lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr); 732 Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value)); 733 auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType()); 734 lmirBuilder_->AppendStmt(GetFirstBB(), stmt); 735 } 736} 737 738void LiteCGIRBuilder::SaveFrameTypeOnFrame(maple::litecg::Function &function, FrameType frameType) 739{ 740 if (compCfg_->IsAArch64()) { 741 function.SetFrameTypeInfo(-slotSize_, true, static_cast<int>(frameType)); 742 return; 743 } 744 Expr fpAddr = CallingFp(false); 745 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); 746 Expr frameJSFuncSlotAddr = lmirBuilder_->Sub( 747 frameAddr.GetType(), frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_))); 748 Expr jsFuncAddr = 749 lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr); 750 Expr liteFramType = 751 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<uintptr_t>(frameType))); 752 auto &stmt = lmirBuilder_->Iassign(liteFramType, jsFuncAddr, jsFuncAddr.GetType()); 753 lmirBuilder_->AppendStmt(GetFirstBB(), stmt); 754} 755 756Expr LiteCGIRBuilder::GetGlue(const std::vector<GateRef> &inList) 757{ 758 GateRef glueGate = inList[static_cast<size_t>(CallInputs::GLUE)]; 759 auto itr = gate2Expr_.find(glueGate); 760 if (itr != gate2Expr_.end()) { 761 return GetExprFromGate(glueGate); 762 } 763 Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetLocalVar("glue")); 764 SaveGate2Expr(glueGate, glue); 765 return glue; 766} 767 768void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, Expr expr, bool isGlueAdd) 769{ 770 if (isGlueAdd) { 771 gate2Expr_[gate] = {LiteCGValueKind::kGlueAdd, lmirBuilder_->GetConstFromExpr(expr)}; 772 return; 773 } else if (expr.IsDread()) { 774 gate2Expr_[gate] = {LiteCGValueKind::kSymbolKind, lmirBuilder_->GetLocalVarFromExpr(expr)}; 775 return; 776 } else if (expr.IsRegread()) { 777 gate2Expr_[gate] = {LiteCGValueKind::kPregKind, lmirBuilder_->GetPregIdxFromExpr(expr)}; 778 return; 779 } else if (expr.IsConstValue()) { 780 gate2Expr_[gate] = {LiteCGValueKind::kConstKind, lmirBuilder_->GetConstFromExpr(expr)}; 781 return; 782 } 783 auto *newNode = cf_.Fold(expr.GetNode()); 784 if (newNode == nullptr || !newNode->IsConstval()) { 785 // check expr is not agg 786 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 787 PregIdx pregIdx = lmirBuilder_->CreatePreg(expr.GetType()); 788 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Regassign(expr, pregIdx)); 789 gate2Expr_[gate] = {LiteCGValueKind::kPregKind, pregIdx}; 790 return; 791 } 792 gate2Expr_[gate] = {LiteCGValueKind::kConstKind, static_cast<maple::ConstvalNode*>(newNode)->GetConstVal()}; 793} 794 795void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, PregIdx pregIdx1, PregIdx pregIdx2) 796{ 797 gate2Expr_[gate] = {LiteCGValueKind::kPregPairKind, std::make_pair(pregIdx1, pregIdx2)}; 798} 799 800Expr LiteCGIRBuilder::GetConstant(GateRef gate) 801{ 802 std::bitset<64> value = acc_.GetConstantValue(gate); // 64 for bit width 803 auto machineType = acc_.GetMachineType(gate); 804 if (machineType == MachineType::ARCH) { 805 ASSERT(compCfg_->Is64Bit()); 806 machineType = MachineType::I64; 807 } 808 809 Const *constVal = nullptr; 810 if (machineType == MachineType::I32) { 811 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, static_cast<int64_t>(value.to_ulong()))); 812 } else if (machineType == MachineType::I64) { 813 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<int64_t>(value.to_ulong()))); 814 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 815 if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) { 816 Expr constExpr = lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, lmirBuilder_->ConstVal(*constVal)); 817 return constExpr; 818 } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) { 819 // do nothing 820 } else { 821 LOG_ECMA(FATAL) << "this branch is unreachable"; 822 UNREACHABLE(); 823 } 824 } else if (machineType == MachineType::F64) { 825 auto doubleValue = base::bit_cast<double>(value.to_ullong()); // actual double value 826 constVal = &(lmirBuilder_->CreateDoubleConst(static_cast<double>(doubleValue))); 827 } else if (machineType == MachineType::I8) { 828 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u8Type, static_cast<int64_t>(value.to_ulong()))); 829 } else if (machineType == MachineType::I16) { 830 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u16Type, static_cast<int64_t>(value.to_ulong()))); 831 } else if (machineType == MachineType::I1) { 832 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u1Type, static_cast<int64_t>(value.to_ulong()))); 833 } else { 834 LOG_ECMA(FATAL) << "this branch is unreachable"; 835 UNREACHABLE(); 836 } 837 return lmirBuilder_->ConstVal(*constVal); 838} 839 840Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate) 841{ 842 if (acc_.GetOpCode(gate) == OpCode::CONSTANT) { 843 return GetConstant(gate); 844 } 845 LiteCGValue value = gate2Expr_[gate]; 846 if (value.kind == LiteCGValueKind::kSymbolKind) { 847 return lmirBuilder_->Dread(*std::get<maple::MIRSymbol*>(value.data)); 848 } else if (value.kind == LiteCGValueKind::kConstKind) { 849 return lmirBuilder_->ConstVal(*std::get<maple::MIRConst*>(value.data)); 850 } else if (value.kind == LiteCGValueKind::kGlueAdd) { 851 auto glue = acc_.GetGlueFromArgList(); 852 return lmirBuilder_->Add(ConvertLiteCGTypeFromGate(glue), GetExprFromGate(glue), 853 lmirBuilder_->ConstVal(*std::get<maple::MIRConst*>(value.data))); 854 } 855 ASSERT(value.kind == LiteCGValueKind::kPregKind); 856 return lmirBuilder_->Regread(std::get<PregIdx>(value.data)); 857} 858 859Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate, uint32_t index) 860{ 861 LiteCGValue value = gate2Expr_[gate]; 862 ASSERT(value.kind == LiteCGValueKind::kPregPairKind); 863 ASSERT(index == 0 || index == 1); 864 std::pair<PregIdx, PregIdx> pair = std::get<std::pair<PregIdx, PregIdx>>(value.data); 865 if (index == 0) { 866 return lmirBuilder_->Regread(pair.first); 867 } 868 return lmirBuilder_->Regread(pair.second); 869} 870 871void LiteCGIRBuilder::InitializeHandlers() 872{ 873 illegalOpHandlers_ = {OpCode::NOP, 874 OpCode::CIRCUIT_ROOT, 875 OpCode::DEPEND_ENTRY, 876 OpCode::DEAD, 877 OpCode::RETURN_LIST, 878 OpCode::ARG_LIST, 879 OpCode::THROW, 880 OpCode::DEPEND_SELECTOR, 881 OpCode::DEPEND_RELAY, 882 OpCode::FRAME_STATE, 883 OpCode::STATE_SPLIT, 884 OpCode::FRAME_ARGS, 885 OpCode::LOOP_EXIT_DEPEND, 886 OpCode::LOOP_EXIT, 887 OpCode::START_ALLOCATE, 888 OpCode::FINISH_ALLOCATE, 889 OpCode::FRAME_VALUES, 890 OpCode::ASM_CALL_BARRIER}; 891} 892 893void LiteCGIRBuilder::HandleReturnVoid([[maybe_unused]] GateRef gate) 894{ 895 return; 896} 897 898void LiteCGIRBuilder::HandleGoto(GateRef gate) 899{ 900 std::vector<GateRef> outs; 901 acc_.GetOutStates(gate, outs); 902 int block = instID2bbID_[acc_.GetId(gate)]; 903 int bbOut = instID2bbID_[acc_.GetId(outs[0])]; 904 switch (acc_.GetOpCode(gate)) { 905 case OpCode::MERGE: 906 case OpCode::LOOP_BEGIN: { 907 for (const auto &out : outs) { 908 bbOut = instID2bbID_[acc_.GetId(out)]; 909 VisitGoto(block, bbOut); 910 } 911 break; 912 } 913 default: { 914 VisitGoto(block, bbOut); 915 break; 916 } 917 } 918} 919 920void LiteCGIRBuilder::VisitGoto(int block, int bbOut) 921{ 922 if (block == bbOut) { 923 return; 924 } 925 BB &srcBB = GetOrCreateBB(block); 926 BB &destBB = GetOrCreateBB(bbOut); 927 928 lmirBuilder_->AppendStmt(srcBB, lmirBuilder_->Goto(destBB)); 929 lmirBuilder_->AppendBB(srcBB); 930} 931 932void LiteCGIRBuilder::HandleParameter(GateRef gate) 933{ 934 return VisitParameter(gate); 935} 936 937void LiteCGIRBuilder::VisitParameter(GateRef gate) 938{ 939 std::vector<GateRef> outs; 940 acc_.GetOuts(gate, outs); 941 if (outs.empty()) { 942 return; 943 } 944 size_t argth = static_cast<size_t>(acc_.TryGetValue(gate)); 945 Var ¶m = lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), argth); 946 SaveGate2Expr(gate, lmirBuilder_->GenExprFromVar(param)); 947} 948 949void LiteCGIRBuilder::HandleConstant(GateRef gate) 950{ 951 // no need to deal with constant separately 952 (void)gate; 953 return; 954} 955 956void LiteCGIRBuilder::HandleAdd(GateRef gate) 957{ 958 auto g0 = acc_.GetIn(gate, 0); 959 auto g1 = acc_.GetIn(gate, 1); 960 VisitAdd(gate, g0, g1); 961} 962 963Expr LiteCGIRBuilder::CanonicalizeToPtr(Expr expr, LiteCGType *type) 964{ 965 if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypePointer) { 966 if (expr.GetType() == type) { 967 return expr; 968 } 969 return lmirBuilder_->Cvt(expr.GetType(), type, expr); 970 } else if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypeScalar) { 971 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, expr); 972 } else { 973 LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: "; 974 UNREACHABLE(); 975 } 976 return expr; 977} 978 979void LiteCGIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2) 980{ 981 Expr e1Value = GetExprFromGate(e1); 982 Expr e2Value = GetExprFromGate(e2); 983 // save glue + offset 984 if (e1 == acc_.GetGlueFromArgList() && acc_.GetOpCode(e2) == OpCode::CONSTANT) { 985 SaveGate2Expr(gate, e2Value, true); 986 return; 987 } 988 989 Expr result; 990 /* 991 * If the first operand is pointer, special treatment is needed 992 * 1) add, pointer, int 993 * 2) add, vector{i8* x 2}, int 994 */ 995 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate); 996 auto machineType = acc_.GetMachineType(gate); 997 if (IsAddIntergerType(machineType)) { 998 auto e1Type = ConvertLiteCGTypeFromGate(e1); 999 auto e1TypeKind = lmirBuilder_->LiteCGGetTypeKind(e1Type); 1000 auto e2Type = ConvertLiteCGTypeFromGate(e2); 1001 if (e1TypeKind == maple::litecg::kLiteCGTypePointer) { 1002 Expr tmp1 = lmirBuilder_->Cvt(e1Type, lmirBuilder_->i64Type, e1Value); 1003 Expr tmp2 = 1004 (e2Type == lmirBuilder_->i64Type) ? e2Value : lmirBuilder_->Cvt(e2Type, lmirBuilder_->i64Type, e2Value); 1005 Expr tmp3 = lmirBuilder_->Add(lmirBuilder_->i64Type, tmp1, tmp2); 1006 result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, returnType, tmp3); 1007 SaveGate2Expr(gate, result); 1008 // set the base reference of derived reference 1009 if (e1Type == lmirBuilder_->i64RefType) { 1010 ASSERT(!e1Value.IsDread()); 1011 auto e1BaseIter = derivedGate2BaseGate_.find(e1); 1012 derivedGate2BaseGate_[gate] = (e1BaseIter == derivedGate2BaseGate_.end() ? e1 : e1BaseIter->second); 1013 } 1014 return; 1015 } else { 1016 Expr tmp1Expr = (e1Type == returnType) ? e1Value : lmirBuilder_->Cvt(e1Type, returnType, e1Value); 1017 Expr tmp2Expr = (e2Type == returnType) ? e2Value : lmirBuilder_->Cvt(e2Type, returnType, e2Value); 1018 result = lmirBuilder_->Add(returnType, tmp1Expr, tmp2Expr); 1019 } 1020 } else if (machineType == MachineType::F64) { 1021 result = lmirBuilder_->Add(lmirBuilder_->f64Type, e1Value, e2Value); 1022 } else { 1023 LOG_ECMA(FATAL) << "this branch is unreachable"; 1024 UNREACHABLE(); 1025 } 1026 SaveGate2Expr(gate, result); 1027} 1028 1029void LiteCGIRBuilder::HandleLoad(GateRef gate) 1030{ 1031 VisitLoad(gate, acc_.GetIn(gate, 1)); 1032} 1033 1034void LiteCGIRBuilder::VisitLoad(GateRef gate, GateRef base) 1035{ 1036 Expr baseAddr = GetExprFromGate(base); 1037 1038 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate); 1039 LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(returnType)) ? lmirBuilder_->CreateRefType(returnType) 1040 : lmirBuilder_->CreatePtrType(returnType); 1041 baseAddr = CanonicalizeToPtr(baseAddr, memType); 1042 Expr result = lmirBuilder_->Iread(returnType, baseAddr, memType); 1043 SaveGate2Expr(gate, result); 1044} 1045 1046void LiteCGIRBuilder::HandleCmp(GateRef gate) 1047{ 1048 GateRef left = acc_.GetIn(gate, 0); 1049 GateRef right = acc_.GetIn(gate, 1); 1050 VisitCmp(gate, left, right); 1051} 1052 1053IntCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const 1054{ 1055 switch (cond) { 1056 case ICmpCondition::SLT: 1057 return IntCmpCondition::kSLT; 1058 case ICmpCondition::SLE: 1059 return IntCmpCondition::kSLE; 1060 case ICmpCondition::SGT: 1061 return IntCmpCondition::kSGT; 1062 case ICmpCondition::SGE: 1063 return IntCmpCondition::kSGE; 1064 case ICmpCondition::ULT: 1065 return IntCmpCondition::kULT; 1066 case ICmpCondition::ULE: 1067 return IntCmpCondition::kULE; 1068 case ICmpCondition::UGT: 1069 return IntCmpCondition::kUGT; 1070 case ICmpCondition::UGE: 1071 return IntCmpCondition::kUGE; 1072 case ICmpCondition::NE: 1073 return IntCmpCondition::kNE; 1074 case ICmpCondition::EQ: 1075 return IntCmpCondition::kEQ; 1076 default: 1077 LOG_COMPILER(FATAL) << "unexpected cond!"; 1078 UNREACHABLE(); 1079 } 1080 return IntCmpCondition::kEQ; 1081} 1082 1083FloatCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const 1084{ 1085 switch (cond) { 1086 case FCmpCondition::OLT: 1087 return FloatCmpCondition::kOLT; 1088 case FCmpCondition::OLE: 1089 return FloatCmpCondition::kOLE; 1090 case FCmpCondition::OGT: 1091 return FloatCmpCondition::kOGT; 1092 case FCmpCondition::OGE: 1093 return FloatCmpCondition::kOGE; 1094 case FCmpCondition::ONE: 1095 return FloatCmpCondition::kONE; 1096 case FCmpCondition::OEQ: 1097 return FloatCmpCondition::kOEQ; 1098 default: 1099 LOG_COMPILER(FATAL) << "unexpected cond!"; 1100 UNREACHABLE(); 1101 } 1102 return FloatCmpCondition::kOEQ; 1103} 1104 1105void LiteCGIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2) 1106{ 1107 Expr e1Value = GetExprFromGate(e1); 1108 Expr e2Value = GetExprFromGate(e2); 1109 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate); 1110 1111 [[maybe_unused]] auto e1ValCode = acc_.GetMachineType(e1); 1112 [[maybe_unused]] auto e2ValCode = acc_.GetMachineType(e2); 1113 ASSERT((e1ValCode == e2ValCode) || 1114 (compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) || 1115 (compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64))); 1116 auto op = acc_.GetOpCode(gate); 1117 if (op == OpCode::ICMP) { 1118 auto cond = acc_.GetICmpCondition(gate); 1119 auto litecgCond = ConvertLiteCGPredicateFromICMP(cond); 1120 Expr result = lmirBuilder_->ICmp(returnType, e1Value, e2Value, litecgCond); 1121 SaveGate2Expr(gate, result); 1122 } else if (op == OpCode::FCMP) { 1123 auto cond = acc_.GetFCmpCondition(gate); 1124 auto litecgCond = ConvertLiteCGPredicateFromFCMP(cond); 1125 Expr result = lmirBuilder_->FCmp(returnType, e1Value, e2Value, litecgCond); 1126 SaveGate2Expr(gate, result); 1127 } else { 1128 LOG_ECMA(FATAL) << "this branch is unreachable"; 1129 UNREACHABLE(); 1130 } 1131} 1132 1133void LiteCGIRBuilder::HandleBranch(GateRef gate) 1134{ 1135 std::vector<GateRef> ins; 1136 acc_.GetIns(gate, ins); 1137 std::vector<GateRef> outs; 1138 acc_.GetOutStates(gate, outs); 1139 GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; 1140 GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; 1141 int bbTrue = instID2bbID_[acc_.GetId(bTrue)]; 1142 int bbFalse = instID2bbID_[acc_.GetId(bFalse)]; 1143 VisitBranch(gate, ins[1], bbTrue, bbFalse); 1144} 1145 1146void LiteCGIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse) 1147{ 1148 if ((gate2Expr_.count(cmp) == 0) && (acc_.GetOpCode(cmp) != OpCode::CONSTANT)) { 1149 OPTIONAL_LOG_COMPILER(ERROR) << "Branch condition gate is nullptr!"; 1150 return; 1151 } 1152 uint32_t trueWeight = 0; 1153 uint32_t falseWeight = 0; 1154 if (acc_.HasBranchWeight(gate)) { 1155 trueWeight = acc_.GetTrueWeight(gate); 1156 falseWeight = acc_.GetFalseWeight(gate); 1157 } 1158 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 1159 lmirBuilder_->AppendBB(curBB); 1160 BB &bb = CreateBB(); 1161 BB &trueBB = GetOrCreateBB(btrue); 1162 BB &falseBB = GetOrCreateBB(bfalse); 1163 // we hope that branch with higher probability can be placed immediatly behind 1164 if (trueWeight < falseWeight) { 1165 Stmt &stmt = lmirBuilder_->Goto(falseBB); 1166 lmirBuilder_->AppendStmt(bb, stmt); 1167 lmirBuilder_->AppendBB(bb); 1168 Expr cond = GetExprFromGate(cmp); 1169 Stmt &condBR = lmirBuilder_->CondGoto(cond, trueBB, true); 1170 lmirBuilder_->AppendStmt(curBB, condBR); 1171 return; 1172 } 1173 Stmt &stmt = lmirBuilder_->Goto(trueBB); 1174 lmirBuilder_->AppendStmt(bb, stmt); 1175 lmirBuilder_->AppendBB(bb); 1176 Expr cond = GetExprFromGate(cmp); 1177 Stmt &condBR = lmirBuilder_->CondGoto(cond, falseBB, false); 1178 lmirBuilder_->AppendStmt(curBB, condBR); 1179} 1180 1181void LiteCGIRBuilder::HandleReturn(GateRef gate) 1182{ 1183 std::vector<GateRef> ins; 1184 acc_.GetIns(gate, ins); 1185 VisitReturn(gate, 1, ins); 1186} 1187 1188void LiteCGIRBuilder::VisitReturn([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef popCount, 1189 const std::vector<GateRef> &operands) 1190{ 1191 // [STATE] [DEPEND] [VALUE] [RETURN_LIST] 1192 GateRef operand = operands[2]; // 2: skip 2 in gate that are not data gate 1193 Expr returnValue = GetExprFromGate(operand); 1194 Stmt &returnNode = lmirBuilder_->Return(returnValue); 1195 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 1196 lmirBuilder_->AppendStmt(curBB, returnNode); 1197 lmirBuilder_->AppendBB(curBB); 1198} 1199 1200Expr LiteCGIRBuilder::GetRTStubOffset(Expr glue, int index) 1201{ 1202 size_t slotOffset = JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit()) + index * slotSize_; 1203 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(slotOffset)); 1204 return lmirBuilder_->ConstVal(constVal); 1205} 1206 1207Expr LiteCGIRBuilder::GetCoStubOffset(Expr glue, int index) const 1208{ 1209 size_t offset = 1210 JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) + static_cast<size_t>(index * slotSize_); 1211 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(offset)); 1212 return lmirBuilder_->ConstVal(constVal); 1213} 1214 1215Expr LiteCGIRBuilder::GetBaselineStubOffset(Expr glue, int index) const 1216{ 1217 size_t offset = 1218 JSThread::GlueData::GetBaselineStubEntriesOffset(compCfg_->Is32Bit()) + static_cast<size_t>(index * slotSize_); 1219 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(offset)); 1220 return lmirBuilder_->ConstVal(constVal); 1221} 1222 1223void LiteCGIRBuilder::HandleRuntimeCall(GateRef gate) 1224{ 1225 std::vector<GateRef> ins; 1226 acc_.GetIns(gate, ins); 1227 VisitRuntimeCall(gate, ins); 1228}; 1229 1230LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromVariableType(VariableType type) const 1231{ 1232 std::map<VariableType, LiteCGType *> machineTypeMap = { 1233 {VariableType::VOID(), lmirBuilder_->voidType}, 1234 {VariableType::BOOL(), lmirBuilder_->u1Type}, 1235 {VariableType::INT8(), lmirBuilder_->i8Type}, 1236 {VariableType::INT16(), lmirBuilder_->i16Type}, 1237 {VariableType::INT32(), lmirBuilder_->i32Type}, 1238 {VariableType::INT64(), lmirBuilder_->i64Type}, 1239 {VariableType::FLOAT32(), lmirBuilder_->f32Type}, 1240 {VariableType::FLOAT64(), lmirBuilder_->f64Type}, 1241 {VariableType::NATIVE_POINTER(), lmirBuilder_->i64Type}, 1242 {VariableType::JS_POINTER(), lmirBuilder_->i64RefType}, 1243 {VariableType::JS_ANY(), lmirBuilder_->i64RefType}, 1244 }; 1245 return machineTypeMap[type]; 1246} 1247 1248LiteCGType *LiteCGIRBuilder::GenerateFuncType(const std::vector<Expr> ¶ms, const CallSignature *stubDescriptor) 1249{ 1250 LiteCGType *retType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType()); 1251 std::vector<LiteCGType *> paramTys; 1252 for (auto value : params) { 1253 paramTys.emplace_back(value.GetType()); 1254 } 1255 LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, retType, false); 1256 return functionType; 1257} 1258 1259LiteCGType *LiteCGIRBuilder::GetFuncType(const CallSignature *stubDescriptor) const 1260{ 1261 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType()); 1262 std::vector<LiteCGType *> paramTys; 1263 auto paramCount = stubDescriptor->GetParametersCount(); 1264 auto paramsType = stubDescriptor->GetParametersType(); 1265 if (paramsType != nullptr) { 1266 LiteCGType *glueType = ConvertLiteCGTypeFromVariableType(paramsType[0]); 1267 paramTys.push_back(glueType); 1268 1269 for (size_t i = 1; i < paramCount; i++) { 1270 paramTys.push_back(ConvertLiteCGTypeFromVariableType(paramsType[i])); 1271 } 1272 } 1273 auto funcType = lmirBuilder_->CreateFuncType(paramTys, returnType, stubDescriptor->IsVariadicArgs()); 1274 return funcType; 1275} 1276 1277Expr LiteCGIRBuilder::GetFunction(BB &bb, Expr glue, const CallSignature *signature, Expr rtbaseoffset, 1278 const std::string &realName) const 1279{ 1280 LiteCGType *rtfuncType = GetFuncType(signature); 1281 LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType); 1282 LiteCGType *rtFuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr); 1283 LiteCGType *glueType = (glue.GetType()); 1284 LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType); 1285 Expr rtbaseAddr = lmirBuilder_->Cvt(rtbaseoffset.GetType(), glueTypePtr, rtbaseoffset); 1286 1287 Expr funcAddr = lmirBuilder_->Iread(glueType, rtbaseAddr, glueTypePtr); 1288 Expr callee = lmirBuilder_->Cvt(glueType, rtFuncTypePtrPtr, funcAddr); 1289 1290 std::string name = realName.empty() ? signature->GetName() : realName; 1291 Stmt &comment = lmirBuilder_->Comment("function: " + name); 1292 lmirBuilder_->AppendStmt(bb, comment); 1293 PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType()); 1294 Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx); 1295 lmirBuilder_->AppendStmt(bb, funcAddrNode); 1296 1297 return lmirBuilder_->Regread(funcPregIdx); 1298} 1299 1300bool LiteCGIRBuilder::IsOptimizedJSFunction() const 1301{ 1302 return circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 1303 circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME; 1304} 1305 1306bool LiteCGIRBuilder::IsOptimized() const 1307{ 1308 return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME; 1309} 1310 1311CallExceptionKind LiteCGIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const 1312{ 1313 bool hasPcOffset = IsOptimizedJSFunction() && 1314 ((op == OpCode::NOGC_RUNTIME_CALL && (kungfu::RuntimeStubCSigns::IsAsmStub(index))) || 1315 (op == OpCode::CALL) || (op == OpCode::RUNTIME_CALL)); 1316 return hasPcOffset ? CallExceptionKind::HAS_PC_OFFSET : CallExceptionKind::NO_PC_OFFSET; 1317} 1318 1319void LiteCGIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList) 1320{ 1321 StubIdType stubId = RTSTUB_ID(CallRuntime); 1322 Expr glue = GetGlue(inList); 1323 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 1324 Expr rtoffset = GetRTStubOffset(glue, stubIndex); 1325 Expr rtbaseOffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); 1326 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId)); 1327 1328 CallExceptionKind kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL); 1329 bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET); 1330 size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size(); // 2: pcOffset and frameArgs 1331 1332 std::vector<Expr> params; 1333 params.push_back(glue); // glue 1334 1335 const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)])); 1336 Expr indexValue = 1337 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(index))); 1338 params.push_back(indexValue); // target 1339 1340 const int64_t argc = actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER); 1341 Expr argcValue = 1342 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(argc))); 1343 params.push_back(argcValue); // argc 1344 1345 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) { 1346 GateRef gateTmp = inList[paraIdx]; 1347 params.push_back(GetExprFromGate(gateTmp)); 1348 } 1349 1350 std::string targetName = RuntimeStubCSigns::GetRTName(index); 1351 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 1352 std::string name = targetName.empty() ? signature->GetName() : targetName; 1353 Expr callee = GetFunction(bb, glue, signature, rtbaseOffset, name); 1354 1355 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType()); 1356 bool returnVoid = (returnType == lmirBuilder_->voidType); 1357 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType); 1358 Stmt &callNode = 1359 returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx); 1360 1361 if (kind == CallExceptionKind::HAS_PC_OFFSET) { 1362 std::unordered_map<int, LiteCGValue> deoptBundleInfo; 1363 auto frameArgs = inList.at(actualNumArgs); 1364 Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1])) 1365 : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0)); 1366 CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs); 1367 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo); 1368 } 1369 lmirBuilder_->SetStmtCallConv(callNode, maple::litecg::Web_Kit_JS_Call); 1370 lmirBuilder_->AppendStmt(bb, callNode); 1371 if (!returnVoid) { 1372 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx)); 1373 } 1374} 1375 1376void LiteCGIRBuilder::HandleZExtInt(GateRef gate) 1377{ 1378 std::vector<GateRef> ins; 1379 acc_.GetIns(gate, ins); 1380 VisitZExtInt(gate, ins[0]); 1381} 1382 1383void LiteCGIRBuilder::VisitZExtInt(GateRef gate, GateRef e1) 1384{ 1385 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <= 1386 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 1387 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1); 1388 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate, false); 1389 Expr result = lmirBuilder_->ZExt(fromType, toType, GetExprFromGate(e1)); 1390 SaveGate2Expr(gate, result); 1391} 1392 1393void LiteCGIRBuilder::HandleIntDiv(GateRef gate) 1394{ 1395 auto g0 = acc_.GetIn(gate, 0); 1396 auto g1 = acc_.GetIn(gate, 1); 1397 VisitIntDiv(gate, g0, g1); 1398} 1399 1400void LiteCGIRBuilder::VisitIntDiv(GateRef gate, GateRef e1, GateRef e2) 1401{ 1402 Expr e1Value = GetExprFromGate(e1); 1403 Expr e2Value = GetExprFromGate(e2); 1404 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1405 Expr result = lmirBuilder_->SDiv(type, e1Value, e2Value); 1406 SaveGate2Expr(gate, result); 1407} 1408 1409Expr LiteCGIRBuilder::GetCallee(maple::litecg::BB &bb, const std::vector<GateRef> &inList, 1410 const CallSignature *signature, const std::string &realName) 1411{ 1412 LiteCGType *rtfuncType = GetFuncType(signature); 1413 LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType); 1414 LiteCGType *rtfuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr); 1415 Expr code = GetExprFromGate(inList[static_cast<size_t>(CallInputs::TARGET)]); 1416 Expr callee = lmirBuilder_->Cvt(code.GetType(), rtfuncTypePtrPtr, code); 1417 1418 std::string name = realName.empty() ? signature->GetName() : realName; 1419 Stmt &comment = lmirBuilder_->Comment("function: " + name); 1420 lmirBuilder_->AppendStmt(bb, comment); 1421 1422 PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType()); 1423 Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx); 1424 lmirBuilder_->AppendStmt(bb, funcAddrNode); 1425 return lmirBuilder_->Regread(funcPregIdx); 1426} 1427 1428void LiteCGIRBuilder::HandleRuntimeCallWithArgv(GateRef gate) 1429{ 1430 std::vector<GateRef> ins; 1431 acc_.GetIns(gate, ins); 1432 VisitRuntimeCallWithArgv(gate, ins); 1433} 1434 1435void LiteCGIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList) 1436{ 1437 ASSERT(IsOptimized() == true); 1438 StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv); 1439 Expr glue = GetGlue(inList); 1440 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 1441 Expr rtoffset = GetRTStubOffset(glue, stubIndex); 1442 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); 1443 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId)); 1444 1445 std::vector<Expr> params; 1446 params.push_back(glue); // glue 1447 1448 uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]); 1449 auto targetId = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, index)); 1450 params.push_back(targetId); // target 1451 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) { 1452 GateRef gateTmp = inList[paraIdx]; 1453 params.push_back(GetExprFromGate(gateTmp)); 1454 } 1455 1456 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 1457 std::string targetName = RuntimeStubCSigns::GetRTName(index); 1458 std::string name = targetName.empty() ? signature->GetName() : targetName; 1459 Expr callee = GetFunction(bb, glue, signature, rtbaseoffset, name); 1460 1461 static uint32_t val = 0; 1462 std::string returnCallValName = name + "Ret" + std::to_string(val++); 1463 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType()); 1464 Var *returnVar = (returnType == lmirBuilder_->voidType) 1465 ? nullptr 1466 : &(lmirBuilder_->CreateLocalVar(returnType, returnCallValName)); 1467 Stmt &callNode = lmirBuilder_->ICall(callee, params, returnVar); 1468 lmirBuilder_->AppendStmt(bb, callNode); 1469 if (returnVar != nullptr) { 1470 SaveGate2Expr(gate, lmirBuilder_->Dread(*returnVar)); 1471 } 1472} 1473 1474void LiteCGIRBuilder::HandleCall(GateRef gate) 1475{ 1476 std::vector<GateRef> ins; 1477 acc_.GetIns(gate, ins); 1478 OpCode callOp = acc_.GetOpCode(gate); 1479 if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL || callOp == OpCode::BUILTINS_CALL || 1480 callOp == OpCode::BUILTINS_CALL_WITH_ARGV || callOp == OpCode::CALL_OPTIMIZED || 1481 callOp == OpCode::FAST_CALL_OPTIMIZED || callOp == OpCode::BASELINE_CALL) { 1482 VisitCall(gate, ins, callOp); 1483 } else { 1484 LOG_ECMA(FATAL) << "this branch is unreachable"; 1485 UNREACHABLE(); 1486 } 1487} 1488 1489void LiteCGIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op) 1490{ 1491 size_t targetIndex = static_cast<size_t>(CallInputs::TARGET); 1492 static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3); 1493 const CallSignature *calleeDescriptor = nullptr; 1494 Expr glue = GetGlue(inList); 1495 Expr callee; 1496 CallExceptionKind kind = CallExceptionKind::NO_PC_OFFSET; 1497 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 1498 if (op == OpCode::CALL) { 1499 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 1500 calleeDescriptor = CommonStubCSigns::Get(index); 1501 Expr rtoffset = GetCoStubOffset(glue, index); 1502 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); 1503 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); 1504 kind = GetCallExceptionKind(index, op); 1505 } else if (op == OpCode::NOGC_RUNTIME_CALL) { 1506 UpdateLeaveFrame(glue); 1507 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 1508 calleeDescriptor = RuntimeStubCSigns::Get(index); 1509 Expr rtoffset = GetRTStubOffset(glue, index); 1510 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); 1511 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); 1512 kind = GetCallExceptionKind(index, op); 1513 } else if (op == OpCode::CALL_OPTIMIZED) { 1514 calleeDescriptor = RuntimeStubCSigns::GetOptimizedCallSign(); 1515 callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName()); 1516 if (IsOptimizedJSFunction()) { 1517 kind = CallExceptionKind::HAS_PC_OFFSET; 1518 } else { 1519 kind = CallExceptionKind::NO_PC_OFFSET; 1520 } 1521 } else if (op == OpCode::FAST_CALL_OPTIMIZED) { 1522 calleeDescriptor = RuntimeStubCSigns::GetOptimizedFastCallSign(); 1523 callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName()); 1524 if (IsOptimizedJSFunction()) { 1525 kind = CallExceptionKind::HAS_PC_OFFSET; 1526 } else { 1527 kind = CallExceptionKind::NO_PC_OFFSET; 1528 } 1529 } else if (op == OpCode::BASELINE_CALL) { 1530 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 1531 calleeDescriptor = BaselineStubCSigns::Get(index); 1532 Expr rtoffset = GetBaselineStubOffset(glue, index); 1533 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset); 1534 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); 1535 kind = GetCallExceptionKind(index, op); 1536 } else { 1537 ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV); 1538 Expr opcodeOffset = GetExprFromGate(inList[targetIndex]); 1539 Expr rtoffset = GetBuiltinsStubOffset(glue); 1540 Expr offset = lmirBuilder_->Add(rtoffset.GetType(), rtoffset, opcodeOffset); 1541 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, offset); 1542 if (op == OpCode::BUILTINS_CALL) { 1543 calleeDescriptor = BuiltinsStubCSigns::BuiltinsCSign(); 1544 } else { 1545 calleeDescriptor = BuiltinsStubCSigns::BuiltinsWithArgvCSign(); 1546 } 1547 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset); 1548 } 1549 1550 std::vector<Expr> params; 1551 const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER); 1552 GateRef glueGate = inList[firstArg]; 1553 params.push_back(GetExprFromGate(glueGate)); 1554 1555 LiteCGType *calleeFuncType = lmirBuilder_->LiteCGGetPointedType(callee.GetType()); 1556 std::vector<LiteCGType *> paramTypes = lmirBuilder_->LiteCGGetFuncParamTypes(calleeFuncType); 1557 1558 bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET); 1559 size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size(); // 2: pcOffset and frameArgs 1560 1561 // then push the actual parameter for js function call 1562 for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) { 1563 GateRef gateTmp = inList[paraIdx]; 1564 Expr gateExpr = GetExprFromGate(gateTmp); 1565 const auto gateTmpType = gateExpr.GetType(); 1566 if (params.size() < paramTypes.size()) { // this condition will be false for variadic arguments 1567 const auto paramType = paramTypes.at(params.size()); 1568 // match parameter types and function signature types 1569 if (lmirBuilder_->IsHeapPointerType(paramType) && !lmirBuilder_->IsHeapPointerType(gateTmpType)) { 1570 Expr cvtI64Expr = lmirBuilder_->Cvt(gateTmpType, lmirBuilder_->i64Type, gateExpr); 1571 params.push_back(lmirBuilder_->Cvt(lmirBuilder_->i64Type, paramType, cvtI64Expr)); 1572 } else { 1573 params.push_back(lmirBuilder_->Cvt(gateTmpType, paramType, gateExpr)); 1574 } 1575 } else { 1576 params.push_back(gateExpr); 1577 } 1578 } 1579 1580 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(calleeFuncType); 1581 bool returnVoid = (returnType == lmirBuilder_->voidType); 1582 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType); 1583 Stmt &callNode = 1584 returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx); 1585 if (kind == CallExceptionKind::HAS_PC_OFFSET) { 1586 std::unordered_map<int, LiteCGValue> deoptBundleInfo; 1587 auto frameArgs = inList.at(actualNumArgs); 1588 Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1])) 1589 : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0)); 1590 CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs); 1591 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo); 1592 } 1593 lmirBuilder_->SetStmtCallConv(callNode, ConvertCallAttr(calleeDescriptor->GetCallConv())); 1594 lmirBuilder_->AppendStmt(bb, callNode); 1595 if (!returnVoid) { 1596 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx)); 1597 } 1598} 1599 1600void LiteCGIRBuilder::CollectExraCallSiteInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo, 1601 maple::litecg::Expr pcOffset, GateRef frameArgs) 1602{ 1603 // pc offset 1604 auto pcIndex = static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX); 1605 ASSERT(pcOffset.IsConstValue()); 1606 deoptBundleInfo.insert(std::pair<int, LiteCGValue>( 1607 pcIndex, {LiteCGValueKind::kConstKind, lmirBuilder_->GetConstFromExpr(pcOffset)})); 1608 1609 if (!enableOptInlining_) { 1610 return; 1611 } 1612 1613 if (frameArgs == Circuit::NullGate()) { 1614 return; 1615 } 1616 if (acc_.GetOpCode(frameArgs) != OpCode::FRAME_ARGS) { 1617 return; 1618 } 1619 uint32_t maxDepth = acc_.GetFrameDepth(frameArgs, OpCode::FRAME_ARGS); 1620 if (maxDepth == 0) { 1621 return; 1622 } 1623 1624 maxDepth = std::min(maxDepth, MAX_METHOD_OFFSET_NUM); 1625 size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM); 1626 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_)); 1627 for (int32_t curDepth = static_cast<int32_t>(maxDepth - 1); curDepth >= 0; curDepth--) { 1628 ASSERT(acc_.GetOpCode(frameArgs) == OpCode::FRAME_ARGS); 1629 // method id 1630 uint32_t methodOffset = acc_.TryGetMethodOffset(frameArgs); 1631 frameArgs = acc_.GetFrameState(frameArgs); 1632 if (methodOffset == FrameStateOutput::INVALID_INDEX) { 1633 methodOffset = 0; 1634 } 1635 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - curDepth; 1636 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specCallTargetIndex, curDepth, shift); 1637 auto constMethodOffset = lmirBuilder_->GetConstFromExpr( 1638 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, methodOffset))); 1639 deoptBundleInfo.insert( 1640 std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kConstKind, constMethodOffset})); 1641 } 1642} 1643 1644maple::litecg::ConvAttr LiteCGIRBuilder::ConvertCallAttr(const CallSignature::CallConv callConv) 1645{ 1646 switch (callConv) { 1647 case CallSignature::CallConv::GHCCallConv: { 1648 return maple::litecg::GHC_Call; 1649 } 1650 case CallSignature::CallConv::WebKitJSCallConv: { 1651 return maple::litecg::Web_Kit_JS_Call; 1652 } 1653 default: { 1654 return maple::litecg::CCall; 1655 } 1656 } 1657} 1658 1659Expr LiteCGIRBuilder::GetBuiltinsStubOffset(Expr glue) 1660{ 1661 Const &constVal = lmirBuilder_->CreateIntConst( 1662 glue.GetType(), JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit())); 1663 return lmirBuilder_->ConstVal(constVal); 1664} 1665 1666void LiteCGIRBuilder::UpdateLeaveFrame(Expr glue) 1667{ 1668 Expr leaveFrameOffset = GetLeaveFrameOffset(glue); 1669 Expr leaveFrameValue = lmirBuilder_->Add(glue.GetType(), glue, leaveFrameOffset); 1670 LiteCGType *glueType = glue.GetType(); 1671 LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType); 1672 Expr leaveFrameAddr = lmirBuilder_->Cvt(leaveFrameValue.GetType(), glueTypePtr, leaveFrameValue); 1673 Expr fpAddr = CallingFp(true); 1674 Expr fp = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); 1675 1676 lmirBuilder_->Iassign(fp, leaveFrameAddr, fp.GetType()); 1677} 1678 1679bool LiteCGIRBuilder::IsInterpreted() const 1680{ 1681 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME; 1682} 1683 1684bool LiteCGIRBuilder::IsBaselineBuiltin() const 1685{ 1686 return circuit_->GetFrameType() == FrameType::BASELINE_BUILTIN_FRAME; 1687} 1688 1689Expr LiteCGIRBuilder::CallingFp(bool /*isCaller*/) 1690{ 1691 ASSERT(!IsInterpreted() && !IsBaselineBuiltin()); 1692 /* 0:calling 1:its caller */ 1693 Function &func = lmirBuilder_->GetCurFunction(); 1694 return lmirBuilder_->LiteCGGetPregFP(func); 1695} 1696 1697Expr LiteCGIRBuilder::GetLeaveFrameOffset(Expr glue) 1698{ 1699 size_t slotOffset = JSThread::GlueData::GetLeaveFrameOffset(compCfg_->Is32Bit()); 1700 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int>(slotOffset)); 1701 return lmirBuilder_->ConstVal(constVal); 1702} 1703 1704void LiteCGIRBuilder::HandleUDiv(GateRef gate) 1705{ 1706 auto g0 = acc_.GetIn(gate, 0); 1707 auto g1 = acc_.GetIn(gate, 1); 1708 VisitUDiv(gate, g0, g1); 1709} 1710 1711void LiteCGIRBuilder::VisitUDiv(GateRef gate, GateRef e1, GateRef e2) 1712{ 1713 Expr e1Value = GetExprFromGate(e1); 1714 Expr e2Value = GetExprFromGate(e2); 1715 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1716 Expr result = lmirBuilder_->UDiv(type, e1Value, e2Value); 1717 SaveGate2Expr(gate, result); 1718} 1719 1720void LiteCGIRBuilder::HandleIntAnd(GateRef gate) 1721{ 1722 auto g0 = acc_.GetIn(gate, 0); 1723 auto g1 = acc_.GetIn(gate, 1); 1724 VisitIntAnd(gate, g0, g1); 1725} 1726 1727void LiteCGIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2) 1728{ 1729 Expr e1Value = GetExprFromGate(e1); 1730 Expr e2Value = GetExprFromGate(e2); 1731 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1732 Expr result = lmirBuilder_->And(type, e1Value, e2Value); 1733 SaveGate2Expr(gate, result); 1734} 1735 1736void LiteCGIRBuilder::HandleIntOr(GateRef gate) 1737{ 1738 auto g0 = acc_.GetIn(gate, 0); 1739 auto g1 = acc_.GetIn(gate, 1); 1740 VisitIntOr(gate, g0, g1); 1741} 1742 1743void LiteCGIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2) 1744{ 1745 Expr e1Value = GetExprFromGate(e1); 1746 Expr e2Value = GetExprFromGate(e2); 1747 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1748 Expr result = lmirBuilder_->Or(type, e1Value, e2Value); 1749 SaveGate2Expr(gate, result); 1750} 1751 1752void LiteCGIRBuilder::HandleIntXor(GateRef gate) 1753{ 1754 auto g0 = acc_.GetIn(gate, 0); 1755 auto g1 = acc_.GetIn(gate, 1); 1756 VisitIntXor(gate, g0, g1); 1757} 1758 1759void LiteCGIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2) 1760{ 1761 Expr e1Value = GetExprFromGate(e1); 1762 Expr e2Value = GetExprFromGate(e2); 1763 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1764 Expr result = lmirBuilder_->Xor(type, e1Value, e2Value); 1765 SaveGate2Expr(gate, result); 1766} 1767 1768void LiteCGIRBuilder::HandleIntLsr(GateRef gate) 1769{ 1770 auto g0 = acc_.GetIn(gate, 0); 1771 auto g1 = acc_.GetIn(gate, 1); 1772 VisitIntLsr(gate, g0, g1); 1773} 1774 1775void LiteCGIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2) 1776{ 1777 Expr e1Value = GetExprFromGate(e1); 1778 Expr e2Value = GetExprFromGate(e2); 1779 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1780 Expr result = lmirBuilder_->LShr(type, e1Value, e2Value); 1781 SaveGate2Expr(gate, result); 1782} 1783 1784void LiteCGIRBuilder::HandleIntAsr(GateRef gate) 1785{ 1786 auto g0 = acc_.GetIn(gate, 0); 1787 auto g1 = acc_.GetIn(gate, 1); 1788 VisitIntAsr(gate, g0, g1); 1789} 1790 1791void LiteCGIRBuilder::VisitIntAsr(GateRef gate, GateRef e1, GateRef e2) 1792{ 1793 Expr e1Value = GetExprFromGate(e1); 1794 Expr e2Value = GetExprFromGate(e2); 1795 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1796 Expr result = lmirBuilder_->AShr(type, e1Value, e2Value); 1797 SaveGate2Expr(gate, result); 1798} 1799 1800void LiteCGIRBuilder::HandleBitCast(GateRef gate) 1801{ 1802 VisitBitCast(gate, acc_.GetIn(gate, 0)); 1803} 1804 1805void LiteCGIRBuilder::VisitBitCast(GateRef gate, GateRef e1) 1806{ 1807 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(gate)) == 1808 GetBitWidthFromMachineType(acc_.GetMachineType(e1))); 1809 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1); 1810 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate); 1811 Expr e1Value = GetExprFromGate(e1); 1812 Expr result = lmirBuilder_->BitCast(fromType, toType, e1Value); 1813 SaveGate2Expr(gate, result); 1814} 1815 1816void LiteCGIRBuilder::HandleIntLsl(GateRef gate) 1817{ 1818 auto g0 = acc_.GetIn(gate, 0); 1819 auto g1 = acc_.GetIn(gate, 1); 1820 VisitIntLsl(gate, g0, g1); 1821} 1822 1823void LiteCGIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2) 1824{ 1825 Expr e1Value = GetExprFromGate(e1); 1826 Expr e2Value = GetExprFromGate(e2); 1827 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1828 Expr result = lmirBuilder_->Shl(type, e1Value, e2Value); 1829 SaveGate2Expr(gate, result); 1830} 1831 1832void LiteCGIRBuilder::HandleMod(GateRef gate) 1833{ 1834 auto g0 = acc_.GetIn(gate, 0); 1835 auto g1 = acc_.GetIn(gate, 1); 1836 VisitMod(gate, g0, g1); 1837} 1838 1839void LiteCGIRBuilder::VisitMod(GateRef gate, GateRef e1, GateRef e2) 1840{ 1841 Expr e1Value = GetExprFromGate(e1); 1842 Expr e2Value = GetExprFromGate(e2); 1843 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1844 ASSERT(type == ConvertLiteCGTypeFromGate(e1)); 1845 ASSERT(type == ConvertLiteCGTypeFromGate(e2)); 1846 auto machineType = acc_.GetMachineType(gate); 1847 Expr result; 1848 if (machineType == MachineType::I32) { 1849 result = lmirBuilder_->SRem(type, e1Value, e2Value); 1850 } else if (machineType != MachineType::F64) { 1851 LOG_ECMA(FATAL) << "this branch is unreachable"; 1852 UNREACHABLE(); 1853 } 1854 SaveGate2Expr(gate, result); 1855} 1856 1857void LiteCGIRBuilder::HandleFinishAllocate(GateRef gate) 1858{ 1859 GateRef g0 = acc_.GetValueIn(gate, 0); 1860 VisitFinishAllocate(gate, g0); 1861} 1862 1863void LiteCGIRBuilder::VisitFinishAllocate(GateRef gate, GateRef e1) 1864{ 1865 Expr result = GetExprFromGate(e1); 1866 SaveGate2Expr(gate, result); 1867} 1868 1869void LiteCGIRBuilder::HandleCastIntXToIntY(GateRef gate) 1870{ 1871 VisitCastIntXToIntY(gate, acc_.GetIn(gate, 0)); 1872} 1873 1874void LiteCGIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1) 1875{ 1876 Expr e1Value = GetExprFromGate(e1); 1877 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >= 1878 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 1879 auto e1Type = ConvertLiteCGTypeFromGate(e1); 1880 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value); 1881 SaveGate2Expr(gate, result); 1882} 1883 1884void LiteCGIRBuilder::HandleChangeInt32ToDouble(GateRef gate) 1885{ 1886 VisitChangeInt32ToDouble(gate, acc_.GetIn(gate, 0)); 1887} 1888 1889void LiteCGIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1) 1890{ 1891 Expr e1Value = GetExprFromGate(e1); 1892 auto e1Type = ConvertLiteCGTypeFromGate(e1); 1893 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value); 1894 SaveGate2Expr(gate, result); 1895} 1896 1897void LiteCGIRBuilder::HandleChangeUInt32ToDouble(GateRef gate) 1898{ 1899 VisitChangeUInt32ToDouble(gate, acc_.GetIn(gate, 0)); 1900} 1901 1902void LiteCGIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1) 1903{ 1904 Expr e1Value = GetExprFromGate(e1); 1905 auto e1Type = ConvertLiteCGTypeFromGate(e1); 1906 if (e1Type != lmirBuilder_->u32Type) { 1907 e1Value = lmirBuilder_->Cvt(e1Type, lmirBuilder_->u32Type, e1Value); 1908 } 1909 Expr result = lmirBuilder_->Cvt(lmirBuilder_->u32Type, ConvertLiteCGTypeFromGate(gate), e1Value); 1910 SaveGate2Expr(gate, result); 1911} 1912 1913void LiteCGIRBuilder::HandleChangeDoubleToInt32(GateRef gate) 1914{ 1915 VisitChangeDoubleToInt32(gate, acc_.GetIn(gate, 0)); 1916} 1917 1918void LiteCGIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1) 1919{ 1920 Expr e1Value = GetExprFromGate(e1); 1921 auto e1Type = ConvertLiteCGTypeFromGate(e1); 1922 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value); 1923 SaveGate2Expr(gate, result); 1924} 1925 1926void LiteCGIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate) 1927{ 1928 VisitChangeTaggedPointerToInt64(gate, acc_.GetIn(gate, 0)); 1929} 1930 1931void LiteCGIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1) 1932{ 1933 Expr result = CanonicalizeToInt(e1); 1934 SaveGate2Expr(gate, result); 1935} 1936 1937Expr LiteCGIRBuilder::CanonicalizeToInt(GateRef gate) 1938{ 1939 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1940 Expr opnd = GetExprFromGate(gate); 1941 if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) { 1942 return lmirBuilder_->Cvt(type, lmirBuilder_->i64Type, opnd); 1943 } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) { 1944 return opnd; 1945 } else { 1946 LOG_COMPILER(FATAL) << "can't Canonicalize to Int64: "; 1947 UNREACHABLE(); 1948 } 1949} 1950 1951void LiteCGIRBuilder::HandleChangeInt64ToTagged(GateRef gate) 1952{ 1953 VisitChangeInt64ToTagged(gate, acc_.GetIn(gate, 0)); 1954} 1955 1956void LiteCGIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1) 1957{ 1958 Expr e1Value = GetExprFromGate(e1); 1959 ASSERT(lmirBuilder_->LiteCGGetTypeKind(ConvertLiteCGTypeFromGate(e1)) == maple::litecg::kLiteCGTypeScalar); 1960 Expr result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, e1Value); 1961 SaveGate2Expr(gate, result); 1962} 1963 1964void LiteCGIRBuilder::HandleDoubleTrunc(GateRef gate) 1965{ 1966 GateRef param = acc_.GetIn(gate, 0); 1967 VisitDoubleTrunc(gate, param); 1968} 1969 1970void LiteCGIRBuilder::VisitDoubleTrunc(GateRef gate, GateRef e1) 1971{ 1972 Expr e1Value = GetExprFromGate(e1); 1973 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 1974 ASSERT(acc_.GetMachineType(e1) == acc_.GetMachineType(gate)); 1975 Expr result = lmirBuilder_->Trunc(type, type, e1Value); 1976 SaveGate2Expr(gate, result); 1977} 1978 1979void LiteCGIRBuilder::HandleSub(GateRef gate) 1980{ 1981 auto g0 = acc_.GetIn(gate, 0); 1982 auto g1 = acc_.GetIn(gate, 1); 1983 VisitSub(gate, g0, g1); 1984} 1985 1986void LiteCGIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2) 1987{ 1988 Expr e1Value = GetExprFromGate(e1); 1989 Expr e2Value = GetExprFromGate(e2); 1990 Expr result; 1991 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate); 1992 auto machineType = acc_.GetMachineType(gate); 1993 if (machineType == MachineType::I16 || machineType == MachineType::I32 || machineType == MachineType::I64 || 1994 machineType == MachineType::ARCH || machineType == MachineType::F64) { 1995 result = lmirBuilder_->Sub(returnType, e1Value, e2Value); 1996 } else { 1997 LOG_ECMA(FATAL) << "this branch is unreachable"; 1998 UNREACHABLE(); 1999 } 2000 SaveGate2Expr(gate, result); 2001} 2002 2003void LiteCGIRBuilder::HandleMul(GateRef gate) 2004{ 2005 auto g0 = acc_.GetIn(gate, 0); 2006 auto g1 = acc_.GetIn(gate, 1); 2007 VisitMul(gate, g0, g1); 2008} 2009 2010void LiteCGIRBuilder::VisitMul(GateRef gate, GateRef e1, GateRef e2) 2011{ 2012 Expr e1Value = GetExprFromGate(e1); 2013 Expr e2Value = GetExprFromGate(e2); 2014 Expr result; 2015 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate); 2016 auto machineType = acc_.GetMachineType(gate); 2017 if (IsMulIntergerType(machineType)) { 2018 result = lmirBuilder_->Mul(returnType, e1Value, e2Value); 2019 } else if (machineType == MachineType::F64) { 2020 result = lmirBuilder_->Mul(returnType, e1Value, e2Value); 2021 } else { 2022 LOG_ECMA(FATAL) << "this branch is unreachable"; 2023 UNREACHABLE(); 2024 } 2025 SaveGate2Expr(gate, result); 2026} 2027 2028void LiteCGIRBuilder::HandleIntRev(GateRef gate) 2029{ 2030 std::vector<GateRef> ins; 2031 acc_.GetIns(gate, ins); 2032 VisitIntRev(gate, ins[0]); 2033} 2034 2035void LiteCGIRBuilder::VisitIntRev(GateRef gate, GateRef e1) 2036{ 2037 Expr e1Value = GetExprFromGate(e1); 2038 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 2039 ASSERT(type == ConvertLiteCGTypeFromGate(e1)); 2040 Expr result; 2041 auto machineType = acc_.GetMachineType(gate); 2042 if (machineType <= MachineType::I64 && machineType >= MachineType::I1) { 2043 if (machineType == MachineType::I1) { 2044 result = lmirBuilder_->Lnot(type, e1Value); 2045 } else { 2046 result = lmirBuilder_->Bnot(type, e1Value); 2047 } 2048 } else { 2049 LOG_ECMA(FATAL) << "this branch is unreachable"; 2050 UNREACHABLE(); 2051 } 2052 SaveGate2Expr(gate, result); 2053} 2054 2055void LiteCGIRBuilder::HandleFloatDiv(GateRef gate) 2056{ 2057 auto g0 = acc_.GetIn(gate, 0); 2058 auto g1 = acc_.GetIn(gate, 1); 2059 VisitFloatDiv(gate, g0, g1); 2060} 2061 2062void LiteCGIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2) 2063{ 2064 Expr e1Value = GetExprFromGate(e1); 2065 Expr e2Value = GetExprFromGate(e2); 2066 Expr result = lmirBuilder_->SDiv(ConvertLiteCGTypeFromGate(gate), e1Value, e2Value); 2067 SaveGate2Expr(gate, result); 2068} 2069 2070void LiteCGIRBuilder::HandleTruncFloatToInt(GateRef gate) 2071{ 2072 auto g0 = acc_.GetIn(gate, 0); 2073 VisitTruncFloatToInt(gate, g0); 2074} 2075 2076void LiteCGIRBuilder::VisitTruncFloatToInt(GateRef gate, GateRef e1) 2077{ 2078 Expr e1Value = GetExprFromGate(e1); 2079 auto machineType = acc_.GetMachineType(e1); 2080 Expr result; 2081 if (machineType <= MachineType::F64 && machineType >= MachineType::F32) { 2082 result = lmirBuilder_->Trunc(ConvertLiteCGTypeFromGate(e1), lmirBuilder_->i64Type, e1Value); 2083 } else { 2084 LOG_ECMA(FATAL) << "this branch is unreachable"; 2085 UNREACHABLE(); 2086 } 2087 SaveGate2Expr(gate, result); 2088} 2089 2090void LiteCGIRBuilder::HandleAddWithOverflow(GateRef gate) 2091{ 2092 auto in0 = acc_.GetIn(gate, 0); 2093 auto in1 = acc_.GetIn(gate, 1); 2094 ASSERT(acc_.GetMachineType(in0) == MachineType::I32); 2095 ASSERT(acc_.GetMachineType(in1) == MachineType::I32); 2096 VisitAddWithOverflow(gate, in0, in1); 2097} 2098 2099void LiteCGIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2) 2100{ 2101 VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_ADD_WITH_OVERFLOW); 2102} 2103 2104void LiteCGIRBuilder::HandleSubWithOverflow(GateRef gate) 2105{ 2106 auto in0 = acc_.GetIn(gate, 0); 2107 auto in1 = acc_.GetIn(gate, 1); 2108 ASSERT(acc_.GetMachineType(in0) == MachineType::I32); 2109 ASSERT(acc_.GetMachineType(in1) == MachineType::I32); 2110 VisitSubWithOverflow(gate, in0, in1); 2111} 2112 2113void LiteCGIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2) 2114{ 2115 VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_SUB_WITH_OVERFLOW); 2116} 2117 2118void LiteCGIRBuilder::HandleMulWithOverflow(GateRef gate) 2119{ 2120 auto in0 = acc_.GetIn(gate, 0); 2121 auto in1 = acc_.GetIn(gate, 1); 2122 ASSERT(acc_.GetMachineType(in0) == MachineType::I32); 2123 ASSERT(acc_.GetMachineType(in1) == MachineType::I32); 2124 VisitMulWithOverflow(gate, in0, in1); 2125} 2126 2127void LiteCGIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2) 2128{ 2129 VisitBinaryOpWithOverflow(gate, e1, e2, IntrinsicId::INTRN_MUL_WITH_OVERFLOW); 2130} 2131 2132void LiteCGIRBuilder::VisitBinaryOpWithOverflow(GateRef gate, GateRef e1, GateRef e2, IntrinsicId intrinsicId) 2133{ 2134 PregIdx preg1 = lmirBuilder_->CreatePreg(lmirBuilder_->i32Type); 2135 PregIdx preg2 = lmirBuilder_->CreatePreg(lmirBuilder_->u1Type); 2136 2137 // generate function call 2138 Expr e1Value = GetExprFromGate(e1); 2139 Expr e2Value = GetExprFromGate(e2); 2140 std::vector<Expr> args = {e1Value, e2Value}; 2141 auto &call = lmirBuilder_->IntrinsicCall(intrinsicId, args, preg1, preg2); 2142 SaveGate2Expr(gate, preg1, preg2); 2143 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call); 2144} 2145 2146void LiteCGIRBuilder::HandleSExtInt(GateRef gate) 2147{ 2148 std::vector<GateRef> ins; 2149 acc_.GetIns(gate, ins); 2150 VisitSExtInt(gate, ins[0]); 2151} 2152 2153void LiteCGIRBuilder::VisitSExtInt(GateRef gate, GateRef e1) 2154{ 2155 Expr e1Value = GetExprFromGate(e1); 2156 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1); 2157 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate); 2158 Expr result = lmirBuilder_->SExt(fromType, toType, e1Value); 2159 SaveGate2Expr(gate, result); 2160} 2161 2162void LiteCGIRBuilder::HandleSqrt(GateRef gate) 2163{ 2164 GateRef param = acc_.GetIn(gate, 0); 2165 VisitSqrt(gate, param); 2166} 2167 2168void LiteCGIRBuilder::VisitSqrt(GateRef gate, GateRef e1) 2169{ 2170 Expr e1Value = GetExprFromGate(e1); 2171 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2172 Expr result; 2173 if (type == lmirBuilder_->f32Type || type == lmirBuilder_->f64Type) { 2174 result = lmirBuilder_->Sqrt(type, e1Value); 2175 } else { 2176 result = lmirBuilder_->Sqrt(lmirBuilder_->f64Type, lmirBuilder_->Cvt(type, lmirBuilder_->f64Type, e1Value)); 2177 } 2178 SaveGate2Expr(gate, result); 2179} 2180 2181void LiteCGIRBuilder::HandleExp(GateRef gate) 2182{ 2183 (void)gate; 2184 CHECK_FATAL(false, "not support exp !"); 2185} 2186 2187void LiteCGIRBuilder::HandleCeil(GateRef gate) 2188{ 2189 VisitCeil(gate, acc_.GetIn(gate, 0)); 2190} 2191 2192void LiteCGIRBuilder::VisitCeil(GateRef gate, GateRef e1) 2193{ 2194 Expr e1Value = GetExprFromGate(e1); 2195 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2196 Expr result = lmirBuilder_->Ceil(type, type, e1Value); 2197 SaveGate2Expr(gate, result); 2198} 2199 2200void LiteCGIRBuilder::HandleAbs(GateRef gate) 2201{ 2202 VisitAbs(gate, acc_.GetIn(gate, 0)); 2203} 2204 2205void LiteCGIRBuilder::VisitAbs(GateRef gate, GateRef e1) 2206{ 2207 auto machineType = acc_.GetMachineType(gate); 2208 ASSERT(acc_.GetMachineType(e1) == machineType); 2209 Expr result; 2210 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2211 Expr e1Value = GetExprFromGate(e1); 2212 if (machineType == MachineType::I32 || machineType == MachineType::F64) { 2213 result = lmirBuilder_->Abs(type, e1Value); 2214 } else { 2215 LOG_ECMA(FATAL) << "`Abs` type should be untagged double or signed int"; 2216 UNREACHABLE(); 2217 } 2218 SaveGate2Expr(gate, result); 2219 return; 2220} 2221 2222void LiteCGIRBuilder::HandleMin(GateRef gate) 2223{ 2224 VisitMin(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U)); 2225} 2226 2227void LiteCGIRBuilder::VisitMin(GateRef gate, GateRef e1, GateRef e2) 2228{ 2229 auto machineType = acc_.GetMachineType(gate); 2230 ASSERT(acc_.GetMachineType(e1) == machineType); 2231 ASSERT(acc_.GetMachineType(e2) == machineType); 2232 Expr result; 2233 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2234 Expr e1Value = GetExprFromGate(e1); 2235 Expr e2Value = GetExprFromGate(e2); 2236 if (machineType == MachineType::I32 || machineType == MachineType::F64) { 2237 result = lmirBuilder_->Min(type, e1Value, e2Value); 2238 } else { 2239 LOG_ECMA(FATAL) << "`Min` type should be untagged double or signed int"; 2240 UNREACHABLE(); 2241 } 2242 SaveGate2Expr(gate, result); 2243 return; 2244} 2245 2246void LiteCGIRBuilder::HandleMax(GateRef gate) 2247{ 2248 VisitMax(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U)); 2249} 2250 2251void LiteCGIRBuilder::VisitMax(GateRef gate, GateRef e1, GateRef e2) 2252{ 2253 auto machineType = acc_.GetMachineType(gate); 2254 ASSERT(acc_.GetMachineType(e1) == machineType); 2255 ASSERT(acc_.GetMachineType(e2) == machineType); 2256 Expr result; 2257 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2258 Expr e1Value = GetExprFromGate(e1); 2259 Expr e2Value = GetExprFromGate(e2); 2260 if (machineType == MachineType::I32 || machineType == MachineType::F64) { 2261 result = lmirBuilder_->Max(type, e1Value, e2Value); 2262 } else { 2263 LOG_ECMA(FATAL) << "`Max` type should be untagged double or signed int"; 2264 UNREACHABLE(); 2265 } 2266 SaveGate2Expr(gate, result); 2267 return; 2268} 2269 2270void LiteCGIRBuilder::HandleFloor(GateRef gate) 2271{ 2272 VisitFloor(gate, acc_.GetIn(gate, 0)); 2273} 2274 2275void LiteCGIRBuilder::VisitFloor(GateRef gate, GateRef e1) 2276{ 2277 Expr e1Value = GetExprFromGate(e1); 2278 LiteCGType *type = ConvertLiteCGTypeFromGate(e1); 2279 Expr result = lmirBuilder_->Floor(type, type, e1Value); 2280 SaveGate2Expr(gate, result); 2281} 2282 2283void LiteCGIRBuilder::HandleClz32(GateRef gate) 2284{ 2285 VisitClz32(gate, acc_.GetIn(gate, 0)); 2286} 2287 2288void LiteCGIRBuilder::VisitClz32(GateRef gate, GateRef param) 2289{ 2290 std::vector<Expr> params; 2291 params.push_back(GetExprFromGate(param)); 2292 LiteCGType *type = ConvertLiteCGTypeFromGate(param); 2293 Expr result = lmirBuilder_->IntrinsicOp(IntrinsicId::INTRN_C_clz32, type, params); 2294 SaveGate2Expr(gate, result); 2295} 2296 2297 2298void LiteCGIRBuilder::HandleReadSp(GateRef gate) 2299{ 2300 ASSERT(acc_.GetOpCode(gate) == OpCode::READSP); 2301 VisitReadSp(gate); 2302} 2303 2304void LiteCGIRBuilder::VisitReadSp(GateRef gate) 2305{ 2306 Expr result = lmirBuilder_->LiteCGGetPregSP(); 2307 SaveGate2Expr(gate, result); 2308} 2309 2310void LiteCGIRBuilder::HandleInitVreg(GateRef gate) 2311{ 2312 ASSERT(acc_.GetOpCode(gate) == OpCode::INITVREG); 2313 VisitInitVreg(gate); 2314} 2315 2316void LiteCGIRBuilder::VisitInitVreg(GateRef gate) 2317{ 2318 size_t vregNumber = acc_.GetInitOffset(gate); 2319 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]); 2320 LiteCGType *i64 = lmirBuilder_->i64Type; 2321 LiteCGType *i64Ptr = lmirBuilder_->i64PtrType; 2322 LiteCGType *i64Ref = lmirBuilder_->i64RefType; 2323 LiteCGType *i32 = lmirBuilder_->i32Type; 2324 switch (vregNumber) { 2325 case INIT_VRGE_GLUE: { 2326 // init glue 2327 Expr glue = lmirBuilder_->GenExprFromVar( 2328 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 0)); // 0 : osr first param - glue 2329 SaveGate2Expr(gate, glue); 2330 return; 2331 } 2332 case INIT_VRGE_ARGS: { 2333 // init argc 2334 SaveGate2Expr(gate, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0))); 2335 return; 2336 } 2337 case INIT_VRGE_FUNCTION: { 2338 // init func 2339 PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref); 2340 // load from frame 2341 Expr sp = lmirBuilder_->GenExprFromVar( 2342 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1)); // 1 : osr second param - sp 2343 Expr offsetFrame = lmirBuilder_->ConstVal( 2344 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64()))); 2345 Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame); 2346 Expr offsetFunc = lmirBuilder_->ConstVal( 2347 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetFunctionOffset(!circuit_->IsArch64()))); 2348 Expr addrFunc = lmirBuilder_->Add(i64Ptr, frame, offsetFunc); 2349 Expr ldrFunc = lmirBuilder_->Iread(i64Ref, addrFunc, lmirBuilder_->CreatePtrType(i64Ptr)); 2350 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrFunc, vreg)); 2351 if (IsOptimizedJSFunction()) { 2352 // reset jsfunc on OptJSFuncFrame 2353 Expr fpAddr = CallingFp(false); 2354 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); 2355 size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 2356 Expr frameJSFuncSlotAddr = 2357 lmirBuilder_->Sub(frameAddr.GetType(), frameAddr, 2358 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset))); 2359 Expr jsFuncAddr = lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), 2360 lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr); 2361 Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->Regread(vreg)); 2362 auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType()); 2363 lmirBuilder_->AppendStmt(bb, stmt); 2364 } 2365 SaveGate2Expr(gate, lmirBuilder_->Regread(vreg)); 2366 return; 2367 } 2368 case INIT_VRGE_NEW_TARGET: { 2369 // init new_target 2370 PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref); 2371 // load func from interpreter sp 2372 Expr sp = lmirBuilder_->GenExprFromVar( 2373 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1)); // 1 : osr second param - sp 2374 Expr offsetFrame = lmirBuilder_->ConstVal( 2375 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64()))); 2376 Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame); 2377 Expr offsetFunc = lmirBuilder_->ConstVal( 2378 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetFunctionOffset(!circuit_->IsArch64()))); 2379 Expr addrFunc = lmirBuilder_->Add(i64Ptr, frame, offsetFunc); 2380 Expr func = lmirBuilder_->Iread(i64Ref, addrFunc, lmirBuilder_->CreatePtrType(i64Ptr)); 2381 // load method from func 2382 Expr offsetMethod = lmirBuilder_->ConstVal( 2383 lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, JSFunctionBase::METHOD_OFFSET)); 2384 Expr addrMethod = lmirBuilder_->Add(i64Ptr, func, offsetMethod); 2385 Expr method = lmirBuilder_->Iread(i64Ptr, addrMethod, lmirBuilder_->CreatePtrType(i64Ptr)); 2386 // load callField from method 2387 Expr offsetCF = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, Method::CALL_FIELD_OFFSET)); 2388 Expr addrCF = lmirBuilder_->Add(i64Ptr, method, offsetCF); 2389 Expr cf = lmirBuilder_->Iread(i64, addrCF, lmirBuilder_->CreatePtrType(i64)); 2390 // cal new target offset from callField 2391 Expr offsetNVSB = 2392 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, MethodLiteral::NumVregsBits::START_BIT)); 2393 Expr offsetNVSZ = lmirBuilder_->ConstVal( 2394 lmirBuilder_->CreateIntConst(i64, (1LLU << MethodLiteral::NumVregsBits::SIZE) - 1)); 2395 Expr offsetHFSB = 2396 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, MethodLiteral::HaveFuncBit::START_BIT)); 2397 Expr offsetHFSZ = lmirBuilder_->ConstVal( 2398 lmirBuilder_->CreateIntConst(i64, (1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1)); 2399 Expr const0 = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0)); 2400 Expr numVregs = lmirBuilder_->Cvt( 2401 i64, i32, lmirBuilder_->And(i64, lmirBuilder_->LShr(i64, cf, offsetNVSB), offsetNVSZ)); 2402 Expr haveFunc = lmirBuilder_->Cvt( 2403 i64, i32, 2404 lmirBuilder_->ICmp(i64, lmirBuilder_->And(i64, lmirBuilder_->LShr(i64, cf, offsetHFSB), offsetHFSZ), 2405 const0, IntCmpCondition::kNE)); 2406 Expr size = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, JSTaggedValue::TaggedTypeSize())); 2407 Expr offsetNewTarget = lmirBuilder_->Mul( 2408 i64Ptr, lmirBuilder_->ZExt(i32, i64Ptr, lmirBuilder_->Add(i32, numVregs, haveFunc)), size); 2409 // load new target from sp 2410 Expr addrNewTarget = lmirBuilder_->Add(i64Ptr, sp, offsetNewTarget); 2411 Expr ldrNewTarget = lmirBuilder_->Iread(i64Ref, addrNewTarget, lmirBuilder_->CreatePtrType(i64Ptr)); 2412 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrNewTarget, vreg)); 2413 SaveGate2Expr(gate, lmirBuilder_->Regread(vreg)); 2414 return; 2415 } 2416 case INIT_VRGE_THIS_OBJECT: { 2417 // init this 2418 PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref); 2419 // load from frame 2420 Expr sp = lmirBuilder_->GenExprFromVar( 2421 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1)); // 1 : osr second param - sp 2422 Expr offsetFrame = lmirBuilder_->ConstVal( 2423 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64()))); 2424 Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame); 2425 Expr offsetThis = lmirBuilder_->ConstVal( 2426 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetThisOffset(!circuit_->IsArch64()))); 2427 Expr addrThis = lmirBuilder_->Add(i64Ptr, frame, offsetThis); 2428 Expr ldrThis = lmirBuilder_->Iread(i64Ref, addrThis, lmirBuilder_->CreatePtrType(i64Ptr)); 2429 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrThis, vreg)); 2430 SaveGate2Expr(gate, lmirBuilder_->Regread(vreg)); 2431 return; 2432 } 2433 case INIT_VRGE_NUM_ARGS: { 2434 // init numargs 2435 SaveGate2Expr(gate, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0))); 2436 return; 2437 } 2438 case INIT_VRGE_ENV: { 2439 // init env 2440 PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref); 2441 // load from frame 2442 Expr sp = lmirBuilder_->GenExprFromVar( 2443 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1)); // 1 : osr second param - sp 2444 Expr offsetFrame = lmirBuilder_->ConstVal( 2445 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64()))); 2446 Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame); 2447 Expr offsetEnv = lmirBuilder_->ConstVal( 2448 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetEnvOffset(!circuit_->IsArch64()))); 2449 Expr addrEnv = lmirBuilder_->Add(i64Ptr, frame, offsetEnv); 2450 Expr ldrEnv = lmirBuilder_->Iread(i64Ref, addrEnv, lmirBuilder_->CreatePtrType(i64Ptr)); 2451 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrEnv, vreg)); 2452 SaveGate2Expr(gate, lmirBuilder_->Regread(vreg)); 2453 return; 2454 } 2455 default: { 2456 // init vregs 2457 PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref); 2458 // load from sp 2459 Expr sp = lmirBuilder_->GenExprFromVar( 2460 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1)); // 1 : osr second param - sp 2461 Expr offset = 2462 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, vregNumber * sizeof(JSTaggedType))); 2463 Expr addr = lmirBuilder_->Add(i64Ptr, sp, offset); 2464 Expr ldrVreg = lmirBuilder_->Iread(i64Ref, addr, lmirBuilder_->CreatePtrType(i64Ptr)); 2465 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrVreg, vreg)); 2466 SaveGate2Expr(gate, lmirBuilder_->Regread(vreg)); 2467 return; 2468 } 2469 } 2470} 2471 2472void LiteCGIRBuilder::HandleFPTrunc(GateRef gate) 2473{ 2474 VisitFPTrunc(gate, acc_.GetIn(gate, 0)); 2475} 2476 2477void LiteCGIRBuilder::VisitFPTrunc(GateRef gate, GateRef e1) 2478{ 2479 Expr e1Value = GetExprFromGate(e1); 2480 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >= 2481 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2482 Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value); 2483 SaveGate2Expr(gate, result); 2484} 2485 2486void LiteCGIRBuilder::HandleFPExt(GateRef gate) 2487{ 2488 VisitFPExt(gate, acc_.GetIn(gate, 0)); 2489} 2490 2491void LiteCGIRBuilder::VisitFPExt(GateRef gate, GateRef e1) 2492{ 2493 Expr e1Value = GetExprFromGate(e1); 2494 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <= 2495 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2496 Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value); 2497 SaveGate2Expr(gate, result); 2498} 2499 2500void LiteCGIRBuilder::HandleExtractValue(GateRef gate) 2501{ 2502 GateRef pointer = acc_.GetIn(gate, 0); 2503 GateRef index = acc_.GetIn(gate, 1); 2504 VisitExtractValue(gate, pointer, index); 2505} 2506 2507void LiteCGIRBuilder::VisitExtractValue(GateRef gate, GateRef e1, GateRef e2) 2508{ 2509 ASSERT((acc_.GetOpCode(e2) == OpCode::CONSTANT) && acc_.GetMachineType(e2) == MachineType::I32); 2510 uint32_t index = static_cast<uint32_t>(acc_.GetConstantValue(e2)); 2511 Expr expr = GetExprFromGate(e1, index); 2512 PregIdx pregIdx = lmirBuilder_->GetPregIdxFromExpr(expr); 2513 SaveGate2Expr(gate, lmirBuilder_->Regread(pregIdx)); 2514} 2515 2516void LiteCGIRBuilder::HandleStore(GateRef gate) 2517{ 2518 GateRef addr = acc_.GetValueIn(gate, 0); 2519 GateRef value = acc_.GetValueIn(gate, 1); 2520 VisitStore(gate, addr, value); 2521} 2522 2523void LiteCGIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef value) 2524{ 2525 Expr baseAddr = GetExprFromGate(base); 2526 Expr data = GetExprFromGate(value); 2527 2528 LiteCGType *returnType = ConvertLiteCGTypeFromGate(value); 2529 LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(baseAddr.GetType())) 2530 ? lmirBuilder_->CreateRefType(returnType) 2531 : lmirBuilder_->CreatePtrType(returnType); 2532 baseAddr = CanonicalizeToPtr(baseAddr, memType); 2533 2534 Stmt &store = lmirBuilder_->Iassign(data, baseAddr, memType); 2535 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), store); 2536} 2537 2538void LiteCGIRBuilder::HandlePhi(GateRef gate) 2539{ 2540 std::vector<GateRef> ins; 2541 acc_.GetIns(gate, ins); 2542 VisitPhi(gate, ins); 2543} 2544 2545void LiteCGIRBuilder::AddPhiDesc(int bbID, PhiDesc &desc, std::map<int, std::vector<PhiDesc>> &bbID2Phis) 2546{ 2547 auto it = bbID2Phis.find(bbID); 2548 if (it == bbID2Phis.end()) { 2549 std::vector<PhiDesc> vec; 2550 vec.push_back(std::move(desc)); 2551 bbID2Phis.insert(std::make_pair(bbID, vec)); 2552 } else { 2553 it->second.push_back(std::move(desc)); 2554 } 2555} 2556 2557LiteCGIRBuilder::DerivedStatus LiteCGIRBuilder::CheckDerivedPhi(GateRef gate, std::set<GateRef> &vis) 2558{ 2559 // if the gate status is cached with derived or base, doesn't need to go forward 2560 if (derivedGateCache_.find(gate) != derivedGateCache_.end()) { 2561 if (derivedGateCache_[gate]) { 2562 return DerivedStatus::IS_DERIVED; 2563 } else { 2564 return DerivedStatus::IS_BASE; 2565 } 2566 } 2567 // for the visited gate in the dfs, if not cached, its status is unknow 2568 if (vis.find(gate) != vis.end()) { 2569 return DerivedStatus::UNKNOW; 2570 } 2571 // cached gate doesn't need insert to visited set 2572 vis.insert(gate); 2573 DerivedStatus derivedStatus = DerivedStatus::IS_BASE; 2574 std::vector<GateRef> phiIns; 2575 acc_.GetIns(gate, phiIns); 2576 std::vector<GateRef> phiStates; 2577 acc_.GetIns(phiIns[0], phiStates); 2578 ASSERT(phiStates.size() + 1 == phiIns.size()); 2579 for (int i = 1; i < static_cast<int>(phiIns.size()); i++) { 2580 auto op = acc_.GetOpCode(phiIns[i]); 2581 if (op == OpCode::ADD) { 2582 derivedStatus = DerivedStatus::IS_DERIVED; 2583 break; 2584 } else if (op == OpCode::VALUE_SELECTOR) { 2585 DerivedStatus status = CheckDerivedPhi(phiIns[i], vis); 2586 if (status == DerivedStatus::IS_DERIVED) { 2587 derivedStatus = DerivedStatus::IS_DERIVED; 2588 break; 2589 } 2590 if (status == DerivedStatus::UNKNOW) { 2591 derivedStatus = DerivedStatus::UNKNOW; 2592 } 2593 } 2594 } 2595 if (derivedStatus == DerivedStatus::IS_DERIVED) { 2596 derivedGateCache_[gate] = true; 2597 } else if (derivedStatus == DerivedStatus::IS_BASE) { 2598 derivedGateCache_[gate] = false; 2599 } 2600 2601 return derivedStatus; 2602} 2603 2604void LiteCGIRBuilder::FindBaseRefForPhi(GateRef gate, const std::vector<GateRef> &phiIns) 2605{ 2606 int curBBId = instID2bbID_[acc_.GetId(gate)]; 2607 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 2608 PregIdx basePregIdx = 0; 2609 bool isDerived = false; 2610 std::set<GateRef> baseIns; 2611 std::vector<PhiDesc> phiDescs; 2612 std::vector<GateRef> phiStates; 2613 acc_.GetIns(phiIns[0], phiStates); 2614 ASSERT(phiStates.size() + 1 == phiIns.size()); 2615 for (int i = 1; i < static_cast<int>(phiIns.size()); i++) { 2616 int preBBId = LookupPredBB(phiStates[i - 1], curBBId); 2617 if (bbID2BB_.count(preBBId) != 0) { 2618 BB *preBB = bbID2BB_[preBBId]; 2619 if (preBB == nullptr) { 2620 OPTIONAL_LOG_COMPILER(ERROR) << "FindBaseRef failed BasicBlock nullptr"; 2621 return; 2622 } 2623 } 2624 auto op = acc_.GetOpCode(phiIns[i]); 2625 if (op == OpCode::ADD) { 2626 auto g0 = acc_.GetIn(phiIns[i], 0); 2627 baseIns.insert(g0); 2628 PhiDesc desc = {preBBId, g0, basePregIdx}; 2629 phiDescs.push_back(desc); 2630 isDerived = true; 2631 ASSERT(ConvertLiteCGTypeFromGate(g0) == lmirBuilder_->i64RefType); 2632 } else if (op == OpCode::VALUE_SELECTOR) { 2633 std::set<GateRef> vis; 2634 if (CheckDerivedPhi(phiIns[i], vis) == DerivedStatus::IS_DERIVED) { 2635 isDerived = true; 2636 } 2637 baseIns.insert(phiIns[i]); 2638 PhiDesc desc = {preBBId, phiIns[i], basePregIdx}; 2639 phiDescs.push_back(desc); 2640 ASSERT(ConvertLiteCGTypeFromGate(phiIns[i]) == lmirBuilder_->i64RefType); 2641 } else { 2642 baseIns.insert(phiIns[i]); 2643 PhiDesc desc = {preBBId, phiIns[i], basePregIdx}; 2644 phiDescs.push_back(desc); 2645 ASSERT(ConvertLiteCGTypeFromGate(phiIns[i]) == lmirBuilder_->i64RefType); 2646 } 2647 } 2648 2649 // use to catch the situation that the phi is derived 2650 if (isDerived) { 2651 LOG_COMPILER(FATAL) << "catch derived case!" << phiDescs.size() << std::endl; 2652 UNREACHABLE(); 2653 } 2654 2655 derivedGateCache_[gate] = isDerived; 2656 2657 if (!isDerived) { 2658 return; 2659 } 2660 2661 if (baseIns.size() == 1) { 2662 // only one base gate for the derived phi reference, doesn't need to insert a new phi 2663 derivedGate2BaseGate_[gate] = *baseIns.begin(); 2664 } else { 2665 basePregIdx = lmirBuilder_->CreatePreg(type); 2666 derivedPhiGate2BasePhiPreg_[gate] = basePregIdx; 2667 for (PhiDesc desc : phiDescs) { 2668 desc.phi = basePregIdx; 2669 AddPhiDesc(curBBId, desc, bbID2basePhis_); 2670 } 2671 } 2672} 2673 2674void LiteCGIRBuilder::VisitPhi(GateRef gate, const std::vector<GateRef> &phiIns) 2675{ 2676 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 2677 PregIdx phiPregIdx = lmirBuilder_->CreatePreg(type); 2678 2679 if (phiIns.size() > 1) { 2680 SaveGate2Expr(gate, lmirBuilder_->Regread(phiPregIdx)); 2681 } 2682 // Collect the states merges of this phi and note the 1-in is the merged states. 2683 std::vector<GateRef> phiStates; 2684 acc_.GetIns(phiIns[0], phiStates); 2685 ASSERT(phiStates.size() + 1 == phiIns.size()); 2686 int curBBId = instID2bbID_[acc_.GetId(gate)]; 2687 for (int i = 1; i < static_cast<int>(phiIns.size()); i++) { 2688 int preBBId = LookupPredBB(phiStates[i - 1], curBBId); 2689 // if bbID2BB_.count(preBBId) = 0 means bb with current bbIdx hasn't been created 2690 if (bbID2BB_.count(preBBId) != 0) { 2691 BB *preBB = bbID2BB_[preBBId]; 2692 if (preBB == nullptr) { 2693 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed BasicBlock nullptr"; 2694 return; 2695 } 2696 PhiDesc desc = {preBBId, phiIns[i], phiPregIdx}; 2697 AddPhiDesc(curBBId, desc, bbID2unmergedPhis_); 2698 } else { 2699 PhiDesc desc = {preBBId, phiIns[i], phiPregIdx}; 2700 AddPhiDesc(curBBId, desc, bbID2unmergedPhis_); 2701 } 2702 } 2703 2704 if (type == lmirBuilder_->i64RefType) { 2705 FindBaseRefForPhi(gate, phiIns); 2706 } 2707} 2708 2709void LiteCGIRBuilder::HandleSwitch(GateRef gate) 2710{ 2711 std::vector<GateRef> ins; 2712 acc_.GetIns(gate, ins); 2713 std::vector<GateRef> outs; 2714 acc_.GetOutStates(gate, outs); 2715 VisitSwitch(gate, ins[1], outs); 2716} 2717 2718void LiteCGIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<GateRef> &outList) 2719{ 2720 Expr cond = GetExprFromGate(input); 2721 int caseNum = static_cast<int>(outList.size()); 2722 BB *defaultOutBB = nullptr; 2723 for (int i = 0; i < caseNum; i++) { 2724 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) { 2725 defaultOutBB = &GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]); 2726 } 2727 } 2728 2729 LiteCGType *type = ConvertLiteCGTypeFromGate(gate); 2730 CHECK_NULL_FATAL(defaultOutBB); 2731 SwitchBuilder builder = lmirBuilder_->Switch(type, cond, *defaultOutBB); 2732 for (int i = 0; i < caseNum; i++) { 2733 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) { 2734 continue; 2735 } 2736 BB &curOutBB = GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]); 2737 builder.Case(acc_.TryGetValue(outList[i]), curOutBB); 2738 } 2739 Stmt &switchStmt = builder.Done(); 2740 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), switchStmt); 2741 lmirBuilder_->AppendBB(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)])); 2742} 2743 2744void LiteCGIRBuilder::HandleDeoptCheck(GateRef gate) 2745{ 2746 int block = instID2bbID_[acc_.GetId(gate)]; 2747 std::vector<GateRef> outs; 2748 acc_.GetOutStates(gate, outs); 2749 int bbOut = instID2bbID_[acc_.GetId(outs[0])]; // 0: output 2750 2751 BB &trueBB = GetOrCreateBB(bbOut); 2752 BB &falseBB = lmirBuilder_->CreateBB(); 2753 GateRef cmp = acc_.GetValueIn(gate, 0); // 0: cond 2754 Expr cond = GetExprFromGate(cmp); 2755 BB &curBB = GetOrCreateBB(block); 2756 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->CondGoto(cond, falseBB, false)); 2757 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Goto(trueBB)); 2758 lmirBuilder_->AppendBB(curBB); 2759 // deopt branch is not expected to be token as often, 2760 // just put them to the end of the function 2761 lmirBuilder_->AppendToLast(falseBB); 2762 2763 VisitDeoptCheck(gate); 2764 Expr returnValue = GetExprFromGate(gate); 2765 lmirBuilder_->AppendStmt(falseBB, lmirBuilder_->Return(returnValue)); 2766} 2767 2768LiteCGType *LiteCGIRBuilder::GetExperimentalDeoptTy() 2769{ 2770 std::vector<LiteCGType *> paramTys = {lmirBuilder_->i64Type, lmirBuilder_->i64RefType, lmirBuilder_->i64RefType}; 2771 LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, lmirBuilder_->i64RefType, false); 2772 return functionType; 2773} 2774 2775void LiteCGIRBuilder::SaveFrameTypeOnFrame(BB &bb, FrameType frameType) 2776{ 2777 Expr llvmFpAddr = CallingFp(false); 2778 Expr frameAddr = lmirBuilder_->Cvt(llvmFpAddr.GetType(), slotType_, llvmFpAddr); 2779 Expr frameTypeSlotAddr = lmirBuilder_->Sub( 2780 slotType_, frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_))); 2781 LiteCGType *slotTypePtr = lmirBuilder_->CreatePtrType(slotType_); 2782 Expr addr = lmirBuilder_->Cvt(frameTypeSlotAddr.GetType(), slotTypePtr, frameTypeSlotAddr); 2783 Expr llvmFrameType = 2784 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, static_cast<uintptr_t>(frameType))); 2785 Stmt &stmt = lmirBuilder_->Iassign(llvmFrameType, addr, slotTypePtr); 2786 lmirBuilder_->AppendStmt(bb, stmt); 2787} 2788 2789void LiteCGIRBuilder::GenDeoptEntry(std::string funcName) 2790{ 2791 BB &bb = CreateBB(); 2792 auto reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); 2793 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); 2794 SaveFrameTypeOnFrame(bb, FrameType::OPTIMIZED_FRAME); 2795 Function &func = lmirBuilder_->GetCurFunction(); 2796 lmirModule_->SetFunction(LMIRModule::kDeoptEntryOffset, funcName, false); 2797 2798 Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 0)); 2799 Expr check = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 1)); 2800 Expr depth = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 2)); 2801 2802 StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm); 2803 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 2804 Expr rtoffset = lmirBuilder_->Add(glue.GetType(), glue, GetRTStubOffset(glue, stubIndex)); 2805 Expr patchAddr = lmirBuilder_->Cvt(glue.GetType(), lmirBuilder_->i64PtrType, rtoffset); 2806 Expr funcAddr = lmirBuilder_->Iread(rtoffset.GetType(), patchAddr, lmirBuilder_->i64PtrType); 2807 2808 LiteCGType *funcType = GetExperimentalDeoptTy(); 2809 LiteCGType *funcTypePtr = lmirBuilder_->CreatePtrType(funcType); 2810 LiteCGType *funcTypePtrPtr = lmirBuilder_->CreatePtrType(funcTypePtr); 2811 Expr callee = lmirBuilder_->Cvt(glue.GetType(), funcTypePtrPtr, funcAddr); 2812 2813 Var &funcVar = lmirBuilder_->CreateLocalVar(callee.GetType(), "DeoptimizeSubFunc"); 2814 Stmt &funcAddrNode = lmirBuilder_->Dassign(callee, funcVar); 2815 lmirBuilder_->AppendStmt(bb, funcAddrNode); 2816 2817 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType); 2818 PregIdx pregIdx = lmirBuilder_->CreatePreg(returnType); 2819 std::vector<Expr> params = {glue, check, depth}; 2820 Stmt &callNode = lmirBuilder_->ICall(lmirBuilder_->Dread(funcVar), params, pregIdx); 2821 lmirBuilder_->AppendStmt(bb, callNode); 2822 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Return(lmirBuilder_->Regread(pregIdx))); 2823 lmirBuilder_->AppendBB(bb); 2824} 2825 2826Function *LiteCGIRBuilder::GetExperimentalDeopt() 2827{ 2828 /* 0:calling 1:its caller */ 2829 std::string funcName = "litecg.experimental.deoptimize.p1i64"; 2830 auto fn = lmirBuilder_->GetFunc(funcName); 2831 if (!fn) { 2832 // save previous func for restore env 2833 Function &preFunc = lmirBuilder_->GetCurFunction(); 2834 auto fnTy = GetExperimentalDeoptTy(); 2835 FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName); 2836 // glue type depth 2837 funcBuilder.Param(lmirBuilder_->i64Type, "glue") 2838 .Param(lmirBuilder_->i64RefType, "deopt_type") 2839 .Param(lmirBuilder_->i64RefType, "max_depth"); 2840 Function &curFunc = funcBuilder.Return(lmirBuilder_->LiteCGGetFuncReturnType(fnTy)).Done(); 2841 funcBuilder.CallConvAttribute(maple::litecg::CCall); 2842 lmirBuilder_->SetCurFunc(curFunc); 2843 GenDeoptEntry(funcName); 2844 fn = &curFunc; 2845 2846 lmirBuilder_->SetCurFunc(preFunc); 2847 } 2848 return fn; 2849} 2850 2851Expr LiteCGIRBuilder::ConvertToTagged(GateRef gate) 2852{ 2853 auto machineType = acc_.GetMachineType(gate); 2854 switch (machineType) { 2855 case MachineType::I1: 2856 return ConvertBoolToTaggedBoolean(gate); 2857 case MachineType::I32: 2858 return ConvertInt32ToTaggedInt(GetExprFromGate(gate)); 2859 case MachineType::F64: 2860 return ConvertFloat64ToTaggedDouble(gate); 2861 case MachineType::I64: 2862 break; 2863 default: 2864 LOG_COMPILER(FATAL) << "unexpected machineType!"; 2865 UNREACHABLE(); 2866 break; 2867 } 2868 return GetExprFromGate(gate); 2869} 2870 2871Expr LiteCGIRBuilder::ConvertInt32ToTaggedInt(Expr value) 2872{ 2873 Expr e1Value = lmirBuilder_->SExt(value.GetType(), lmirBuilder_->i64Type, value); 2874 Expr tagMask = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_INT)); 2875 Expr result = lmirBuilder_->Or(lmirBuilder_->i64Type, e1Value, tagMask); 2876 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result); 2877} 2878 2879Expr LiteCGIRBuilder::ConvertBoolToTaggedBoolean(GateRef gate) 2880{ 2881 Expr value = GetExprFromGate(gate); 2882 Expr e1Value = lmirBuilder_->ZExt(value.GetType(), lmirBuilder_->u64Type, value); 2883 Expr tagMask = 2884 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_BOOLEAN_MASK)); 2885 Expr result = lmirBuilder_->Or(lmirBuilder_->u64Type, e1Value, tagMask); 2886 return lmirBuilder_->Cvt(lmirBuilder_->u64Type, lmirBuilder_->i64RefType, result); 2887} 2888 2889Expr LiteCGIRBuilder::ConvertFloat64ToTaggedDouble(GateRef gate) 2890{ 2891 Expr value = GetExprFromGate(gate); 2892 Expr e1Value = lmirBuilder_->BitCast(value.GetType(), lmirBuilder_->i64Type, value); 2893 Expr offset = lmirBuilder_->ConstVal( 2894 lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::DOUBLE_ENCODE_OFFSET)); 2895 Expr result = lmirBuilder_->Add(lmirBuilder_->i64Type, e1Value, offset); 2896 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result); 2897} 2898 2899void LiteCGIRBuilder::SaveDeoptVregInfo(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb, int32_t index, 2900 size_t curDepth, size_t shift, GateRef gate) 2901{ 2902 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift); 2903 Expr value = ConvertToTagged(gate); 2904 PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType()); 2905 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx)); 2906 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kPregKind, pregIdx})); 2907} 2908 2909void LiteCGIRBuilder::SaveDeoptVregInfoWithI64(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb, 2910 int32_t index, size_t curDepth, size_t shift, GateRef gate) 2911{ 2912 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift); 2913 Expr expr = GetExprFromGate(gate); 2914 Expr value = ConvertInt32ToTaggedInt(lmirBuilder_->Cvt(expr.GetType(), lmirBuilder_->i32Type, expr)); 2915 PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType()); 2916 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx)); 2917 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kPregKind, pregIdx})); 2918} 2919 2920void LiteCGIRBuilder::VisitDeoptCheck(GateRef gate) 2921{ 2922 BB &bb = lmirBuilder_->GetLastAppendedBB(); // falseBB of deopt check 2923 Expr glue = GetExprFromGate(acc_.GetGlueFromArgList()); 2924 GateRef deoptFrameState = acc_.GetValueIn(gate, 1); // 1: frame state 2925 ASSERT(acc_.GetOpCode(deoptFrameState) == OpCode::FRAME_STATE); 2926 std::vector<Expr> params; 2927 params.push_back(glue); // glue 2928 GateRef deoptType = acc_.GetValueIn(gate, 2); // 2: deopt type 2929 uint64_t v = acc_.GetConstantValue(deoptType); 2930 Expr constV = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(v))); 2931 params.push_back(ConvertInt32ToTaggedInt(constV)); // deoptType 2932 Function *callee = GetExperimentalDeopt(); 2933 LiteCGType *funcType = GetExperimentalDeoptTy(); 2934 2935 std::unordered_map<int, LiteCGValue> deoptBundleInfo; 2936 size_t maxDepth = 0; 2937 GateRef frameState = acc_.GetFrameState(deoptFrameState); 2938 while ((acc_.GetOpCode(frameState) == OpCode::FRAME_STATE)) { 2939 maxDepth++; 2940 frameState = acc_.GetFrameState(frameState); 2941 } 2942 Expr constMaxDepth = 2943 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(maxDepth))); 2944 params.push_back(ConvertInt32ToTaggedInt(constMaxDepth)); 2945 size_t shift = Deoptimizier::ComputeShift(maxDepth); 2946 frameState = deoptFrameState; 2947 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_)); 2948 for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) { 2949 ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE); 2950 GateRef frameValues = acc_.GetValueIn(frameState, 1); // 1: frame values 2951 const size_t numValueIn = acc_.GetNumValueIn(frameValues); 2952 const size_t envIndex = numValueIn - 2; // 2: env valueIn index 2953 CHECK_FATAL(numValueIn > 0, "must not be zero"); 2954 const size_t accIndex = numValueIn - 1; // 1: acc valueIn index 2955 GateRef env = acc_.GetValueIn(frameValues, envIndex); 2956 GateRef acc = acc_.GetValueIn(frameValues, accIndex); 2957 auto pc = acc_.TryGetPcOffset(frameState); 2958 GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC); 2959 GateRef newTarget = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::NEW_TARGET); 2960 GateRef thisObj = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::THIS_OBJECT); 2961 GateRef actualArgc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::ACTUAL_ARGC); 2962 // vreg 2963 for (size_t i = 0; i < envIndex; i++) { 2964 GateRef vregValue = acc_.GetValueIn(frameValues, i); 2965 if (acc_.IsConstantTaggedValue(vregValue, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2966 continue; 2967 } 2968 SaveDeoptVregInfo(deoptBundleInfo, bb, i, curDepth, shift, vregValue); 2969 } 2970 // env 2971 if (!acc_.IsConstantTaggedValue(env, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2972 int32_t specEnvVregIndex = static_cast<int32_t>(SpecVregIndex::ENV_INDEX); 2973 SaveDeoptVregInfo(deoptBundleInfo, bb, specEnvVregIndex, curDepth, shift, env); 2974 } 2975 // acc 2976 if (!acc_.IsConstantTaggedValue(acc, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2977 int32_t specAccVregIndex = static_cast<int32_t>(SpecVregIndex::ACC_INDEX); 2978 SaveDeoptVregInfo(deoptBundleInfo, bb, specAccVregIndex, curDepth, shift, acc); 2979 } 2980 // pc offset 2981 int32_t specPcOffsetIndex = static_cast<int32_t>(SpecVregIndex::PC_OFFSET_INDEX); 2982 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specPcOffsetIndex, curDepth, shift); 2983 Const &pcConst = lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, pc); 2984 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kConstKind, &pcConst})); 2985 2986 // func 2987 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FUNC_INDEX); 2988 SaveDeoptVregInfo(deoptBundleInfo, bb, specCallTargetIndex, curDepth, shift, jsFunc); 2989 // newTarget 2990 int32_t specNewTargetIndex = static_cast<int32_t>(SpecVregIndex::NEWTARGET_INDEX); 2991 SaveDeoptVregInfo(deoptBundleInfo, bb, specNewTargetIndex, curDepth, shift, newTarget); 2992 // this object 2993 int32_t specThisIndex = static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX); 2994 SaveDeoptVregInfo(deoptBundleInfo, bb, specThisIndex, curDepth, shift, thisObj); 2995 int32_t specArgcIndex = static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX); 2996 SaveDeoptVregInfoWithI64(deoptBundleInfo, bb, specArgcIndex, curDepth, shift, actualArgc); 2997 frameState = acc_.GetFrameState(frameState); 2998 } 2999 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType); 3000 3001 bool returnVoid = (returnType == lmirBuilder_->voidType); 3002 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType); 3003 3004 Stmt &callNode = lmirBuilder_->Call(*callee, params, returnPregIdx); 3005 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo); 3006 3007 lmirBuilder_->AppendStmt(bb, callNode); 3008 if (!returnVoid) { 3009 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx)); 3010 } 3011} 3012 3013int64_t LiteCGIRBuilder::GetBitWidthFromMachineType(MachineType machineType) const 3014{ 3015 switch (machineType) { 3016 case NOVALUE: 3017 return 0; 3018 case ARCH: 3019 return 48; // 48: Pointer representation in different architectures 3020 case I1: 3021 return 1; 3022 case I8: 3023 return 8; // 8: bit width 3024 case I16: 3025 return 16; // 16: bit width 3026 case I32: 3027 return 32; // 32: bit width 3028 case I64: 3029 return 64; // 64: bit width 3030 case F32: 3031 return 32; // 32: bit width 3032 case F64: 3033 return 64; // 64: bit width 3034 case FLEX: 3035 case ANYVALUE: 3036 LOG_ECMA(FATAL) << "this branch is unreachable"; 3037 UNREACHABLE(); 3038 default: 3039 LOG_ECMA(FATAL) << "this branch is unreachable"; 3040 UNREACHABLE(); 3041 } 3042} 3043 3044int LiteCGIRBuilder::LookupPredBB(GateRef start, int bbID) 3045{ 3046 GateId gateId = acc_.GetId(start); 3047 int owner = instID2bbID_[gateId]; 3048 if (owner != bbID) { 3049 return owner; 3050 } 3051 GateRef pred = start; 3052 while (owner == bbID) { 3053 pred = acc_.GetState(pred); 3054 auto id = acc_.GetId(pred); 3055 owner = instID2bbID_[id]; 3056 } 3057 return owner; 3058} 3059 3060} // namespace panda::ecmascript::kungfu 3061