• 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 "ecmascript/compiler/argument_accessor.h"
19 #include "ecmascript/compiler/bc_call_signature.h"
20 #include "ecmascript/compiler/circuit.h"
21 #include "ecmascript/compiler/call_signature.h"
22 #include "ecmascript/compiler/common_stubs.h"
23 #include "ecmascript/compiler/gate.h"
24 #include "ecmascript/compiler/rt_call_signature.h"
25 #include "ecmascript/deoptimizer/deoptimizer.h"
26 #include "ecmascript/frames.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/method.h"
29 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
30 
31 #if defined(__clang__)
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wshadow"
34 #pragma clang diagnostic ignored "-Wunused-parameter"
35 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
36 #elif defined(__GNUC__)
37 #pragma GCC diagnostic push
38 #pragma GCC diagnostic ignored "-Wshadow"
39 #pragma GCC diagnostic ignored "-Wunused-parameter"
40 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
41 #endif
42 
43 #include "llvm/IR/Instructions.h"
44 
45 #if defined(__clang__)
46 #pragma clang diagnostic pop
47 #elif defined(__GNUC__)
48 #pragma GCC diagnostic pop
49 #endif
50 
51 #include "llvm/Support/Host.h"
52 #include "securec.h"
53 
54 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)55 LLVMIRBuilder::LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
56                              LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
57                              CallSignature::CallConv callConv, bool enableLog)
58     : compCfg_(cfg), scheduledGates_(schedule), circuit_(circuit), acc_(circuit), module_(module->GetModule()),
59       function_(function), llvmModule_(module), callConv_(callConv), enableLog_(enableLog)
60 {
61     builder_ = LLVMCreateBuilder();
62     context_ = LLVMGetGlobalContext();
63     bbID2BB_.clear();
64     SetFunctionCallConv();
65     InitializeHandlers();
66 
67     LLVMSetGC(function_, "statepoint-example");
68     if (compCfg_->Is32Bit()) {
69         slotSize_ = sizeof(uint32_t);
70         slotType_ = LLVMInt32Type();
71     } else {
72         slotSize_ = sizeof(uint64_t);
73         slotType_ = LLVMInt64Type();
74     }
75     if (compCfg_->Is32Bit()) {
76         // hard float instruction
77         LLVMAddTargetDependentFunctionAttr(function_, "target-features", "+armv8-a");
78     }
79 }
80 
~LLVMIRBuilder()81 LLVMIRBuilder::~LLVMIRBuilder()
82 {
83     if (builder_ != nullptr) {
84         LLVMDisposeBuilder(builder_);
85     }
86 }
87 
SetFunctionCallConv()88 void LLVMIRBuilder::SetFunctionCallConv()
89 {
90     switch (callConv_) {
91         case CallSignature::CallConv::GHCCallConv:
92             LLVMSetFunctionCallConv(function_, LLVMGHCCallConv);
93             break;
94         case CallSignature::CallConv::WebKitJSCallConv: {
95             if (!compCfg_->Is32Bit()) {
96                 LLVMSetFunctionCallConv(function_, LLVMWebKitJSCallConv);
97             } else {
98                 LLVMSetFunctionCallConv(function_, LLVMCCallConv);
99             }
100             break;
101         }
102         default: {
103             LLVMSetFunctionCallConv(function_, LLVMCCallConv);
104             callConv_ = CallSignature::CallConv::CCallConv;
105             break;
106         }
107     }
108 }
109 
FindBasicBlock(GateRef gate) const110 int LLVMIRBuilder::FindBasicBlock(GateRef gate) const
111 {
112     for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
113         const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx);
114         for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
115             GateRef tmp = bb[instIdx - 1];
116             if (tmp == gate) {
117                 return bbIdx;
118             }
119         }
120     }
121     return -1;
122 }
123 
InitializeHandlers()124 void LLVMIRBuilder::InitializeHandlers()
125 {
126     opHandlers_ = {
127         {OpCode::STATE_ENTRY, &LLVMIRBuilder::HandleGoto},
128         {OpCode::RETURN, &LLVMIRBuilder::HandleReturn},
129         {OpCode::RETURN_VOID, &LLVMIRBuilder::HandleReturnVoid},
130         {OpCode::IF_BRANCH, &LLVMIRBuilder::HandleBranch},
131         {OpCode::SWITCH_BRANCH, &LLVMIRBuilder::HandleSwitch},
132         {OpCode::ORDINARY_BLOCK, &LLVMIRBuilder::HandleGoto},
133         {OpCode::IF_TRUE, &LLVMIRBuilder::HandleGoto},
134         {OpCode::IF_FALSE, &LLVMIRBuilder::HandleGoto},
135         {OpCode::SWITCH_CASE, &LLVMIRBuilder::HandleGoto},
136         {OpCode::MERGE, &LLVMIRBuilder::HandleGoto},
137         {OpCode::DEFAULT_CASE, &LLVMIRBuilder::HandleGoto},
138         {OpCode::LOOP_BEGIN, &LLVMIRBuilder::HandleGoto},
139         {OpCode::LOOP_BACK, &LLVMIRBuilder::HandleGoto},
140         {OpCode::VALUE_SELECTOR, &LLVMIRBuilder::HandlePhi},
141         {OpCode::RUNTIME_CALL, &LLVMIRBuilder::HandleRuntimeCall},
142         {OpCode::RUNTIME_CALL_WITH_ARGV, &LLVMIRBuilder::HandleRuntimeCallWithArgv},
143         {OpCode::NOGC_RUNTIME_CALL, &LLVMIRBuilder::HandleCall},
144         {OpCode::CALL, &LLVMIRBuilder::HandleCall},
145         {OpCode::BYTECODE_CALL, &LLVMIRBuilder::HandleBytecodeCall},
146         {OpCode::DEBUGGER_BYTECODE_CALL, &LLVMIRBuilder::HandleBytecodeCall},
147         {OpCode::BUILTINS_CALL, &LLVMIRBuilder::HandleCall},
148         {OpCode::BUILTINS_CALL_WITH_ARGV, &LLVMIRBuilder::HandleCall},
149         {OpCode::ALLOCA, &LLVMIRBuilder::HandleAlloca},
150         {OpCode::ARG, &LLVMIRBuilder::HandleParameter},
151         {OpCode::CONSTANT, &LLVMIRBuilder::HandleConstant},
152         {OpCode::RELOCATABLE_DATA, &LLVMIRBuilder::HandleRelocatableData},
153         {OpCode::ZEXT, &LLVMIRBuilder::HandleZExtInt},
154         {OpCode::SEXT, &LLVMIRBuilder::HandleSExtInt},
155         {OpCode::TRUNC, &LLVMIRBuilder::HandleCastIntXToIntY},
156         {OpCode::FEXT, &LLVMIRBuilder::HandleFPExt},
157         {OpCode::FTRUNC, &LLVMIRBuilder::HandleFPTrunc},
158         {OpCode::REV, &LLVMIRBuilder::HandleIntRev},
159         {OpCode::ADD, &LLVMIRBuilder::HandleAdd},
160         {OpCode::SUB, &LLVMIRBuilder::HandleSub},
161         {OpCode::MUL, &LLVMIRBuilder::HandleMul},
162         {OpCode::FDIV, &LLVMIRBuilder::HandleFloatDiv},
163         {OpCode::SDIV, &LLVMIRBuilder::HandleIntDiv},
164         {OpCode::UDIV, &LLVMIRBuilder::HandleUDiv},
165         {OpCode::AND, &LLVMIRBuilder::HandleIntAnd},
166         {OpCode::OR, &LLVMIRBuilder::HandleIntOr},
167         {OpCode::XOR, &LLVMIRBuilder::HandleIntXor},
168         {OpCode::LSR, &LLVMIRBuilder::HandleIntLsr},
169         {OpCode::ASR, &LLVMIRBuilder::HandleIntAsr},
170         {OpCode::ICMP, &LLVMIRBuilder::HandleCmp},
171         {OpCode::FCMP, &LLVMIRBuilder::HandleCmp},
172         {OpCode::LOAD, &LLVMIRBuilder::HandleLoad},
173         {OpCode::STORE, &LLVMIRBuilder::HandleStore},
174         {OpCode::SIGNED_INT_TO_FLOAT, &LLVMIRBuilder::HandleChangeInt32ToDouble},
175         {OpCode::UNSIGNED_INT_TO_FLOAT, &LLVMIRBuilder::HandleChangeUInt32ToDouble},
176         {OpCode::FLOAT_TO_SIGNED_INT, &LLVMIRBuilder::HandleChangeDoubleToInt32},
177         {OpCode::TAGGED_TO_INT64, &LLVMIRBuilder::HandleChangeTaggedPointerToInt64},
178         {OpCode::INT64_TO_TAGGED, &LLVMIRBuilder::HandleChangeInt64ToTagged},
179         {OpCode::BITCAST, &LLVMIRBuilder::HandleBitCast},
180         {OpCode::LSL, &LLVMIRBuilder::HandleIntLsl},
181         {OpCode::SMOD, &LLVMIRBuilder::HandleMod},
182         {OpCode::FMOD, &LLVMIRBuilder::HandleMod},
183         {OpCode::DEOPT, &LLVMIRBuilder::HandleDeopt},
184         {OpCode::TRUNC_FLOAT_TO_INT64, &LLVMIRBuilder::HandleTruncFloatToInt},
185     };
186     illegalOpHandlers_ = {
187         OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY,
188         OpCode::RETURN_LIST,
189         OpCode::ARG_LIST, OpCode::THROW,
190         OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND,
191         OpCode::FRAME_STATE, OpCode::STATE_SPLIT
192     };
193 }
194 
LLVMValueToString(LLVMValueRef val) const195 std::string LLVMIRBuilder::LLVMValueToString(LLVMValueRef val) const
196 {
197     char* msg = LLVMPrintValueToString(val);
198     std::string str(msg);
199     LLVMDisposeMessage(msg);
200     return str;
201 }
202 
Build()203 void LLVMIRBuilder::Build()
204 {
205     for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
206         const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx);
207         for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
208             GateId gateId = acc_.GetId(bb[instIdx - 1]);
209             instID2bbID_[gateId] = static_cast<int>(bbIdx);
210         }
211     }
212 
213     for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
214         const std::vector<GateRef>& bb = scheduledGates_->at(bbIdx);
215         OperandsVector predecessors;
216         auto ins = acc_.Ins(bb[0]);
217         for (auto i = ins.begin(); i != ins.end(); i++) {
218             GateRef r = *i;
219             if (!acc_.GetMetaData(r)->IsState()) {
220                 continue;
221             }
222             predecessors.insert(instID2bbID_[acc_.GetId(r)]);
223         }
224         LinkToLLVMCfg(bbIdx, predecessors);
225 
226         for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
227             GateRef gate = bb[instIdx - 1];
228             auto found = opHandlers_.find(acc_.GetOpCode(gate));
229             if (found != opHandlers_.end()) {
230                 (this->*(found->second))(gate);
231                 continue;
232             }
233             if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) {
234                 LOG_COMPILER(ERROR) << "The gate below need to be translated ";
235                 acc_.Print(gate);
236                 UNREACHABLE();
237             }
238         }
239     }
240     Finish();
241 }
242 
EnsureBB(int id)243 BasicBlock *LLVMIRBuilder::EnsureBB(int id)
244 {
245     BasicBlock *bb = nullptr;
246     if (bbID2BB_.count(id) == 0) {
247         auto newBB = std::make_unique<BasicBlock>(id);
248         bb = newBB.get();
249         bbID2BB_[id] = std::move(newBB);
250     } else {
251         bb = bbID2BB_[id].get();
252     }
253     return bb;
254 }
255 
SetToCfg(BasicBlock * bb) const256 void LLVMIRBuilder::SetToCfg(BasicBlock *bb) const
257 {
258     EnsureLBB(bb);
259     BasicBlockImpl *impl = bb->GetImpl<BasicBlockImpl>();
260     if ((impl == nullptr) || (impl->lBB_ == nullptr)) {
261         LOG_COMPILER(ERROR) << "SetToCfg failed ";
262         return;
263     }
264     impl->started = true;
265     bb->SetImpl(impl);
266     LLVMPositionBuilderAtEnd(builder_, impl->lBB_);
267 }
268 
ProcessPhiWorkList()269 void LLVMIRBuilder::ProcessPhiWorkList()
270 {
271     for (BasicBlock *bb : phiRebuildWorklist_) {
272         auto impl = bb->GetImpl<BasicBlockImpl>();
273         for (auto &e : impl->unmergedPhis_) {
274             BasicBlock *pred = e.pred;
275             if (impl->started == 0) {
276                 OPTIONAL_LOG_COMPILER(ERROR) << " ProcessPhiWorkList error hav't start ";
277                 return;
278             }
279             LLVMValueRef value = gate2LValue_[e.operand];
280             if (LLVMTypeOf(value) != LLVMTypeOf(e.phi)) {
281                 OPTIONAL_LOG_COMPILER(ERROR) << " ProcessPhiWorkList LLVMTypeOf don't match error ";
282             }
283             LLVMBasicBlockRef llvmBB = EnsureLBB(pred);
284             LLVMAddIncoming(e.phi, &value, &llvmBB, 1);
285         }
286         impl->unmergedPhis_.clear();
287     }
288     phiRebuildWorklist_.clear();
289 }
290 
EndCurrentBlock() const291 void LLVMIRBuilder::EndCurrentBlock() const
292 {
293     BasicBlockImpl *impl = currentBb_->GetImpl<BasicBlockImpl>();
294     impl->ended = true;
295 }
296 
Finish()297 void LLVMIRBuilder::Finish()
298 {
299     ASSERT(!!currentBb_);
300     EndCurrentBlock();
301     ProcessPhiWorkList();
302     for (auto &it : bbID2BB_) {
303         it.second->ResetImpl<BasicBlockImpl>();
304     }
305 }
306 
EnsureBBImpl(BasicBlock * bb) const307 BasicBlockImpl *LLVMIRBuilder::EnsureBBImpl(BasicBlock *bb) const
308 {
309     if (bb->GetImpl<BasicBlockImpl>()) {
310         return bb->GetImpl<BasicBlockImpl>();
311     }
312     auto impl = std::make_unique<BasicBlockImpl>();
313     bb->SetImpl(impl.release());
314     return bb->GetImpl<BasicBlockImpl>();
315 }
316 
GenPrologue()317 void LLVMIRBuilder::GenPrologue()
318 {
319     if (compCfg_->Is32Bit()) {
320         return;
321     }
322     auto frameType = circuit_->GetFrameType();
323     if (IsInterpreted()) {
324         return;
325     }
326     LLVMAddTargetDependentFunctionAttr(function_, "frame-pointer", "all");
327 
328     size_t reservedSlotsSize = 0;
329     if (frameType == FrameType::OPTIMIZED_FRAME) {
330         reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
331         LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
332                                            std::to_string(reservedSlotsSize).c_str());
333         SaveFrameTypeOnFrame(frameType);
334     } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
335         reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
336         LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots",
337                                            std::to_string(reservedSlotsSize).c_str());
338         auto ArgList = circuit_->GetArgRoot();
339         auto uses = acc_.Uses(ArgList);
340         for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
341             int argth = static_cast<int>(acc_.TryGetValue(*useIt));
342             LLVMValueRef value = LLVMGetParam(function_, argth);
343             if (argth == static_cast<int>(CommonArgIdx::FUNC)) {
344                 SaveJSFuncOnOptJSFuncFrame(value);
345                 SaveFrameTypeOnFrame(frameType);
346             }
347         }
348     } else {
349         LOG_COMPILER(FATAL) << "frameType interpret type error !";
350         ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !");
351     }
352 }
353 
SaveFrameTypeOnFrame(FrameType frameType)354 void LLVMIRBuilder::SaveFrameTypeOnFrame(FrameType frameType)
355 {
356     LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
357 
358     LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
359     LLVMValueRef frameTypeSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, slotSize_, false), "");
360     LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr");
361     LLVMValueRef llvmFrameType = LLVMConstInt(slotType_, static_cast<uintptr_t>(frameType), 0);
362     LLVMBuildStore(builder_, llvmFrameType, addr);
363 }
364 
CallingFp(LLVMModuleRef & module,LLVMBuilderRef & builder,bool isCaller)365 LLVMValueRef LLVMIRBuilder::CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller)
366 {
367     if (IsInterpreted()) {
368         return LLVMGetParam(function_, static_cast<unsigned>(InterpreterHandlerInputs::SP));
369     }
370     /* 0:calling 1:its caller */
371     std::vector<LLVMValueRef> args = {LLVMConstInt(LLVMInt32Type(), 0, isCaller)};
372     auto fn = LLVMGetNamedFunction(module, "llvm.frameaddress.p0i8");
373     if (!fn) {
374         /* init instrinsic function declare */
375         LLVMTypeRef paramTys1[] = {
376             LLVMInt32Type(),
377         };
378         auto fnTy = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), paramTys1, 1, 0);
379         fn = LLVMAddFunction(module, "llvm.frameaddress.p0i8", fnTy);
380     }
381     LLVMValueRef fAddrRet = LLVMBuildCall(builder, fn, args.data(), 1, "");
382     return fAddrRet;
383 }
384 
ReadRegister(LLVMModuleRef & module,LLVMBuilderRef & builder,LLVMMetadataRef meta)385 LLVMValueRef LLVMIRBuilder::ReadRegister(LLVMModuleRef &module, [[maybe_unused]] LLVMBuilderRef &builder,
386     LLVMMetadataRef meta)
387 {
388     std::vector<LLVMValueRef> args = {LLVMMetadataAsValue(context_, meta)};
389     auto fn = LLVMGetNamedFunction(module, "llvm.read_register.i64");
390     if (!fn) {
391         /* init instrinsic function declare */
392         LLVMTypeRef paramTys1[] = {
393             GetMachineRepType(MachineRep::K_META),
394         };
395         auto fnTy = LLVMFunctionType(LLVMInt64Type(), paramTys1, 1, 0);
396         fn = LLVMAddFunction(module, "llvm.read_register.i64", fnTy);
397     }
398     LLVMValueRef fAddrRet = LLVMBuildCall(builder_, fn, args.data(), 1, "");
399     return fAddrRet;
400 }
401 
EnsureLBB(BasicBlock * bb) const402 LLVMBasicBlockRef LLVMIRBuilder::EnsureLBB(BasicBlock *bb) const
403 {
404     BasicBlockImpl *impl = EnsureBBImpl(bb);
405     if (impl->lBB_) {
406         return impl->lBB_;
407     }
408 
409     std::string buf = "B" + std::to_string(bb->GetId());
410     LLVMBasicBlockRef llvmBB = LLVMAppendBasicBlock(function_, buf.c_str());
411     impl->lBB_ = llvmBB;
412     impl->continuation = llvmBB;
413     bb->SetImpl(impl);
414     return llvmBB;
415 }
416 
GetMachineRepType(MachineRep rep) const417 LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const
418 {
419     LLVMTypeRef dstType;
420     switch (rep) {
421         case MachineRep::K_BIT:
422             dstType = LLVMInt1TypeInContext(context_);
423             break;
424         case MachineRep::K_WORD8:
425             dstType = LLVMInt8TypeInContext(context_);
426             break;
427         case MachineRep::K_WORD16:
428             dstType = LLVMInt16TypeInContext(context_);
429             break;
430         case MachineRep::K_WORD32:
431             dstType = LLVMInt32TypeInContext(context_);
432             break;
433         case MachineRep::K_FLOAT64:
434             dstType = LLVMDoubleTypeInContext(context_);
435             break;
436         case MachineRep::K_WORD64:
437             dstType = LLVMInt64TypeInContext(context_);
438             break;
439         case MachineRep::K_PTR_1:
440             if (compCfg_->Is32Bit()) {
441                 dstType = LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2); // 2: packed vector type
442             } else {
443                 dstType = LLVMPointerType(LLVMInt64TypeInContext(context_), 1);
444             }
445             break;
446         case MachineRep::K_META:
447             dstType = LLVMMetadataTypeInContext(context_);
448             break;
449         default:
450             UNREACHABLE();
451             break;
452     }
453     return dstType;
454 }
455 
HandleCall(GateRef gate)456 void LLVMIRBuilder::HandleCall(GateRef gate)
457 {
458     std::vector<GateRef> ins;
459     acc_.GetIns(gate, ins);
460     OpCode callOp = acc_.GetOpCode(gate);
461     if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL ||
462         callOp == OpCode::BUILTINS_CALL || callOp == OpCode::BUILTINS_CALL_WITH_ARGV) {
463         VisitCall(gate, ins, callOp);
464     } else {
465         UNREACHABLE();
466     }
467 }
468 
HandleBytecodeCall(GateRef gate)469 void LLVMIRBuilder::HandleBytecodeCall(GateRef gate)
470 {
471     std::vector<GateRef> ins;
472     acc_.GetIns(gate, ins);
473     VisitBytecodeCall(gate, ins);
474 }
475 
HandleRuntimeCall(GateRef gate)476 void LLVMIRBuilder::HandleRuntimeCall(GateRef gate)
477 {
478     std::vector<GateRef> ins;
479     acc_.GetIns(gate, ins);
480     VisitRuntimeCall(gate, ins);
481 }
482 
GetFunction(LLVMValueRef glue,const CallSignature * signature,LLVMValueRef rtbaseoffset,const std::string & realName) const483 LLVMValueRef LLVMIRBuilder::GetFunction(LLVMValueRef glue, const CallSignature *signature,
484                                         LLVMValueRef rtbaseoffset, const std::string &realName) const
485 {
486     LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature);
487     LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0);
488     LLVMTypeRef glueType = LLVMTypeOf(glue);
489     LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(glueType, 0), "");
490     std::string name = realName.empty()
491             ? signature->GetName()
492             : realName;
493     LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, name.c_str());
494     LLVMValueRef callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, (name + "-cast").c_str());
495     ASSERT(callee != nullptr);
496     return callee;
497 }
498 
GetFunctionFromGlobalValue(LLVMValueRef glue,const CallSignature * signature,LLVMValueRef reloc) const499 LLVMValueRef LLVMIRBuilder::GetFunctionFromGlobalValue([[maybe_unused]]LLVMValueRef glue,
500     const CallSignature *signature, LLVMValueRef reloc) const
501 {
502     LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature);
503     LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0);
504     LLVMValueRef callee = LLVMBuildIntToPtr(builder_, reloc, rtfuncTypePtr, "cast");
505     assert(callee != nullptr);
506     return callee;
507 }
508 
IsInterpreted()509 bool LLVMIRBuilder::IsInterpreted()
510 {
511     return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
512 }
513 
IsOptimized()514 bool LLVMIRBuilder::IsOptimized()
515 {
516     return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME;
517 }
518 
VisitRuntimeCall(GateRef gate,const std::vector<GateRef> & inList)519 void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList)
520 {
521     ASSERT(llvmModule_ != nullptr);
522     StubIdType stubId = RTSTUB_ID(CallRuntime);
523     LLVMValueRef glue = GetGlue(inList);
524     int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
525     LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex);
526     LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
527     const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
528 
529     std::vector<LLVMValueRef> params;
530     params.push_back(glue); // glue
531     const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)]));
532     params.push_back(LLVMConstInt(LLVMInt64Type(), index, 0)); // target
533     params.push_back(LLVMConstInt(LLVMInt64Type(),
534         inList.size() - static_cast<size_t>(CallInputs::FIRST_PARAMETER), 0)); // argc
535     for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
536         GateRef gateTmp = inList[paraIdx];
537         params.push_back(gate2LValue_[gateTmp]);
538     }
539 
540     LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature);
541     std::string targetName = RuntimeStubCSigns::GetRTName(index);
542     LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset, targetName);
543     callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
544     LLVMValueRef runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size(), "");
545     if (!compCfg_->Is32Bit()) {  // Arm32 not support webkit jscc calling convention
546         LLVMSetInstructionCallConv(runtimeCall, LLVMWebKitJSCallConv);
547     }
548     gate2LValue_[gate] = runtimeCall;
549 }
550 
HandleRuntimeCallWithArgv(GateRef gate)551 void LLVMIRBuilder::HandleRuntimeCallWithArgv(GateRef gate)
552 {
553     std::vector<GateRef> ins;
554     acc_.GetIns(gate, ins);
555     VisitRuntimeCallWithArgv(gate, ins);
556 }
557 
VisitRuntimeCallWithArgv(GateRef gate,const std::vector<GateRef> & inList)558 void LLVMIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList)
559 {
560     ASSERT(IsOptimized() == true);
561     StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv);
562     LLVMValueRef glue = GetGlue(inList);
563     int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
564     LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex);
565     LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
566     const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
567     LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
568 
569     std::vector<LLVMValueRef> params;
570     params.push_back(glue); // glue
571 
572     uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]);
573     auto targetId = LLVMConstInt(LLVMInt64Type(), index, 0);
574     params.push_back(targetId); // target
575     for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
576         GateRef gateTmp = inList[paraIdx];
577         params.push_back(gate2LValue_[gateTmp]);
578     }
579 
580     LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature);
581     callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
582     LLVMValueRef runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size() - 1, "");
583     gate2LValue_[gate] = runtimeCall;
584 }
585 
GetCurrentSP()586 LLVMValueRef LLVMIRBuilder::GetCurrentSP()
587 {
588     LLVMMetadataRef meta;
589     if (compCfg_->IsAmd64()) {
590         meta = LLVMMDStringInContext2(context_, "rsp", 4);   // 4 : 4 means len of "rsp"
591     } else {
592         meta = LLVMMDStringInContext2(context_, "sp", 3);   // 3 : 3 means len of "sp"
593     }
594     LLVMMetadataRef metadataNode = LLVMMDNodeInContext2(context_, &meta, 1);
595     LLVMValueRef spValue = ReadRegister(module_, builder_, metadataNode);
596     return spValue;
597 }
598 
GetCurrentFrameType(LLVMValueRef currentSpFrameAddr)599 LLVMValueRef LLVMIRBuilder::GetCurrentFrameType(LLVMValueRef currentSpFrameAddr)
600 {
601     LLVMValueRef tmp = LLVMBuildSub(builder_, currentSpFrameAddr, LLVMConstInt(slotType_, slotSize_, 1), "");
602     LLVMValueRef frameTypeAddr = LLVMBuildIntToPtr(builder_, tmp, LLVMPointerType(LLVMInt64Type(), 0), "");
603     LLVMValueRef frameType = LLVMBuildLoad(builder_, frameTypeAddr, "");
604     return frameType;
605 }
606 
SetGCLeafFunction(LLVMValueRef call)607 void LLVMIRBuilder::SetGCLeafFunction(LLVMValueRef call)
608 {
609     const char *attrName = "gc-leaf-function";
610     const char *attrValue = "true";
611     LLVMAttributeRef llvmAttr = LLVMCreateStringAttribute(context_, attrName, strlen(attrName), attrValue,
612                                                           strlen(attrValue));
613     LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex, llvmAttr);
614 }
615 
SetCallConvAttr(const CallSignature * calleeDescriptor,LLVMValueRef call)616 void LLVMIRBuilder::SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call)
617 {
618     ASSERT(calleeDescriptor != nullptr);
619     if (calleeDescriptor->GetCallConv() == CallSignature::CallConv::GHCCallConv) {
620         LLVMSetTailCall(call, true);
621         SetGCLeafFunction(call);
622         LLVMSetInstructionCallConv(call, LLVMGHCCallConv);
623     } else if (calleeDescriptor->GetCallConv() == CallSignature::CallConv::WebKitJSCallConv) {
624         LLVMSetInstructionCallConv(call, LLVMWebKitJSCallConv);
625     }
626     if (calleeDescriptor->GetTailCall()) {
627         LLVMSetTailCall(call, true);
628     }
629     if (calleeDescriptor->GetGCLeafFunction()) {
630         SetGCLeafFunction(call);
631     }
632 }
633 
IsHeapPointerType(LLVMTypeRef valueType)634 bool LLVMIRBuilder::IsHeapPointerType(LLVMTypeRef valueType)
635 {
636     return LLVMGetTypeKind(valueType) == LLVMPointerTypeKind && LLVMGetPointerAddressSpace(valueType) > 0;
637 }
638 
GetGlue(const std::vector<GateRef> & inList)639 LLVMValueRef LLVMIRBuilder::GetGlue(const std::vector<GateRef> &inList)
640 {
641     return gate2LValue_[inList[static_cast<size_t>(CallInputs::GLUE)]];
642 }
643 
GetLeaveFrameOffset(LLVMValueRef glue)644 LLVMValueRef LLVMIRBuilder::GetLeaveFrameOffset(LLVMValueRef glue)
645 {
646     LLVMTypeRef glueType = LLVMTypeOf(glue);
647     return LLVMConstInt(glueType,
648         static_cast<int>(JSThread::GlueData::GetLeaveFrameOffset(compCfg_->Is32Bit())), 0);
649 }
650 
GetRTStubOffset(LLVMValueRef glue,int index)651 LLVMValueRef LLVMIRBuilder::GetRTStubOffset(LLVMValueRef glue, int index)
652 {
653     LLVMTypeRef glueType = LLVMTypeOf(glue);
654     return LLVMConstInt(glueType,
655         static_cast<int>(JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit())) + index * slotSize_, 0);
656 }
657 
GetCoStubOffset(LLVMValueRef glue,int index)658 LLVMValueRef LLVMIRBuilder::GetCoStubOffset(LLVMValueRef glue, int index)
659 {
660     LLVMTypeRef glueType = LLVMTypeOf(glue);
661     return LLVMConstInt(glueType, JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) +
662         static_cast<size_t>(index * slotSize_), 0);
663 }
664 
GetBCStubOffset(LLVMValueRef glue)665 LLVMValueRef LLVMIRBuilder::GetBCStubOffset(LLVMValueRef glue)
666 {
667     LLVMTypeRef glueType = LLVMTypeOf(glue);
668     return LLVMConstInt(glueType, JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit()), 0);
669 }
670 
GetBCDebugStubOffset(LLVMValueRef glue)671 LLVMValueRef LLVMIRBuilder::GetBCDebugStubOffset(LLVMValueRef glue)
672 {
673     LLVMTypeRef glueType = LLVMTypeOf(glue);
674     return LLVMConstInt(glueType, JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit()), 0);
675 }
676 
GetBuiltinsStubOffset(LLVMValueRef glue)677 LLVMValueRef LLVMIRBuilder::GetBuiltinsStubOffset(LLVMValueRef glue)
678 {
679     LLVMTypeRef glueType = LLVMTypeOf(glue);
680     return LLVMConstInt(glueType, JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()), 0);
681 }
682 
ComputeArgCountAndBCOffset(size_t & actualNumArgs,LLVMValueRef & bcOffset,const std::vector<GateRef> & inList,CallExceptionKind kind)683 void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset,
684                                                const std::vector<GateRef> &inList, CallExceptionKind kind)
685 {
686     if (kind == CallExceptionKind::HAS_BC_OFFSET) {
687         actualNumArgs = inList.size() - 1;
688         bcOffset = gate2LValue_[inList[actualNumArgs]];
689     } else {
690         actualNumArgs = inList.size();
691     }
692 }
693 
GetCallExceptionKind(size_t index,OpCode op) const694 LLVMIRBuilder::CallExceptionKind LLVMIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const
695 {
696     bool hasBcOffset = (callConv_ == CallSignature::CallConv::WebKitJSCallConv && op == OpCode::NOGC_RUNTIME_CALL &&
697         index == RTSTUB_ID(JSCall));
698     return hasBcOffset ? CallExceptionKind::HAS_BC_OFFSET : CallExceptionKind::NO_BC_OFFSET;
699 }
700 
UpdateLeaveFrame(LLVMValueRef glue)701 void LLVMIRBuilder::UpdateLeaveFrame(LLVMValueRef glue)
702 {
703     LLVMValueRef leaveFrameOffset = GetLeaveFrameOffset(glue);
704     LLVMValueRef leaveFrameValue = LLVMBuildAdd(builder_, glue, leaveFrameOffset, "");
705     LLVMTypeRef glueType = LLVMTypeOf(glue);
706     LLVMValueRef leaveFrameAddr = LLVMBuildIntToPtr(builder_, leaveFrameValue, LLVMPointerType(glueType, 0), "");
707     LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, true);
708     LLVMValueRef fp = LLVMBuildPtrToInt(builder_, llvmFpAddr, LLVMInt64Type(), "cast_int64_t");
709     LLVMBuildStore(builder_, fp, leaveFrameAddr);
710 }
711 
VisitCall(GateRef gate,const std::vector<GateRef> & inList,OpCode op)712 void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
713 {
714     size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
715     static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3);
716     const CallSignature *calleeDescriptor = nullptr;
717     LLVMValueRef glue = GetGlue(inList);
718     LLVMValueRef rtoffset;
719     LLVMValueRef rtbaseoffset;
720     LLVMValueRef callee;
721     CallExceptionKind kind = CallExceptionKind::NO_BC_OFFSET;
722     if (op == OpCode::CALL) {
723         const size_t index = acc_.GetConstantValue(inList[targetIndex]);
724         calleeDescriptor = CommonStubCSigns::Get(index);
725         rtoffset = GetCoStubOffset(glue, index);
726         rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
727         callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
728     } else if (op == OpCode::NOGC_RUNTIME_CALL) {
729         UpdateLeaveFrame(glue);
730         const size_t index = acc_.GetConstantValue(inList[targetIndex]);
731         calleeDescriptor = RuntimeStubCSigns::Get(index);
732         rtoffset = GetRTStubOffset(glue, index);
733         rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
734         callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
735         kind = GetCallExceptionKind(index, op);
736     } else {
737         ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV);
738         LLVMValueRef opcodeOffset = gate2LValue_[inList[targetIndex]];
739         rtoffset = GetBuiltinsStubOffset(glue);
740         rtbaseoffset = LLVMBuildAdd(
741             builder_, glue, LLVMBuildAdd(builder_, rtoffset, opcodeOffset, ""), "");
742         if (op == OpCode::BUILTINS_CALL) {
743             calleeDescriptor = BuiltinsStubCSigns::BuiltinsCSign();
744         } else {
745             calleeDescriptor = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
746         }
747         callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
748     }
749 
750     std::vector<LLVMValueRef> params;
751     const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
752     GateRef glueGate = inList[firstArg];
753     params.push_back(gate2LValue_[glueGate]);
754 
755     // get parameter types
756     LLVMTypeRef calleeFuncType = LLVMGetElementType(LLVMTypeOf(callee));
757     std::vector<LLVMTypeRef> paramTypes(LLVMCountParamTypes(calleeFuncType));
758     LLVMGetParamTypes(calleeFuncType, paramTypes.data());
759 
760     int extraParameterCnt = 0;
761     size_t actualNumArgs = 0;
762     LLVMValueRef bcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
763     ComputeArgCountAndBCOffset(actualNumArgs, bcOffset, inList, kind);
764 
765     // then push the actual parameter for js function call
766     for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
767         GateRef gateTmp = inList[paraIdx];
768         const auto gateTmpType = LLVMTypeOf(gate2LValue_[gateTmp]);
769         if (params.size() < paramTypes.size()) {  // this condition will be false for variadic arguments
770             const auto paramType = paramTypes.at(params.size());
771             // match parameter types and function signature types
772             if (IsHeapPointerType(paramType) && !IsHeapPointerType(gateTmpType)) {
773                 params.push_back(
774                     LLVMBuildIntToPtr(builder_, LLVMBuildBitCast(builder_, gate2LValue_[gateTmp], LLVMInt64Type(), ""),
775                                       paramType, ""));
776             } else {
777                 params.push_back(LLVMBuildBitCast(builder_, gate2LValue_[gateTmp], paramType, ""));
778             }
779         } else {
780             params.push_back(gate2LValue_[gateTmp]);
781         }
782     }
783 
784     LLVMValueRef call = nullptr;
785     LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, calleeDescriptor);
786     callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
787     if (kind == CallExceptionKind::HAS_BC_OFFSET) {
788         std::vector<LLVMValueRef> values;
789         auto bcIndex = LLVMConstInt(LLVMInt64Type(), static_cast<int>(SpecVregIndex::BC_OFFSET_INDEX), 1);
790         values.push_back(bcIndex);
791         values.push_back(bcOffset);
792         call = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt,
793                               "", values.data(), values.size());
794     } else {
795         call = LLVMBuildCall2(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt,
796                               "");
797     }
798     SetCallConvAttr(calleeDescriptor, call);
799     gate2LValue_[gate] = call;
800 }
801 
VisitBytecodeCall(GateRef gate,const std::vector<GateRef> & inList)802 void LLVMIRBuilder::VisitBytecodeCall(GateRef gate, const std::vector<GateRef> &inList)
803 {
804     size_t paraStartIndex = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
805     size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
806     size_t glueIndex = static_cast<size_t>(CallInputs::GLUE);
807     LLVMValueRef opcodeOffset = gate2LValue_[inList[targetIndex]];
808     ASSERT(llvmModule_ != nullptr);
809 
810     // start index of bytecode handler csign in llvmModule
811     LLVMValueRef glue = gate2LValue_[inList[glueIndex]];
812     LLVMValueRef baseOffset = GetBaseOffset(gate, glue);
813     LLVMValueRef rtbaseoffset = LLVMBuildAdd(
814         builder_, glue, LLVMBuildAdd(builder_, baseOffset, opcodeOffset, ""), "");
815     const CallSignature *signature = BytecodeStubCSigns::BCHandler();
816     LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
817 
818     std::vector<LLVMValueRef> params;
819     for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) {
820         GateRef gateTmp = inList[paraIdx];
821         params.push_back(gate2LValue_[gateTmp]);
822     }
823 
824     LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, signature);
825     callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
826     LLVMValueRef call = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size() - paraStartIndex, "");
827     SetGCLeafFunction(call);
828     LLVMSetTailCall(call, true);
829     LLVMSetInstructionCallConv(call, LLVMGHCCallConv);
830     gate2LValue_[gate] = call;
831 }
832 
GetBaseOffset(GateRef gate,LLVMValueRef glue)833 LLVMValueRef LLVMIRBuilder::GetBaseOffset(GateRef gate, LLVMValueRef glue)
834 {
835     switch (acc_.GetOpCode(gate)) {
836         case OpCode::BYTECODE_CALL:
837             return GetBCStubOffset(glue);
838         case OpCode::DEBUGGER_BYTECODE_CALL:
839             return GetBCDebugStubOffset(glue);
840         default:
841             UNREACHABLE();
842     }
843 }
844 
HandleAlloca(GateRef gate)845 void LLVMIRBuilder::HandleAlloca(GateRef gate)
846 {
847     return VisitAlloca(gate);
848 }
849 
VisitAlloca(GateRef gate)850 void LLVMIRBuilder::VisitAlloca(GateRef gate)
851 {
852     uint64_t machineRep = acc_.TryGetValue(gate);
853     LLVMTypeRef dataType = GetMachineRepType(static_cast<MachineRep>(machineRep));
854     gate2LValue_[gate] = LLVMBuildPtrToInt(builder_, LLVMBuildAlloca(builder_, dataType, ""),
855                                               ConvertLLVMTypeFromGate(gate), "");
856 }
857 
HandlePhi(GateRef gate)858 void LLVMIRBuilder::HandlePhi(GateRef gate)
859 {
860     std::vector<GateRef> ins;
861     acc_.GetIns(gate, ins);
862     VisitPhi(gate, ins);
863 }
864 
VisitPhi(GateRef gate,const std::vector<GateRef> & srcGates)865 void LLVMIRBuilder::VisitPhi(GateRef gate, const std::vector<GateRef> &srcGates)
866 {
867     LLVMTypeRef type = ConvertLLVMTypeFromGate(gate);
868     LLVMValueRef phi = LLVMBuildPhi(builder_, type, "");
869     std::vector<GateRef> relMergeIns;
870     acc_.GetIns(srcGates[0], relMergeIns);
871     bool addToPhiRebuildList = false;
872     for (int i = 1; i < static_cast<int>(srcGates.size()); i++) {
873         GateId gateId = acc_.GetId(relMergeIns[i - 1]);
874         int bbIdx = instID2bbID_[gateId];
875         int cnt = static_cast<int>(bbID2BB_.count(bbIdx));
876         // if cnt = 0 means bb with current bbIdx hasn't been created
877         if (cnt > 0) {
878             BasicBlock *bb = bbID2BB_[bbIdx].get();
879             if (bb == nullptr) {
880                 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed BasicBlock nullptr";
881                 return;
882             }
883             BasicBlockImpl *impl = bb->GetImpl<BasicBlockImpl>();
884             if (impl == nullptr) {
885                 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed impl nullptr";
886                 return;
887             }
888             LLVMBasicBlockRef llvmBB = EnsureLBB(bb);  // The llvm bb
889             LLVMValueRef value = gate2LValue_[srcGates[i]];
890 
891             if (impl->started) {
892                 LLVMAddIncoming(phi, &value, &llvmBB, 1);
893             } else {
894                 addToPhiRebuildList = true;
895                 impl = currentBb_->GetImpl<BasicBlockImpl>();
896                 impl->unmergedPhis_.emplace_back();
897                 auto &not_merged_phi = impl->unmergedPhis_.back();
898                 not_merged_phi.phi = phi;
899                 not_merged_phi.pred = bb;
900                 not_merged_phi.operand = srcGates[i];
901             }
902         } else {
903             addToPhiRebuildList = true;
904         }
905         if (addToPhiRebuildList) {
906             phiRebuildWorklist_.push_back(currentBb_);
907         }
908         gate2LValue_[gate] = phi;
909     }
910 }
911 
VisitReturn(GateRef gate,GateRef popCount,const std::vector<GateRef> & operands)912 void LLVMIRBuilder::VisitReturn([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef popCount,
913                                 const std::vector<GateRef> &operands)
914 {
915     // [STATE] [DEPEND] [VALUE] [RETURN_LIST]
916     GateRef operand = operands[2];  // 2: skip 2 in gate that are not data gate
917     LLVMValueRef returnValue = gate2LValue_[operand];
918     LLVMBuildRet(builder_, returnValue);
919 }
920 
HandleReturn(GateRef gate)921 void LLVMIRBuilder::HandleReturn(GateRef gate)
922 {
923     std::vector<GateRef> ins;
924     acc_.GetIns(gate, ins);
925     VisitReturn(gate, 1, ins);
926 }
927 
VisitReturnVoid(GateRef gate)928 void LLVMIRBuilder::VisitReturnVoid([[maybe_unused]] GateRef gate)
929 {
930     // [STATE] [DEPEND] [VALUE] [RETURN_LIST]
931     LLVMBuildRetVoid(builder_);
932 }
933 
HandleReturnVoid(GateRef gate)934 void LLVMIRBuilder::HandleReturnVoid(GateRef gate)
935 {
936     VisitReturnVoid(gate);
937 }
938 
LinkToLLVMCfg(int bbId,const OperandsVector & predecessors)939 void LLVMIRBuilder::LinkToLLVMCfg(int bbId, const OperandsVector &predecessors)
940 {
941     BasicBlock *bb = EnsureBB(bbId);
942     if (bb == nullptr) {
943         OPTIONAL_LOG_COMPILER(ERROR) << " block create failed ";
944         return;
945     }
946     currentBb_ = bb;
947     LLVMBasicBlockRef lBB = EnsureLBB(bb);
948     SetToCfg(bb);
949     for (int predecessor : predecessors) {
950         BasicBlock *pre = EnsureBB(predecessor);
951         if (pre == nullptr) {
952             OPTIONAL_LOG_COMPILER(ERROR) << " block setup failed, predecessor:%d nullptr" << predecessor;
953             return;
954         }
955         LLVMBasicBlockRef preLBB = EnsureLBB(pre);
956         LLVMMoveBasicBlockBefore(preLBB, lBB);
957     }
958     if (isPrologue(bbId)) {
959         GenPrologue();
960     }
961 }
962 
HandleGoto(GateRef gate)963 void LLVMIRBuilder::HandleGoto(GateRef gate)
964 {
965     std::vector<GateRef> outs;
966     acc_.GetOutStates(gate, outs);
967     int block = instID2bbID_[acc_.GetId(gate)];
968     int bbOut = instID2bbID_[acc_.GetId(outs[0])];
969     switch (acc_.GetOpCode(gate)) {
970         case OpCode::MERGE:
971         case OpCode::LOOP_BEGIN: {
972             for (const auto &out : outs) {
973                 bbOut = instID2bbID_[acc_.GetId(out)];
974                 VisitGoto(block, bbOut);
975             }
976             break;
977         }
978         default: {
979             VisitGoto(block, bbOut);
980             break;
981         }
982     }
983 }
984 
VisitGoto(int block,int bbOut)985 void LLVMIRBuilder::VisitGoto(int block, int bbOut)
986 {
987     if (block == bbOut) {
988         return;
989     }
990     BasicBlock *bb = EnsureBB(bbOut);
991     if (bb == nullptr) {
992         OPTIONAL_LOG_COMPILER(ERROR) << " block is nullptr ";
993         return;
994     }
995     llvm::BasicBlock *self = llvm::unwrap(EnsureLBB(bbID2BB_[block].get()));
996     llvm::BasicBlock *out = llvm::unwrap(EnsureLBB(bbID2BB_[bbOut].get()));
997     llvm::BranchInst::Create(out, self);
998     EndCurrentBlock();
999 }
1000 
HandleConstant(GateRef gate)1001 void LLVMIRBuilder::HandleConstant(GateRef gate)
1002 {
1003     std::bitset<64> value = acc_.GetConstantValue(gate); // 64: bit width
1004     VisitConstant(gate, value);
1005 }
1006 
VisitConstant(GateRef gate,std::bitset<64> value)1007 void LLVMIRBuilder::VisitConstant(GateRef gate, std::bitset<64> value) // 64: bit width
1008 {
1009     LLVMValueRef llvmValue = nullptr;
1010     auto machineType = acc_.GetMachineType(gate);
1011     if (machineType == MachineType::ARCH) {
1012         machineType = compCfg_->Is32Bit() ? MachineType::I32 : MachineType::I64;
1013     }
1014     if (machineType == MachineType::I32) {
1015         llvmValue = LLVMConstInt(LLVMInt32Type(), value.to_ulong(), 0);
1016     } else if (machineType == MachineType::I64) {
1017         llvmValue = LLVMConstInt(LLVMInt64Type(), value.to_ullong(), 0);
1018         LLVMTypeRef type = ConvertLLVMTypeFromGate(gate);
1019         if (LLVMGetTypeKind(type) == LLVMPointerTypeKind) {
1020             llvmValue = LLVMBuildIntToPtr(builder_, llvmValue, type, "");
1021         } else if (LLVMGetTypeKind(type) == LLVMVectorTypeKind) {
1022             LLVMValueRef tmp1Value =
1023                     LLVMBuildLShr(builder_, llvmValue, LLVMConstInt(LLVMInt64Type(), 32, 0), ""); // 32: offset
1024             LLVMValueRef tmp2Value = LLVMBuildIntCast(builder_, llvmValue, LLVMInt32Type(), ""); // low
1025             LLVMValueRef emptyValue = LLVMGetUndef(type);
1026             tmp1Value = LLVMBuildIntToPtr(builder_, tmp1Value, LLVMPointerType(LLVMInt8Type(), 1), "");
1027             tmp2Value = LLVMBuildIntToPtr(builder_, tmp2Value, LLVMPointerType(LLVMInt8Type(), 1), "");
1028             llvmValue = LLVMBuildInsertElement(
1029                 builder_, emptyValue, tmp2Value, LLVMConstInt(LLVMInt32Type(), 0, 0), "");
1030             llvmValue = LLVMBuildInsertElement(builder_, llvmValue, tmp1Value, LLVMConstInt(LLVMInt32Type(), 1, 0), "");
1031         } else if (LLVMGetTypeKind(type) == LLVMIntegerTypeKind) {
1032             // do nothing
1033         } else {
1034             UNREACHABLE();
1035         }
1036     } else if (machineType == MachineType::F64) {
1037         auto doubleValue = bit_cast<double>(value.to_ullong()); // actual double value
1038         llvmValue = LLVMConstReal(LLVMDoubleType(), doubleValue);
1039     } else if (machineType == MachineType::I8) {
1040         llvmValue = LLVMConstInt(LLVMInt8Type(), value.to_ulong(), 0);
1041     } else if (machineType == MachineType::I16) {
1042         llvmValue = LLVMConstInt(LLVMInt16Type(), value.to_ulong(), 0);
1043     } else if (machineType == MachineType::I1) {
1044         llvmValue = LLVMConstInt(LLVMInt1Type(), value.to_ulong(), 0);
1045     } else {
1046         UNREACHABLE();
1047     }
1048     gate2LValue_[gate] = llvmValue;
1049 }
1050 
HandleRelocatableData(GateRef gate)1051 void LLVMIRBuilder::HandleRelocatableData(GateRef gate)
1052 {
1053     uint64_t value = acc_.TryGetValue(gate);
1054     VisitRelocatableData(gate, value);
1055 }
1056 
VisitRelocatableData(GateRef gate,uint64_t value)1057 void LLVMIRBuilder::VisitRelocatableData(GateRef gate, uint64_t value)
1058 {
1059     LLVMValueRef globalValue = LLVMAddGlobal(module_, LLVMInt64Type(), "G");
1060     LLVMSetInitializer(globalValue, LLVMConstInt(LLVMInt64Type(), value, 0));
1061     gate2LValue_[gate] = globalValue;
1062 }
1063 
HandleZExtInt(GateRef gate)1064 void LLVMIRBuilder::HandleZExtInt(GateRef gate)
1065 {
1066     std::vector<GateRef> ins;
1067     acc_.GetIns(gate, ins);
1068     VisitZExtInt(gate, ins[0]);
1069 }
1070 
HandleSExtInt(GateRef gate)1071 void LLVMIRBuilder::HandleSExtInt(GateRef gate)
1072 {
1073     std::vector<GateRef> ins;
1074     acc_.GetIns(gate, ins);
1075     VisitSExtInt(gate, ins[0]);
1076 }
1077 
HandleParameter(GateRef gate)1078 void LLVMIRBuilder::HandleParameter(GateRef gate)
1079 {
1080     return VisitParameter(gate);
1081 }
1082 
VisitParameter(GateRef gate)1083 void LLVMIRBuilder::VisitParameter(GateRef gate)
1084 {
1085     int argth = static_cast<int>(acc_.TryGetValue(gate));
1086     LLVMValueRef value = LLVMGetParam(function_, argth);
1087     ASSERT(LLVMTypeOf(value) == ConvertLLVMTypeFromGate(gate));
1088     gate2LValue_[gate] = value;
1089     // NOTE: caller put args, otherwise crash
1090     ASSERT(value != nullptr);
1091 }
1092 
SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value)1093 void LLVMIRBuilder::SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value)
1094 {
1095     ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
1096     LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false);
1097     LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t");
1098     size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
1099     LLVMValueRef frameJSFuncSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_,
1100         reservedOffset, false), "");
1101     LLVMValueRef jsFuncAddr = LLVMBuildIntToPtr(builder_, frameJSFuncSlotAddr,
1102         LLVMPointerType(slotType_, 0), "jsfunc.Addr");
1103     LLVMValueRef jsFuncValue = LLVMBuildPtrToInt(builder_, value, slotType_, "cast_to_i64");
1104     LLVMBuildStore(builder_, jsFuncValue, jsFuncAddr);
1105 }
1106 
HandleBranch(GateRef gate)1107 void LLVMIRBuilder::HandleBranch(GateRef gate)
1108 {
1109     std::vector<GateRef> ins;
1110     acc_.GetIns(gate, ins);
1111     std::vector<GateRef> outs;
1112     acc_.GetOutStates(gate, outs);
1113     GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1];
1114     GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1];
1115     int bbTrue = instID2bbID_[acc_.GetId(bTrue)];
1116     int bbFalse = instID2bbID_[acc_.GetId(bFalse)];
1117     VisitBranch(gate, ins[1], bbTrue, bbFalse);
1118 }
1119 
HandleMod(GateRef gate)1120 void LLVMIRBuilder::HandleMod(GateRef gate)
1121 {
1122     auto g0 = acc_.GetIn(gate, 0);
1123     auto g1 = acc_.GetIn(gate, 1);
1124     VisitMod(gate, g0, g1);
1125 }
1126 
VisitMod(GateRef gate,GateRef e1,GateRef e2)1127 void LLVMIRBuilder::VisitMod(GateRef gate, GateRef e1, GateRef e2)
1128 {
1129     LLVMValueRef e1Value = gate2LValue_[e1];
1130     LLVMValueRef e2Value = gate2LValue_[e2];
1131     LLVMValueRef result = nullptr;
1132     ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e1));
1133     ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e2));
1134     auto machineType = acc_.GetMachineType(gate);
1135     if (machineType == MachineType::I32) {
1136         result = LLVMBuildSRem(builder_, e1Value, e2Value, "");
1137     } else if (machineType == MachineType::F64) {
1138         result = LLVMBuildFRem(builder_, e1Value, e2Value, "");
1139     } else {
1140         UNREACHABLE();
1141     }
1142     gate2LValue_[gate] = result;
1143 }
1144 
VisitBranch(GateRef gate,GateRef cmp,int btrue,int bfalse)1145 void LLVMIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse)
1146 {
1147     if (gate2LValue_.count(cmp) == 0) {
1148         OPTIONAL_LOG_COMPILER(ERROR) << "Branch condition gate is nullptr!";
1149         return;
1150     }
1151     LLVMValueRef cond = gate2LValue_[cmp];
1152 
1153     BasicBlock *trueBB = EnsureBB(btrue);
1154     BasicBlock *falseBB = EnsureBB(bfalse);
1155     EnsureLBB(trueBB);
1156     EnsureLBB(falseBB);
1157 
1158     LLVMBasicBlockRef llvmTrueBB = trueBB->GetImpl<BasicBlockImpl>()->lBB_;
1159     LLVMBasicBlockRef llvmFalseBB = falseBB->GetImpl<BasicBlockImpl>()->lBB_;
1160     LLVMValueRef result = LLVMBuildCondBr(builder_, cond, llvmTrueBB, llvmFalseBB);
1161     EndCurrentBlock();
1162     gate2LValue_[gate] = result;
1163 }
1164 
HandleSwitch(GateRef gate)1165 void LLVMIRBuilder::HandleSwitch(GateRef gate)
1166 {
1167     std::vector<GateRef> ins;
1168     acc_.GetIns(gate, ins);
1169     std::vector<GateRef> outs;
1170     acc_.GetOutStates(gate, outs);
1171     VisitSwitch(gate, ins[1], outs);
1172 }
1173 
VisitSwitch(GateRef gate,GateRef input,const std::vector<GateRef> & outList)1174 void LLVMIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<GateRef> &outList)
1175 {
1176     LLVMValueRef cond = gate2LValue_[input];
1177     int caseNum = static_cast<int>(outList.size());
1178     BasicBlock *curOutBB = nullptr;
1179     LLVMBasicBlockRef llvmDefaultOutBB = nullptr;
1180     for (int i = 0; i < caseNum; i++) {
1181         curOutBB = EnsureBB(instID2bbID_[acc_.GetId(outList[i])]);
1182         EnsureLBB(curOutBB);
1183         if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
1184             llvmDefaultOutBB = curOutBB->GetImpl<BasicBlockImpl>()->lBB_;
1185         }
1186     }
1187     LLVMValueRef result = LLVMBuildSwitch(builder_, cond, llvmDefaultOutBB, static_cast<uint32_t>(caseNum - 1));
1188     LLVMBasicBlockRef llvmCurOutBB = nullptr;
1189     for (int i = 0; i < caseNum; i++) {
1190         if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
1191             continue;
1192         }
1193         curOutBB = EnsureBB(instID2bbID_[acc_.GetId(outList[i])]);
1194         llvmCurOutBB = curOutBB->GetImpl<BasicBlockImpl>()->lBB_;
1195         LLVMAddCase(result, LLVMConstInt(ConvertLLVMTypeFromGate(input), acc_.TryGetValue(outList[i]), 0),
1196                     llvmCurOutBB);
1197     }
1198     EndCurrentBlock();
1199     gate2LValue_[gate] = result;
1200 }
1201 
VisitLoad(GateRef gate,GateRef base)1202 void LLVMIRBuilder::VisitLoad(GateRef gate, GateRef base)
1203 {
1204     LLVMValueRef baseAddr = gate2LValue_[base];
1205     LLVMTypeRef returnType;
1206     baseAddr = CanonicalizeToPtr(baseAddr);
1207     returnType = ConvertLLVMTypeFromGate(gate);
1208     baseAddr = LLVMBuildPointerCast(builder_, baseAddr,
1209         LLVMPointerType(returnType, LLVMGetPointerAddressSpace(LLVMTypeOf(baseAddr))), "");
1210     LLVMValueRef result = LLVMBuildLoad(builder_, baseAddr, "");
1211     gate2LValue_[gate] = result;
1212 }
1213 
VisitStore(GateRef gate,GateRef base,GateRef dataToStore)1214 void LLVMIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef dataToStore)
1215 {
1216     LLVMValueRef baseAddr = gate2LValue_[base];
1217     baseAddr = CanonicalizeToPtr(baseAddr);
1218     LLVMValueRef data = gate2LValue_[dataToStore];
1219     baseAddr = LLVMBuildPointerCast(builder_, baseAddr,
1220         LLVMPointerType(ConvertLLVMTypeFromGate(dataToStore), LLVMGetPointerAddressSpace(LLVMTypeOf(baseAddr))), "");
1221     LLVMValueRef value = LLVMBuildStore(builder_, data, baseAddr);
1222     gate2LValue_[gate] = value;
1223 }
1224 
CanonicalizeToInt(LLVMValueRef value)1225 LLVMValueRef LLVMIRBuilder::CanonicalizeToInt(LLVMValueRef value)
1226 {
1227     if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) {
1228         LLVMValueRef e1Value0 = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 0, 1), "");
1229         LLVMValueRef e1Value1 = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 1, 1), "");
1230         LLVMValueRef tmp1 = LLVMBuildPtrToInt(builder_, e1Value1, LLVMInt64Type(), "");
1231         LLVMValueRef constValue = LLVMConstInt(LLVMInt64Type(), 32, 0); // 32: offset
1232         LLVMValueRef tmp1Value = LLVMBuildShl(builder_, tmp1, constValue, "");
1233         LLVMValueRef tmp2Value = LLVMBuildPtrToInt(builder_, e1Value0, LLVMInt64Type(), "");
1234         LLVMValueRef resultValue = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, "");
1235         return resultValue;
1236     } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) {
1237         return LLVMBuildPtrToInt(builder_, value, LLVMInt64Type(), "");
1238     } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) {
1239         return value;
1240     } else {
1241         LOG_COMPILER(ERROR) << "can't Canonicalize to Int64: ";
1242         UNREACHABLE();
1243     }
1244 }
1245 
CanonicalizeToPtr(LLVMValueRef value)1246 LLVMValueRef LLVMIRBuilder::CanonicalizeToPtr(LLVMValueRef value)
1247 {
1248     if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMVectorTypeKind) {
1249         LLVMValueRef tmp = LLVMBuildExtractElement(builder_, value, LLVMConstInt(LLVMInt32Type(), 0, 1), "");
1250         return LLVMBuildPointerCast(builder_, tmp, LLVMPointerType(LLVMInt8Type(), 1), "");
1251     } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind) {
1252         return LLVMBuildPointerCast(builder_, value,
1253             LLVMPointerType(LLVMInt8Type(), LLVMGetPointerAddressSpace(LLVMTypeOf(value))), "");
1254     } else if (LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMIntegerTypeKind) {
1255         LLVMValueRef tmp = LLVMBuildIntToPtr(builder_, value, LLVMPointerType(LLVMInt64Type(), 0), "");
1256         return LLVMBuildPointerCast(builder_, tmp, LLVMPointerType(LLVMInt8Type(), 0), "");
1257     } else {
1258         LOG_COMPILER(ERROR) << "can't Canonicalize to Ptr: ";
1259         UNREACHABLE();
1260     }
1261 }
1262 
HandleIntRev(GateRef gate)1263 void LLVMIRBuilder::HandleIntRev(GateRef gate)
1264 {
1265     std::vector<GateRef> ins;
1266     acc_.GetIns(gate, ins);
1267     VisitIntRev(gate, ins[0]);
1268 }
1269 
VisitIntRev(GateRef gate,GateRef e1)1270 void LLVMIRBuilder::VisitIntRev(GateRef gate, GateRef e1)
1271 {
1272     LLVMValueRef e1Value = gate2LValue_[e1];
1273     ASSERT(ConvertLLVMTypeFromGate(gate) == ConvertLLVMTypeFromGate(e1));
1274     auto machineType = acc_.GetMachineType(gate);
1275     LLVMValueRef result = nullptr;
1276     if (machineType <= MachineType::I64 && machineType >= MachineType::I1) {
1277         result = LLVMBuildNot(builder_, e1Value, "");
1278     } else {
1279         UNREACHABLE();
1280     }
1281     gate2LValue_[gate] = result;
1282 }
1283 
PointerAdd(LLVMValueRef baseAddr,LLVMValueRef offset,LLVMTypeRef rep)1284 LLVMValueRef LLVMIRBuilder::PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offset, LLVMTypeRef rep)
1285 {
1286     LLVMValueRef ptr = CanonicalizeToPtr(baseAddr);
1287     LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, "");
1288     LLVMValueRef result = LLVMBuildPointerCast(builder_, dstRef8, rep, "");
1289     return result;
1290 }
1291 
VectorAdd(LLVMValueRef baseAddr,LLVMValueRef offset,LLVMTypeRef rep)1292 LLVMValueRef LLVMIRBuilder::VectorAdd(LLVMValueRef baseAddr, LLVMValueRef offset, [[maybe_unused]] LLVMTypeRef rep)
1293 {
1294     LLVMValueRef ptr = CanonicalizeToPtr(baseAddr);
1295     LLVMValueRef dstRef8 = LLVMBuildGEP(builder_, ptr, &offset, 1, "");
1296     LLVMValueRef result = LLVMBuildInsertElement(builder_, baseAddr, dstRef8, LLVMConstInt(LLVMInt32Type(), 0, 0), "");
1297     return result;
1298 }
1299 
ConvertLLVMTypeFromGate(GateRef gate) const1300 LLVMTypeRef LLVMIRBuilder::ConvertLLVMTypeFromGate(GateRef gate) const
1301 {
1302     if (acc_.IsGCRelated(gate)) {
1303         if (compCfg_->Is32Bit()) {
1304             return LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2);
1305         } else {
1306             return LLVMPointerType(LLVMInt64Type(), 1);
1307         }
1308     }
1309     MachineType t = acc_.GetMachineType(gate);
1310     switch (t) {
1311         case MachineType::NOVALUE:
1312             return LLVMVoidType();
1313         case MachineType::I1:
1314             return LLVMInt1Type();
1315         case MachineType::I8:
1316             return LLVMInt8Type();
1317         case MachineType::I16:
1318             return LLVMInt16Type();
1319         case MachineType::I32:
1320             return LLVMInt32Type();
1321         case MachineType::I64:
1322             return LLVMInt64Type();
1323         case MachineType::F32:
1324             return LLVMFloatType();
1325         case MachineType::F64:
1326             return LLVMDoubleType();
1327         case MachineType::ARCH: {
1328             if (compCfg_->Is32Bit()) {
1329                 return LLVMInt32Type();
1330             } else {
1331                 return LLVMInt64Type();
1332             }
1333         }
1334         default:
1335             UNREACHABLE();
1336     }
1337 }
1338 
GetBitWidthFromMachineType(MachineType machineType) const1339 int64_t LLVMIRBuilder::GetBitWidthFromMachineType(MachineType machineType) const
1340 {
1341     switch (machineType) {
1342         case NOVALUE:
1343             return 0;
1344         case ARCH:
1345             return 48;  // 48: Pointer representation in different architectures
1346         case I1:
1347             return 1;
1348         case I8:
1349             return 8; // 8: bit width
1350         case I16:
1351             return 16; // 16: bit width
1352         case I32:
1353             return 32; // 32: bit width
1354         case I64:
1355             return 64; // 64: bit width
1356         case F32:
1357             return 32; // 32: bit width
1358         case F64:
1359             return 64; // 64: bit width
1360         case FLEX:
1361         case ANYVALUE:
1362             UNREACHABLE();
1363         default:
1364             UNREACHABLE();
1365     }
1366 }
1367 
HandleAdd(GateRef gate)1368 void LLVMIRBuilder::HandleAdd(GateRef gate)
1369 {
1370     auto g0 = acc_.GetIn(gate, 0);
1371     auto g1 = acc_.GetIn(gate, 1);
1372     VisitAdd(gate, g0, g1);
1373 }
1374 
HandleTruncFloatToInt(GateRef gate)1375 void LLVMIRBuilder::HandleTruncFloatToInt(GateRef gate)
1376 {
1377     auto g0 = acc_.GetIn(gate, 0);
1378     VisitTruncFloatToInt(gate, g0);
1379 }
1380 
VisitTruncFloatToInt(GateRef gate,GateRef e1)1381 void LLVMIRBuilder::VisitTruncFloatToInt(GateRef gate, GateRef e1)
1382 {
1383     LLVMValueRef e1Value = gate2LValue_[e1];
1384     auto machineType = acc_.GetMachineType(e1);
1385     LLVMValueRef result = nullptr;
1386     if (machineType <= MachineType::F64 && machineType >= MachineType::F32) {
1387         result = LLVMBuildFPToSI(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1388     } else {
1389         UNREACHABLE();
1390     }
1391     gate2LValue_[gate] = result;
1392 }
1393 
IsAddIntergerType(MachineType machineType)1394 bool IsAddIntergerType(MachineType machineType)
1395 {
1396     switch (machineType) {
1397         case MachineType::I8:
1398         case MachineType::I16:
1399         case MachineType::I32:
1400         case MachineType::I64:
1401         case MachineType::ARCH:
1402             return true;
1403         default:
1404             return false;
1405     }
1406 }
1407 
VisitAdd(GateRef gate,GateRef e1,GateRef e2)1408 void LLVMIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2)
1409 {
1410     LLVMValueRef e1Value = gate2LValue_[e1];
1411     LLVMValueRef e2Value = gate2LValue_[e2];
1412     LLVMValueRef result = nullptr;
1413     /*
1414      *  If the first operand is pointer, special treatment is needed
1415      *  1) add, pointer, int
1416      *  2) add, vector{i8* x 2}, int
1417      */
1418     LLVMTypeRef returnType = ConvertLLVMTypeFromGate(gate);
1419 
1420     auto machineType = acc_.GetMachineType(gate);
1421     if (IsAddIntergerType(machineType)) {
1422         auto e1Type = LLVMGetTypeKind(ConvertLLVMTypeFromGate(e1));
1423         if (e1Type == LLVMVectorTypeKind) {
1424             result = VectorAdd(e1Value, e2Value, returnType);
1425         } else if (e1Type == LLVMPointerTypeKind) {
1426             result = PointerAdd(e1Value, e2Value, returnType);
1427         } else {
1428             LLVMValueRef tmp1Value = LLVMBuildIntCast2(builder_, e1Value, returnType, 0, "");
1429             LLVMValueRef tmp2Value = LLVMBuildIntCast2(builder_, e2Value, returnType, 0, "");
1430             result = LLVMBuildAdd(builder_, tmp1Value, tmp2Value, "");
1431             if (LLVMTypeOf(tmp1Value) != LLVMTypeOf(tmp2Value)) {
1432                 ASSERT(LLVMTypeOf(tmp1Value) == LLVMTypeOf(tmp2Value));
1433             }
1434         }
1435     } else if (machineType == MachineType::F64) {
1436         result = LLVMBuildFAdd(builder_, e1Value, e2Value, "");
1437     } else {
1438         UNREACHABLE();
1439     }
1440     gate2LValue_[gate] = result;
1441 }
1442 
HandleSub(GateRef gate)1443 void LLVMIRBuilder::HandleSub(GateRef gate)
1444 {
1445     auto g0 = acc_.GetIn(gate, 0);
1446     auto g1 = acc_.GetIn(gate, 1);
1447     VisitSub(gate, g0, g1);
1448 }
1449 
VisitSub(GateRef gate,GateRef e1,GateRef e2)1450 void LLVMIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2)
1451 {
1452     LLVMValueRef e1Value = gate2LValue_[e1];
1453     LLVMValueRef e2Value = gate2LValue_[e2];
1454     LLVMValueRef result = nullptr;
1455     auto machineType = acc_.GetMachineType(gate);
1456     if (machineType == MachineType::I16 || machineType == MachineType::I32 ||
1457         machineType == MachineType::I64 || machineType == MachineType::ARCH) {
1458         result = LLVMBuildSub(builder_, e1Value, e2Value, "");
1459     } else if (machineType == MachineType::F64) {
1460         result = LLVMBuildFSub(builder_, e1Value, e2Value, "");
1461     } else {
1462         UNREACHABLE();
1463     }
1464     gate2LValue_[gate] = result;
1465 }
1466 
HandleMul(GateRef gate)1467 void LLVMIRBuilder::HandleMul(GateRef gate)
1468 {
1469     auto g0 = acc_.GetIn(gate, 0);
1470     auto g1 = acc_.GetIn(gate, 1);
1471     VisitMul(gate, g0, g1);
1472 }
1473 
IsMulIntergerType(MachineType machineType)1474 bool IsMulIntergerType(MachineType machineType)
1475 {
1476     switch (machineType) {
1477         case MachineType::I32:
1478         case MachineType::I64:
1479         case MachineType::ARCH:
1480             return true;
1481         default:
1482             return false;
1483     }
1484 }
1485 
VisitMul(GateRef gate,GateRef e1,GateRef e2)1486 void LLVMIRBuilder::VisitMul(GateRef gate, GateRef e1, GateRef e2)
1487 {
1488     LLVMValueRef e1Value = gate2LValue_[e1];
1489     LLVMValueRef e2Value = gate2LValue_[e2];
1490     LLVMValueRef result = nullptr;
1491     auto machineType = acc_.GetMachineType(gate);
1492     if (IsMulIntergerType(machineType)) {
1493         result = LLVMBuildMul(builder_, e1Value, e2Value, "");
1494     } else if (machineType == MachineType::F64) {
1495         result = LLVMBuildFMul(builder_, e1Value, e2Value, "");
1496     } else {
1497         UNREACHABLE();
1498     }
1499     gate2LValue_[gate] = result;
1500 }
1501 
HandleFloatDiv(GateRef gate)1502 void LLVMIRBuilder::HandleFloatDiv(GateRef gate)
1503 {
1504     auto g0 = acc_.GetIn(gate, 0);
1505     auto g1 = acc_.GetIn(gate, 1);
1506     VisitFloatDiv(gate, g0, g1);
1507 }
1508 
HandleIntDiv(GateRef gate)1509 void LLVMIRBuilder::HandleIntDiv(GateRef gate)
1510 {
1511     auto g0 = acc_.GetIn(gate, 0);
1512     auto g1 = acc_.GetIn(gate, 1);
1513     VisitIntDiv(gate, g0, g1);
1514 }
1515 
HandleUDiv(GateRef gate)1516 void LLVMIRBuilder::HandleUDiv(GateRef gate)
1517 {
1518     auto g0 = acc_.GetIn(gate, 0);
1519     auto g1 = acc_.GetIn(gate, 1);
1520     VisitUDiv(gate, g0, g1);
1521 }
1522 
HandleIntOr(GateRef gate)1523 void LLVMIRBuilder::HandleIntOr(GateRef gate)
1524 {
1525     auto g0 = acc_.GetIn(gate, 0);
1526     auto g1 = acc_.GetIn(gate, 1);
1527     VisitIntOr(gate, g0, g1);
1528 }
1529 
HandleIntXor(GateRef gate)1530 void LLVMIRBuilder::HandleIntXor(GateRef gate)
1531 {
1532     auto g0 = acc_.GetIn(gate, 0);
1533     auto g1 = acc_.GetIn(gate, 1);
1534     VisitIntXor(gate, g0, g1);
1535 }
1536 
HandleIntLsr(GateRef gate)1537 void LLVMIRBuilder::HandleIntLsr(GateRef gate)
1538 {
1539     auto g0 = acc_.GetIn(gate, 0);
1540     auto g1 = acc_.GetIn(gate, 1);
1541     VisitIntLsr(gate, g0, g1);
1542 }
1543 
HandleIntAsr(GateRef gate)1544 void LLVMIRBuilder::HandleIntAsr(GateRef gate)
1545 {
1546     auto g0 = acc_.GetIn(gate, 0);
1547     auto g1 = acc_.GetIn(gate, 1);
1548     VisitIntAsr(gate, g0, g1);
1549 }
1550 
HandleCmp(GateRef gate)1551 void LLVMIRBuilder::HandleCmp(GateRef gate)
1552 {
1553     GateRef left = acc_.GetIn(gate, 0);
1554     GateRef right = acc_.GetIn(gate, 1);
1555     VisitCmp(gate, left, right);
1556 }
1557 
ConvertLLVMPredicateFromICMP(ICmpCondition cond)1558 LLVMIntPredicate LLVMIRBuilder::ConvertLLVMPredicateFromICMP(ICmpCondition cond)
1559 {
1560     switch (cond) {
1561         case ICmpCondition::SLT:
1562             return LLVMIntSLT;
1563         case ICmpCondition::SLE:
1564             return LLVMIntSLE;
1565         case ICmpCondition::SGT:
1566             return LLVMIntSGT;
1567         case ICmpCondition::SGE:
1568             return LLVMIntSGE;
1569         case ICmpCondition::ULT:
1570             return LLVMIntULT;
1571         case ICmpCondition::ULE:
1572             return LLVMIntULE;
1573         case ICmpCondition::UGT:
1574             return LLVMIntUGT;
1575         case ICmpCondition::UGE:
1576             return LLVMIntUGE;
1577         case ICmpCondition::NE:
1578             return LLVMIntNE;
1579         case ICmpCondition::EQ:
1580             return LLVMIntEQ;
1581         default:
1582             LOG_COMPILER(ERROR) << "unexpected cond!";
1583             UNREACHABLE();
1584     }
1585     return LLVMIntEQ;
1586 }
1587 
ConvertLLVMPredicateFromFCMP(FCmpCondition cond)1588 LLVMRealPredicate LLVMIRBuilder::ConvertLLVMPredicateFromFCMP(FCmpCondition cond)
1589 {
1590     switch (cond) {
1591         case FCmpCondition::OLT:
1592             return LLVMRealOLT;
1593         case FCmpCondition::OLE:
1594             return LLVMRealOLE;
1595         case FCmpCondition::OGT:
1596             return LLVMRealOGT;
1597         case FCmpCondition::OGE:
1598             return LLVMRealOGE;
1599         case FCmpCondition::ONE:
1600             return LLVMRealONE;
1601         case FCmpCondition::OEQ:
1602             return LLVMRealOEQ;
1603         default:
1604             LOG_COMPILER(ERROR) << "unexpected cond!";
1605             UNREACHABLE();
1606     }
1607     return LLVMRealOEQ;
1608 }
1609 
VisitCmp(GateRef gate,GateRef e1,GateRef e2)1610 void LLVMIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
1611 {
1612     LLVMValueRef e1Value = gate2LValue_[e1];
1613     LLVMValueRef e2Value = gate2LValue_[e2];
1614     LLVMValueRef result = nullptr;
1615     [[maybe_unused]]auto e1ValCode = acc_.GetMachineType(e1);
1616     [[maybe_unused]]auto e2ValCode = acc_.GetMachineType(e2);
1617     ASSERT((e1ValCode == e2ValCode) ||
1618         (compCfg_->Is32Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I32)) ||
1619         (compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) ||
1620         (compCfg_->Is32Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I32)) ||
1621         (compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64)));
1622     LLVMIntPredicate intOpcode = LLVMIntEQ;
1623     LLVMRealPredicate realOpcode = LLVMRealPredicateFalse;
1624     auto op = acc_.GetOpCode(gate);
1625     if (op == OpCode::ICMP) {
1626         auto cond = acc_.GetICmpCondition(gate);
1627         intOpcode = ConvertLLVMPredicateFromICMP(cond);
1628         result = LLVMBuildICmp(builder_, intOpcode, e1Value, e2Value, "");
1629     } else if (op == OpCode::FCMP) {
1630         auto cond = acc_.GetFCmpCondition(gate);
1631         realOpcode = ConvertLLVMPredicateFromFCMP(cond);
1632         result = LLVMBuildFCmp(builder_, realOpcode, e1Value, e2Value, "");
1633     } else {
1634         UNREACHABLE();
1635     }
1636 
1637     gate2LValue_[gate] = result;
1638 }
1639 
HandleLoad(GateRef gate)1640 void LLVMIRBuilder::HandleLoad(GateRef gate)
1641 {
1642     VisitLoad(gate, acc_.GetIn(gate, 1));
1643 }
1644 
HandleStore(GateRef gate)1645 void LLVMIRBuilder::HandleStore(GateRef gate)
1646 {
1647     VisitStore(gate, acc_.GetIn(gate, 2), acc_.GetIn(gate, 1));  // 2:baseAddr gate, 1:data gate
1648 }
1649 
HandleChangeInt32ToDouble(GateRef gate)1650 void LLVMIRBuilder::HandleChangeInt32ToDouble(GateRef gate)
1651 {
1652     VisitChangeInt32ToDouble(gate, acc_.GetIn(gate, 0));
1653 }
1654 
HandleChangeUInt32ToDouble(GateRef gate)1655 void LLVMIRBuilder::HandleChangeUInt32ToDouble(GateRef gate)
1656 {
1657     VisitChangeUInt32ToDouble(gate, acc_.GetIn(gate, 0));
1658 }
1659 
HandleChangeDoubleToInt32(GateRef gate)1660 void LLVMIRBuilder::HandleChangeDoubleToInt32(GateRef gate)
1661 {
1662     VisitChangeDoubleToInt32(gate, acc_.GetIn(gate, 0));
1663 }
1664 
HandleChangeTaggedPointerToInt64(GateRef gate)1665 void LLVMIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate)
1666 {
1667     VisitChangeTaggedPointerToInt64(gate, acc_.GetIn(gate, 0));
1668 }
1669 
HandleChangeInt64ToTagged(GateRef gate)1670 void LLVMIRBuilder::HandleChangeInt64ToTagged(GateRef gate)
1671 {
1672     VisitChangeInt64ToTagged(gate, acc_.GetIn(gate, 0));
1673 }
1674 
VisitIntDiv(GateRef gate,GateRef e1,GateRef e2)1675 void LLVMIRBuilder::VisitIntDiv(GateRef gate, GateRef e1, GateRef e2)
1676 {
1677     LLVMValueRef e1Value = gate2LValue_[e1];
1678     LLVMValueRef e2Value = gate2LValue_[e2];
1679     LLVMValueRef result = LLVMBuildSDiv(builder_, e1Value, e2Value, "");
1680     gate2LValue_[gate] = result;
1681 }
1682 
VisitUDiv(GateRef gate,GateRef e1,GateRef e2)1683 void LLVMIRBuilder::VisitUDiv(GateRef gate, GateRef e1, GateRef e2)
1684 {
1685     LLVMValueRef e1Value = gate2LValue_[e1];
1686     LLVMValueRef e2Value = gate2LValue_[e2];
1687     LLVMValueRef result = LLVMBuildUDiv(builder_, e1Value, e2Value, "");
1688     gate2LValue_[gate] = result;
1689 }
1690 
VisitFloatDiv(GateRef gate,GateRef e1,GateRef e2)1691 void LLVMIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2)
1692 {
1693     LLVMValueRef e1Value = gate2LValue_[e1];
1694     LLVMValueRef e2Value = gate2LValue_[e2];
1695 
1696     LLVMValueRef result = LLVMBuildFDiv(builder_, e1Value, e2Value, "");
1697     gate2LValue_[gate] = result;
1698 }
1699 
VisitIntOr(GateRef gate,GateRef e1,GateRef e2)1700 void LLVMIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2)
1701 {
1702     LLVMValueRef e1Value = gate2LValue_[e1];
1703     LLVMValueRef e2Value = gate2LValue_[e2];
1704     LLVMValueRef result = LLVMBuildOr(builder_, e1Value, e2Value, "");
1705     gate2LValue_[gate] = result;
1706 }
1707 
HandleIntAnd(GateRef gate)1708 void LLVMIRBuilder::HandleIntAnd(GateRef gate)
1709 {
1710     auto g0 = acc_.GetIn(gate, 0);
1711     auto g1 = acc_.GetIn(gate, 1);
1712     VisitIntAnd(gate, g0, g1);
1713 }
1714 
VisitIntAnd(GateRef gate,GateRef e1,GateRef e2)1715 void LLVMIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2)
1716 {
1717     LLVMValueRef e1Value = gate2LValue_[e1];
1718     LLVMValueRef e2Value = gate2LValue_[e2];
1719     LLVMValueRef result = LLVMBuildAnd(builder_, e1Value, e2Value, "");
1720     gate2LValue_[gate] = result;
1721 }
1722 
VisitIntXor(GateRef gate,GateRef e1,GateRef e2)1723 void LLVMIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2)
1724 {
1725     LLVMValueRef e1Value = gate2LValue_[e1];
1726     LLVMValueRef e2Value = gate2LValue_[e2];
1727     LLVMValueRef result = LLVMBuildXor(builder_, e1Value, e2Value, "");
1728     gate2LValue_[gate] = result;
1729 }
1730 
VisitIntLsr(GateRef gate,GateRef e1,GateRef e2)1731 void LLVMIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2)
1732 {
1733     LLVMValueRef e1Value = gate2LValue_[e1];
1734     LLVMValueRef e2Value = gate2LValue_[e2];
1735     LLVMValueRef result = LLVMBuildLShr(builder_, e1Value, e2Value, "");
1736     gate2LValue_[gate] = result;
1737 }
1738 
VisitIntAsr(GateRef gate,GateRef e1,GateRef e2)1739 void LLVMIRBuilder::VisitIntAsr(GateRef gate, GateRef e1, GateRef e2)
1740 {
1741     LLVMValueRef e1Value = gate2LValue_[e1];
1742     LLVMValueRef e2Value = gate2LValue_[e2];
1743     LLVMValueRef result = LLVMBuildAShr(builder_, e1Value, e2Value, "");
1744     gate2LValue_[gate] = result;
1745 }
1746 
HandleIntLsl(GateRef gate)1747 void LLVMIRBuilder::HandleIntLsl(GateRef gate)
1748 {
1749     auto g0 = acc_.GetIn(gate, 0);
1750     auto g1 = acc_.GetIn(gate, 1);
1751     VisitIntLsl(gate, g0, g1);
1752 }
1753 
VisitIntLsl(GateRef gate,GateRef e1,GateRef e2)1754 void LLVMIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2)
1755 {
1756     LLVMValueRef e1Value = gate2LValue_[e1];
1757     LLVMValueRef e2Value = gate2LValue_[e2];
1758     LLVMValueRef result = LLVMBuildShl(builder_, e1Value, e2Value, "");
1759     gate2LValue_[gate] = result;
1760 }
1761 
VisitZExtInt(GateRef gate,GateRef e1)1762 void LLVMIRBuilder::VisitZExtInt(GateRef gate, GateRef e1)
1763 {
1764     LLVMValueRef e1Value = gate2LValue_[e1];
1765     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
1766            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1767     LLVMValueRef result = LLVMBuildZExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1768     gate2LValue_[gate] = result;
1769 }
1770 
VisitSExtInt(GateRef gate,GateRef e1)1771 void LLVMIRBuilder::VisitSExtInt(GateRef gate, GateRef e1)
1772 {
1773     LLVMValueRef e1Value = gate2LValue_[e1];
1774     LLVMValueRef result = LLVMBuildSExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1775     gate2LValue_[gate] = result;
1776 }
1777 
HandleCastIntXToIntY(GateRef gate)1778 void LLVMIRBuilder::HandleCastIntXToIntY(GateRef gate)
1779 {
1780     VisitCastIntXToIntY(gate, acc_.GetIn(gate, 0));
1781 }
1782 
VisitCastIntXToIntY(GateRef gate,GateRef e1)1783 void LLVMIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1)
1784 {
1785     LLVMValueRef e1Value = gate2LValue_[e1];
1786     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
1787            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1788     LLVMValueRef result = LLVMBuildIntCast2(builder_, e1Value, ConvertLLVMTypeFromGate(gate), 1, "");
1789     gate2LValue_[gate] = result;
1790 }
1791 
HandleFPExt(GateRef gate)1792 void LLVMIRBuilder::HandleFPExt(GateRef gate)
1793 {
1794     VisitFPExt(gate, acc_.GetIn(gate, 0));
1795 }
1796 
VisitFPExt(GateRef gate,GateRef e1)1797 void LLVMIRBuilder::VisitFPExt(GateRef gate, GateRef e1)
1798 {
1799     LLVMValueRef e1Value = gate2LValue_[e1];
1800     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
1801            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1802     LLVMValueRef result = LLVMBuildFPExt(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1803     gate2LValue_[gate] = result;
1804 }
1805 
HandleFPTrunc(GateRef gate)1806 void LLVMIRBuilder::HandleFPTrunc(GateRef gate)
1807 {
1808     VisitFPTrunc(gate, acc_.GetIn(gate, 0));
1809 }
1810 
VisitFPTrunc(GateRef gate,GateRef e1)1811 void LLVMIRBuilder::VisitFPTrunc(GateRef gate, GateRef e1)
1812 {
1813     LLVMValueRef e1Value = gate2LValue_[e1];
1814     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
1815            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1816     LLVMValueRef result = LLVMBuildFPTrunc(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1817     gate2LValue_[gate] = result;
1818 }
1819 
VisitChangeInt32ToDouble(GateRef gate,GateRef e1)1820 void LLVMIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1)
1821 {
1822     LLVMValueRef e1Value = gate2LValue_[e1];
1823     LLVMValueRef result = LLVMBuildSIToFP(builder_, e1Value, ConvertLLVMTypeFromGate(gate), "");
1824     gate2LValue_[gate] = result;
1825 }
1826 
VisitChangeUInt32ToDouble(GateRef gate,GateRef e1)1827 void LLVMIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1)
1828 {
1829     LLVMValueRef e1Value = gate2LValue_[e1];
1830     LLVMValueRef result = LLVMBuildUIToFP(builder_, e1Value, LLVMDoubleType(), "");
1831     gate2LValue_[gate] = result;
1832 }
1833 
VisitChangeDoubleToInt32(GateRef gate,GateRef e1)1834 void LLVMIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1)
1835 {
1836     LLVMValueRef e1Value = gate2LValue_[e1];
1837     LLVMValueRef result = LLVMBuildFPToSI(builder_, e1Value, LLVMInt32Type(), "");
1838     gate2LValue_[gate] = result;
1839 }
1840 
VisitChangeTaggedPointerToInt64(GateRef gate,GateRef e1)1841 void LLVMIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1)
1842 {
1843     LLVMValueRef e1Value = gate2LValue_[e1];
1844     LLVMValueRef result = CanonicalizeToInt(e1Value);
1845     gate2LValue_[gate] = result;
1846 }
1847 
VisitChangeInt64ToTagged(GateRef gate,GateRef e1)1848 void LLVMIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1)
1849 {
1850     LLVMValueRef e1Value = gate2LValue_[e1];
1851     ASSERT(LLVMGetTypeKind(LLVMTypeOf(e1Value)) == LLVMIntegerTypeKind);
1852     LLVMValueRef result;
1853     if (compCfg_->Is32Bit()) {
1854         LLVMValueRef tmp1Value =
1855             LLVMBuildLShr(builder_, e1Value, LLVMConstInt(LLVMInt64Type(), 32, 0), ""); // 32: offset
1856         LLVMValueRef tmp2Value = LLVMBuildIntCast(builder_, e1Value, LLVMInt32Type(), ""); // low
1857         LLVMTypeRef vectorType = LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2);  // 2: packed vector type
1858         LLVMValueRef emptyValue = LLVMGetUndef(vectorType);
1859         tmp1Value = LLVMBuildIntToPtr(builder_, tmp1Value, LLVMPointerType(LLVMInt8Type(), 1), "");
1860         tmp2Value = LLVMBuildIntToPtr(builder_, tmp2Value, LLVMPointerType(LLVMInt8Type(), 1), "");
1861         result = LLVMBuildInsertElement(builder_, emptyValue, tmp2Value, LLVMConstInt(LLVMInt32Type(), 0, 0), "");
1862         result = LLVMBuildInsertElement(builder_, result, tmp1Value, LLVMConstInt(LLVMInt32Type(), 1, 0), "");
1863     } else {
1864         result = LLVMBuildIntToPtr(builder_, e1Value, LLVMPointerType(LLVMInt64Type(), 1), "");
1865     }
1866     gate2LValue_[gate] = result;
1867 }
1868 
HandleBitCast(GateRef gate)1869 void LLVMIRBuilder::HandleBitCast(GateRef gate)
1870 {
1871     VisitBitCast(gate, acc_.GetIn(gate, 0));
1872 }
1873 
VisitBitCast(GateRef gate,GateRef e1)1874 void LLVMIRBuilder::VisitBitCast(GateRef gate, GateRef e1)
1875 {
1876     LLVMValueRef e1Value = gate2LValue_[e1];
1877     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(gate)) ==
1878            GetBitWidthFromMachineType(acc_.GetMachineType(e1)));
1879     auto returnType = ConvertLLVMTypeFromGate(gate);
1880     LLVMValueRef result = LLVMBuildBitCast(builder_, e1Value, returnType, "");
1881     gate2LValue_[gate] = result;
1882 }
1883 
HandleDeopt(GateRef gate)1884 void LLVMIRBuilder::HandleDeopt(GateRef gate)
1885 {
1886     VisitDeopt(gate);
1887 }
1888 
GetExperimentalDeoptTy()1889 LLVMTypeRef LLVMIRBuilder::GetExperimentalDeoptTy()
1890 {
1891     auto fnTy = LLVMFunctionType(LLVMPointerType(LLVMInt64Type(), 1), nullptr, 0, 1);
1892     return fnTy;
1893 }
1894 
GetExperimentalDeopt(LLVMModuleRef & module)1895 LLVMValueRef LLVMIRBuilder::GetExperimentalDeopt(LLVMModuleRef &module)
1896 {
1897     /* 0:calling 1:its caller */
1898     auto fn = LLVMGetNamedFunction(module, "llvm.experimental.deoptimize.p1i64");
1899     if (!fn) {
1900         auto fnTy = GetExperimentalDeoptTy();
1901         fn = LLVMAddFunction(module, "llvm.experimental.deoptimize.p1i64", fnTy);
1902     }
1903     return fn;
1904 }
1905 
VisitDeopt(GateRef gate)1906 void LLVMIRBuilder::VisitDeopt(GateRef gate)
1907 {
1908     LLVMValueRef glue = gate2LValue_.at(acc_.GetIn(gate, 2));
1909     GateRef frameState = acc_.GetIn(gate, 1);
1910     std::vector<LLVMValueRef> params;
1911     params.push_back(glue); // glue
1912     GateRef deoptType = acc_.GetIn(gate, 3);
1913     uint64_t v = acc_.GetConstantValue(deoptType);
1914     params.push_back(LLVMConstInt(LLVMInt64Type(), v, false)); // deoptType
1915     LLVMValueRef callee = GetExperimentalDeopt(module_);
1916     LLVMTypeRef funcType = GetExperimentalDeoptTy();
1917 
1918     const size_t numValueIn = acc_.GetNumValueIn(frameState);
1919     const size_t envIndex = numValueIn - 3; // 3: env valueIn index
1920     const size_t accIndex = numValueIn - 2; // 2: acc valueIn index
1921     const size_t pcIndex = numValueIn - 1;
1922     GateRef env = acc_.GetValueIn(frameState, envIndex);
1923     GateRef acc = acc_.GetValueIn(frameState, accIndex);
1924     GateRef pc = acc_.GetValueIn(frameState, pcIndex);
1925     std::vector<LLVMValueRef> values;
1926     for (size_t i = 0; i < envIndex; i++) {
1927         GateRef vregValue = acc_.GetValueIn(frameState, i);
1928         if (acc_.IsConstantValue(vregValue, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
1929             continue;
1930         }
1931         values.emplace_back(LLVMConstInt(LLVMInt32Type(), i, false));
1932         values.emplace_back(gate2LValue_.at(vregValue));
1933     }
1934     if (!acc_.IsConstantValue(env, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
1935         values.emplace_back(LLVMConstInt(LLVMInt32Type(), static_cast<int>(SpecVregIndex::ENV_INDEX), false));
1936         values.emplace_back(gate2LValue_.at(env));
1937     }
1938     if (!acc_.IsConstantValue(acc, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
1939         values.emplace_back(LLVMConstInt(LLVMInt32Type(), static_cast<int>(SpecVregIndex::ACC_INDEX), false));
1940         values.emplace_back(gate2LValue_.at(acc));
1941     }
1942     values.emplace_back(LLVMConstInt(LLVMInt32Type(), static_cast<int>(SpecVregIndex::PC_INDEX), false));
1943     values.emplace_back(gate2LValue_.at(pc));
1944     LLVMValueRef runtimeCall =
1945         LLVMBuildCall3(builder_, funcType, callee, params.data(), params.size(), "", values.data(), values.size());
1946     gate2LValue_[gate] = runtimeCall;
1947 }
1948 
LLVMModule(const std::string & name,const std::string & triple,bool enablePGOProfiler)1949 LLVMModule::LLVMModule(const std::string &name, const std::string &triple, bool enablePGOProfiler)
1950     : cfg_(triple, enablePGOProfiler)
1951 {
1952     module_ = LLVMModuleCreateWithName(name.c_str());
1953     LLVMSetTarget(module_, triple.c_str());
1954 }
1955 
~LLVMModule()1956 LLVMModule::~LLVMModule()
1957 {
1958     if (module_ != nullptr) {
1959         LLVMDisposeModule(module_);
1960         module_ = nullptr;
1961     }
1962 }
1963 
InitialLLVMFuncTypeAndFuncByModuleCSigns()1964 void LLVMModule::InitialLLVMFuncTypeAndFuncByModuleCSigns()
1965 {
1966     for (size_t i = 0; i < callSigns_.size(); i++) {
1967         const CallSignature* cs = callSigns_[i];
1968         ASSERT(!cs->GetName().empty());
1969         LLVMValueRef value = AddAndGetFunc(cs);
1970         SetFunction(i, value);
1971     }
1972 }
1973 
SetUpForCommonStubs()1974 void LLVMModule::SetUpForCommonStubs()
1975 {
1976     CommonStubCSigns::GetCSigns(callSigns_);
1977     InitialLLVMFuncTypeAndFuncByModuleCSigns();
1978 }
1979 
SetUpForBytecodeHandlerStubs()1980 void LLVMModule::SetUpForBytecodeHandlerStubs()
1981 {
1982     BytecodeStubCSigns::GetCSigns(callSigns_);
1983     InitialLLVMFuncTypeAndFuncByModuleCSigns();
1984 }
1985 
SetUpForBuiltinsStubs()1986 void LLVMModule::SetUpForBuiltinsStubs()
1987 {
1988     BuiltinsStubCSigns::GetCSigns(callSigns_);
1989     InitialLLVMFuncTypeAndFuncByModuleCSigns();
1990 }
1991 
AddAndGetFunc(const CallSignature * stubDescriptor)1992 LLVMValueRef LLVMModule::AddAndGetFunc(const CallSignature *stubDescriptor)
1993 {
1994     auto funcType = GetFuncType(stubDescriptor);
1995     return LLVMAddFunction(module_, stubDescriptor->GetName().c_str(), funcType);
1996 }
1997 
GetFuncType(const CallSignature * stubDescriptor)1998 LLVMTypeRef LLVMModule::GetFuncType(const CallSignature *stubDescriptor)
1999 {
2000     LLVMTypeRef returnType = ConvertLLVMTypeFromVariableType(stubDescriptor->GetReturnType());
2001     std::vector<LLVMTypeRef> paramTys;
2002     auto paramCount = stubDescriptor->GetParametersCount();
2003     int extraParameterCnt = 0;
2004     auto paramsType = stubDescriptor->GetParametersType();
2005     if (paramsType != nullptr) {
2006         LLVMTypeRef glueType = ConvertLLVMTypeFromVariableType(paramsType[0]);
2007         paramTys.push_back(glueType);
2008 
2009         for (size_t i = 1; i < paramCount; i++) {
2010             paramTys.push_back(ConvertLLVMTypeFromVariableType(paramsType[i]));
2011         }
2012     }
2013     auto functype = LLVMFunctionType(returnType, paramTys.data(), paramCount + extraParameterCnt,
2014         stubDescriptor->IsVariadicArgs());
2015     return functype;
2016 }
2017 
GenerateFuncType(const std::vector<LLVMValueRef> & params,const CallSignature * stubDescriptor)2018 LLVMTypeRef LLVMModule::GenerateFuncType(const std::vector<LLVMValueRef> &params, const CallSignature *stubDescriptor)
2019 {
2020     LLVMTypeRef returnType = ConvertLLVMTypeFromVariableType(stubDescriptor->GetReturnType());
2021     std::vector<LLVMTypeRef> paramTys;
2022     for (auto value : params) {
2023         paramTys.emplace_back(LLVMTypeOf(value));
2024     }
2025     auto functionType = LLVMFunctionType(returnType, paramTys.data(), paramTys.size(), false);
2026     return functionType;
2027 }
2028 
ConvertLLVMTypeFromVariableType(VariableType type)2029 LLVMTypeRef LLVMModule::ConvertLLVMTypeFromVariableType(VariableType type)
2030 {
2031     static std::map<VariableType, LLVMTypeRef> machineTypeMap = {
2032         {VariableType::VOID(), LLVMVoidType()},
2033         {VariableType::BOOL(), LLVMInt1Type()},
2034         {VariableType::INT8(), LLVMInt8Type()},
2035         {VariableType::INT16(), LLVMInt16Type()},
2036         {VariableType::INT32(), LLVMInt32Type()},
2037         {VariableType::INT64(), LLVMInt64Type()},
2038         {VariableType::INT8(), LLVMInt8Type()},
2039         {VariableType::INT16(), LLVMInt16Type()},
2040         {VariableType::INT32(), LLVMInt32Type()},
2041         {VariableType::INT64(), LLVMInt64Type()},
2042         {VariableType::FLOAT32(), LLVMFloatType()},
2043         {VariableType::FLOAT64(), LLVMDoubleType()},
2044         {VariableType::NATIVE_POINTER(), LLVMInt64Type()},
2045         {VariableType::JS_POINTER(), LLVMPointerType(LLVMInt64Type(), 1)},
2046         {VariableType::JS_ANY(), LLVMPointerType(LLVMInt64Type(), 1)},
2047     };
2048     if (cfg_.Is32Bit()) {
2049         machineTypeMap[VariableType::NATIVE_POINTER()] = LLVMInt32Type();
2050         LLVMTypeRef vectorType = LLVMVectorType(LLVMPointerType(LLVMInt8Type(), 1), 2);  // 2: packed vector type
2051         machineTypeMap[VariableType::JS_POINTER()] = vectorType;
2052         machineTypeMap[VariableType::JS_ANY()] = vectorType;
2053     }
2054     return machineTypeMap[type];
2055 }
2056 
AddFunc(const panda::ecmascript::MethodLiteral * methodLiteral,const JSPandaFile * jsPandaFile)2057 LLVMValueRef LLVMModule::AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile)
2058 {
2059     LLVMTypeRef returnType = NewLType(MachineType::I64, GateType::TaggedValue());  // possibly get it for circuit
2060     LLVMTypeRef glue = NewLType(MachineType::I64, GateType::NJSValue());
2061     LLVMTypeRef lexEnv = NewLType(MachineType::I64, GateType::TaggedValue());
2062     LLVMTypeRef actualArgc = NewLType(MachineType::I64, GateType::NJSValue());
2063     std::vector<LLVMTypeRef> paramTys = { glue, lexEnv, actualArgc };
2064     auto funcIndex = static_cast<uint32_t>(CommonArgIdx::FUNC);
2065     auto numOfComArgs = static_cast<uint32_t>(CommonArgIdx::NUM_OF_ARGS);
2066     auto paramCount = methodLiteral->GetNumArgs() + numOfComArgs;
2067     auto numOfRestArgs = paramCount - funcIndex;
2068     paramTys.insert(paramTys.end(), numOfRestArgs, NewLType(MachineType::I64, GateType::TaggedValue()));
2069     auto funcType = LLVMFunctionType(returnType, paramTys.data(), paramCount, false); // not variable args
2070     auto offsetInPandaFile = methodLiteral->GetMethodId().GetOffset();
2071 
2072     std::string fileName = jsPandaFile->GetFileName();
2073     std::string name = MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId());
2074     name += std::string("@") + std::to_string(offsetInPandaFile) + std::string("@") + fileName;
2075 
2076     auto function = LLVMAddFunction(module_, name.c_str(), funcType);
2077     SetFunction(offsetInPandaFile, function);
2078     return function;
2079 }
2080 
NewLType(MachineType machineType,GateType gateType)2081 LLVMTypeRef LLVMModule::NewLType(MachineType machineType, GateType gateType)
2082 {
2083     VariableType vType(machineType, gateType);
2084     return ConvertLLVMTypeFromVariableType(vType);
2085 }
2086 }  // namespace panda::ecmascript::kungfu
2087