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