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