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