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