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