• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params, 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