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