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