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/llvm/llvm_ir_builder.h" 17 18#include <cmath> 19 20#include "ecmascript/compiler/argument_accessor.h" 21#include "ecmascript/compiler/bc_call_signature.h" 22#include "ecmascript/compiler/baseline/baseline_call_signature.h" 23#include "ecmascript/compiler/circuit.h" 24#include "ecmascript/compiler/call_signature.h" 25#include "ecmascript/compiler/debug_info.h" 26#include "ecmascript/compiler/gate.h" 27#include "ecmascript/compiler/share_gate_meta_data.h" 28#include "ecmascript/compiler/rt_call_signature.h" 29#include "ecmascript/compiler/baseline/baseline_stub_csigns.h" 30#include "ecmascript/deoptimizer/deoptimizer.h" 31#include "ecmascript/frames.h" 32#include "ecmascript/js_thread.h" 33#include "ecmascript/method.h" 34#include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h" 35 36#if defined(__clang__) 37#pragma clang diagnostic push 38#pragma clang diagnostic ignored "-Wshadow" 39#pragma clang diagnostic ignored "-Wunused-parameter" 40#pragma clang diagnostic ignored "-Wdeprecated-declarations" 41#elif defined(__GNUC__) 42#pragma GCC diagnostic push 43#pragma GCC diagnostic ignored "-Wshadow" 44#pragma GCC diagnostic ignored "-Wunused-parameter" 45#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 46#endif 47 48#include "llvm/IR/Instructions.h" 49#include "llvm/IR/Intrinsics.h" 50#include "llvm/IR/IRBuilder.h" 51 52#if defined(__clang__) 53#pragma clang diagnostic pop 54#elif defined(__GNUC__) 55#pragma GCC diagnostic pop 56#endif 57 58#include "llvm/Support/Host.h" 59#include "securec.h" 60 61namespace panda::ecmascript::kungfu { 62LLVMIRBuilder::LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit, 63 LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg, 64 CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, 65 const std::string &funcName, bool enableOptInlining, bool enableBranchProfiling) 66 : compCfg_(cfg), scheduledGates_(schedule), circuit_(circuit), acc_(circuit), module_(module->GetModule()), 67 function_(function), llvmModule_(module), callConv_(callConv), enableLog_(enableLog), 68 isFastCallAot_(isFastCallAot), enableOptInlining_(enableOptInlining), 69 enableOptBranchProfiling_(enableBranchProfiling) 70{ 71 ASSERT(compCfg_->Is64Bit()); 72 context_ = module->GetContext(); 73 builder_ = LLVMCreateBuilderInContext(context_); 74 bbID2BB_.clear(); 75 SetFunctionCallConv(); 76 InitializeHandlers(); 77 78 LLVMSetGC(function_, "statepoint-example"); 79 slotSize_ = sizeof(uint64_t); 80 slotType_ = GetInt64T(); 81 82 LLVMMetadataRef dFile = llvmModule_->GetDFileMD(); 83 LLVMMetadataRef funcTyMD = GetFunctionTypeMD(dFile); 84 size_t funcOffset = 0; 85 dFuncMD_ = LLVMDIBuilderCreateFunction(GetDIBuilder(), dFile, funcName.c_str(), funcName.size(), 86 funcName.c_str(), funcName.size(), dFile, funcOffset, 87 funcTyMD, true, true, 0, LLVMDIFlags::LLVMDIFlagZero, false); 88 LLVMSetSubprogram(function_, dFuncMD_); 89 std::string triple = LLVMGetTarget(module->GetModule()); 90 ASSERT(GlobalTargetBuilders().count(triple) && "unsupported target"); 91 targetBuilder_ = GlobalTargetBuilders()[triple](); 92 ASMBarrierCall_ = targetBuilder_->GetASMBarrierCall(module); 93} 94 95LLVMMetadataRef LLVMIRBuilder::GetFunctionTypeMD(LLVMMetadataRef dFile) 96{ 97 LLVMDIBuilderRef builder = GetDIBuilder(); 98 LLVMMetadataRef Int64Ty = LLVMDIBuilderCreateBasicType(builder, "Int64", 5, 64, 0, LLVMDIFlags::LLVMDIFlagZero); 99 LLVMMetadataRef paramT[] = { nullptr, Int64Ty }; // need to compute the real types for parameters in the future. 100 LLVMMetadataRef funcTy = LLVMDIBuilderCreateSubroutineType(builder, dFile, paramT, 2, LLVMDIFlags::LLVMDIFlagZero); 101 return funcTy; 102} 103 104LLVMIRBuilder::~LLVMIRBuilder() 105{ 106 if (builder_ != nullptr) { 107 LLVMDisposeBuilder(builder_); 108 builder_ = nullptr; 109 } 110 delete targetBuilder_; 111} 112 113void LLVMIRBuilder::SetFunctionCallConv() 114{ 115 switch (callConv_) { 116 case CallSignature::CallConv::GHCCallConv: 117 LLVMSetFunctionCallConv(function_, LLVMGHCCallConv); 118 break; 119 case CallSignature::CallConv::WebKitJSCallConv: { 120 LLVMSetFunctionCallConv(function_, LLVMWebKitJSCallConv); 121 break; 122 } 123 default: { 124 LLVMSetFunctionCallConv(function_, LLVMCCallConv); 125 callConv_ = CallSignature::CallConv::CCallConv; 126 break; 127 } 128 } 129} 130 131int LLVMIRBuilder::FindBasicBlock(GateRef gate) const 132{ 133 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) { 134 const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx); 135 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) { 136 GateRef tmp = bb[instIdx - 1]; 137 if (tmp == gate) { 138 return bbIdx; 139 } 140 } 141 } 142 return -1; 143} 144 145void LLVMIRBuilder::InitializeHandlers() 146{ 147 opHandlers_ = { 148 {OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto}, 149 {OpCode::RETURN, &LLVMIRBuilder::HandleReturn}, 150 {OpCode::RETURN_VOID, &LLVMIRBuilder::HandleReturnVoid}, 151 {OpCode::IF_BRANCH, &LLVMIRBuilder::HandleBranch}, 152 {OpCode::SWITCH_BRANCH, &LLVMIRBuilder::HandleSwitch}, 153 {OpCode::ORDINARY_BLOCK, &LLVMIRBuilder::HandleGoto}, 154 {OpCode::IF_TRUE, &LLVMIRBuilder::HandleGoto}, 155 {OpCode::IF_FALSE, &LLVMIRBuilder::HandleGoto}, 156 {OpCode::SWITCH_CASE, &LLVMIRBuilder::HandleGoto}, 157 {OpCode::MERGE, &LLVMIRBuilder::HandleGoto}, 158 {OpCode::DEFAULT_CASE, &LLVMIRBuilder::HandleGoto}, 159 {OpCode::LOOP_BEGIN, &LLVMIRBuilder::HandleGoto}, 160 {OpCode::LOOP_BACK, &LLVMIRBuilder::HandleGoto}, 161 {OpCode::VALUE_SELECTOR, &LLVMIRBuilder::HandlePhi}, 162 {OpCode::ASM_CALL_BARRIER, &LLVMIRBuilder::HandleCall}, 163 {OpCode::RUNTIME_CALL, &LLVMIRBuilder::HandleRuntimeCall}, 164 {OpCode::RUNTIME_CALL_WITH_ARGV, &LLVMIRBuilder::HandleRuntimeCallWithArgv}, 165 {OpCode::NOGC_RUNTIME_CALL, &LLVMIRBuilder::HandleCall}, 166 {OpCode::CALL_OPTIMIZED, &LLVMIRBuilder::HandleCall}, 167 {OpCode::FAST_CALL_OPTIMIZED, &LLVMIRBuilder::HandleCall}, 168 {OpCode::CALL, &LLVMIRBuilder::HandleCall}, 169 {OpCode::BASELINE_CALL, &LLVMIRBuilder::HandleCall}, 170 {OpCode::BYTECODE_CALL, &LLVMIRBuilder::HandleBytecodeCall}, 171 {OpCode::DEBUGGER_BYTECODE_CALL, &LLVMIRBuilder::HandleBytecodeCall}, 172 {OpCode::BUILTINS_CALL, &LLVMIRBuilder::HandleCall}, 173 {OpCode::BUILTINS_CALL_WITH_ARGV, &LLVMIRBuilder::HandleCall}, 174 {OpCode::ALLOCA, &LLVMIRBuilder::HandleAlloca}, 175 {OpCode::ARG, &LLVMIRBuilder::HandleParameter}, 176 {OpCode::CONSTANT, &LLVMIRBuilder::HandleConstant}, 177 {OpCode::CONSTSTRING, &LLVMIRBuilder::HandleConstString}, 178 {OpCode::RELOCATABLE_DATA, &LLVMIRBuilder::HandleRelocatableData}, 179 {OpCode::ZEXT, &LLVMIRBuilder::HandleZExtInt}, 180 {OpCode::SEXT, &LLVMIRBuilder::HandleSExtInt}, 181 {OpCode::TRUNC, &LLVMIRBuilder::HandleCastIntXToIntY}, 182 {OpCode::FEXT, &LLVMIRBuilder::HandleFPExt}, 183 {OpCode::FTRUNC, &LLVMIRBuilder::HandleFPTrunc}, 184 {OpCode::REV, &LLVMIRBuilder::HandleIntRev}, 185 {OpCode::ADD, &LLVMIRBuilder::HandleAdd}, 186 {OpCode::SUB, &LLVMIRBuilder::HandleSub}, 187 {OpCode::MUL, &LLVMIRBuilder::HandleMul}, 188 {OpCode::FDIV, &LLVMIRBuilder::HandleFloatDiv}, 189 {OpCode::SDIV, &LLVMIRBuilder::HandleIntDiv}, 190 {OpCode::UDIV, &LLVMIRBuilder::HandleUDiv}, 191 {OpCode::AND, &LLVMIRBuilder::HandleIntAnd}, 192 {OpCode::OR, &LLVMIRBuilder::HandleIntOr}, 193 {OpCode::XOR, &LLVMIRBuilder::HandleIntXor}, 194 {OpCode::LSR, &LLVMIRBuilder::HandleIntLsr}, 195 {OpCode::ASR, &LLVMIRBuilder::HandleIntAsr}, 196 {OpCode::ICMP, &LLVMIRBuilder::HandleCmp}, 197 {OpCode::FCMP, &LLVMIRBuilder::HandleCmp}, 198 {OpCode::LOAD, &LLVMIRBuilder::HandleLoad}, 199 {OpCode::STORE_WITHOUT_BARRIER, &LLVMIRBuilder::HandleStore}, 200 {OpCode::SIGNED_INT_TO_FLOAT, &LLVMIRBuilder::HandleChangeInt32ToDouble}, 201 {OpCode::UNSIGNED_INT_TO_FLOAT, &LLVMIRBuilder::HandleChangeUInt32ToDouble}, 202 {OpCode::FLOAT_TO_SIGNED_INT, &LLVMIRBuilder::HandleChangeDoubleToInt32}, 203 {OpCode::TAGGED_TO_INT64, &LLVMIRBuilder::HandleChangeTaggedPointerToInt64}, 204 {OpCode::INT64_TO_TAGGED, &LLVMIRBuilder::HandleChangeInt64ToTagged}, 205 {OpCode::BITCAST, &LLVMIRBuilder::HandleBitCast}, 206 {OpCode::LSL, &LLVMIRBuilder::HandleIntLsl}, 207 {OpCode::SMOD, &LLVMIRBuilder::HandleMod}, 208 {OpCode::FMOD, &LLVMIRBuilder::HandleMod}, 209 {OpCode::DEOPT_CHECK, &LLVMIRBuilder::HandleDeoptCheck}, 210 {OpCode::TRUNC_FLOAT_TO_INT64, &LLVMIRBuilder::HandleTruncFloatToInt}, 211 {OpCode::TRUNC_FLOAT_TO_INT32, &LLVMIRBuilder::HandleTruncFloatToInt}, 212 {OpCode::ADD_WITH_OVERFLOW, &LLVMIRBuilder::HandleAddWithOverflow}, 213 {OpCode::SUB_WITH_OVERFLOW, &LLVMIRBuilder::HandleSubWithOverflow}, 214 {OpCode::MUL_WITH_OVERFLOW, &LLVMIRBuilder::HandleMulWithOverflow}, 215 {OpCode::EXTRACT_VALUE, &LLVMIRBuilder::HandleExtractValue}, 216 {OpCode::SQRT, &LLVMIRBuilder::HandleSqrt}, 217 {OpCode::EXP, &LLVMIRBuilder::HandleExp}, 218 {OpCode::ABS, &LLVMIRBuilder::HandleAbs}, 219 {OpCode::MIN, &LLVMIRBuilder::HandleMin}, 220 {OpCode::MAX, &LLVMIRBuilder::HandleMax}, 221 {OpCode::CLZ32, &LLVMIRBuilder::HandleClz32}, 222 {OpCode::DOUBLE_TRUNC, &LLVMIRBuilder::HandleDoubleTrunc}, 223 {OpCode::CEIL, &LLVMIRBuilder::HandleCeil}, 224 {OpCode::FLOOR, &LLVMIRBuilder::HandleFloor}, 225 {OpCode::READSP, &LLVMIRBuilder::HandleReadSp}, 226 {OpCode::FINISH_ALLOCATE, &LLVMIRBuilder::HandleFinishAllocate}, 227 }; 228 illegalOpHandlers_ = { 229 OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY, 230 OpCode::DEAD, OpCode::RETURN_LIST, 231 OpCode::ARG_LIST, OpCode::THROW, 232 OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, 233 OpCode::FRAME_STATE, OpCode::STATE_SPLIT, OpCode::FRAME_ARGS, 234 OpCode::LOOP_EXIT_DEPEND, OpCode::LOOP_EXIT, 235 OpCode::START_ALLOCATE, OpCode::FRAME_VALUES 236 }; 237} 238 239std::string LLVMIRBuilder::LLVMValueToString(LLVMValueRef val) const 240{ 241 char* msg = LLVMPrintValueToString(val); 242 std::string str(msg); 243 LLVMDisposeMessage(msg); 244 return str; 245} 246 247void LLVMIRBuilder::Build() 248{ 249 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) { 250 const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx); 251 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) { 252 GateId gateId = acc_.GetId(bb[instIdx - 1]); 253 instID2bbID_[gateId] = static_cast<int>(bbIdx); 254 } 255 } 256 257 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) { 258 const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx); 259 OperandsVector predecessors; 260 auto ins = acc_.Ins(bb[0]); 261 for (auto i = ins.begin(); i != ins.end(); i++) { 262 GateRef r = *i; 263 if (!acc_.IsState(r)) { 264 continue; 265 } 266 predecessors.insert(instID2bbID_[acc_.GetId(r)]); 267 } 268 LinkToLLVMCfg(bbIdx, predecessors); 269 270 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) { 271 GateRef gate = bb[instIdx - 1]; 272 auto found = opHandlers_.find(acc_.GetOpCode(gate)); 273 if (found != opHandlers_.end()) { 274 (this->*(found->second))(gate); 275 continue; 276 } 277 if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) { 278 acc_.Print(gate); 279 LOG_COMPILER(FATAL) << "The gate below need to be translated "; 280 UNREACHABLE(); 281 } 282 } 283 } 284 Finish(); 285} 286 287BasicBlock *LLVMIRBuilder::EnsureBB(int id) 288{ 289 BasicBlock *bb = nullptr; 290 if (bbID2BB_.count(id) == 0) { 291 auto newBB = std::make_unique<BasicBlock>(id); 292 bb = newBB.get(); 293 bbID2BB_[id] = std::move(newBB); 294 } else { 295 bb = bbID2BB_[id].get(); 296 } 297 return bb; 298} 299 300void LLVMIRBuilder::SetToCfg(BasicBlock *bb) const 301{ 302 EnsureLBB(bb); 303 BasicBlockImpl *impl = bb->GetImpl<BasicBlockImpl>(); 304 if ((impl == nullptr) || (impl->lBB_ == nullptr)) { 305 LOG_COMPILER(ERROR) << "SetToCfg failed "; 306 return; 307 } 308 impl->started = true; 309 bb->SetImpl(impl); 310 LLVMPositionBuilderAtEnd(builder_, impl->lBB_); 311} 312 313void LLVMIRBuilder::ProcessPhiWorkList() 314{ 315 for (BasicBlock *bb : phiRebuildWorklist_) { 316 auto impl = bb->GetImpl<BasicBlockImpl>(); 317 for (auto &e : impl->unmergedPhis_) { 318 ASSERT(bbID2BB_.count(e.predBBId) > 0); 319 BasicBlock *pred = bbID2BB_[e.predBBId].get(); 320 if (!impl->started) { 321 OPTIONAL_LOG_COMPILER(ERROR) << " ProcessPhiWorkList error hav't start "; 322 return; 323 } 324 LLVMValueRef value = GetLValue(e.operand); 325 if (LLVMTypeOf(value) != LLVMTypeOf(e.phi)) { 326 OPTIONAL_LOG_COMPILER(ERROR) << " ProcessPhiWorkList LLVMTypeOf don't match error "; 327 } 328 LLVMBasicBlockRef llvmBB = EnsureLBB(pred); 329 LLVMAddIncoming(e.phi, &value, &llvmBB, 1); 330 } 331 impl->unmergedPhis_.clear(); 332 } 333 phiRebuildWorklist_.clear(); 334} 335 336void LLVMIRBuilder::EndCurrentBlock() const 337{ 338 BasicBlockImpl *impl = currentBb_->GetImpl<BasicBlockImpl>(); 339 impl->ended = true; 340} 341 342void LLVMIRBuilder::Finish() 343{ 344 ASSERT(!!currentBb_); 345 EndCurrentBlock(); 346 ProcessPhiWorkList(); 347 for (auto &it : bbID2BB_) { 348 it.second->ResetImpl<BasicBlockImpl>(); 349 } 350 LLVMDIBuilderFinalize(GetDIBuilder()); 351} 352 353BasicBlockImpl *LLVMIRBuilder::EnsureBBImpl(BasicBlock *bb) const 354{ 355 if (bb->GetImpl<BasicBlockImpl>()) { 356 return bb->GetImpl<BasicBlockImpl>(); 357 } 358 auto impl = std::make_unique<BasicBlockImpl>(); 359 bb->SetImpl(impl.release()); 360 return bb->GetImpl<BasicBlockImpl>(); 361} 362 363void LLVMIRBuilder::AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType) 364{ 365 LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", 366 std::to_string(reservedSlotsSize).c_str()); 367 auto ArgList = circuit_->GetArgRoot(); 368 auto uses = acc_.Uses(ArgList); 369 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { 370 int argth = static_cast<int>(acc_.TryGetValue(*useIt)); 371 LLVMValueRef value = LLVMGetParam(function_, argth); 372 int funcIndex = 0; 373 if (isFastCallAot_) { 374 frameType = FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 375 funcIndex = static_cast<int>(FastCallArgIdx::FUNC); 376 } else { 377 funcIndex = static_cast<int>(CommonArgIdx::FUNC); 378 } 379 if (argth == funcIndex) { 380 SaveByteCodePcOnOptJSFuncFrame(value); 381 SaveJSFuncOnOptJSFuncFrame(value); 382 SaveFrameTypeOnFrame(frameType, builder_); 383 } 384 } 385} 386 387void LLVMIRBuilder::GenPrologue() 388{ 389 auto frameType = circuit_->GetFrameType(); 390 if (IsInterpreted()) { 391 return; 392 } 393 LLVMAddTargetDependentFunctionAttr(function_, "frame-pointer", "all"); 394 395 size_t reservedSlotsSize = 0; 396 if (frameType == FrameType::OPTIMIZED_FRAME) { 397 reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); 398 LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", 399 std::to_string(reservedSlotsSize).c_str()); 400 SaveFrameTypeOnFrame(frameType, builder_); 401 } else if (frameType == FrameType::BASELINE_BUILTIN_FRAME) { 402 reservedSlotsSize = BaselineBuiltinFrame::ComputeReservedSize(slotSize_); 403 LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", 404 std::to_string(reservedSlotsSize).c_str()); 405 SaveFrameTypeOnFrame(frameType, builder_); 406 } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { 407 reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 408 LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", 409 std::to_string(reservedSlotsSize).c_str()); 410 auto ArgList = circuit_->GetArgRoot(); 411 auto uses = acc_.Uses(ArgList); 412 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) { 413 int argth = static_cast<int>(acc_.TryGetValue(*useIt)); 414 LLVMValueRef value = LLVMGetParam(function_, argth); 415 int funcIndex = 0; 416 if (isFastCallAot_) { 417 frameType = FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME; 418 funcIndex = static_cast<int>(FastCallArgIdx::FUNC); 419 } else { 420 funcIndex = static_cast<int>(CommonArgIdx::FUNC); 421 } 422 if (argth == funcIndex) { 423 SaveJSFuncOnOptJSFuncFrame(value); 424 SaveFrameTypeOnFrame(frameType, builder_); 425 } 426 } 427 } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) { 428 reservedSlotsSize = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_); 429 AssistGenPrologue(reservedSlotsSize, frameType); 430 } else { 431 LOG_COMPILER(FATAL) << "frameType interpret type error !"; 432 ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !"); 433 } 434} 435 436void LLVMIRBuilder::SaveByteCodePcOnOptJSFuncFrame(LLVMValueRef value) 437{ 438 ASSERT(circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME); 439 // load method 440 LLVMValueRef func = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64"); 441 LLVMValueRef offsetMethod = LLVMConstInt(GetInt64T(), JSFunctionBase::METHOD_OFFSET, false); 442 LLVMValueRef addrMethod = LLVMBuildAdd(builder_, func, offsetMethod, ""); 443 LLVMValueRef methodPtr = LLVMBuildIntToPtr(builder_, addrMethod, GetTaggedPtrT(), ""); 444 LLVMValueRef method = LLVMBuildLoad(builder_, methodPtr, ""); 445 // load byteCodePc 446 LLVMValueRef offsetByteCodePc = LLVMConstInt(GetInt64T(), Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET, false); 447 LLVMValueRef addrByteCodePc = LLVMBuildAdd(builder_, method, offsetByteCodePc, ""); 448 LLVMValueRef byteCodePcPtr = LLVMBuildIntToPtr(builder_, addrByteCodePc, GetTaggedPtrT(), ""); 449 LLVMValueRef byteCodePc = LLVMBuildLoad(builder_, byteCodePcPtr, ""); 450 // push byteCodePc 451 LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); 452 LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); 453 size_t reservedOffset = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_); 454 LLVMValueRef byteCodePcSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, 455 reservedOffset, false), ""); 456 LLVMValueRef byteCodePcAddr = LLVMBuildIntToPtr(builder_, byteCodePcSlotAddr, 457 LLVMPointerType(slotType_, 0), "byteCodePc.Addr"); 458 LLVMBuildStore(builder_, byteCodePc, byteCodePcAddr); 459} 460 461void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder) 462{ 463 LLVMValueRef llvmFpAddr = CallingFp(module_, builder, false); 464 465 LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder, llvmFpAddr, slotType_, "cast_int_t"); 466 LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder, frameAddr, LLVMConstInt(slotType_, slotSize_, false), ""); 467 LLVMValueRef addr = LLVMBuildIntToPtr(builder, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr"); 468 LLVMValueRef llvmFrameType = LLVMConstInt(slotType_, static_cast<uintptr_t>(frameType), 0); 469 LLVMBuildStore(builder, llvmFrameType, addr); 470} 471 472LLVMValueRef LLVMIRBuilder::CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller) 473{ 474 if (IsInterpreted()) { 475 return LLVMGetParam(function_, static_cast<unsigned>(InterpreterHandlerInputs::SP)); 476 } 477 /* 0:calling 1:its caller */ 478 std::vector<LLVMValueRef> args = {LLVMConstInt(GetInt32T(), 0, isCaller)}; 479 auto fn = LLVMGetNamedFunction(module, "llvm.frameaddress.p0i8"); 480 if (!fn) { 481 /* init instrinsic function declare */ 482 LLVMTypeRef paramTys1[] = { GetInt32T() }; 483 auto fnTy = LLVMFunctionType(GetRawPtrT(), paramTys1, 1, 0); 484 fn = LLVMAddFunction(module, "llvm.frameaddress.p0i8", fnTy); 485 } 486 LLVMValueRef fAddrRet = LLVMBuildCall(builder, fn, args.data(), 1, ""); 487 return fAddrRet; 488} 489 490LLVMValueRef LLVMIRBuilder::ReadRegister(LLVMModuleRef &module, [[maybe_unused]] LLVMBuilderRef &builder, 491 LLVMMetadataRef meta) 492{ 493 std::vector<LLVMValueRef> args = {LLVMMetadataAsValue(context_, meta)}; 494 auto fn = LLVMGetNamedFunction(module, "llvm.read_register.i64"); 495 if (!fn) { 496 /* init instrinsic function declare */ 497 LLVMTypeRef paramTys1[] = { 498 GetMachineRepType(MachineRep::K_META), 499 }; 500 auto fnTy = LLVMFunctionType(GetInt64T(), paramTys1, 1, 0); 501 fn = LLVMAddFunction(module, "llvm.read_register.i64", fnTy); 502 } 503 LLVMValueRef fAddrRet = LLVMBuildCall(builder_, fn, args.data(), 1, ""); 504 return fAddrRet; 505} 506 507LLVMBasicBlockRef LLVMIRBuilder::EnsureLBB(BasicBlock *bb) const 508{ 509 BasicBlockImpl *impl = EnsureBBImpl(bb); 510 ASSERT(impl != nullptr); 511 if (impl->lBB_) { 512 return impl->lBB_; 513 } 514 515 std::string buf = "B" + std::to_string(bb->GetId()); 516 LLVMBasicBlockRef llvmBB = LLVMAppendBasicBlockInContext(context_, function_, buf.c_str()); 517 impl->lBB_ = llvmBB; 518 impl->continuation = llvmBB; 519 bb->SetImpl(impl); 520 return llvmBB; 521} 522 523LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const 524{ 525 LLVMTypeRef dstType; 526 switch (rep) { 527 case MachineRep::K_BIT: 528 dstType = GetInt1T(); 529 break; 530 case MachineRep::K_WORD8: 531 dstType = GetInt8T(); 532 break; 533 case MachineRep::K_WORD16: 534 dstType = GetInt16T(); 535 break; 536 case MachineRep::K_WORD32: 537 dstType = GetInt32T(); 538 break; 539 case MachineRep::K_FLOAT64: 540 dstType = GetDoubleT(); 541 break; 542 case MachineRep::K_WORD64: 543 dstType = GetInt64T(); 544 break; 545 case MachineRep::K_PTR_1: 546 dstType = GetTaggedHPtrT(); 547 break; 548 case MachineRep::K_META: 549 dstType = LLVMMetadataTypeInContext(context_); 550 break; 551 default: 552 LOG_ECMA(FATAL) << "this branch is unreachable"; 553 UNREACHABLE(); 554 break; 555 } 556 return dstType; 557} 558 559void LLVMIRBuilder::HandleReadSp(GateRef gate) 560{ 561 ASSERT(acc_.GetOpCode(gate) == OpCode::READSP); 562 VisitReadSp(gate); 563} 564 565void LLVMIRBuilder::HandleCall(GateRef gate) 566{ 567 std::vector<GateRef> ins; 568 acc_.GetIns(gate, ins); 569 OpCode callOp = acc_.GetOpCode(gate); 570 if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL || 571 callOp == OpCode::BUILTINS_CALL || callOp == OpCode::BUILTINS_CALL_WITH_ARGV || 572 callOp == OpCode::CALL_OPTIMIZED || callOp == OpCode::FAST_CALL_OPTIMIZED || 573 callOp == OpCode::BASELINE_CALL || callOp == OpCode::ASM_CALL_BARRIER) { 574 VisitCall(gate, ins, callOp); 575 } else { 576 LOG_ECMA(FATAL) << "this branch is unreachable"; 577 UNREACHABLE(); 578 } 579} 580 581void LLVMIRBuilder::HandleBytecodeCall(GateRef gate) 582{ 583 std::vector<GateRef> ins; 584 acc_.GetIns(gate, ins); 585 VisitBytecodeCall(gate, ins); 586} 587 588void LLVMIRBuilder::HandleRuntimeCall(GateRef gate) 589{ 590 std::vector<GateRef> ins; 591 acc_.GetIns(gate, ins); 592 VisitRuntimeCall(gate, ins); 593} 594 595LLVMValueRef LLVMIRBuilder::GetFunction(LLVMValueRef glue, const CallSignature *signature, 596 LLVMValueRef rtbaseoffset, const std::string &realName) const 597{ 598 LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature); 599 LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); 600 LLVMTypeRef glueType = LLVMTypeOf(glue); 601 LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(glueType, 0), ""); 602 std::string name = realName.empty() 603 ? signature->GetName() 604 : realName; 605 LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, name.c_str()); 606 LLVMValueRef callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, (name + "-cast").c_str()); 607 ASSERT(callee != nullptr); 608 return callee; 609} 610 611LLVMValueRef LLVMIRBuilder::GetFunctionFromGlobalValue([[maybe_unused]] LLVMValueRef glue, 612 const CallSignature *signature, LLVMValueRef reloc) const 613{ 614 LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature); 615 LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); 616 LLVMValueRef callee = LLVMBuildIntToPtr(builder_, reloc, rtfuncTypePtr, "cast"); 617 assert(callee != nullptr); 618 return callee; 619} 620 621bool LLVMIRBuilder::IsInterpreted() const 622{ 623 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME; 624} 625 626bool LLVMIRBuilder::IsBaselineBuiltin() const 627{ 628 return circuit_->GetFrameType() == FrameType::BASELINE_BUILTIN_FRAME; 629} 630 631bool LLVMIRBuilder::IsOptimized() const 632{ 633 return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME; 634} 635 636bool LLVMIRBuilder::IsOptimizedJSFunction() const 637{ 638 return circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || 639 circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME; 640} 641 642void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList) 643{ 644 ASSERT(llvmModule_ != nullptr); 645 StubIdType stubId = RTSTUB_ID(CallRuntime); 646 LLVMValueRef glue = GetGlue(inList); 647 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 648 LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex); 649 LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 650 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId)); 651 652 auto kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL); 653 654 size_t actualNumArgs = 0; 655 LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0); 656 GateRef frameArgs = Circuit::NullGate(); 657 ComputeArgCountAndExtraInfo(actualNumArgs, pcOffset, frameArgs, inList, kind); 658 659 std::vector<LLVMValueRef> params; 660 params.push_back(glue); // glue 661 const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)])); 662 params.push_back(LLVMConstInt(GetInt64T(), index, 0)); // target 663 params.push_back(LLVMConstInt(GetInt64T(), 664 actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER), 0)); // argc 665 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) { 666 GateRef gateTmp = inList[paraIdx]; 667 params.push_back(GetLValue(gateTmp)); 668 } 669 670 LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature); 671 std::string targetName = RuntimeStubCSigns::GetRTName(index); 672 LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset, targetName); 673 callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), ""); 674 LLVMValueRef runtimeCall = nullptr; 675 if (kind == CallExceptionKind::HAS_PC_OFFSET) { 676 std::vector<LLVMValueRef> values; 677 CollectExraCallSiteInfo(values, pcOffset, frameArgs); 678 runtimeCall = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs, 679 "", values.data(), values.size()); 680 } else { 681 runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), actualNumArgs, ""); 682 } 683 LLVMSetInstructionCallConv(runtimeCall, LLVMWebKitJSCallConv); 684 if (RuntimeStubCSigns::IsCold(index)) { 685 unsigned ColdAttrKind = LLVMGetEnumAttributeKindForName(COLD_ATTR.data(), COLD_ATTR.size()); 686 LLVMAttributeRef ColdAttribute = LLVMCreateEnumAttribute(context_, ColdAttrKind, 0); 687 LLVMAddCallSiteAttribute(runtimeCall, LLVMAttributeFunctionIndex, ColdAttribute); 688 } 689 Bind(gate, runtimeCall); 690 691 if (IsLogEnabled()) { 692 SetDebugInfo(gate, runtimeCall); 693 } 694} 695 696bool LLVMIRBuilder::SetDebugInfo(GateRef g, LLVMValueRef r) 697{ 698 if (r != nullptr) { 699 LLVMValueKind k = LLVMGetValueKind(r); 700 if (k == LLVMInstructionValueKind) { 701 std::string comment = acc_.ToString(g); 702 circuit_->AddComment(g, std::move(comment)); 703 size_t index = 0; 704 circuit_->GetDebugInfo(g, index); 705 LLVMMetadataRef loc = LLVMDIBuilderCreateDebugLocation(context_, index + 1, 0, dFuncMD_, NULL); 706 LLVMInstructionSetDebugLoc(r, loc); 707 return true; 708 } 709 } 710 return false; 711} 712 713void LLVMIRBuilder::HandleRuntimeCallWithArgv(GateRef gate) 714{ 715 std::vector<GateRef> ins; 716 acc_.GetIns(gate, ins); 717 VisitRuntimeCallWithArgv(gate, ins); 718} 719 720void LLVMIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList) 721{ 722 ASSERT(IsOptimized() == true); 723 StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv); 724 LLVMValueRef glue = GetGlue(inList); 725 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 726 LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex); 727 LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 728 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId)); 729 LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset); 730 731 std::vector<LLVMValueRef> params; 732 params.push_back(glue); // glue 733 734 uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]); 735 auto targetId = LLVMConstInt(GetInt64T(), index, 0); 736 params.push_back(targetId); // target 737 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) { 738 GateRef gateTmp = inList[paraIdx]; 739 params.push_back(GetLValue(gateTmp)); 740 } 741 742 LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature); 743 callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), ""); 744 LLVMValueRef runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size() - 1, ""); 745 Bind(gate, runtimeCall); 746 747 if (IsLogEnabled()) { 748 SetDebugInfo(gate, runtimeCall); 749 } 750} 751 752LLVMValueRef LLVMIRBuilder::GetCurrentSP() 753{ 754 LLVMMetadataRef meta; 755 if (compCfg_->IsAmd64()) { 756 meta = LLVMMDStringInContext2(context_, "rsp", 4); // 4 : 4 means len of "rsp" 757 } else { 758 meta = LLVMMDStringInContext2(context_, "sp", 3); // 3 : 3 means len of "sp" 759 } 760 LLVMMetadataRef metadataNode = LLVMMDNodeInContext2(context_, &meta, 1); 761 LLVMValueRef spValue = ReadRegister(module_, builder_, metadataNode); 762 return spValue; 763} 764 765LLVMValueRef LLVMIRBuilder::GetCurrentFrameType(LLVMValueRef currentSpFrameAddr) 766{ 767 LLVMValueRef tmp = LLVMBuildSub(builder_, currentSpFrameAddr, LLVMConstInt(slotType_, slotSize_, 1), ""); 768 LLVMValueRef frameTypeAddr = 769 LLVMBuildIntToPtr(builder_, tmp, LLVMPointerType(GetInt64T(), 0), ""); 770 LLVMValueRef frameType = LLVMBuildLoad(builder_, frameTypeAddr, ""); 771 return frameType; 772} 773 774void LLVMIRBuilder::SetGCLeafFunction(LLVMValueRef call) 775{ 776 const char *attrName = "gc-leaf-function"; 777 const char *attrValue = "true"; 778 LLVMAttributeRef llvmAttr = LLVMCreateStringAttribute(context_, attrName, strlen(attrName), attrValue, 779 strlen(attrValue)); 780 LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex, llvmAttr); 781} 782 783void LLVMIRBuilder::SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call) 784{ 785 ASSERT(calleeDescriptor != nullptr); 786 if (calleeDescriptor->GetCallConv() == CallSignature::CallConv::GHCCallConv) { 787 LLVMSetTailCall(call, true); 788 SetGCLeafFunction(call); 789 LLVMSetInstructionCallConv(call, LLVMGHCCallConv); 790 } else if (calleeDescriptor->GetCallConv() == CallSignature::CallConv::WebKitJSCallConv) { 791 LLVMSetInstructionCallConv(call, LLVMWebKitJSCallConv); 792 } 793 if (calleeDescriptor->GetTailCall()) { 794 LLVMSetTailCall(call, true); 795 } 796 if (calleeDescriptor->GetGCLeafFunction()) { 797 SetGCLeafFunction(call); 798 } 799} 800 801bool LLVMIRBuilder::IsHeapPointerType(LLVMTypeRef valueType) 802{ 803 return LLVMGetTypeKind(valueType) == LLVMPointerTypeKind && LLVMGetPointerAddressSpace(valueType) > 0; 804} 805 806LLVMValueRef LLVMIRBuilder::GetGlue(const std::vector<GateRef> &inList) 807{ 808 auto g = inList.at(static_cast<size_t>(CallInputs::GLUE)); 809 return GetLValue(g); 810} 811 812LLVMValueRef LLVMIRBuilder::GetLeaveFrameOffset(LLVMValueRef glue) 813{ 814 LLVMTypeRef glueType = LLVMTypeOf(glue); 815 return LLVMConstInt(glueType, 816 static_cast<int>(JSThread::GlueData::GetLeaveFrameOffset(compCfg_->Is32Bit())), 0); 817} 818 819LLVMValueRef LLVMIRBuilder::GetRTStubOffset(LLVMValueRef glue, int index) 820{ 821 LLVMTypeRef glueType = LLVMTypeOf(glue); 822 return LLVMConstInt(glueType, 823 static_cast<int>(JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit())) + index * slotSize_, 0); 824} 825 826LLVMValueRef LLVMIRBuilder::GetCoStubOffset(LLVMValueRef glue, int index) 827{ 828 LLVMTypeRef glueType = LLVMTypeOf(glue); 829 return LLVMConstInt(glueType, JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) + 830 static_cast<size_t>(index * slotSize_), 0); 831} 832 833LLVMValueRef LLVMIRBuilder::GetBaselineStubOffset(LLVMValueRef glue, int index) 834{ 835 LLVMTypeRef glueType = LLVMTypeOf(glue); 836 return LLVMConstInt(glueType, JSThread::GlueData::GetBaselineStubEntriesOffset(compCfg_->Is32Bit()) + 837 static_cast<size_t>(index * slotSize_), 0); 838} 839 840LLVMValueRef LLVMIRBuilder::GetBCStubOffset(LLVMValueRef glue) 841{ 842 LLVMTypeRef glueType = LLVMTypeOf(glue); 843 return LLVMConstInt(glueType, JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit()), 0); 844} 845 846LLVMValueRef LLVMIRBuilder::GetBCDebugStubOffset(LLVMValueRef glue) 847{ 848 LLVMTypeRef glueType = LLVMTypeOf(glue); 849 return LLVMConstInt(glueType, JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit()), 0); 850} 851 852LLVMValueRef LLVMIRBuilder::GetBuiltinsStubOffset(LLVMValueRef glue) 853{ 854 LLVMTypeRef glueType = LLVMTypeOf(glue); 855 return LLVMConstInt(glueType, JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()), 0); 856} 857 858void LLVMIRBuilder::ComputeArgCountAndExtraInfo(size_t &actualNumArgs, LLVMValueRef &pcOffset, GateRef &frameArgs, 859 const std::vector<GateRef> &inList, CallExceptionKind kind) 860{ 861 if (kind == CallExceptionKind::HAS_PC_OFFSET) { 862 actualNumArgs = inList.size() - 2; // 2: pcOffset and frameArgs 863 pcOffset = GetLValue(inList.at(actualNumArgs + 1)); 864 frameArgs = inList.at(actualNumArgs); 865 ASSERT(acc_.GetOpCode(inList.at(actualNumArgs + 1)) == OpCode::CONSTANT); 866 } else { 867 actualNumArgs = inList.size(); 868 } 869} 870 871CallExceptionKind LLVMIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const 872{ 873 bool hasPcOffset = IsOptimizedJSFunction() && 874 ((op == OpCode::NOGC_RUNTIME_CALL && (kungfu::RuntimeStubCSigns::IsAsmStub(index))) || 875 (op == OpCode::CALL) || 876 (op == OpCode::RUNTIME_CALL)); 877 return hasPcOffset ? CallExceptionKind::HAS_PC_OFFSET : CallExceptionKind::NO_PC_OFFSET; 878} 879 880void LLVMIRBuilder::UpdateLeaveFrame(LLVMValueRef glue) 881{ 882 LLVMValueRef leaveFrameOffset = GetLeaveFrameOffset(glue); 883 LLVMValueRef leaveFrameValue = LLVMBuildAdd(builder_, glue, leaveFrameOffset, ""); 884 LLVMTypeRef glueType = LLVMTypeOf(glue); 885 LLVMValueRef leaveFrameAddr = LLVMBuildIntToPtr(builder_, leaveFrameValue, LLVMPointerType(glueType, 0), ""); 886 LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, true); 887 LLVMValueRef fp = LLVMBuildPtrToInt(builder_, llvmFpAddr, GetInt64T(), "cast_int64_t"); 888 LLVMBuildStore(builder_, fp, leaveFrameAddr); 889} 890 891LLVMValueRef LLVMIRBuilder::GetCallee(const std::vector<GateRef> &inList, const CallSignature *signature, 892 const std::string &realName) 893{ 894 LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature); 895 LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0); 896 897 std::string name = realName.empty() 898 ? signature->GetName() 899 : realName; 900 LLVMValueRef code = GetLValue(inList.at(static_cast<size_t>(CallInputs::TARGET))); 901 LLVMValueRef callee = LLVMBuildIntToPtr(builder_, code, rtfuncTypePtr, (name + "-cast").c_str()); 902 ASSERT(callee != nullptr); 903 return callee; 904} 905 906void LLVMIRBuilder::VisitReadSp(GateRef gate) 907{ 908 LLVMValueRef spValue = GetCurrentSP(); 909 Bind(gate, spValue); 910} 911 912void LLVMIRBuilder::CollectExraCallSiteInfo(std::vector<LLVMValueRef> &values, LLVMValueRef pcOffset, 913 GateRef frameArgs) 914{ 915 // pc offset 916 auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1); 917 values.push_back(pcIndex); 918 values.push_back(pcOffset); 919 920 if (!enableOptInlining_) { 921 return; 922 } 923 924 if (frameArgs == Circuit::NullGate()) { 925 return; 926 } 927 if (acc_.GetOpCode(frameArgs) != OpCode::FRAME_ARGS) { 928 return; 929 } 930 uint32_t maxDepth = acc_.GetFrameDepth(frameArgs, OpCode::FRAME_ARGS); 931 if (maxDepth == 0) { 932 return; 933 } 934 935 maxDepth = std::min(maxDepth, MAX_METHOD_OFFSET_NUM); 936 size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM); 937 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_)); 938 for (int32_t curDepth = static_cast<int32_t>(maxDepth - 1); curDepth >= 0; curDepth--) { 939 ASSERT(acc_.GetOpCode(frameArgs) == OpCode::FRAME_ARGS); 940 // method id 941 uint32_t methodOffset = acc_.TryGetMethodOffset(frameArgs); 942 frameArgs = acc_.GetFrameState(frameArgs); 943 if (methodOffset == FrameStateOutput::INVALID_INDEX) { 944 methodOffset = 0; 945 } 946 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - curDepth; 947 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specCallTargetIndex, curDepth, shift); 948 values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false)); 949 values.emplace_back(LLVMConstInt(GetInt32T(), methodOffset, false)); 950 } 951} 952 953void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op) 954{ 955 size_t targetIndex = static_cast<size_t>(CallInputs::TARGET); 956 static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3); 957 const CallSignature *calleeDescriptor = nullptr; 958 LLVMValueRef glue = GetGlue(inList); 959 LLVMValueRef rtoffset; 960 LLVMValueRef rtbaseoffset; 961 LLVMValueRef callee; 962 CallExceptionKind kind = CallExceptionKind::NO_PC_OFFSET; 963 bool isNoGC = false; 964 if (op == OpCode::CALL) { 965 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 966 calleeDescriptor = CommonStubCSigns::Get(index); 967 rtoffset = GetCoStubOffset(glue, index); 968 rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 969 callee = GetFunction(glue, calleeDescriptor, rtbaseoffset); 970 kind = GetCallExceptionKind(index, op); 971 } else if (op == OpCode::NOGC_RUNTIME_CALL) { 972 UpdateLeaveFrame(glue); 973 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 974 calleeDescriptor = RuntimeStubCSigns::Get(index); 975 rtoffset = GetRTStubOffset(glue, index); 976 rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 977 callee = GetFunction(glue, calleeDescriptor, rtbaseoffset); 978 kind = GetCallExceptionKind(index, op); 979 } else if (op == OpCode::CALL_OPTIMIZED) { 980 calleeDescriptor = RuntimeStubCSigns::GetOptimizedCallSign(); 981 callee = GetCallee(inList, calleeDescriptor); 982 if (IsOptimizedJSFunction()) { 983 kind = CallExceptionKind::HAS_PC_OFFSET; 984 } else { 985 kind = CallExceptionKind::NO_PC_OFFSET; 986 } 987 isNoGC = acc_.IsNoGC(gate); 988 } else if (op == OpCode::FAST_CALL_OPTIMIZED) { 989 calleeDescriptor = RuntimeStubCSigns::GetOptimizedFastCallSign(); 990 callee = GetCallee(inList, calleeDescriptor); 991 if (IsOptimizedJSFunction()) { 992 kind = CallExceptionKind::HAS_PC_OFFSET; 993 } else { 994 kind = CallExceptionKind::NO_PC_OFFSET; 995 } 996 isNoGC = acc_.IsNoGC(gate); 997 } else if (op == OpCode::BASELINE_CALL) { 998 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 999 calleeDescriptor = BaselineStubCSigns::Get(index); 1000 rtoffset = GetBaselineStubOffset(glue, index); 1001 rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 1002 callee = GetFunction(glue, calleeDescriptor, rtbaseoffset); 1003 kind = GetCallExceptionKind(index, op); 1004 } else if (op == OpCode::ASM_CALL_BARRIER) { 1005 const size_t index = acc_.GetConstantValue(inList[targetIndex]); 1006 calleeDescriptor = RuntimeStubCSigns::Get(index); 1007 rtoffset = GetRTStubOffset(glue, index); 1008 rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); 1009 callee = GetFunction(glue, calleeDescriptor, rtbaseoffset); 1010 isNoGC = true; 1011 } else { 1012 ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV); 1013 LLVMValueRef opcodeOffset = GetLValue(inList.at(targetIndex)); 1014 rtoffset = GetBuiltinsStubOffset(glue); 1015 rtbaseoffset = LLVMBuildAdd( 1016 builder_, glue, LLVMBuildAdd(builder_, rtoffset, opcodeOffset, ""), ""); 1017 if (op == OpCode::BUILTINS_CALL) { 1018 calleeDescriptor = BuiltinsStubCSigns::BuiltinsCSign(); 1019 } else { 1020 calleeDescriptor = BuiltinsStubCSigns::BuiltinsWithArgvCSign(); 1021 } 1022 callee = GetFunction(glue, calleeDescriptor, rtbaseoffset); 1023 } 1024 1025 std::vector<LLVMValueRef> params; 1026 const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER); 1027 GateRef glueGate = inList[firstArg]; 1028 params.push_back(GetLValue(glueGate)); 1029 1030 // get parameter types 1031 LLVMTypeRef calleeFuncType = LLVMGetElementType(LLVMTypeOf(callee)); 1032 std::vector<LLVMTypeRef> paramTypes(LLVMCountParamTypes(calleeFuncType)); 1033 LLVMGetParamTypes(calleeFuncType, paramTypes.data()); 1034 1035 int extraParameterCnt = 0; 1036 size_t actualNumArgs = 0; 1037 LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0); 1038 GateRef frameArgs = Circuit::NullGate(); 1039 ComputeArgCountAndExtraInfo(actualNumArgs, pcOffset, frameArgs, inList, kind); 1040 std::vector<CallSignature::ParamAttr> *paramAttr = calleeDescriptor->GetParamAttr(); 1041 // then push the actual parameter for js function call 1042 for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) { 1043 GateRef gateTmp = inList[paraIdx]; 1044 const auto gateTmpType = LLVMTypeOf(GetLValue(gateTmp)); 1045 if (paramAttr != nullptr && params.size() < paramAttr->size() && 1046 paramAttr->at(params.size()) == CallSignature::ParamAttr::Dead) { 1047 params.push_back(LLVMGetUndef(gateTmpType)); 1048 continue; 1049 } 1050 if (params.size() < paramTypes.size()) { // this condition will be false for variadic arguments 1051 const auto paramType = paramTypes.at(params.size()); 1052 // match parameter types and function signature types 1053 if (IsHeapPointerType(paramType) && !IsHeapPointerType(gateTmpType)) { 1054 params.push_back(LLVMBuildIntToPtr(builder_, 1055 LLVMBuildBitCast(builder_, GetLValue(gateTmp), GetInt64T(), ""), 1056 paramType, "")); 1057 } else { 1058 params.push_back(LLVMBuildBitCast(builder_, GetLValue(gateTmp), paramType, "")); 1059 } 1060 } else { 1061 params.push_back(GetLValue(gateTmp)); 1062 } 1063 } 1064 1065 LLVMValueRef call = nullptr; 1066 if (op == OpCode::ASM_CALL_BARRIER) { 1067 callee = LLVMBuildPointerCast(builder_, callee, llvmModule_->GetRawPtrT(), ""); 1068 params.insert(params.begin(), callee); 1069 call = LLVMBuildCall(builder_, ASMBarrierCall_, params.data(), params.size(), ""); 1070 } else { 1071 LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, calleeDescriptor); 1072 callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), ""); 1073 if (kind == CallExceptionKind::HAS_PC_OFFSET) { 1074 std::vector<LLVMValueRef> values; 1075 CollectExraCallSiteInfo(values, pcOffset, frameArgs); 1076 call = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + 1077 extraParameterCnt, "", values.data(), values.size()); 1078 } else { 1079 call = LLVMBuildCall2(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + 1080 extraParameterCnt, ""); 1081 } 1082 SetCallConvAttr(calleeDescriptor, call); 1083 } 1084 if (isNoGC) { 1085 SetGCLeafFunction(call); 1086 } 1087 Bind(gate, call); 1088 1089 if (IsLogEnabled()) { 1090 SetDebugInfo(gate, call); 1091 } 1092} 1093 1094void LLVMIRBuilder::VisitBytecodeCall(GateRef gate, const std::vector<GateRef> &inList) 1095{ 1096 size_t paraStartIndex = static_cast<size_t>(CallInputs::FIRST_PARAMETER); 1097 size_t targetIndex = static_cast<size_t>(CallInputs::TARGET); 1098 size_t glueIndex = static_cast<size_t>(CallInputs::GLUE); 1099 LLVMValueRef opcodeOffset = GetLValue(inList.at(targetIndex)); 1100 ASSERT(llvmModule_ != nullptr); 1101 1102 // start index of bytecode handler csign in llvmModule 1103 LLVMValueRef glue = GetLValue(inList.at(glueIndex)); 1104 LLVMValueRef baseOffset = GetBaseOffset(gate, glue); 1105 LLVMValueRef rtbaseoffset = LLVMBuildAdd( 1106 builder_, glue, LLVMBuildAdd(builder_, baseOffset, opcodeOffset, ""), ""); 1107 const CallSignature *signature = BytecodeStubCSigns::BCHandler(); 1108 LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset); 1109 1110 std::vector<LLVMValueRef> params; 1111 for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) { 1112 GateRef gateTmp = inList[paraIdx]; 1113 params.push_back(GetLValue(gateTmp)); 1114 } 1115 1116 LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature); 1117 callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), ""); 1118 LLVMValueRef call = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size() - paraStartIndex, ""); 1119 SetGCLeafFunction(call); 1120 LLVMSetTailCall(call, true); 1121 LLVMSetInstructionCallConv(call, LLVMGHCCallConv); 1122 Bind(gate, call); 1123 1124 if (IsLogEnabled()) { 1125 SetDebugInfo(gate, call); 1126 } 1127} 1128 1129LLVMValueRef LLVMIRBuilder::GetBaseOffset(GateRef gate, LLVMValueRef glue) 1130{ 1131 switch (acc_.GetOpCode(gate)) { 1132 case OpCode::BYTECODE_CALL: 1133 return GetBCStubOffset(glue); 1134 case OpCode::DEBUGGER_BYTECODE_CALL: 1135 return GetBCDebugStubOffset(glue); 1136 default: 1137 LOG_ECMA(FATAL) << "this branch is unreachable"; 1138 UNREACHABLE(); 1139 } 1140} 1141 1142void LLVMIRBuilder::HandleAlloca(GateRef gate) 1143{ 1144 return VisitAlloca(gate); 1145} 1146 1147void LLVMIRBuilder::VisitAlloca(GateRef gate) 1148{ 1149 uint64_t machineRep = acc_.TryGetValue(gate); 1150 LLVMTypeRef dataType = GetMachineRepType(static_cast<MachineRep>(machineRep)); 1151 auto lv = LLVMBuildPtrToInt(builder_, 1152 LLVMBuildAlloca(builder_, dataType, ""), 1153 ConvertLLVMTypeFromGate(gate), ""); 1154 Bind(gate, lv); 1155} 1156 1157void LLVMIRBuilder::HandlePhi(GateRef gate) 1158{ 1159 std::vector<GateRef> ins; 1160 acc_.GetIns(gate, ins); 1161 VisitPhi(gate, ins); 1162} 1163 1164int LLVMIRBuilder::LookupPredBB(GateRef start, int bbID) 1165{ 1166 GateId gateId = acc_.GetId(start); 1167 int owner = instID2bbID_[gateId]; 1168 if (owner != bbID) { 1169 return owner; 1170 } 1171 GateRef pred = start; 1172 while (owner == bbID) { 1173 pred = acc_.GetState(pred); 1174 auto id = acc_.GetId(pred); 1175 owner = instID2bbID_[id]; 1176 } 1177 return owner; 1178} 1179 1180void LLVMIRBuilder::VisitPhi(GateRef gate, const std::vector<GateRef> &phiIns) 1181{ 1182 LLVMTypeRef type = ConvertLLVMTypeFromGate(gate); 1183 LLVMValueRef phi = LLVMBuildPhi(builder_, type, ""); 1184 if (phiIns.size() > 1) { 1185 Bind(gate, phi); 1186 } 1187 // Collect the states merges of this phi and note the 1-in is the merged states. 1188 std::vector<GateRef> phiStates; 1189 acc_.GetIns(phiIns.at(0), phiStates); 1190 ASSERT(phiStates.size() + 1 == phiIns.size()); 1191 for (int i = 1; i < static_cast<int>(phiIns.size()); i++) { 1192 int bbIdx = LookupPredBB(phiStates.at(i - 1), currentBb_->GetId()); 1193 1194 int cnt = static_cast<int>(bbID2BB_.count(bbIdx)); 1195 // if cnt = 0 means bb with current bbIdx hasn't been created 1196 if (cnt > 0) { 1197 BasicBlock *bb = bbID2BB_[bbIdx].get(); 1198 if (bb == nullptr) { 1199 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed BasicBlock nullptr"; 1200 return; 1201 } 1202 BasicBlockImpl *impl = bb->GetImpl<BasicBlockImpl>(); 1203 if (impl == nullptr) { 1204 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed impl nullptr"; 1205 return; 1206 } 1207 LLVMBasicBlockRef llvmBB = EnsureLBB(bb); // The llvm bb 1208 LLVMValueRef value = GetLValue(phiIns.at(i)); 1209 1210 if (impl->started) { 1211 LLVMAddIncoming(phi, &value, &llvmBB, 1); 1212 } else { 1213 impl = currentBb_->GetImpl<BasicBlockImpl>(); 1214 NotMergedPhiDesc d = { bbIdx, phiIns.at(i), phi }; 1215 impl->unmergedPhis_.emplace_back(d); 1216 phiRebuildWorklist_.push_back(currentBb_); 1217 } 1218 } else { 1219 BasicBlockImpl* impl = currentBb_->GetImpl<BasicBlockImpl>(); 1220 NotMergedPhiDesc d = { bbIdx, phiIns.at(i), phi }; 1221 impl->unmergedPhis_.emplace_back(d); 1222 phiRebuildWorklist_.push_back(currentBb_); 1223 } 1224 } 1225} 1226 1227void LLVMIRBuilder::VisitReturn([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef popCount, 1228 const std::vector<GateRef> &operands) 1229{ 1230 // [STATE] [DEPEND] [VALUE] [RETURN_LIST] 1231 GateRef operand = operands[2]; // 2: skip 2 in gate that are not data gate 1232 LLVMValueRef returnValue = GetLValue(operand); 1233 LLVMBuildRet(builder_, returnValue); 1234 1235 if (IsLogEnabled()) { 1236 SetDebugInfo(gate, returnValue); 1237 } 1238} 1239 1240void LLVMIRBuilder::HandleReturn(GateRef gate) 1241{ 1242 std::vector<GateRef> ins; 1243 acc_.GetIns(gate, ins); 1244 VisitReturn(gate, 1, ins); 1245} 1246 1247void LLVMIRBuilder::VisitReturnVoid([[maybe_unused]] GateRef gate) 1248{ 1249 // [STATE] [DEPEND] [VALUE] [RETURN_LIST] 1250 LLVMBuildRetVoid(builder_); 1251} 1252 1253void LLVMIRBuilder::HandleReturnVoid(GateRef gate) 1254{ 1255 VisitReturnVoid(gate); 1256} 1257 1258void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors) 1259{ 1260 BasicBlock *bb = EnsureBB(bbId); 1261 if (bb == nullptr) { 1262 OPTIONAL_LOG_COMPILER(ERROR) << " block create failed "; 1263 return; 1264 } 1265 currentBb_ = bb; 1266 LLVMBasicBlockRef lBB = EnsureLBB(bb); 1267 SetToCfg(bb); 1268 for (int predecessor : predecessors) { 1269 BasicBlock *pre = EnsureBB(predecessor); 1270 if (pre == nullptr) { 1271 OPTIONAL_LOG_COMPILER(ERROR) << " block setup failed, predecessor:%d nullptr" << predecessor; 1272 return; 1273 } 1274 LLVMBasicBlockRef preLBB = EnsureLBB(pre); 1275 LLVMMoveBasicBlockBefore(preLBB, lBB); 1276 } 1277 if (IsPrologue(bbId)) { 1278 GenPrologue(); 1279 } 1280} 1281 1282void LLVMIRBuilder::HandleGoto(GateRef gate) 1283{ 1284 std::vector<GateRef> outs; 1285 acc_.GetOutStates(gate, outs); 1286 int block = instID2bbID_[acc_.GetId(gate)]; 1287 switch (acc_.GetOpCode(gate)) { 1288 case OpCode::MERGE: 1289 case OpCode::LOOP_BEGIN: { 1290 for (const auto &out : outs) { 1291 int bbOut = instID2bbID_[acc_.GetId(out)]; 1292 VisitGoto(block, bbOut); 1293 } 1294 break; 1295 } 1296 default: { 1297 int bbOut = instID2bbID_[acc_.GetId(outs[0])]; 1298 VisitGoto(block, bbOut); 1299 break; 1300 } 1301 } 1302} 1303 1304void LLVMIRBuilder::VisitGoto(int block, int bbOut) 1305{ 1306 if (block == bbOut) { 1307 return; 1308 } 1309 BasicBlock *bb = EnsureBB(bbOut); 1310 if (bb == nullptr) { 1311 OPTIONAL_LOG_COMPILER(ERROR) << " block is nullptr "; 1312 return; 1313 } 1314 llvm::BasicBlock *self = llvm::unwrap(EnsureLBB(bbID2BB_[block].get())); 1315 llvm::BasicBlock *out = llvm::unwrap(EnsureLBB(bbID2BB_[bbOut].get())); 1316 llvm::BranchInst::Create(out, self); 1317 EndCurrentBlock(); 1318} 1319 1320void LLVMIRBuilder::HandleConstant(GateRef gate) 1321{ 1322 std::bitset<64> value = acc_.GetConstantValue(gate); // 64: bit width 1323 VisitConstant(gate, value); 1324} 1325 1326void LLVMIRBuilder::VisitConstant(GateRef gate, std::bitset<64> value) // 64: bit width 1327{ 1328 LLVMValueRef llvmValue = nullptr; 1329 auto machineType = acc_.GetMachineType(gate); 1330 if (machineType == MachineType::ARCH) { 1331 ASSERT(compCfg_->Is64Bit()); 1332 machineType = MachineType::I64; 1333 } 1334 if (machineType == MachineType::I32) { 1335 llvmValue = LLVMConstInt(GetInt32T(), value.to_ulong(), 0); 1336 } else if (machineType == MachineType::I64) { 1337 llvmValue = LLVMConstInt(GetInt64T(), value.to_ullong(), 0); 1338 LLVMTypeRef type = ConvertLLVMTypeFromGate(gate); 1339 if (LLVMGetTypeKind(type) == LLVMPointerTypeKind) { 1340 llvmValue = LLVMBuildIntToPtr(builder_, llvmValue, type, ""); 1341 } else if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind) { 1342 // do nothing 1343 } else { 1344 LOG_ECMA(FATAL) << "this branch is unreachable"; 1345 UNREACHABLE(); 1346 } 1347 } else if (machineType == MachineType::F64) { 1348 auto doubleValue = base::bit_cast<double>(value.to_ullong()); // actual double value 1349 llvmValue = LLVMConstReal(GetDoubleT(), doubleValue); 1350 } else if (machineType == MachineType::I8) { 1351 llvmValue = LLVMConstInt(GetInt8T(), value.to_ulong(), 0); 1352 } else if (machineType == MachineType::I16) { 1353 llvmValue = LLVMConstInt(GetInt16T(), value.to_ulong(), 0); 1354 } else if (machineType == MachineType::I1) { 1355 llvmValue = LLVMConstInt(GetInt1T(), value.to_ulong(), 0); 1356 } else { 1357 LOG_ECMA(FATAL) << "this branch is unreachable"; 1358 UNREACHABLE(); 1359 } 1360 Bind(gate, llvmValue); 1361} 1362 1363void LLVMIRBuilder::HandleConstString(GateRef gate) 1364{ 1365 const ChunkVector<char> &str = acc_.GetConstantString(gate); // 64: bit width 1366 VisitConstString(gate, str); 1367} 1368 1369void LLVMIRBuilder::VisitConstString(GateRef gate, const ChunkVector<char> &str) // 64: bit width 1370{ 1371 ASSERT(acc_.GetMachineType(gate) == MachineType::ARCH); 1372 LLVMValueRef llvmValue1 = LLVMConstStringInContext(context_, str.data(), str.size(), 0); 1373 LLVMValueRef addr = LLVMBuildAlloca(builder_, LLVMTypeOf(llvmValue1), ""); 1374 LLVMBuildStore(builder_, llvmValue1, addr); 1375 Bind(gate, addr); 1376} 1377 1378void LLVMIRBuilder::HandleRelocatableData(GateRef gate) 1379{ 1380 uint64_t value = acc_.TryGetValue(gate); 1381 VisitRelocatableData(gate, value); 1382} 1383 1384void LLVMIRBuilder::VisitRelocatableData(GateRef gate, uint64_t value) 1385{ 1386 LLVMValueRef globalValue = LLVMAddGlobal(module_, GetInt64T(), "G"); 1387 LLVMSetInitializer(globalValue, LLVMConstInt(GetInt64T(), value, 0)); 1388 Bind(gate, globalValue); 1389} 1390 1391void LLVMIRBuilder::HandleZExtInt(GateRef gate) 1392{ 1393 std::vector<GateRef> ins; 1394 acc_.GetIns(gate, ins); 1395 VisitZExtInt(gate, ins[0]); 1396} 1397 1398void LLVMIRBuilder::HandleSExtInt(GateRef gate) 1399{ 1400 std::vector<GateRef> ins; 1401 acc_.GetIns(gate, ins); 1402 VisitSExtInt(gate, ins[0]); 1403} 1404 1405void LLVMIRBuilder::HandleParameter(GateRef gate) 1406{ 1407 return VisitParameter(gate); 1408} 1409 1410void LLVMIRBuilder::VisitParameter(GateRef gate) 1411{ 1412 int argth = static_cast<int>(acc_.TryGetValue(gate)); 1413 LLVMValueRef value = LLVMGetParam(function_, argth); 1414 ASSERT(LLVMTypeOf(value) == ConvertLLVMTypeFromGate(gate)); 1415 Bind(gate, value); 1416 // NOTE: caller put args, otherwise crash 1417 ASSERT(value != nullptr); 1418} 1419 1420void LLVMIRBuilder::SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value) 1421{ 1422 ASSERT(IsOptimizedJSFunction()); 1423 size_t reservedOffset = 0; 1424 LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); 1425 LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); 1426 if (circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { 1427 reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 1428 } else { 1429 reservedOffset = FASTJITFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); 1430 } 1431 LLVMValueRef frameJSFuncSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, 1432 reservedOffset, false), ""); 1433 LLVMValueRef jsFuncAddr = LLVMBuildIntToPtr(builder_, frameJSFuncSlotAddr, 1434 LLVMPointerType(slotType_, 0), "jsfunc.Addr"); 1435 LLVMValueRef jsFuncValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64"); 1436 LLVMBuildStore(builder_, jsFuncValue, jsFuncAddr); 1437} 1438 1439void LLVMIRBuilder::HandleBranch(GateRef gate) 1440{ 1441 std::vector<GateRef> ins; 1442 acc_.GetIns(gate, ins); 1443 std::vector<GateRef> outs; 1444 acc_.GetOutStates(gate, outs); 1445 GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1]; 1446 GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1]; 1447 int bbTrue = instID2bbID_[acc_.GetId(bTrue)]; 1448 int bbFalse = instID2bbID_[acc_.GetId(bFalse)]; 1449 VisitBranch(gate, ins[1], bbTrue, bbFalse); 1450} 1451 1452void LLVMIRBuilder::HandleMod(GateRef gate) 1453{ 1454 auto g0 = acc_.GetIn(gate, 0); 1455 auto g1 = acc_.GetIn(gate, 1); 1456 VisitMod(gate, g0, g1); 1457} 1458 1459void LLVMIRBuilder::VisitMod(GateRef gate, GateRef e1, GateRef e2) 1460{ 1461 LLVMValueRef e1Value = GetLValue(e1); 1462 LLVMValueRef e2Value = GetLValue(e2); 1463 LLVMValueRef result = nullptr; 1464 ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e1)); 1465 ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e2)); 1466 auto machineType = acc_.GetMachineType(gate); 1467 if (machineType == MachineType::I32) { 1468 result = LLVMBuildSRem(builder_, e1Value, e2Value, ""); 1469 } else if (machineType == MachineType::F64) { 1470 result = LLVMBuildFRem(builder_, e1Value, e2Value, ""); 1471 } else { 1472 LOG_ECMA(FATAL) << "this branch is unreachable"; 1473 UNREACHABLE(); 1474 } 1475 Bind(gate, result); 1476 1477 if (IsLogEnabled()) { 1478 SetDebugInfo(gate, result); 1479 } 1480} 1481 1482void LLVMIRBuilder::HandleFinishAllocate(GateRef gate) 1483{ 1484 auto g0 = acc_.GetValueIn(gate, 0); 1485 VisitFinishAllocate(gate, g0); 1486} 1487 1488void LLVMIRBuilder::VisitFinishAllocate(GateRef gate, GateRef e1) 1489{ 1490 LLVMValueRef result = GetLValue(e1); 1491 Bind(gate, result); 1492 if (IsLogEnabled()) { 1493 SetDebugInfo(gate, result); 1494 } 1495} 1496 1497void LLVMIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse) 1498{ 1499 if (gate2LValue_.count(cmp) == 0) { 1500 OPTIONAL_LOG_COMPILER(ERROR) << "Branch condition gate is nullptr!"; 1501 return; 1502 } 1503 LLVMValueRef cond = GetLValue(cmp); 1504 1505 BasicBlock *trueBB = EnsureBB(btrue); 1506 BasicBlock *falseBB = EnsureBB(bfalse); 1507 EnsureLBB(trueBB); 1508 EnsureLBB(falseBB); 1509 1510 LLVMBasicBlockRef llvmTrueBB = trueBB->GetImpl<BasicBlockImpl>()->lBB_; 1511 LLVMBasicBlockRef llvmFalseBB = falseBB->GetImpl<BasicBlockImpl>()->lBB_; 1512 LLVMValueRef result = LLVMBuildCondBr(builder_, cond, llvmTrueBB, llvmFalseBB); 1513 EndCurrentBlock(); 1514 1515 if (enableOptBranchProfiling_ && acc_.HasBranchWeight(gate)) { 1516 auto trueWeight = acc_.GetTrueWeight(gate); 1517 auto falseWeight = acc_.GetFalseWeight(gate); 1518 LLVMMetadataRef branch_weights = LLVMMDStringInContext2(context_, "branch_weights", 14); 1519 LLVMMetadataRef weight1 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), trueWeight, 0)); 1520 LLVMMetadataRef weight2 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), falseWeight, 0)); 1521 LLVMMetadataRef mds[] = {branch_weights, weight1, weight2}; 1522 LLVMMetadataRef metadata = LLVMMDNodeInContext2(context_, mds, 3); 1523 LLVMValueRef metadata_value = LLVMMetadataAsValue(context_, metadata); 1524 LLVMSetMetadata(result, LLVMGetMDKindID("prof", 4), metadata_value); // 4: length of "prof" 1525 } 1526 Bind(gate, result); 1527 1528 if (IsLogEnabled()) { 1529 SetDebugInfo(gate, result); 1530 } 1531} 1532 1533void LLVMIRBuilder::HandleSwitch(GateRef gate) 1534{ 1535 std::vector<GateRef> ins; 1536 acc_.GetIns(gate, ins); 1537 std::vector<GateRef> outs; 1538 acc_.GetOutStates(gate, outs); 1539 VisitSwitch(gate, ins[1], outs); 1540} 1541 1542void LLVMIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<GateRef> &outList) 1543{ 1544 LLVMValueRef cond = GetLValue(input); 1545 int caseNum = static_cast<int>(outList.size()); 1546 BasicBlock *curOutBB = nullptr; 1547 LLVMBasicBlockRef llvmDefaultOutBB = nullptr; 1548 for (int i = 0; i < caseNum; i++) { 1549 curOutBB = EnsureBB(instID2bbID_[acc_.GetId(outList[i])]); 1550 EnsureLBB(curOutBB); 1551 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) { 1552 llvmDefaultOutBB = curOutBB->GetImpl<BasicBlockImpl>()->lBB_; 1553 } 1554 } 1555 LLVMValueRef result = LLVMBuildSwitch(builder_, cond, llvmDefaultOutBB, static_cast<uint32_t>(caseNum - 1)); 1556 LLVMBasicBlockRef llvmCurOutBB = nullptr; 1557 for (int i = 0; i < caseNum; i++) { 1558 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) { 1559 continue; 1560 } 1561 curOutBB = EnsureBB(instID2bbID_[acc_.GetId(outList[i])]); 1562 llvmCurOutBB = curOutBB->GetImpl<BasicBlockImpl>()->lBB_; 1563 LLVMAddCase(result, LLVMConstInt(ConvertLLVMTypeFromGate(input), acc_.TryGetValue(outList[i]), 0), 1564 llvmCurOutBB); 1565 } 1566 EndCurrentBlock(); 1567 Bind(gate, result); 1568 1569 if (IsLogEnabled()) { 1570 SetDebugInfo(gate, result); 1571 } 1572} 1573 1574unsigned LLVMIRBuilder::GetPtrAddressSpace(LLVMValueRef v) const 1575{ 1576 auto ty = LLVMTypeOf(v); 1577 if (LLVMGetTypeKind(ty) == LLVMPointerTypeKind) { 1578 return LLVMGetPointerAddressSpace(ty); 1579 } 1580 return 0; 1581} 1582 1583void LLVMIRBuilder::VisitLoad(GateRef gate, GateRef base) 1584{ 1585 LLVMValueRef baseAddr = GetLValue(base); 1586 1587 LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate); 1588 LLVMTypeRef memType = LLVMPointerType(returnType, GetPtrAddressSpace(baseAddr)); 1589 baseAddr = CanonicalizeToPtr(baseAddr, memType); 1590 1591 LLVMValueRef result = LLVMBuildLoad(builder_, baseAddr, ""); 1592 auto order = acc_.GetMemoryAttribute(gate); 1593 switch (order.GetOrder()) { 1594 case MemoryAttribute::MEMORY_ORDER_RELEASE: { 1595 LLVMSetOrdering(result, LLVMAtomicOrderingRelease); 1596 break; 1597 } 1598 case MemoryAttribute::NOT_ATOMIC: { 1599 break; 1600 } 1601 default: { 1602 UNREACHABLE(); 1603 break; 1604 } 1605 } 1606 Bind(gate, result); 1607 1608 if (IsLogEnabled()) { 1609 SetDebugInfo(gate, result); 1610 } 1611} 1612 1613void LLVMIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef value) 1614{ 1615 LLVMValueRef baseAddr = GetLValue(base); 1616 LLVMValueRef data = GetLValue(value); 1617 1618 LLVMTypeRef returnType = ConvertLLVMTypeFromGate(value); 1619 LLVMTypeRef ptrType = LLVMPointerType(returnType, GetPtrAddressSpace(baseAddr)); 1620 baseAddr = CanonicalizeToPtr(baseAddr, ptrType); 1621 1622 LLVMValueRef result = LLVMBuildStore(builder_, data, baseAddr); 1623 auto order = acc_.GetMemoryAttribute(gate); 1624 switch (order.GetOrder()) { 1625 case MemoryAttribute::MEMORY_ORDER_RELEASE: { 1626 LLVMSetOrdering(result, LLVMAtomicOrderingRelease); 1627 break; 1628 } 1629 case MemoryAttribute::NOT_ATOMIC: { 1630 break; 1631 } 1632 default: { 1633 UNREACHABLE(); 1634 break; 1635 } 1636 } 1637 Bind(gate, result); 1638 1639 if (IsLogEnabled()) { 1640 SetDebugInfo(gate, result); 1641 } 1642} 1643 1644LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value) const 1645{ 1646 if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) { 1647 return LLVMBuildPtrToInt(builder_, value, GetInt64T(), ""); 1648 } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) { 1649 return value; 1650 } else { 1651 LOG_COMPILER(FATAL) << "can't Canonicalize to Int64: "; 1652 UNREACHABLE(); 1653 } 1654} 1655 1656LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const 1657{ 1658 LLVMTypeRef valueT = LLVMTypeOf(value); 1659 if (LLVMGetTypeKind(valueT) == LLVMPointerTypeKind) { 1660 if (valueT != ptrType) { 1661 return LLVMBuildPointerCast(builder_, value, ptrType, ""); 1662 } 1663 } else if (LLVMGetTypeKind(valueT) == LLVMIntegerTypeKind) { 1664 LLVMValueRef result = LLVMBuildIntToPtr(builder_, value, ptrType, ""); 1665 return result; 1666 } else { 1667 LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: "; 1668 UNREACHABLE(); 1669 } 1670 return value; 1671} 1672 1673LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value) const 1674{ 1675 LLVMTypeRef valueT = LLVMTypeOf(value); 1676 if (LLVMGetTypeKind(valueT) == LLVMPointerTypeKind) { 1677 auto ptrType = LLVMPointerType(GetInt8T(), GetPtrAddressSpace(value)); 1678 return LLVMBuildPointerCast(builder_, value, ptrType, ""); 1679 } else if (LLVMGetTypeKind(valueT) == LLVMIntegerTypeKind) { 1680 LLVMValueRef result = LLVMBuildIntToPtr(builder_, value, GetRawPtrT(), ""); 1681 return result; 1682 } else { 1683 LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: "; 1684 UNREACHABLE(); 1685 } 1686} 1687 1688void LLVMIRBuilder::HandleIntRev(GateRef gate) 1689{ 1690 std::vector<GateRef> ins; 1691 acc_.GetIns(gate, ins); 1692 VisitIntRev(gate, ins[0]); 1693} 1694 1695void LLVMIRBuilder::VisitIntRev(GateRef gate, GateRef e1) 1696{ 1697 LLVMValueRef e1Value = GetLValue(e1); 1698 ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e1)); 1699 auto machineType = acc_.GetMachineType(gate); 1700 LLVMValueRef result = nullptr; 1701 if (machineType <= MachineType::I64 && machineType >= MachineType::I1) { 1702 result = LLVMBuildNot(builder_, e1Value, ""); 1703 } else { 1704 LOG_ECMA(FATAL) << "this branch is unreachable"; 1705 UNREACHABLE(); 1706 } 1707 Bind(gate, result); 1708 1709 if (IsLogEnabled()) { 1710 SetDebugInfo(gate, result); 1711 } 1712} 1713 1714bool LLVMIRBuilder::IsLInteger(LLVMValueRef v) const 1715{ 1716 LLVMTypeRef r = LLVMTypeOf(v); 1717 return LLVMGetTypeKind(r) == LLVMIntegerTypeKind; 1718} 1719 1720bool LLVMIRBuilder::IsLPointer(LLVMValueRef v) const 1721{ 1722 LLVMTypeRef r = LLVMTypeOf(v); 1723 return LLVMGetTypeKind(r) == LLVMPointerTypeKind; 1724} 1725 1726LLVMValueRef LLVMIRBuilder::PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep) 1727{ 1728 LLVMValueRef ptr = CanonicalizeToPtr(baseAddr); 1729 LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offsetInByte, 1, ""); 1730 LLVMValueRef result = LLVMBuildPointerCast(builder_, dstRef8, rep, ""); 1731 return result; 1732} 1733 1734LLVMTypeRef LLVMIRBuilder::ConvertLLVMTypeFromGate(GateRef gate) const 1735{ 1736 if (acc_.IsGCRelated(gate)) { 1737 return GetTaggedHPtrT(); 1738 } 1739 MachineType t = acc_.GetMachineType(gate); 1740 switch (t) { 1741 case MachineType::NOVALUE: 1742 return GetVoidT(); 1743 case MachineType::I1: 1744 return GetInt1T(); 1745 case MachineType::I8: 1746 return GetInt8T(); 1747 case MachineType::I16: 1748 return GetInt16T(); 1749 case MachineType::I32: 1750 return GetInt32T(); 1751 case MachineType::I64: 1752 return GetInt64T(); 1753 case MachineType::F32: 1754 return GetFloatT(); 1755 case MachineType::F64: 1756 return GetDoubleT(); 1757 case MachineType::ARCH: { 1758 return GetInt64T(); 1759 } 1760 default: 1761 LOG_ECMA(FATAL) << "this branch is unreachable"; 1762 UNREACHABLE(); 1763 } 1764} 1765 1766int64_t LLVMIRBuilder::GetBitWidthFromMachineType(MachineType machineType) const 1767{ 1768 switch (machineType) { 1769 case NOVALUE: 1770 return 0; 1771 case ARCH: 1772 return 48; // 48: Pointer representation in different architectures 1773 case I1: 1774 return 1; 1775 case I8: 1776 return 8; // 8: bit width 1777 case I16: 1778 return 16; // 16: bit width 1779 case I32: 1780 return 32; // 32: bit width 1781 case I64: 1782 return 64; // 64: bit width 1783 case F32: 1784 return 32; // 32: bit width 1785 case F64: 1786 return 64; // 64: bit width 1787 case FLEX: 1788 case ANYVALUE: 1789 LOG_ECMA(FATAL) << "this branch is unreachable"; 1790 UNREACHABLE(); 1791 default: 1792 LOG_ECMA(FATAL) << "this branch is unreachable"; 1793 UNREACHABLE(); 1794 } 1795} 1796 1797void LLVMIRBuilder::HandleAdd(GateRef gate) 1798{ 1799 auto g0 = acc_.GetIn(gate, 0); 1800 auto g1 = acc_.GetIn(gate, 1); 1801 VisitAdd(gate, g0, g1); 1802} 1803 1804void LLVMIRBuilder::HandleTruncFloatToInt(GateRef gate) 1805{ 1806 auto g0 = acc_.GetIn(gate, 0); 1807 VisitTruncFloatToInt(gate, g0); 1808} 1809 1810void LLVMIRBuilder::VisitTruncFloatToInt(GateRef gate, GateRef e1) 1811{ 1812 LLVMValueRef e1Value = GetLValue(e1); 1813 auto machineType = acc_.GetMachineType(e1); 1814 LLVMValueRef result = nullptr; 1815 if (machineType <= MachineType::F64 && machineType >= MachineType::F32) { 1816 result = LLVMBuildFPToSI(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 1817 } else { 1818 LOG_ECMA(FATAL) << "this branch is unreachable"; 1819 UNREACHABLE(); 1820 } 1821 Bind(gate, result); 1822 1823 if (IsLogEnabled()) { 1824 SetDebugInfo(gate, result); 1825 } 1826} 1827 1828void LLVMIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2) 1829{ 1830 LLVMValueRef e1Value = GetLValue(e1); 1831 LLVMValueRef e2Value = GetLValue(e2); 1832 LLVMValueRef result = nullptr; 1833 1834 LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate); 1835 auto machineType = acc_.GetMachineType(gate); 1836 if (IsAddIntergerType(machineType)) { 1837 auto e1Type = LLVMGetTypeKind(ConvertLLVMTypeFromGate(e1)); 1838 if (e1Type == LLVMPointerTypeKind) { 1839 result = PointerAdd(e1Value, e2Value, returnType); 1840 } else { 1841 LLVMValueRef tmp1Value = LLVMBuildIntCast2(builder_, e1Value, returnType, 0, ""); 1842 LLVMValueRef tmp2Value = LLVMBuildIntCast2(builder_, e2Value, returnType, 0, ""); 1843 result = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, ""); 1844 if (LLVMTypeOf(tmp1Value) != LLVMTypeOf(tmp2Value)) { 1845 ASSERT(LLVMTypeOf(tmp1Value) == LLVMTypeOf(tmp2Value)); 1846 } 1847 } 1848 } else if (machineType == MachineType::F64) { 1849 result = LLVMBuildFAdd(builder_, e1Value, e2Value, ""); 1850 } else { 1851 LOG_ECMA(FATAL) << "this branch is unreachable"; 1852 UNREACHABLE(); 1853 } 1854 Bind(gate, result); 1855 1856 if (IsLogEnabled()) { 1857 SetDebugInfo(gate, result); 1858 } 1859} 1860 1861void LLVMIRBuilder::HandleSub(GateRef gate) 1862{ 1863 auto g0 = acc_.GetIn(gate, 0); 1864 auto g1 = acc_.GetIn(gate, 1); 1865 VisitSub(gate, g0, g1); 1866} 1867 1868void LLVMIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2) 1869{ 1870 LLVMValueRef e1Value = GetLValue(e1); 1871 LLVMValueRef e2Value = GetLValue(e2); 1872 LLVMValueRef result = nullptr; 1873 auto machineType = acc_.GetMachineType(gate); 1874 if (machineType == MachineType::I16 || machineType == MachineType::I32 || 1875 machineType == MachineType::I64 || machineType == MachineType::ARCH) { 1876 result = LLVMBuildSub(builder_, e1Value, e2Value, ""); 1877 } else if (machineType == MachineType::F64) { 1878 result = LLVMBuildFSub(builder_, e1Value, e2Value, ""); 1879 } else { 1880 LOG_ECMA(FATAL) << "this branch is unreachable"; 1881 UNREACHABLE(); 1882 } 1883 Bind(gate, result); 1884 1885 if (IsLogEnabled()) { 1886 SetDebugInfo(gate, result); 1887 } 1888} 1889 1890void LLVMIRBuilder::HandleMul(GateRef gate) 1891{ 1892 auto g0 = acc_.GetIn(gate, 0); 1893 auto g1 = acc_.GetIn(gate, 1); 1894 VisitMul(gate, g0, g1); 1895} 1896 1897void LLVMIRBuilder::VisitMul(GateRef gate, GateRef e1, GateRef e2) 1898{ 1899 LLVMValueRef e1Value = GetLValue(e1); 1900 LLVMValueRef e2Value = GetLValue(e2); 1901 LLVMValueRef result = nullptr; 1902 auto machineType = acc_.GetMachineType(gate); 1903 if (IsMulIntergerType(machineType)) { 1904 result = LLVMBuildMul(builder_, e1Value, e2Value, ""); 1905 } else if (machineType == MachineType::F64) { 1906 result = LLVMBuildFMul(builder_, e1Value, e2Value, ""); 1907 } else { 1908 LOG_ECMA(FATAL) << "this branch is unreachable"; 1909 UNREACHABLE(); 1910 } 1911 Bind(gate, result); 1912 1913 if (IsLogEnabled()) { 1914 SetDebugInfo(gate, result); 1915 } 1916} 1917 1918void LLVMIRBuilder::HandleFloatDiv(GateRef gate) 1919{ 1920 auto g0 = acc_.GetIn(gate, 0); 1921 auto g1 = acc_.GetIn(gate, 1); 1922 VisitFloatDiv(gate, g0, g1); 1923} 1924 1925void LLVMIRBuilder::HandleIntDiv(GateRef gate) 1926{ 1927 auto g0 = acc_.GetIn(gate, 0); 1928 auto g1 = acc_.GetIn(gate, 1); 1929 VisitIntDiv(gate, g0, g1); 1930} 1931 1932void LLVMIRBuilder::HandleUDiv(GateRef gate) 1933{ 1934 auto g0 = acc_.GetIn(gate, 0); 1935 auto g1 = acc_.GetIn(gate, 1); 1936 VisitUDiv(gate, g0, g1); 1937} 1938 1939void LLVMIRBuilder::HandleIntOr(GateRef gate) 1940{ 1941 auto g0 = acc_.GetIn(gate, 0); 1942 auto g1 = acc_.GetIn(gate, 1); 1943 VisitIntOr(gate, g0, g1); 1944} 1945 1946void LLVMIRBuilder::HandleIntXor(GateRef gate) 1947{ 1948 auto g0 = acc_.GetIn(gate, 0); 1949 auto g1 = acc_.GetIn(gate, 1); 1950 VisitIntXor(gate, g0, g1); 1951} 1952 1953void LLVMIRBuilder::HandleIntLsr(GateRef gate) 1954{ 1955 auto g0 = acc_.GetIn(gate, 0); 1956 auto g1 = acc_.GetIn(gate, 1); 1957 VisitIntLsr(gate, g0, g1); 1958} 1959 1960void LLVMIRBuilder::HandleIntAsr(GateRef gate) 1961{ 1962 auto g0 = acc_.GetIn(gate, 0); 1963 auto g1 = acc_.GetIn(gate, 1); 1964 VisitIntAsr(gate, g0, g1); 1965} 1966 1967void LLVMIRBuilder::HandleCmp(GateRef gate) 1968{ 1969 GateRef left = acc_.GetIn(gate, 0); 1970 GateRef right = acc_.GetIn(gate, 1); 1971 VisitCmp(gate, left, right); 1972} 1973 1974void LLVMIRBuilder::HandleAddWithOverflow(GateRef gate) 1975{ 1976 GateRef left = acc_.GetIn(gate, 0); 1977 GateRef right = acc_.GetIn(gate, 1); 1978 ASSERT(acc_.GetMachineType(left) == MachineType::I32); 1979 ASSERT(acc_.GetMachineType(right) == MachineType::I32); 1980 VisitAddWithOverflow(gate, left, right); 1981} 1982 1983void LLVMIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2) 1984{ 1985 LLVMValueRef e1Value = GetLValue(e1); 1986 LLVMValueRef e2Value = GetLValue(e2); 1987 std::vector<LLVMValueRef> args = { e1Value, e2Value }; 1988 auto fn = LLVMGetNamedFunction(module_, "llvm.sadd.with.overflow.i32"); 1989 if (!fn) { 1990 /* init instrinsic function declare */ 1991 LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() }; 1992 LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() }; 1993 LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0); 1994 auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0); 1995 fn = LLVMAddFunction(module_, "llvm.sadd.with.overflow.i32", fnTy); 1996 } 1997 LLVMValueRef result = LLVMBuildCall(builder_, fn, args.data(), 2, ""); 1998 Bind(gate, result); 1999 2000 if (IsLogEnabled()) { 2001 SetDebugInfo(gate, result); 2002 } 2003} 2004 2005void LLVMIRBuilder::HandleSubWithOverflow(GateRef gate) 2006{ 2007 GateRef left = acc_.GetIn(gate, 0); 2008 GateRef right = acc_.GetIn(gate, 1); 2009 ASSERT(acc_.GetMachineType(left) == MachineType::I32); 2010 ASSERT(acc_.GetMachineType(right) == MachineType::I32); 2011 VisitSubWithOverflow(gate, left, right); 2012} 2013 2014void LLVMIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2) 2015{ 2016 LLVMValueRef e1Value = GetLValue(e1); 2017 LLVMValueRef e2Value = GetLValue(e2); 2018 std::vector<LLVMValueRef> args = { e1Value, e2Value }; 2019 auto fn = LLVMGetNamedFunction(module_, "llvm.ssub.with.overflow.i32"); 2020 if (!fn) { 2021 /* init instrinsic function declare */ 2022 LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() }; 2023 LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() }; 2024 LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0); 2025 auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0); 2026 fn = LLVMAddFunction(module_, "llvm.ssub.with.overflow.i32", fnTy); 2027 } 2028 LLVMValueRef result = LLVMBuildCall(builder_, fn, args.data(), 2, ""); 2029 Bind(gate, result); 2030 2031 if (IsLogEnabled()) { 2032 SetDebugInfo(gate, result); 2033 } 2034} 2035 2036void LLVMIRBuilder::HandleMulWithOverflow(GateRef gate) 2037{ 2038 GateRef left = acc_.GetIn(gate, 0); 2039 GateRef right = acc_.GetIn(gate, 1); 2040 ASSERT(acc_.GetMachineType(left) == MachineType::I32); 2041 ASSERT(acc_.GetMachineType(right) == MachineType::I32); 2042 VisitMulWithOverflow(gate, left, right); 2043} 2044 2045void LLVMIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2) 2046{ 2047 LLVMValueRef e1Value = GetLValue(e1); 2048 LLVMValueRef e2Value = GetLValue(e2); 2049 std::vector<LLVMValueRef> args = { e1Value, e2Value }; 2050 auto fn = LLVMGetNamedFunction(module_, "llvm.smul.with.overflow.i32"); 2051 if (!fn) { 2052 /* init instrinsic function declare */ 2053 LLVMTypeRef paramTys1[] = { GetInt32T(), GetInt32T() }; 2054 LLVMTypeRef structTys[] = { GetInt32T(), GetInt1T() }; 2055 LLVMTypeRef returnType = LLVMStructTypeInContext(context_, structTys, 2, 0); 2056 auto fnTy = LLVMFunctionType(returnType, paramTys1, 2, 0); 2057 fn = LLVMAddFunction(module_, "llvm.smul.with.overflow.i32", fnTy); 2058 } 2059 LLVMValueRef result = LLVMBuildCall(builder_, fn, args.data(), 2, ""); 2060 Bind(gate, result); 2061 2062 if (IsLogEnabled()) { 2063 SetDebugInfo(gate, result); 2064 } 2065} 2066 2067void LLVMIRBuilder::HandleExtractValue(GateRef gate) 2068{ 2069 GateRef pointer = acc_.GetIn(gate, 0); 2070 GateRef index = acc_.GetIn(gate, 1); 2071 VisitExtractValue(gate, pointer, index); 2072} 2073 2074void LLVMIRBuilder::VisitExtractValue(GateRef gate, GateRef e1, GateRef e2) 2075{ 2076 LLVMValueRef e1Value = GetLValue(e1); 2077 ASSERT((acc_.GetOpCode(e2) == OpCode::CONSTANT) && acc_.GetMachineType(e2) == MachineType::I32); 2078 uint32_t index = static_cast<uint32_t>(acc_.GetConstantValue(e2)); 2079 LLVMValueRef result = LLVMBuildExtractValue(builder_, e1Value, index, ""); 2080 Bind(gate, result); 2081 2082 if (IsLogEnabled()) { 2083 SetDebugInfo(gate, result); 2084 } 2085} 2086 2087void LLVMIRBuilder::HandleSqrt(GateRef gate) 2088{ 2089 GateRef param = acc_.GetIn(gate, 0); 2090 VisitSqrt(gate, param); 2091} 2092 2093void LLVMIRBuilder::VisitSqrt(GateRef gate, GateRef e1) 2094{ 2095 LLVMValueRef e1Value = GetLValue(e1); 2096 std::vector<LLVMValueRef> args = { e1Value }; 2097 auto fn = LLVMGetNamedFunction(module_, "llvm.sqrt.f64"); 2098 if (!fn) { 2099 /* init instrinsic function declare */ 2100 LLVMTypeRef paramTys1[] = { GetDoubleT() }; 2101 auto fnTy = LLVMFunctionType(GetDoubleT(), paramTys1, 1, 0); 2102 fn = LLVMAddFunction(module_, "llvm.sqrt.f64", fnTy); 2103 } 2104 LLVMValueRef result = LLVMBuildCall(builder_, fn, args.data(), 1, ""); 2105 Bind(gate, result); 2106 2107 if (IsLogEnabled()) { 2108 SetDebugInfo(gate, result); 2109 } 2110} 2111 2112void LLVMIRBuilder::HandleExp(GateRef gate) 2113{ 2114 GateRef base = acc_.GetIn(gate, 0U); 2115 GateRef power = acc_.GetIn(gate, 1U); 2116 VisitExp(gate, base, power); 2117} 2118 2119void LLVMIRBuilder::VisitExp([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef e1, [[maybe_unused]] GateRef e2) 2120{ 2121#ifdef SUPPORT_LLVM_INTRINSICS_WITH_CALLS 2122 llvm::Value *e1Value = llvm::unwrap(GetLValue(e1)); 2123 llvm::Value *e2Value = llvm::unwrap(GetLValue(e2)); 2124 2125 [[maybe_unused]] auto machineType = acc_.GetMachineType(gate); 2126 ASSERT(machineType == MachineType::F64); 2127 ASSERT(acc_.GetMachineType(e1) == machineType); 2128 ASSERT(acc_.GetMachineType(e2) == machineType); 2129 2130 llvm::Value *result = nullptr; 2131 2132 constexpr double one = 1.0; 2133 if (acc_.IsConstant(e1) && acc_.GetFloat64FromConstant(e1) == std::exp(one)) { 2134 llvm::Intrinsic::ID llvmId = llvm::Intrinsic::exp; 2135 result = llvm::unwrap(builder_)->CreateUnaryIntrinsic(llvmId, e2Value); 2136 } else { 2137 llvm::Intrinsic::ID llvmId = llvm::Intrinsic::pow; 2138 result = llvm::unwrap(builder_)->CreateBinaryIntrinsic(llvmId, e1Value, e2Value); 2139 } 2140#else 2141 UNREACHABLE(); 2142#endif 2143} 2144 2145void LLVMIRBuilder::HandleCeil(GateRef gate) 2146{ 2147 GateRef param = acc_.GetIn(gate, 0); 2148 VisitCeil(gate, param); 2149} 2150 2151void LLVMIRBuilder::VisitCeil(GateRef gate, GateRef e1) 2152{ 2153 llvm::Value *e1Value = llvm::unwrap(GetLValue(e1)); 2154 ASSERT(acc_.GetMachineType(e1) == acc_.GetMachineType(gate)); 2155 llvm::Intrinsic::ID llvmId = llvm::Intrinsic::ceil; 2156 llvm::Value *result = llvm::unwrap(builder_)->CreateUnaryIntrinsic(llvmId, e1Value); 2157 Bind(gate, llvm::wrap(result)); 2158 2159 if (IsLogEnabled()) { 2160 SetDebugInfo(gate, llvm::wrap(result)); 2161 } 2162} 2163 2164template<typename... Ts> 2165static llvm::CallInst *BuildLLVMIntrinsic(llvm::IRBuilder<> *builder, llvm::Intrinsic::ID llvmId, Ts... inputs) 2166{ 2167 static_assert((std::is_same_v<Ts, llvm::Value *> && ...)); 2168 if constexpr (sizeof...(inputs) == 1) { 2169 return builder->CreateUnaryIntrinsic(llvmId, inputs...); 2170 } else { 2171 static_assert(sizeof...(inputs) == 2); 2172 return builder->CreateBinaryIntrinsic(llvmId, inputs...); 2173 } 2174} 2175 2176void LLVMIRBuilder::HandleAbs(GateRef gate) 2177{ 2178 VisitAbs(gate, acc_.GetIn(gate, 0)); 2179} 2180 2181void LLVMIRBuilder::VisitAbs(GateRef gate, GateRef e1) 2182{ 2183 auto machineType = acc_.GetMachineType(gate); 2184 ASSERT(acc_.GetMachineType(e1) == machineType); 2185 llvm::Intrinsic::ID llvmId = 0; 2186 auto *builder = llvm::unwrap(builder_); 2187 llvm::Value *value = llvm::unwrap(GetLValue(e1)); 2188 LLVMValueRef result; 2189 if (machineType == MachineType::I32) { 2190 llvmId = llvm::Intrinsic::abs; 2191 llvm::Type *type = llvm::Type::getInt1Ty(*llvm::unwrap(context_)); 2192 llvm::Value *poison = llvm::Constant::getIntegerValue(type, llvm::APInt(1, 0)); 2193 result = llvm::wrap(BuildLLVMIntrinsic(builder, llvmId, value, poison)); 2194 } else if (machineType == MachineType::F64) { 2195 llvmId = llvm::Intrinsic::fabs; 2196 result = llvm::wrap(BuildLLVMIntrinsic(builder, llvmId, value)); 2197 } else { 2198 LOG_ECMA(FATAL) << "`Abs` type should be untagged double or signed int"; 2199 UNREACHABLE(); 2200 } 2201 Bind(gate, result); 2202 2203 if (IsLogEnabled()) { 2204 SetDebugInfo(gate, result); 2205 } 2206} 2207 2208void LLVMIRBuilder::HandleMin(GateRef gate) 2209{ 2210 VisitMin(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U)); 2211} 2212 2213void LLVMIRBuilder::VisitMin(GateRef gate, GateRef e1, GateRef e2) 2214{ 2215 auto machineType = acc_.GetMachineType(gate); 2216 ASSERT(acc_.GetMachineType(e1) == machineType); 2217 ASSERT(acc_.GetMachineType(e2) == machineType); 2218 llvm::Intrinsic::ID llvmId = 0; 2219 if (machineType == MachineType::I32) { 2220 llvmId = llvm::Intrinsic::smin; 2221 } else if (machineType == MachineType::F64) { 2222 llvmId = llvm::Intrinsic::minimum; 2223 } else { 2224 LOG_ECMA(FATAL) << "`Min` type should be untagged double or signed int"; 2225 UNREACHABLE(); 2226 } 2227 VisitIntrinsic(gate, llvmId, e1, e2); 2228} 2229 2230void LLVMIRBuilder::HandleMax(GateRef gate) 2231{ 2232 VisitMax(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U)); 2233} 2234 2235void LLVMIRBuilder::VisitMax(GateRef gate, GateRef e1, GateRef e2) 2236{ 2237 auto machineType = acc_.GetMachineType(gate); 2238 ASSERT(acc_.GetMachineType(e1) == machineType); 2239 ASSERT(acc_.GetMachineType(e2) == machineType); 2240 llvm::Intrinsic::ID llvmId = 0; 2241 if (machineType == MachineType::I32) { 2242 llvmId = llvm::Intrinsic::smax; 2243 } else if (machineType == MachineType::F64) { 2244 llvmId = llvm::Intrinsic::maximum; 2245 } else { 2246 LOG_ECMA(FATAL) << "`Max` type should be untagged double or signed int"; 2247 UNREACHABLE(); 2248 } 2249 VisitIntrinsic(gate, llvmId, e1, e2); 2250} 2251 2252void LLVMIRBuilder::HandleFloor(GateRef gate) 2253{ 2254 VisitIntrinsic(gate, llvm::Intrinsic::floor, acc_.GetIn(gate, 0)); 2255} 2256 2257template<typename... Ts> 2258void LLVMIRBuilder::VisitIntrinsic(GateRef gate, llvm::Intrinsic::ID llvmId, Ts... inputs) 2259{ 2260 static_assert((std::is_same_v<Ts, GateRef> && ...)); 2261 2262 auto *builder = llvm::unwrap(builder_); 2263 LLVMValueRef result = llvm::wrap(BuildLLVMIntrinsic(builder, llvmId, llvm::unwrap(GetLValue(inputs))...)); 2264 Bind(gate, result); 2265 2266 if (IsLogEnabled()) { 2267 SetDebugInfo(gate, result); 2268 } 2269} 2270 2271LLVMIntPredicate LLVMIRBuilder::ConvertLLVMPredicateFromICMP(ICmpCondition cond) 2272{ 2273 switch (cond) { 2274 case ICmpCondition::SLT: 2275 return LLVMIntSLT; 2276 case ICmpCondition::SLE: 2277 return LLVMIntSLE; 2278 case ICmpCondition::SGT: 2279 return LLVMIntSGT; 2280 case ICmpCondition::SGE: 2281 return LLVMIntSGE; 2282 case ICmpCondition::ULT: 2283 return LLVMIntULT; 2284 case ICmpCondition::ULE: 2285 return LLVMIntULE; 2286 case ICmpCondition::UGT: 2287 return LLVMIntUGT; 2288 case ICmpCondition::UGE: 2289 return LLVMIntUGE; 2290 case ICmpCondition::NE: 2291 return LLVMIntNE; 2292 case ICmpCondition::EQ: 2293 return LLVMIntEQ; 2294 default: 2295 LOG_COMPILER(FATAL) << "unexpected cond!"; 2296 UNREACHABLE(); 2297 } 2298 return LLVMIntEQ; 2299} 2300 2301LLVMRealPredicate LLVMIRBuilder::ConvertLLVMPredicateFromFCMP(FCmpCondition cond) 2302{ 2303 switch (cond) { 2304 case FCmpCondition::OLT: 2305 return LLVMRealOLT; 2306 case FCmpCondition::OLE: 2307 return LLVMRealOLE; 2308 case FCmpCondition::OGT: 2309 return LLVMRealOGT; 2310 case FCmpCondition::OGE: 2311 return LLVMRealOGE; 2312 case FCmpCondition::ONE: 2313 return LLVMRealONE; 2314 case FCmpCondition::OEQ: 2315 return LLVMRealOEQ; 2316 default: 2317 LOG_COMPILER(FATAL) << "unexpected cond!"; 2318 UNREACHABLE(); 2319 } 2320 return LLVMRealOEQ; 2321} 2322 2323void LLVMIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2) 2324{ 2325 LLVMValueRef e1Value = GetLValue(e1); 2326 LLVMValueRef e2Value = GetLValue(e2); 2327 LLVMValueRef result = nullptr; 2328 [[maybe_unused]] auto e1ValCode = acc_.GetMachineType(e1); 2329 [[maybe_unused]] auto e2ValCode = acc_.GetMachineType(e2); 2330 ASSERT((e1ValCode == e2ValCode) || 2331 (compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) || 2332 (compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64))); 2333 LLVMIntPredicate intOpcode = LLVMIntEQ; 2334 LLVMRealPredicate realOpcode = LLVMRealPredicateFalse; 2335 auto op = acc_.GetOpCode(gate); 2336 if (op == OpCode::ICMP) { 2337 auto cond = acc_.GetICmpCondition(gate); 2338 intOpcode = ConvertLLVMPredicateFromICMP(cond); 2339 result = LLVMBuildICmp(builder_, intOpcode, e1Value, e2Value, ""); 2340 } else if (op == OpCode::FCMP) { 2341 auto cond = acc_.GetFCmpCondition(gate); 2342 realOpcode = ConvertLLVMPredicateFromFCMP(cond); 2343 result = LLVMBuildFCmp(builder_, realOpcode, e1Value, e2Value, ""); 2344 } else { 2345 LOG_ECMA(FATAL) << "this branch is unreachable"; 2346 UNREACHABLE(); 2347 } 2348 Bind(gate, result); 2349 2350 if (IsLogEnabled()) { 2351 SetDebugInfo(gate, result); 2352 } 2353} 2354 2355void LLVMIRBuilder::HandleLoad(GateRef gate) 2356{ 2357 VisitLoad(gate, acc_.GetIn(gate, 1)); 2358} 2359 2360void LLVMIRBuilder::HandleStore(GateRef gate) 2361{ 2362 GateRef addr = acc_.GetValueIn(gate, 0); 2363 GateRef value = acc_.GetValueIn(gate, 1); 2364 VisitStore(gate, addr, value); 2365} 2366 2367void LLVMIRBuilder::HandleChangeInt32ToDouble(GateRef gate) 2368{ 2369 VisitChangeInt32ToDouble(gate, acc_.GetIn(gate, 0)); 2370} 2371 2372void LLVMIRBuilder::HandleChangeUInt32ToDouble(GateRef gate) 2373{ 2374 VisitChangeUInt32ToDouble(gate, acc_.GetIn(gate, 0)); 2375} 2376 2377void LLVMIRBuilder::HandleChangeDoubleToInt32(GateRef gate) 2378{ 2379 VisitChangeDoubleToInt32(gate, acc_.GetIn(gate, 0)); 2380} 2381 2382void LLVMIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate) 2383{ 2384 VisitChangeTaggedPointerToInt64(gate, acc_.GetIn(gate, 0)); 2385} 2386 2387void LLVMIRBuilder::HandleChangeInt64ToTagged(GateRef gate) 2388{ 2389 VisitChangeInt64ToTagged(gate, acc_.GetIn(gate, 0)); 2390} 2391 2392void LLVMIRBuilder::HandleDoubleTrunc(GateRef gate) 2393{ 2394 GateRef param = acc_.GetIn(gate, 0); 2395 VisitDoubleTrunc(gate, param); 2396} 2397 2398void LLVMIRBuilder::VisitDoubleTrunc(GateRef gate, GateRef e1) 2399{ 2400 llvm::Value *e1Value = llvm::unwrap(GetLValue(e1)); 2401 ASSERT(acc_.GetMachineType(e1) == acc_.GetMachineType(gate)); 2402 llvm::Intrinsic::ID llvmId = llvm::Intrinsic::trunc; 2403 llvm::Value *result = llvm::unwrap(builder_)->CreateUnaryIntrinsic(llvmId, e1Value); 2404 Bind(gate, llvm::wrap(result)); 2405 2406 if (IsLogEnabled()) { 2407 SetDebugInfo(gate, llvm::wrap(result)); 2408 } 2409} 2410 2411void LLVMIRBuilder::VisitIntDiv(GateRef gate, GateRef e1, GateRef e2) 2412{ 2413 LLVMValueRef e1Value = GetLValue(e1); 2414 LLVMValueRef e2Value = GetLValue(e2); 2415 LLVMValueRef result = LLVMBuildSDiv(builder_, e1Value, e2Value, ""); 2416 Bind(gate, result); 2417 2418 if (IsLogEnabled()) { 2419 SetDebugInfo(gate, result); 2420 } 2421} 2422 2423void LLVMIRBuilder::VisitUDiv(GateRef gate, GateRef e1, GateRef e2) 2424{ 2425 LLVMValueRef e1Value = GetLValue(e1); 2426 LLVMValueRef e2Value = GetLValue(e2); 2427 LLVMValueRef result = LLVMBuildUDiv(builder_, e1Value, e2Value, ""); 2428 Bind(gate, result); 2429 2430 if (IsLogEnabled()) { 2431 SetDebugInfo(gate, result); 2432 } 2433} 2434 2435void LLVMIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2) 2436{ 2437 LLVMValueRef e1Value = GetLValue(e1); 2438 LLVMValueRef e2Value = GetLValue(e2); 2439 2440 LLVMValueRef result = LLVMBuildFDiv(builder_, e1Value, e2Value, ""); 2441 Bind(gate, result); 2442 2443 if (IsLogEnabled()) { 2444 SetDebugInfo(gate, result); 2445 } 2446} 2447 2448void LLVMIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2) 2449{ 2450 LLVMValueRef e1Value = GetLValue(e1); 2451 LLVMValueRef e2Value = GetLValue(e2); 2452 LLVMValueRef result = LLVMBuildOr(builder_, e1Value, e2Value, ""); 2453 Bind(gate, result); 2454 2455 if (IsLogEnabled()) { 2456 SetDebugInfo(gate, result); 2457 } 2458} 2459 2460void LLVMIRBuilder::HandleIntAnd(GateRef gate) 2461{ 2462 auto g0 = acc_.GetIn(gate, 0); 2463 auto g1 = acc_.GetIn(gate, 1); 2464 VisitIntAnd(gate, g0, g1); 2465} 2466 2467void LLVMIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2) 2468{ 2469 LLVMValueRef e1Value = GetLValue(e1); 2470 LLVMValueRef e2Value = GetLValue(e2); 2471 LLVMValueRef result = LLVMBuildAnd(builder_, e1Value, e2Value, ""); 2472 Bind(gate, result); 2473 2474 if (IsLogEnabled()) { 2475 SetDebugInfo(gate, result); 2476 } 2477} 2478 2479void LLVMIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2) 2480{ 2481 LLVMValueRef e1Value = GetLValue(e1); 2482 LLVMValueRef e2Value = GetLValue(e2); 2483 LLVMValueRef result = LLVMBuildXor(builder_, e1Value, e2Value, ""); 2484 Bind(gate, result); 2485 2486 if (IsLogEnabled()) { 2487 SetDebugInfo(gate, result); 2488 } 2489} 2490 2491void LLVMIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2) 2492{ 2493 LLVMValueRef e1Value = GetLValue(e1); 2494 LLVMValueRef e2Value = GetLValue(e2); 2495 LLVMValueRef result = LLVMBuildLShr(builder_, e1Value, e2Value, ""); 2496 Bind(gate, result); 2497 2498 if (IsLogEnabled()) { 2499 SetDebugInfo(gate, result); 2500 } 2501} 2502 2503void LLVMIRBuilder::VisitIntAsr(GateRef gate, GateRef e1, GateRef e2) 2504{ 2505 LLVMValueRef e1Value = GetLValue(e1); 2506 LLVMValueRef e2Value = GetLValue(e2); 2507 LLVMValueRef result = LLVMBuildAShr(builder_, e1Value, e2Value, ""); 2508 Bind(gate, result); 2509 2510 if (IsLogEnabled()) { 2511 SetDebugInfo(gate, result); 2512 } 2513} 2514 2515void LLVMIRBuilder::HandleIntLsl(GateRef gate) 2516{ 2517 auto g0 = acc_.GetIn(gate, 0); 2518 auto g1 = acc_.GetIn(gate, 1); 2519 VisitIntLsl(gate, g0, g1); 2520} 2521 2522void LLVMIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2) 2523{ 2524 LLVMValueRef e1Value = GetLValue(e1); 2525 LLVMValueRef e2Value = GetLValue(e2); 2526 LLVMValueRef result = LLVMBuildShl(builder_, e1Value, e2Value, ""); 2527 Bind(gate, result); 2528 2529 if (IsLogEnabled()) { 2530 SetDebugInfo(gate, result); 2531 } 2532} 2533 2534void LLVMIRBuilder::VisitZExtInt(GateRef gate, GateRef e1) 2535{ 2536 LLVMValueRef e1Value = GetLValue(e1); 2537 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <= 2538 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2539 LLVMValueRef result = LLVMBuildZExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 2540 Bind(gate, result); 2541 2542 if (IsLogEnabled()) { 2543 SetDebugInfo(gate, result); 2544 } 2545} 2546 2547void LLVMIRBuilder::VisitSExtInt(GateRef gate, GateRef e1) 2548{ 2549 LLVMValueRef e1Value = GetLValue(e1); 2550 LLVMValueRef result = LLVMBuildSExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 2551 Bind(gate, result); 2552 2553 if (IsLogEnabled()) { 2554 SetDebugInfo(gate, result); 2555 } 2556} 2557 2558void LLVMIRBuilder::HandleCastIntXToIntY(GateRef gate) 2559{ 2560 VisitCastIntXToIntY(gate, acc_.GetIn(gate, 0)); 2561} 2562 2563void LLVMIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1) 2564{ 2565 LLVMValueRef e1Value = GetLValue(e1); 2566 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >= 2567 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2568 LLVMValueRef result = LLVMBuildIntCast2(builder_, e1Value, ConvertLLVMTypeFromGate(gate), 1, ""); 2569 Bind(gate, result); 2570 2571 if (IsLogEnabled()) { 2572 SetDebugInfo(gate, result); 2573 } 2574} 2575 2576void LLVMIRBuilder::HandleFPExt(GateRef gate) 2577{ 2578 VisitFPExt(gate, acc_.GetIn(gate, 0)); 2579} 2580 2581void LLVMIRBuilder::VisitFPExt(GateRef gate, GateRef e1) 2582{ 2583 LLVMValueRef e1Value = GetLValue(e1); 2584 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <= 2585 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2586 LLVMValueRef result = LLVMBuildFPExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 2587 Bind(gate, result); 2588 2589 if (IsLogEnabled()) { 2590 SetDebugInfo(gate, result); 2591 } 2592} 2593 2594void LLVMIRBuilder::HandleFPTrunc(GateRef gate) 2595{ 2596 VisitFPTrunc(gate, acc_.GetIn(gate, 0)); 2597} 2598 2599void LLVMIRBuilder::VisitFPTrunc(GateRef gate, GateRef e1) 2600{ 2601 LLVMValueRef e1Value = GetLValue(e1); 2602 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >= 2603 GetBitWidthFromMachineType(acc_.GetMachineType(gate))); 2604 LLVMValueRef result = LLVMBuildFPTrunc(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 2605 Bind(gate, result); 2606 2607 if (IsLogEnabled()) { 2608 SetDebugInfo(gate, result); 2609 } 2610} 2611 2612void LLVMIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1) 2613{ 2614 LLVMValueRef e1Value = GetLValue(e1); 2615 LLVMValueRef result = LLVMBuildSIToFP(builder_, e1Value, ConvertLLVMTypeFromGate(gate), ""); 2616 Bind(gate, result); 2617 2618 if (IsLogEnabled()) { 2619 SetDebugInfo(gate, result); 2620 } 2621} 2622 2623void LLVMIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1) 2624{ 2625 LLVMValueRef e1Value = GetLValue(e1); 2626 LLVMValueRef result = LLVMBuildUIToFP(builder_, e1Value, GetDoubleT(), ""); 2627 Bind(gate, result); 2628 2629 if (IsLogEnabled()) { 2630 SetDebugInfo(gate, result); 2631 } 2632} 2633 2634void LLVMIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1) 2635{ 2636 LLVMValueRef e1Value = GetLValue(e1); 2637 LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, GetInt32T(), ""); 2638 Bind(gate, result); 2639 2640 if (IsLogEnabled()) { 2641 SetDebugInfo(gate, result); 2642 } 2643} 2644 2645void LLVMIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1) 2646{ 2647 LLVMValueRef e1Value = GetLValue(e1); 2648 LLVMValueRef result = CanonicalizeToInt(e1Value); 2649 Bind(gate, result); 2650 2651 if (IsLogEnabled()) { 2652 SetDebugInfo(gate, result); 2653 } 2654} 2655 2656void LLVMIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1) 2657{ 2658 LLVMValueRef e1Value = GetLValue(e1); 2659 ASSERT(LLVMGetTypeKind(LLVMTypeOf(e1Value)) == LLVMIntegerTypeKind); 2660 LLVMValueRef result = LLVMBuildIntToPtr(builder_, e1Value, GetTaggedHPtrT(), ""); 2661 Bind(gate, result); 2662 2663 if (IsLogEnabled()) { 2664 SetDebugInfo(gate, result); 2665 } 2666} 2667 2668void LLVMIRBuilder::HandleBitCast(GateRef gate) 2669{ 2670 VisitBitCast(gate, acc_.GetIn(gate, 0)); 2671} 2672 2673void LLVMIRBuilder::VisitBitCast(GateRef gate, GateRef e1) 2674{ 2675 LLVMValueRef e1Value = GetLValue(e1); 2676 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(gate)) == 2677 GetBitWidthFromMachineType(acc_.GetMachineType(e1))); 2678 auto returnType = ConvertLLVMTypeFromGate(gate); 2679 LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, returnType, ""); 2680 Bind(gate, result); 2681 2682 if (IsLogEnabled()) { 2683 SetDebugInfo(gate, result); 2684 } 2685} 2686 2687void LLVMIRBuilder::HandleDeoptCheck(GateRef gate) 2688{ 2689 int block = instID2bbID_[acc_.GetId(gate)]; 2690 std::vector<GateRef> outs; 2691 acc_.GetOutStates(gate, outs); 2692 int bbOut = instID2bbID_[acc_.GetId(outs[0])]; // 0: output 2693 2694 BasicBlock *trueBB = EnsureBB(bbOut); 2695 LLVMBasicBlockRef llvmTrueBB = EnsureLBB(trueBB); 2696 std::string buf = "deopt if false B" + std::to_string(block); 2697 LLVMBasicBlockRef llvmFalseBB = LLVMAppendBasicBlock(function_, buf.c_str()); 2698 GateRef cmp = acc_.GetValueIn(gate, 0); // 0: cond 2699 LLVMValueRef cond = GetLValue(cmp); 2700 LLVMValueRef result = LLVMBuildCondBr(builder_, cond, llvmTrueBB, llvmFalseBB); 2701 2702 if (enableOptBranchProfiling_) { 2703 LLVMMetadataRef branch_weights = LLVMMDStringInContext2(context_, "branch_weights", 14); 2704 LLVMMetadataRef weight1 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), BranchWeight::DEOPT_WEIGHT, 0)); 2705 LLVMMetadataRef weight2 = LLVMValueAsMetadata(LLVMConstInt(LLVMIntType(32), BranchWeight::ONE_WEIGHT, 0)); 2706 LLVMMetadataRef mds[] = {branch_weights, weight1, weight2}; 2707 LLVMMetadataRef metadata = LLVMMDNodeInContext2(context_, mds, 3); // 3: size of mds 2708 LLVMValueRef metadata_value = LLVMMetadataAsValue(context_, metadata); 2709 LLVMSetMetadata(result, LLVMGetMDKindID("prof", 4), metadata_value); // 4: length of "prof" 2710 } 2711 2712 EndCurrentBlock(); 2713 2714 LLVMPositionBuilderAtEnd(builder_, llvmFalseBB); 2715 LLVMBasicBlockRef preLBB = EnsureLBB(EnsureBB(block)); 2716 LLVMMoveBasicBlockBefore(preLBB, llvmFalseBB); 2717 2718 VisitDeoptCheck(gate); 2719 LLVMValueRef returnValue = GetLValue(gate); 2720 if (IsLogEnabled()) { 2721 SetDebugInfo(gate, returnValue); 2722 } 2723 LLVMBuildRet(builder_, returnValue); 2724 Bind(gate, result); 2725} 2726 2727void LLVMIRBuilder::HandleClz32(GateRef gate) 2728{ 2729 VisitClz32(gate, acc_.GetIn(gate, 0)); 2730} 2731 2732void LLVMIRBuilder::VisitClz32(GateRef gate, GateRef param) 2733{ 2734 LLVMValueRef value = GetLValue(param); 2735 LLVMValueRef trueConst = LLVMConstInt(GetInt1T(), 0, true); 2736 2737 llvm::CallInst *result = llvm::unwrap(builder_)->CreateBinaryIntrinsic(llvm::Intrinsic::ctlz, 2738 llvm::unwrap(value), 2739 llvm::unwrap(trueConst)); 2740 Bind(gate, llvm::wrap(result)); 2741 2742 if (IsLogEnabled()) { 2743 SetDebugInfo(gate, value); 2744 } 2745} 2746 2747LLVMTypeRef LLVMIRBuilder::GetExperimentalDeoptTy() 2748{ 2749 auto fnTy = LLVMFunctionType(GetTaggedHPtrT(), nullptr, 0, 1); 2750 return fnTy; 2751} 2752 2753LLVMValueRef LLVMModule::GetDeoptFunction() 2754{ 2755 auto fn = LLVMGetNamedFunction(module_, Deoptimizier::GetLLVMDeoptRelocateSymbol()); 2756 return fn; 2757} 2758 2759void LLVMIRBuilder::GenDeoptEntry(LLVMModuleRef &module) 2760{ 2761 // glue type depth 2762 std::vector<LLVMTypeRef> paramTys = { GetInt64T(), GetInt64T(), GetInt64T() }; 2763 auto funcType = LLVMFunctionType(GetInt64T(), paramTys.data(), paramTys.size(), 0); 2764 auto function = LLVMAddFunction(module, Deoptimizier::GetLLVMDeoptRelocateSymbol(), funcType); 2765 LLVMSetFunctionCallConv(function, LLVMCCallConv); 2766 llvmModule_->SetFunction(LLVMModule::kDeoptEntryOffset, function, false); 2767 2768 LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context_, function, "entry"); 2769 LLVMBuilderRef builder = LLVMCreateBuilderInContext(context_); 2770 LLVMPositionBuilderAtEnd(builder, entry); 2771 2772 auto reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); 2773 LLVMAddTargetDependentFunctionAttr(function, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); 2774 SaveFrameTypeOnFrame(FrameType::OPTIMIZED_FRAME, builder); 2775 2776 LLVMValueRef glue = LLVMGetParam(function, 0); 2777 LLVMValueRef check = LLVMGetParam(function, 1); 2778 LLVMValueRef depth = LLVMGetParam(function, 2); 2779 2780 StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm); 2781 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId)); 2782 LLVMValueRef rtoffset = LLVMBuildAdd(builder, glue, GetRTStubOffset(glue, stubIndex), ""); 2783 LLVMValueRef patchAddr = LLVMBuildIntToPtr(builder, rtoffset, GetTaggedPtrT(), ""); 2784 LLVMValueRef llvmAddr = LLVMBuildLoad(builder, patchAddr, ""); 2785 LLVMTypeRef rtfuncTypePtr = LLVMPointerType(funcType, 0); 2786 LLVMValueRef callee = LLVMBuildIntToPtr(builder, llvmAddr, rtfuncTypePtr, ""); 2787 std::vector<LLVMValueRef> params = {glue, check, depth}; 2788 LLVMValueRef runtimeCall = LLVMBuildCall2(builder, funcType, callee, params.data(), params.size(), ""); 2789 LLVMBuildRet(builder, runtimeCall); 2790 LLVMPositionBuilderAtEnd(builder, entry); 2791 LLVMDisposeBuilder(builder); 2792} 2793 2794LLVMValueRef LLVMIRBuilder::GetExperimentalDeopt(LLVMModuleRef &module) 2795{ 2796 /* 0:calling 1:its caller */ 2797 auto fn = LLVMGetNamedFunction(module, "llvm.experimental.deoptimize.p1i64"); 2798 if (!fn) { 2799 auto fnTy = GetExperimentalDeoptTy(); 2800 fn = LLVMAddFunction(module, "llvm.experimental.deoptimize.p1i64", fnTy); 2801 GenDeoptEntry(module); 2802 } 2803 return fn; 2804} 2805 2806LLVMValueRef LLVMIRBuilder::ConvertBoolToTaggedBoolean(GateRef gate) 2807{ 2808 LLVMValueRef value = GetLValue(gate); 2809 LLVMValueRef e1Value = LLVMBuildZExt(builder_, value, GetInt64T(), ""); 2810 auto tagMask = LLVMConstInt(GetInt64T(), JSTaggedValue::TAG_BOOLEAN_MASK, 0); 2811 LLVMValueRef result = LLVMBuildOr(builder_, e1Value, tagMask, ""); 2812 return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), ""); 2813} 2814 2815LLVMValueRef LLVMIRBuilder::ConvertInt32ToTaggedInt(GateRef gate) 2816{ 2817 LLVMValueRef value = GetLValue(gate); 2818 return ConvertInt32ToTaggedInt(value); 2819} 2820 2821LLVMValueRef LLVMIRBuilder::ConvertInt32ToTaggedInt(LLVMValueRef value) 2822{ 2823 LLVMValueRef e1Value = LLVMBuildSExt(builder_, value, GetInt64T(), ""); 2824 auto tagMask = LLVMConstInt(GetInt64T(), JSTaggedValue::TAG_INT, 0); 2825 LLVMValueRef result = LLVMBuildOr(builder_, e1Value, tagMask, ""); 2826 return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), ""); 2827} 2828 2829LLVMValueRef LLVMIRBuilder::ConvertFloat64ToTaggedDouble(GateRef gate) 2830{ 2831 LLVMValueRef value = GetLValue(gate); 2832 LLVMValueRef e1Value = LLVMBuildBitCast(builder_, value, GetInt64T(), ""); 2833 auto offset = LLVMConstInt(GetInt64T(), JSTaggedValue::DOUBLE_ENCODE_OFFSET, 0); 2834 LLVMValueRef result = LLVMBuildAdd(builder_, e1Value, offset, ""); 2835 return LLVMBuildIntToPtr(builder_, result, GetTaggedHPtrT(), ""); 2836} 2837 2838LLVMValueRef LLVMIRBuilder::ConvertToTagged(GateRef gate) 2839{ 2840 auto machineType = acc_.GetMachineType(gate); 2841 switch (machineType) { 2842 case MachineType::I1: 2843 return ConvertBoolToTaggedBoolean(gate); 2844 case MachineType::I32: 2845 return ConvertInt32ToTaggedInt(gate); 2846 case MachineType::F64: 2847 return ConvertFloat64ToTaggedDouble(gate); 2848 case MachineType::I64: 2849 break; 2850 default: 2851 LOG_COMPILER(FATAL) << "unexpected machineType!"; 2852 UNREACHABLE(); 2853 break; 2854 } 2855 return gate2LValue_.at(gate); 2856} 2857 2858void LLVMIRBuilder::SaveDeoptVregInfo(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift, 2859 GateRef gate) 2860{ 2861 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift); 2862 values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false)); 2863 values.emplace_back(ConvertToTagged(gate)); 2864} 2865 2866void LLVMIRBuilder::SaveDeoptVregInfoWithI64(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, 2867 size_t shift, GateRef gate) 2868{ 2869 LLVMValueRef value = LLVMBuildIntCast2(builder_, gate2LValue_.at(gate), GetInt32T(), 1, ""); 2870 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift); 2871 values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false)); 2872 values.emplace_back(ConvertInt32ToTaggedInt(value)); 2873} 2874 2875void LLVMIRBuilder::VisitDeoptCheck(GateRef gate) 2876{ 2877 LLVMValueRef glue = gate2LValue_.at(acc_.GetGlueFromArgList()); 2878 GateRef deoptFrameState = acc_.GetValueIn(gate, 1); // 1: frame state 2879 ASSERT(acc_.GetOpCode(deoptFrameState) == OpCode::FRAME_STATE); 2880 std::vector<LLVMValueRef> params; 2881 params.push_back(glue); // glue 2882 GateRef deoptType = acc_.GetValueIn(gate, 2); // 2: deopt type 2883 uint64_t v = acc_.GetConstantValue(deoptType); 2884 params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(GetInt32T(), static_cast<uint32_t>(v), false))); // deoptType 2885 LLVMValueRef callee = GetExperimentalDeopt(module_); 2886 LLVMTypeRef funcType = GetExperimentalDeoptTy(); 2887 2888 std::vector<LLVMValueRef> values; 2889 size_t maxDepth = acc_.GetFrameDepth(deoptFrameState, OpCode::FRAME_STATE); 2890 params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(GetInt32T(), static_cast<uint32_t>(maxDepth), false))); 2891 size_t shift = Deoptimizier::ComputeShift(maxDepth); 2892 GateRef frameState = deoptFrameState; 2893 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_)); 2894 for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) { 2895 ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE); 2896 GateRef frameValues = acc_.GetValueIn(frameState, 1); // 1: frame values 2897 const size_t numValueIn = acc_.GetNumValueIn(frameValues); 2898 ASSERT(numValueIn > 1); 2899 const size_t envIndex = numValueIn - 2; // 2: env valueIn index 2900 const size_t accIndex = numValueIn - 1; // 1: acc valueIn index 2901 GateRef env = acc_.GetValueIn(frameValues, envIndex); 2902 GateRef acc = acc_.GetValueIn(frameValues, accIndex); 2903 auto pc = acc_.TryGetPcOffset(frameState); 2904 GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC); 2905 GateRef newTarget = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::NEW_TARGET); 2906 GateRef thisObj = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::THIS_OBJECT); 2907 GateRef actualArgc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::ACTUAL_ARGC); 2908 // vreg 2909 for (size_t i = 0; i < envIndex; i++) { 2910 GateRef vregValue = acc_.GetValueIn(frameValues, i); 2911 if (acc_.IsConstantTaggedValue(vregValue, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2912 continue; 2913 } 2914 SaveDeoptVregInfo(values, i, curDepth, shift, vregValue); 2915 } 2916 // env 2917 if (!acc_.IsConstantTaggedValue(env, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2918 int32_t specEnvVregIndex = static_cast<int32_t>(SpecVregIndex::ENV_INDEX); 2919 SaveDeoptVregInfo(values, specEnvVregIndex, curDepth, shift, env); 2920 } 2921 // acc 2922 if (!acc_.IsConstantTaggedValue(acc, JSTaggedValue::VALUE_OPTIMIZED_OUT)) { 2923 int32_t specAccVregIndex = static_cast<int32_t>(SpecVregIndex::ACC_INDEX); 2924 SaveDeoptVregInfo(values, specAccVregIndex, curDepth, shift, acc); 2925 } 2926 // pc offset 2927 int32_t specPcOffsetIndex = static_cast<int32_t>(SpecVregIndex::PC_OFFSET_INDEX); 2928 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specPcOffsetIndex, curDepth, shift); 2929 values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false)); 2930 values.emplace_back(LLVMConstInt(GetInt32T(), pc, false)); 2931 // func 2932 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FUNC_INDEX); 2933 SaveDeoptVregInfo(values, specCallTargetIndex, curDepth, shift, jsFunc); 2934 // newTarget 2935 int32_t specNewTargetIndex = static_cast<int32_t>(SpecVregIndex::NEWTARGET_INDEX); 2936 SaveDeoptVregInfo(values, specNewTargetIndex, curDepth, shift, newTarget); 2937 // this object 2938 int32_t specThisIndex = static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX); 2939 SaveDeoptVregInfo(values, specThisIndex, curDepth, shift, thisObj); 2940 int32_t specArgcIndex = static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX); 2941 SaveDeoptVregInfoWithI64(values, specArgcIndex, curDepth, shift, actualArgc); 2942 frameState = acc_.GetFrameState(frameState); 2943 } 2944 LLVMValueRef runtimeCall = 2945 LLVMBuildCall3(builder_, funcType, callee, params.data(), params.size(), "", values.data(), values.size()); 2946 Bind(gate, runtimeCall); 2947} 2948 2949LLVMModule::LLVMModule(NativeAreaAllocator* allocator, const std::string &name, bool logDbg, const std::string &triple) 2950 : IRModule(allocator, logDbg, triple) 2951{ 2952 context_ = LLVMContextCreate(); 2953 module_ = LLVMModuleCreateWithNameInContext(name.c_str(), context_); 2954 LLVMSetTarget(module_, triple.c_str()); 2955 dBuilder_ = LLVMCreateDIBuilder(module_); 2956 dFileMD_ = LLVMDIBuilderCreateFile(dBuilder_, name.c_str(), name.size(), ".", 1); 2957 dUnitMD_ = LLVMDIBuilderCreateCompileUnit(dBuilder_, LLVMDWARFSourceLanguageC_plus_plus, dFileMD_, "ArkCompiler", 2958 0, 0, NULL, 0, 0, NULL, 0, LLVMDWARFEmissionFull, 2959 0, 0, 0, "/", 1, "", 0); 2960 2961 voidT_ = LLVMVoidTypeInContext(context_); 2962 int1T_ = LLVMInt1TypeInContext(context_); 2963 int8T_ = LLVMInt8TypeInContext(context_); 2964 int16T_ = LLVMInt16TypeInContext(context_); 2965 int32T_ = LLVMInt32TypeInContext(context_); 2966 int64T_ = LLVMInt64TypeInContext(context_); 2967 floatT_ = LLVMFloatTypeInContext(context_); 2968 doubleT_ = LLVMDoubleTypeInContext(context_); 2969 taggedHPtrT_ = LLVMPointerType(LLVMInt64TypeInContext(context_), 1); 2970 taggedPtrT_ = LLVMPointerType(LLVMInt64TypeInContext(context_), 0); 2971 rawPtrT_ = LLVMPointerType(LLVMInt8TypeInContext(context_), 0); 2972} 2973 2974LLVMModule::~LLVMModule() 2975{ 2976 if (module_ != nullptr) { 2977 LLVMDisposeModule(module_); 2978 module_ = nullptr; 2979 } 2980 if (context_ != nullptr) { 2981 LLVMContextDispose(context_); 2982 context_ = nullptr; 2983 } 2984 if (dBuilder_ != nullptr) { 2985 LLVMDisposeDIBuilder(dBuilder_); 2986 dBuilder_ = nullptr; 2987 } 2988} 2989 2990void LLVMModule::InitialLLVMFuncTypeAndFuncByModuleCSigns() 2991{ 2992 for (size_t i = 0; i < callSigns_.size(); i++) { 2993 const CallSignature* cs = callSigns_[i]; 2994 ASSERT(!cs->GetName().empty()); 2995 LLVMValueRef value = AddAndGetFunc(cs); 2996 SetFunction(i, value, false); 2997 } 2998} 2999 3000void LLVMModule::SetUpForCommonStubs() 3001{ 3002 CommonStubCSigns::GetCSigns(callSigns_); 3003 InitialLLVMFuncTypeAndFuncByModuleCSigns(); 3004} 3005 3006void LLVMModule::SetUpForBytecodeHandlerStubs() 3007{ 3008 BytecodeStubCSigns::GetCSigns(callSigns_); 3009 InitialLLVMFuncTypeAndFuncByModuleCSigns(); 3010} 3011 3012void LLVMModule::SetUpForBuiltinsStubs() 3013{ 3014 BuiltinsStubCSigns::GetCSigns(callSigns_); 3015 InitialLLVMFuncTypeAndFuncByModuleCSigns(); 3016} 3017 3018void LLVMModule::SetUpForBaselineStubs() 3019{ 3020 BaselineStubCSigns::GetCSigns(callSigns_); 3021 InitialLLVMFuncTypeAndFuncByModuleCSigns(); 3022} 3023 3024LLVMValueRef LLVMModule::AddAndGetFunc(const CallSignature *stubDescriptor) 3025{ 3026 auto funcType = GetFuncType(stubDescriptor); 3027 return LLVMAddFunction(module_, stubDescriptor->GetName().c_str(), funcType); 3028} 3029 3030LLVMTypeRef LLVMModule::GetFuncType(const CallSignature *stubDescriptor) 3031{ 3032 LLVMTypeRef returnType = ConvertLLVMTypeFromVariableType(stubDescriptor->GetReturnType()); 3033 std::vector<LLVMTypeRef> paramTys; 3034 auto paramCount = stubDescriptor->GetParametersCount(); 3035 int extraParameterCnt = 0; 3036 auto paramsType = stubDescriptor->GetParametersType(); 3037 if (paramsType != nullptr) { 3038 LLVMTypeRef glueType = ConvertLLVMTypeFromVariableType(paramsType[0]); 3039 paramTys.push_back(glueType); 3040 3041 for (size_t i = 1; i < paramCount; i++) { 3042 paramTys.push_back(ConvertLLVMTypeFromVariableType(paramsType[i])); 3043 } 3044 } 3045 auto functype = LLVMFunctionType(returnType, paramTys.data(), paramCount + extraParameterCnt, 3046 stubDescriptor->IsVariadicArgs()); 3047 return functype; 3048} 3049 3050LLVMTypeRef LLVMModule::GenerateFuncType(const std::vector<LLVMValueRef> ¶ms, const CallSignature *stubDescriptor) 3051{ 3052 LLVMTypeRef returnType = ConvertLLVMTypeFromVariableType(stubDescriptor->GetReturnType()); 3053 std::vector<LLVMTypeRef> paramTys; 3054 for (auto value : params) { 3055 paramTys.emplace_back(LLVMTypeOf(value)); 3056 } 3057 auto functionType = LLVMFunctionType(returnType, paramTys.data(), paramTys.size(), false); 3058 return functionType; 3059} 3060 3061LLVMTypeRef LLVMModule::ConvertLLVMTypeFromVariableType(VariableType type) 3062{ 3063 std::map<VariableType, LLVMTypeRef> machineTypeMap = { 3064 {VariableType::VOID(), GetVoidT() }, 3065 {VariableType::BOOL(), GetInt1T() }, 3066 {VariableType::INT8(), GetInt8T() }, 3067 {VariableType::INT16(), GetInt16T() }, 3068 {VariableType::INT32(), GetInt32T() }, 3069 {VariableType::INT64(), GetInt64T() }, 3070 {VariableType::INT8(), GetInt8T() }, 3071 {VariableType::INT16(), GetInt16T() }, 3072 {VariableType::INT32(), GetInt32T() }, 3073 {VariableType::INT64(), GetInt64T() }, 3074 {VariableType::FLOAT32(), GetFloatT() }, 3075 {VariableType::FLOAT64(), GetDoubleT() }, 3076 {VariableType::NATIVE_POINTER(), GetInt64T() }, 3077 {VariableType::JS_POINTER(), GetTaggedHPtrT() }, 3078 {VariableType::JS_ANY(), GetTaggedHPtrT()}, 3079 }; 3080 return machineTypeMap[type]; 3081} 3082 3083LLVMValueRef LLVMModule::AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile) 3084{ 3085 LLVMTypeRef returnType = NewLType(MachineType::I64, GateType::TaggedValue()); // possibly get it for circuit 3086 LLVMTypeRef glue = NewLType(MachineType::I64, GateType::NJSValue()); 3087 uint32_t paramCount = 0; 3088 std::vector<LLVMTypeRef> paramTys = { glue }; 3089 if (!methodLiteral->IsFastCall()) { 3090 LLVMTypeRef actualArgc = NewLType(MachineType::I64, GateType::NJSValue()); 3091 LLVMTypeRef actualArgv = NewLType(MachineType::I64, GateType::NJSValue()); 3092 paramTys.emplace_back(actualArgc); 3093 paramTys.emplace_back(actualArgv); 3094 auto funcIndex = static_cast<uint32_t>(CommonArgIdx::FUNC); 3095 auto numOfComArgs = static_cast<uint32_t>(CommonArgIdx::NUM_OF_ARGS); 3096 paramCount = methodLiteral->GetNumArgsWithCallField() + numOfComArgs; 3097 auto numOfRestArgs = paramCount - funcIndex; 3098 paramTys.insert(paramTys.end(), numOfRestArgs, NewLType(MachineType::I64, GateType::TaggedValue())); 3099 } else { 3100 auto funcIndex = static_cast<uint32_t>(FastCallArgIdx::FUNC); 3101 auto numOfComArgs = static_cast<uint32_t>(FastCallArgIdx::NUM_OF_ARGS); 3102 paramCount = methodLiteral->GetNumArgsWithCallField() + numOfComArgs; 3103 auto numOfRestArgs = paramCount - funcIndex; 3104 paramTys.insert(paramTys.end(), numOfRestArgs, NewLType(MachineType::I64, GateType::TaggedValue())); 3105 } 3106 auto funcType = LLVMFunctionType(returnType, paramTys.data(), paramCount, false); // not variable args 3107 3108 std::string name = GetFuncName(methodLiteral, jsPandaFile); 3109 auto offsetInPandaFile = methodLiteral->GetMethodId().GetOffset(); 3110 auto function = LLVMAddFunction(module_, name.c_str(), funcType); 3111 ASSERT(offsetInPandaFile != LLVMModule::kDeoptEntryOffset); 3112 SetFunction(offsetInPandaFile, function, methodLiteral->IsFastCall()); 3113 3114 return function; 3115} 3116 3117LLVMTypeRef LLVMModule::NewLType(MachineType machineType, GateType gateType) 3118{ 3119 VariableType vType(machineType, gateType); 3120 return ConvertLLVMTypeFromVariableType(vType); 3121} 3122} // namespace panda::ecmascript::kungfu 3123