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