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/litecg_ir_builder.h"
17
18 #include <cmath>
19 #include <cstdint>
20
21 #include "ecmascript/compiler/argument_accessor.h"
22 #include "ecmascript/compiler/bc_call_signature.h"
23 #include "ecmascript/compiler/circuit.h"
24 #include "ecmascript/compiler/call_signature.h"
25 #include "ecmascript/compiler/common_stubs.h"
26 #include "ecmascript/compiler/debug_info.h"
27 #include "ecmascript/compiler/gate.h"
28 #include "ecmascript/compiler/rt_call_signature.h"
29 #include "ecmascript/deoptimizer/deoptimizer.h"
30 #include "ecmascript/frames.h"
31 #include "ecmascript/js_thread.h"
32 #include "ecmascript/method.h"
33 #include "lmir_builder.h"
34
35 namespace panda::ecmascript::kungfu {
36 using FunctionBuilder = maple::litecg::LMIRBuilder::FunctionBuilder;
37 using SwitchBuilder = maple::litecg::LMIRBuilder::SwitchBuilder;
38 using Function = maple::litecg::Function;
39 using LMIRBuilder = maple::litecg::LMIRBuilder;
40 using BB = maple::litecg::BB;
41 using Expr = maple::litecg::Expr;
42 using Stmt = maple::litecg::Stmt;
43 using Const = maple::litecg::Const;
44 using LiteCGType = maple::litecg::Type;
45 using IntCmpCondition = maple::litecg::IntCmpCondition;
46 using FloatCmpCondition = maple::litecg::FloatCmpCondition;
47 using Var = maple::litecg::Var;
48 using PregIdx = maple::litecg::PregIdx;
49 using IntrinsicId = maple::litecg::IntrinsicId;
50 using maple::litecg::LiteCGValue;
51 using maple::litecg::LiteCGValueKind;
52
53 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, Expr>;
54
LiteCGIRBuilder(const std::vector<std::vector<GateRef>> * schedule,Circuit * circuit,LMIRModule * module,const CompilationConfig * cfg,CallSignature::CallConv callConv,bool enableLog,bool enableOptInlining,const panda::ecmascript::MethodLiteral * methodLiteral,const JSPandaFile * jsPandaFile,const std::string & funcName)55 LiteCGIRBuilder::LiteCGIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
56 LMIRModule *module, const CompilationConfig *cfg, CallSignature::CallConv callConv,
57 bool enableLog, bool enableOptInlining,
58 const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile,
59 const std::string &funcName)
60 : scheduledGates_(schedule),
61 circuit_(circuit),
62 lmirModule_(module),
63 compCfg_(cfg),
64 callConv_(callConv),
65 enableLog_(enableLog),
66 enableOptInlining_(enableOptInlining),
67 methodLiteral_(methodLiteral),
68 jsPandaFile_(jsPandaFile),
69 funcName_(funcName),
70 acc_(circuit)
71 {
72 lmirBuilder_ = new LMIRBuilder(*module->GetModule());
73 ASSERT(compCfg_->Is64Bit());
74 slotSize_ = sizeof(uint64_t);
75 slotType_ = lmirBuilder_->i64Type;
76 InitializeHandlers();
77 }
78
~LiteCGIRBuilder()79 LiteCGIRBuilder::~LiteCGIRBuilder()
80 {
81 delete lmirBuilder_;
82 }
83
BuildInstID2BBIDMap()84 void LiteCGIRBuilder::BuildInstID2BBIDMap()
85 {
86 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
87 const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx);
88 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
89 GateId gateId = acc_.GetId(bb[instIdx - 1]);
90 instID2bbID_[gateId] = static_cast<int>(bbIdx);
91 }
92 }
93 }
94
GetOrCreateBB(int bbID)95 BB &LiteCGIRBuilder::GetOrCreateBB(int bbID)
96 {
97 auto itr = bbID2BB_.find(bbID);
98 if (itr != bbID2BB_.end()) {
99 return *(itr->second);
100 }
101 BB &bb = lmirBuilder_->CreateBB();
102 bbID2BB_[bbID] = &bb;
103 return bb;
104 }
105
GetFirstBB()106 BB &LiteCGIRBuilder::GetFirstBB()
107 {
108 // Obtain the first BB (i.e. the BB with id zero) for inserting prologue information
109 return GetOrCreateBB(0);
110 }
111
CreateBB()112 BB &LiteCGIRBuilder::CreateBB()
113 {
114 BB &bb = lmirBuilder_->CreateBB(false);
115 return bb;
116 }
117
ConvertLiteCGTypeFromGate(GateRef gate,bool isSigned) const118 LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromGate(GateRef gate, bool isSigned) const
119 {
120 if (acc_.IsGCRelated(gate)) {
121 return lmirBuilder_->i64RefType;
122 }
123
124 MachineType t = acc_.GetMachineType(gate);
125 switch (t) {
126 case MachineType::NOVALUE:
127 return lmirBuilder_->voidType;
128 case MachineType::I1:
129 return lmirBuilder_->u1Type;
130 case MachineType::I8:
131 return isSigned ? lmirBuilder_->i8Type : lmirBuilder_->u8Type;
132 case MachineType::I16:
133 return isSigned ? lmirBuilder_->i16Type : lmirBuilder_->u16Type;
134 case MachineType::I32:
135 return isSigned ? lmirBuilder_->i32Type : lmirBuilder_->u32Type;
136 case MachineType::I64:
137 return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type;
138 case MachineType::F32:
139 return lmirBuilder_->f32Type;
140 case MachineType::F64:
141 return lmirBuilder_->f64Type;
142 case MachineType::ARCH:
143 return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type;
144 default:
145 LOG_ECMA(FATAL) << "this branch is unreachable";
146 UNREACHABLE();
147 }
148 }
149
AddFunc()150 void LiteCGIRBuilder::AddFunc()
151 {
152 // setup function type
153 std::string funcName = lmirModule_->GetFuncName(methodLiteral_, jsPandaFile_);
154 FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName);
155 funcBuilder.Param(lmirBuilder_->i64Type, "glue");
156 if (!methodLiteral_->IsFastCall()) {
157 funcBuilder.Param(lmirBuilder_->i64Type, "actualArgc")
158 .Param(lmirBuilder_->i64RefType, "func")
159 .Param(lmirBuilder_->i64RefType, "new_target")
160 .Param(lmirBuilder_->i64RefType, "this_object");
161 for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) {
162 funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i));
163 }
164 } else {
165 funcBuilder.Param(lmirBuilder_->i64RefType, "func").Param(lmirBuilder_->i64RefType, "this_object");
166 for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) {
167 funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i));
168 }
169 }
170
171 funcBuilder.CallConvAttribute(ConvertCallAttr(callConv_));
172 Function &function = funcBuilder.Return(lmirBuilder_->i64RefType).Done();
173 lmirBuilder_->SetCurFunc(function);
174 lmirBuilder_->RenameFormal2Preg(function);
175 GenPrologue(function);
176 auto offsetInPandaFile = methodLiteral_->GetMethodId().GetOffset();
177 lmirModule_->SetFunction(offsetInPandaFile, funcName, methodLiteral_->IsFastCall());
178 }
179
Build()180 void LiteCGIRBuilder::Build()
181 {
182 BuildInstID2BBIDMap();
183 AddFunc();
184 LOG_COMPILER(INFO) << "============== building litecg ir=======" << std::endl;
185
186 std::unordered_set<OpCode> usedOpcodeSet;
187 for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
188 const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx);
189
190 for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
191 GateRef gate = bb[instIdx - 1];
192 auto found = opHandlers_.find(acc_.GetOpCode(gate));
193 if (found != opHandlers_.end()) {
194 (this->*(found->second))(gate);
195 InsertUsedOpcodeSet(usedOpcodeSet, found->first);
196 continue;
197 }
198 if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) {
199 LOG_COMPILER(FATAL) << "can't process opcode: " << acc_.GetOpCode(gate) << std::endl;
200 }
201 }
202 }
203
204 if (enableLog_) {
205 for (auto &opcode : usedOpcodeSet) {
206 LOG_COMPILER(INFO) << "OPCODE: " << opcode << std::endl;
207 }
208 }
209
210 std::map<int, std::vector<std::pair<PregIdx, PregIdx>>> bbID2phiAssign;
211 for (auto &pair : bbID2unmergedPhis_) {
212 for (auto &desc : pair.second) {
213 Expr value = GetExprFromGate(desc.operand);
214 PregIdx tmpPhiPregIdx = lmirBuilder_->CreatePreg(value.GetType());
215 Stmt &tmpPhiAssign = lmirBuilder_->Regassign(value, tmpPhiPregIdx);
216 lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(desc.predBBId), tmpPhiAssign);
217 bbID2phiAssign[desc.predBBId].emplace_back(std::make_pair(tmpPhiPregIdx, desc.phi));
218 }
219 }
220
221 for (auto &pair: bbID2phiAssign) {
222 for (auto &expr: pair.second) {
223 auto &stmt = lmirBuilder_->Regassign(lmirBuilder_->Regread(expr.first), expr.second);
224 lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(pair.first), stmt);
225 }
226 }
227 bbID2unmergedPhis_.clear();
228 bbID2phiAssign.clear();
229
230 lmirBuilder_->AppendBB(lmirBuilder_->GetLastPosBB());
231 }
232
GenPrologue(maple::litecg::Function & function)233 void LiteCGIRBuilder::GenPrologue(maple::litecg::Function &function)
234 {
235 auto frameType = circuit_->GetFrameType();
236 if (IsInterpreted()) {
237 return;
238 }
239 lmirBuilder_->SetFuncFramePointer("all");
240 size_t reservedSlotsSize = 0;
241 if (frameType == FrameType::OPTIMIZED_FRAME) {
242 reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
243 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
244 SaveFrameTypeOnFrame(frameType);
245 } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
246 reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
247 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
248 auto ArgList = circuit_->GetArgRoot();
249 auto uses = acc_.Uses(ArgList);
250 for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
251 int argth = static_cast<int>(acc_.TryGetValue(*useIt));
252 Var &value = lmirBuilder_->GetParam(function, argth);
253 int funcIndex = 0;
254 if (methodLiteral_->IsFastCall()) {
255 frameType = FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
256 funcIndex = static_cast<int>(FastCallArgIdx::FUNC);
257 } else {
258 funcIndex = static_cast<int>(CommonArgIdx::FUNC);
259 }
260 if (argth == funcIndex) {
261 SaveJSFuncOnOptJSFuncFrame(value);
262 SaveFrameTypeOnFrame(frameType);
263 }
264 }
265 } else {
266 LOG_COMPILER(FATAL) << "frameType interpret type error !";
267 ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !");
268 }
269 }
270
SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var & value)271 void LiteCGIRBuilder::SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var &value)
272 {
273 ASSERT(circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
274 Expr fpAddr = CallingFp(false);
275 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
276 size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
277 Expr frameJSFuncSlotAddr =
278 lmirBuilder_->Sub(frameAddr.GetType(), frameAddr,
279 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset)));
280 Expr jsFuncAddr =
281 lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr);
282 Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value));
283 auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType());
284 lmirBuilder_->AppendStmt(GetFirstBB(), stmt);
285 }
286
SaveFrameTypeOnFrame(FrameType frameType)287 void LiteCGIRBuilder::SaveFrameTypeOnFrame(FrameType frameType)
288 {
289 Expr fpAddr = CallingFp(false);
290 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
291 Expr frameJSFuncSlotAddr = lmirBuilder_->Sub(
292 frameAddr.GetType(), frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_)));
293 Expr jsFuncAddr =
294 lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr);
295 Expr liteFramType =
296 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<uintptr_t>(frameType)));
297 auto &stmt = lmirBuilder_->Iassign(liteFramType, jsFuncAddr, jsFuncAddr.GetType());
298 lmirBuilder_->AppendStmt(GetFirstBB(), stmt);
299 }
300
GetGlue(const std::vector<GateRef> & inList)301 Expr LiteCGIRBuilder::GetGlue(const std::vector<GateRef> &inList)
302 {
303 GateRef glueGate = inList[static_cast<size_t>(CallInputs::GLUE)];
304 auto itr = gate2Expr_.find(glueGate);
305 if (itr != gate2Expr_.end()) {
306 return GetExprFromGate(glueGate);
307 }
308 Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetLocalVar("glue"));
309 SaveGate2Expr(glueGate, glue);
310 return glue;
311 }
312
SaveGate2Expr(GateRef gate,Expr expr)313 void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, Expr expr)
314 {
315 if (expr.IsDread()) {
316 LiteCGValue value;
317 value.kind = LiteCGValueKind::kSymbolKind;
318 value.symbol = lmirBuilder_->GetLocalVarFromExpr(expr);
319 gate2Expr_[gate] = value;
320 return;
321 }
322 if (expr.IsRegread()) {
323 LiteCGValue value;
324 value.kind = LiteCGValueKind::kPregKind;
325 value.pregIdx = lmirBuilder_->GetPregIdxFromExpr(expr);
326 gate2Expr_[gate] = value;
327 return;
328 }
329 // check expr is not agg
330 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
331 PregIdx pregIdx = lmirBuilder_->CreatePreg(expr.GetType());
332 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Regassign(expr, pregIdx));
333 LiteCGValue value;
334 value.kind = LiteCGValueKind::kPregKind;
335 value.pregIdx = pregIdx;
336 gate2Expr_[gate] = value;
337 }
338
GetConstant(GateRef gate)339 Expr LiteCGIRBuilder::GetConstant(GateRef gate)
340 {
341 std::bitset<64> value = acc_.GetConstantValue(gate); // 64 for bit width
342 auto machineType = acc_.GetMachineType(gate);
343 if (machineType == MachineType::ARCH) {
344 ASSERT(compCfg_->Is64Bit());
345 machineType = MachineType::I64;
346 }
347
348 Const *constVal = nullptr;
349 if (machineType == MachineType::I32) {
350 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, static_cast<int64_t>(value.to_ulong())));
351 } else if (machineType == MachineType::I64) {
352 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<int64_t>(value.to_ulong())));
353 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
354 if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) {
355 Expr constExpr = lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, lmirBuilder_->ConstVal(*constVal));
356 return constExpr;
357 } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) {
358 // do nothing
359 } else {
360 LOG_ECMA(FATAL) << "this branch is unreachable";
361 UNREACHABLE();
362 }
363 } else if (machineType == MachineType::F64) {
364 auto doubleValue = base::bit_cast<double>(value.to_ullong()); // actual double value
365 constVal = &(lmirBuilder_->CreateDoubleConst(static_cast<double>(doubleValue)));
366 } else if (machineType == MachineType::I8) {
367 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u8Type, static_cast<int64_t>(value.to_ulong())));
368 } else if (machineType == MachineType::I16) {
369 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u16Type, static_cast<int64_t>(value.to_ulong())));
370 } else if (machineType == MachineType::I1) {
371 constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u1Type, static_cast<int64_t>(value.to_ulong())));
372 } else {
373 LOG_ECMA(FATAL) << "this branch is unreachable";
374 UNREACHABLE();
375 }
376 return lmirBuilder_->ConstVal(*constVal);
377 }
378
GetExprFromGate(GateRef gate)379 Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate)
380 {
381 if (acc_.GetOpCode(gate) == OpCode::CONSTANT) {
382 return GetConstant(gate);
383 }
384 LiteCGValue value = gate2Expr_[gate];
385 if (value.kind == LiteCGValueKind::kSymbolKind) {
386 return lmirBuilder_->Dread(*value.symbol);
387 }
388 ASSERT(value.kind == LiteCGValueKind::kPregKind);
389 return lmirBuilder_->Regread(value.pregIdx);
390 }
391
InitializeHandlers()392 void LiteCGIRBuilder::InitializeHandlers()
393 {
394 opHandlers_ = {
395 {OpCode::STATE_ENTRY, &LiteCGIRBuilder::HandleGoto},
396 {OpCode::RETURN, &LiteCGIRBuilder::HandleReturn},
397 {OpCode::RETURN_VOID, &LiteCGIRBuilder::HandleReturnVoid},
398 {OpCode::IF_BRANCH, &LiteCGIRBuilder::HandleBranch},
399 {OpCode::ORDINARY_BLOCK, &LiteCGIRBuilder::HandleGoto},
400 {OpCode::IF_TRUE, &LiteCGIRBuilder::HandleGoto},
401 {OpCode::IF_FALSE, &LiteCGIRBuilder::HandleGoto},
402 {OpCode::SWITCH_CASE, &LiteCGIRBuilder::HandleGoto},
403 {OpCode::MERGE, &LiteCGIRBuilder::HandleGoto},
404 {OpCode::DEFAULT_CASE, &LiteCGIRBuilder::HandleGoto},
405 {OpCode::LOOP_BEGIN, &LiteCGIRBuilder::HandleGoto},
406 {OpCode::LOOP_BACK, &LiteCGIRBuilder::HandleGoto},
407 {OpCode::VALUE_SELECTOR, &LiteCGIRBuilder::HandlePhi},
408 {OpCode::RUNTIME_CALL, &LiteCGIRBuilder::HandleRuntimeCall},
409 {OpCode::RUNTIME_CALL_WITH_ARGV, &LiteCGIRBuilder::HandleRuntimeCallWithArgv},
410 {OpCode::NOGC_RUNTIME_CALL, &LiteCGIRBuilder::HandleCall},
411 {OpCode::CALL_OPTIMIZED, &LiteCGIRBuilder::HandleCall},
412 {OpCode::FAST_CALL_OPTIMIZED, &LiteCGIRBuilder::HandleCall},
413 {OpCode::CALL, &LiteCGIRBuilder::HandleCall},
414 {OpCode::BUILTINS_CALL, &LiteCGIRBuilder::HandleCall},
415 {OpCode::BUILTINS_CALL_WITH_ARGV, &LiteCGIRBuilder::HandleCall},
416 {OpCode::ARG, &LiteCGIRBuilder::HandleParameter},
417 {OpCode::CONSTANT, &LiteCGIRBuilder::HandleConstant},
418 {OpCode::ZEXT, &LiteCGIRBuilder::HandleZExtInt},
419 {OpCode::SEXT, &LiteCGIRBuilder::HandleSExtInt},
420 {OpCode::TRUNC, &LiteCGIRBuilder::HandleCastIntXToIntY},
421 {OpCode::FEXT, &LiteCGIRBuilder::HandleFPExt},
422 {OpCode::FTRUNC, &LiteCGIRBuilder::HandleFPTrunc},
423 {OpCode::REV, &LiteCGIRBuilder::HandleIntRev},
424 {OpCode::ADD, &LiteCGIRBuilder::HandleAdd},
425 {OpCode::SUB, &LiteCGIRBuilder::HandleSub},
426 {OpCode::MUL, &LiteCGIRBuilder::HandleMul},
427 {OpCode::FDIV, &LiteCGIRBuilder::HandleFloatDiv},
428 {OpCode::SDIV, &LiteCGIRBuilder::HandleIntDiv},
429 {OpCode::UDIV, &LiteCGIRBuilder::HandleUDiv},
430 {OpCode::AND, &LiteCGIRBuilder::HandleIntAnd},
431 {OpCode::OR, &LiteCGIRBuilder::HandleIntOr},
432 {OpCode::XOR, &LiteCGIRBuilder::HandleIntXor},
433 {OpCode::LSR, &LiteCGIRBuilder::HandleIntLsr},
434 {OpCode::ASR, &LiteCGIRBuilder::HandleIntAsr},
435 {OpCode::ICMP, &LiteCGIRBuilder::HandleCmp},
436 {OpCode::FCMP, &LiteCGIRBuilder::HandleCmp},
437 {OpCode::LOAD, &LiteCGIRBuilder::HandleLoad},
438 {OpCode::STORE, &LiteCGIRBuilder::HandleStore},
439 {OpCode::SIGNED_INT_TO_FLOAT, &LiteCGIRBuilder::HandleChangeInt32ToDouble},
440 {OpCode::UNSIGNED_INT_TO_FLOAT, &LiteCGIRBuilder::HandleChangeUInt32ToDouble},
441 {OpCode::FLOAT_TO_SIGNED_INT, &LiteCGIRBuilder::HandleChangeDoubleToInt32},
442 {OpCode::TAGGED_TO_INT64, &LiteCGIRBuilder::HandleChangeTaggedPointerToInt64},
443 {OpCode::INT64_TO_TAGGED, &LiteCGIRBuilder::HandleChangeInt64ToTagged},
444 {OpCode::BITCAST, &LiteCGIRBuilder::HandleBitCast},
445 {OpCode::LSL, &LiteCGIRBuilder::HandleIntLsl},
446 {OpCode::SMOD, &LiteCGIRBuilder::HandleMod},
447 {OpCode::FMOD, &LiteCGIRBuilder::HandleMod},
448 {OpCode::DEOPT_CHECK, &LiteCGIRBuilder::HandleDeoptCheck},
449 {OpCode::TRUNC_FLOAT_TO_INT64, &LiteCGIRBuilder::HandleTruncFloatToInt},
450 {OpCode::TRUNC_FLOAT_TO_INT32, &LiteCGIRBuilder::HandleTruncFloatToInt},
451 {OpCode::ADD_WITH_OVERFLOW, &LiteCGIRBuilder::HandleAddWithOverflow},
452 {OpCode::SUB_WITH_OVERFLOW, &LiteCGIRBuilder::HandleSubWithOverflow},
453 {OpCode::MUL_WITH_OVERFLOW, &LiteCGIRBuilder::HandleMulWithOverflow},
454 {OpCode::EXTRACT_VALUE, &LiteCGIRBuilder::HandleExtractValue},
455 {OpCode::SQRT, &LiteCGIRBuilder::HandleSqrt},
456 {OpCode::READSP, &LiteCGIRBuilder::HandleReadSp},
457 };
458 illegalOpHandlers_ = {OpCode::NOP,
459 OpCode::CIRCUIT_ROOT,
460 OpCode::DEPEND_ENTRY,
461 OpCode::DEAD,
462 OpCode::RETURN_LIST,
463 OpCode::ARG_LIST,
464 OpCode::THROW,
465 OpCode::DEPEND_SELECTOR,
466 OpCode::DEPEND_RELAY,
467 OpCode::FRAME_STATE,
468 OpCode::STATE_SPLIT,
469 OpCode::FRAME_ARGS,
470 OpCode::LOOP_EXIT_DEPEND,
471 OpCode::LOOP_EXIT,
472 OpCode::START_ALLOCATE,
473 OpCode::FINISH_ALLOCATE,
474 OpCode::FRAME_VALUES};
475 }
476
HandleReturnVoid(GateRef gate)477 void LiteCGIRBuilder::HandleReturnVoid([[maybe_unused]] GateRef gate)
478 {
479 return;
480 }
481
HandleGoto(GateRef gate)482 void LiteCGIRBuilder::HandleGoto(GateRef gate)
483 {
484 std::vector<GateRef> outs;
485 acc_.GetOutStates(gate, outs);
486 int block = instID2bbID_[acc_.GetId(gate)];
487 int bbOut = instID2bbID_[acc_.GetId(outs[0])];
488 switch (acc_.GetOpCode(gate)) {
489 case OpCode::MERGE:
490 case OpCode::LOOP_BEGIN: {
491 for (const auto &out : outs) {
492 bbOut = instID2bbID_[acc_.GetId(out)];
493 VisitGoto(block, bbOut);
494 }
495 break;
496 }
497 default: {
498 VisitGoto(block, bbOut);
499 break;
500 }
501 }
502 }
503
VisitGoto(int block,int bbOut)504 void LiteCGIRBuilder::VisitGoto(int block, int bbOut)
505 {
506 if (block == bbOut) {
507 return;
508 }
509 BB &srcBB = GetOrCreateBB(block);
510 BB &destBB = GetOrCreateBB(bbOut);
511
512 lmirBuilder_->AppendStmt(srcBB, lmirBuilder_->Goto(destBB));
513 lmirBuilder_->AppendBB(srcBB);
514 }
515
HandleParameter(GateRef gate)516 void LiteCGIRBuilder::HandleParameter(GateRef gate)
517 {
518 return VisitParameter(gate);
519 }
520
VisitParameter(GateRef gate)521 void LiteCGIRBuilder::VisitParameter(GateRef gate)
522 {
523 size_t argth = static_cast<size_t>(acc_.TryGetValue(gate));
524 Var ¶m = lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), argth);
525 SaveGate2Expr(gate, lmirBuilder_->GenExprFromVar(param));
526 }
527
HandleConstant(GateRef gate)528 void LiteCGIRBuilder::HandleConstant(GateRef gate)
529 {
530 // no need to deal with constant separately
531 (void)gate;
532 return;
533 }
534
HandleAdd(GateRef gate)535 void LiteCGIRBuilder::HandleAdd(GateRef gate)
536 {
537 auto g0 = acc_.GetIn(gate, 0);
538 auto g1 = acc_.GetIn(gate, 1);
539 VisitAdd(gate, g0, g1);
540 }
541
CanonicalizeToPtr(Expr expr,LiteCGType * type)542 Expr LiteCGIRBuilder::CanonicalizeToPtr(Expr expr, LiteCGType *type)
543 {
544 if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypePointer) {
545 if (expr.GetType() == type) {
546 return expr;
547 }
548 return lmirBuilder_->Cvt(expr.GetType(), type, expr);
549 } else if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypeScalar) {
550 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, expr);
551 } else {
552 LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: ";
553 UNREACHABLE();
554 }
555 return expr;
556 }
557
VisitAdd(GateRef gate,GateRef e1,GateRef e2)558 void LiteCGIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2)
559 {
560 Expr e1Value = GetExprFromGate(e1);
561 Expr e2Value = GetExprFromGate(e2);
562
563 Expr result;
564 /*
565 * If the first operand is pointer, special treatment is needed
566 * 1) add, pointer, int
567 * 2) add, vector{i8* x 2}, int
568 */
569 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
570 auto machineType = acc_.GetMachineType(gate);
571 if (IsAddIntergerType(machineType)) {
572 auto e1Type = ConvertLiteCGTypeFromGate(e1);
573 auto e1TypeKind = lmirBuilder_->LiteCGGetTypeKind(e1Type);
574 auto e2Type = ConvertLiteCGTypeFromGate(e2);
575 if (e1TypeKind == maple::litecg::kLiteCGTypePointer) {
576 Expr tmp1 = lmirBuilder_->Cvt(e1Type, lmirBuilder_->i64Type, e1Value);
577 Expr tmp2 =
578 (e2Type == lmirBuilder_->i64Type) ? e2Value : lmirBuilder_->Cvt(e2Type, lmirBuilder_->i64Type, e2Value);
579 Expr tmp3 = lmirBuilder_->Add(lmirBuilder_->i64Type, tmp1, tmp2);
580 result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, returnType, tmp3);
581 SaveGate2Expr(gate, result);
582 // set the base reference of derived reference
583 LiteCGValue resultValue = gate2Expr_[gate];
584 if ((e1Type == lmirBuilder_->i64RefType) && (acc_.GetOpCode(e1) != OpCode::CONSTANT)) {
585 lmirBuilder_->SetFunctionDerived2BaseRef(resultValue.pregIdx,
586 lmirBuilder_->GetPregIdxFromExpr(e1Value));
587 }
588 return;
589 } else {
590 Expr tmp1Expr = (e1Type == returnType) ? e1Value : lmirBuilder_->Cvt(e1Type, returnType, e1Value);
591 Expr tmp2Expr = (e2Type == returnType) ? e2Value : lmirBuilder_->Cvt(e2Type, returnType, e2Value);
592 result = lmirBuilder_->Add(returnType, tmp1Expr, tmp2Expr);
593 }
594 } else if (machineType == MachineType::F64) {
595 result = lmirBuilder_->Add(returnType, e1Value, e2Value);
596 } else {
597 LOG_ECMA(FATAL) << "this branch is unreachable";
598 UNREACHABLE();
599 }
600 SaveGate2Expr(gate, result);
601 }
602
HandleLoad(GateRef gate)603 void LiteCGIRBuilder::HandleLoad(GateRef gate)
604 {
605 VisitLoad(gate, acc_.GetIn(gate, 1));
606 }
607
VisitLoad(GateRef gate,GateRef base)608 void LiteCGIRBuilder::VisitLoad(GateRef gate, GateRef base)
609 {
610 Expr baseAddr = GetExprFromGate(base);
611
612 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
613 LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(returnType)) ? lmirBuilder_->CreateRefType(returnType)
614 : lmirBuilder_->CreatePtrType(returnType);
615 baseAddr = CanonicalizeToPtr(baseAddr, memType);
616 Expr result = lmirBuilder_->Iread(returnType, baseAddr, memType);
617 SaveGate2Expr(gate, result);
618 }
619
HandleCmp(GateRef gate)620 void LiteCGIRBuilder::HandleCmp(GateRef gate)
621 {
622 GateRef left = acc_.GetIn(gate, 0);
623 GateRef right = acc_.GetIn(gate, 1);
624 VisitCmp(gate, left, right);
625 }
626
ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const627 IntCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const
628 {
629 switch (cond) {
630 case ICmpCondition::SLT:
631 return IntCmpCondition::kSLT;
632 case ICmpCondition::SLE:
633 return IntCmpCondition::kSLE;
634 case ICmpCondition::SGT:
635 return IntCmpCondition::kSGT;
636 case ICmpCondition::SGE:
637 return IntCmpCondition::kSGE;
638 case ICmpCondition::ULT:
639 return IntCmpCondition::kULT;
640 case ICmpCondition::ULE:
641 return IntCmpCondition::kULE;
642 case ICmpCondition::UGT:
643 return IntCmpCondition::kUGT;
644 case ICmpCondition::UGE:
645 return IntCmpCondition::kUGE;
646 case ICmpCondition::NE:
647 return IntCmpCondition::kNE;
648 case ICmpCondition::EQ:
649 return IntCmpCondition::kEQ;
650 default:
651 LOG_COMPILER(FATAL) << "unexpected cond!";
652 UNREACHABLE();
653 }
654 return IntCmpCondition::kEQ;
655 }
656
ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const657 FloatCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const
658 {
659 switch (cond) {
660 case FCmpCondition::OLT:
661 return FloatCmpCondition::kOLT;
662 case FCmpCondition::OLE:
663 return FloatCmpCondition::kOLE;
664 case FCmpCondition::OGT:
665 return FloatCmpCondition::kOGT;
666 case FCmpCondition::OGE:
667 return FloatCmpCondition::kOGE;
668 case FCmpCondition::ONE:
669 return FloatCmpCondition::kONE;
670 case FCmpCondition::OEQ:
671 return FloatCmpCondition::kOEQ;
672 default:
673 LOG_COMPILER(FATAL) << "unexpected cond!";
674 UNREACHABLE();
675 }
676 return FloatCmpCondition::kOEQ;
677 }
678
VisitCmp(GateRef gate,GateRef e1,GateRef e2)679 void LiteCGIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
680 {
681 Expr e1Value = GetExprFromGate(e1);
682 Expr e2Value = GetExprFromGate(e2);
683 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
684
685 [[maybe_unused]] auto e1ValCode = acc_.GetMachineType(e1);
686 [[maybe_unused]] auto e2ValCode = acc_.GetMachineType(e2);
687 ASSERT((e1ValCode == e2ValCode) ||
688 (compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) ||
689 (compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64)));
690 auto op = acc_.GetOpCode(gate);
691 if (op == OpCode::ICMP) {
692 auto cond = acc_.GetICmpCondition(gate);
693 auto litecgCond = ConvertLiteCGPredicateFromICMP(cond);
694 Expr result = lmirBuilder_->ICmp(returnType, e1Value, e2Value, litecgCond);
695 SaveGate2Expr(gate, result);
696 } else if (op == OpCode::FCMP) {
697 auto cond = acc_.GetFCmpCondition(gate);
698 auto litecgCond = ConvertLiteCGPredicateFromFCMP(cond);
699 Expr result = lmirBuilder_->FCmp(returnType, e1Value, e2Value, litecgCond);
700 SaveGate2Expr(gate, result);
701 } else {
702 LOG_ECMA(FATAL) << "this branch is unreachable";
703 UNREACHABLE();
704 }
705 }
706
HandleBranch(GateRef gate)707 void LiteCGIRBuilder::HandleBranch(GateRef gate)
708 {
709 std::vector<GateRef> ins;
710 acc_.GetIns(gate, ins);
711 std::vector<GateRef> outs;
712 acc_.GetOutStates(gate, outs);
713 GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1];
714 GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1];
715 int bbTrue = instID2bbID_[acc_.GetId(bTrue)];
716 int bbFalse = instID2bbID_[acc_.GetId(bFalse)];
717 VisitBranch(gate, ins[1], bbTrue, bbFalse);
718 }
719
VisitBranch(GateRef gate,GateRef cmp,int btrue,int bfalse)720 void LiteCGIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse)
721 {
722 if ((gate2Expr_.count(cmp) == 0) && (acc_.GetOpCode(cmp) != OpCode::CONSTANT)) {
723 OPTIONAL_LOG_COMPILER(ERROR) << "Branch condition gate is nullptr!";
724 return;
725 }
726 uint32_t trueWeight = 0;
727 uint32_t falseWeight = 0;
728 if (acc_.HasBranchWeight(gate)) {
729 trueWeight = acc_.GetTrueWeight(gate);
730 falseWeight = acc_.GetFalseWeight(gate);
731 }
732 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
733 lmirBuilder_->AppendBB(curBB);
734 BB &bb = CreateBB();
735 BB &trueBB = GetOrCreateBB(btrue);
736 BB &falseBB = GetOrCreateBB(bfalse);
737 // we hope that branch with higher probability can be placed immediatly behind
738 if (trueWeight < falseWeight) {
739 Stmt &stmt = lmirBuilder_->Goto(falseBB);
740 lmirBuilder_->AppendStmt(bb, stmt);
741 lmirBuilder_->AppendBB(bb);
742 Expr cond = GetExprFromGate(cmp);
743 Stmt &condBR = lmirBuilder_->CondGoto(cond, trueBB, true);
744 lmirBuilder_->AppendStmt(curBB, condBR);
745 return;
746 }
747 Stmt &stmt = lmirBuilder_->Goto(trueBB);
748 lmirBuilder_->AppendStmt(bb, stmt);
749 lmirBuilder_->AppendBB(bb);
750 Expr cond = GetExprFromGate(cmp);
751 Stmt &condBR = lmirBuilder_->CondGoto(cond, falseBB, false);
752 lmirBuilder_->AppendStmt(curBB, condBR);
753 }
754
HandleReturn(GateRef gate)755 void LiteCGIRBuilder::HandleReturn(GateRef gate)
756 {
757 std::vector<GateRef> ins;
758 acc_.GetIns(gate, ins);
759 VisitReturn(gate, 1, ins);
760 }
761
VisitReturn(GateRef gate,GateRef popCount,const std::vector<GateRef> & operands)762 void LiteCGIRBuilder::VisitReturn([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef popCount,
763 const std::vector<GateRef> &operands)
764 {
765 // [STATE] [DEPEND] [VALUE] [RETURN_LIST]
766 GateRef operand = operands[2]; // 2: skip 2 in gate that are not data gate
767 Expr returnValue = GetExprFromGate(operand);
768 Stmt &returnNode = lmirBuilder_->Return(returnValue);
769 BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
770 lmirBuilder_->AppendStmt(curBB, returnNode);
771 lmirBuilder_->AppendBB(curBB);
772 }
773
GetRTStubOffset(Expr glue,int index)774 Expr LiteCGIRBuilder::GetRTStubOffset(Expr glue, int index)
775 {
776 size_t slotOffset = JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit()) + index * slotSize_;
777 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(slotOffset));
778 return lmirBuilder_->ConstVal(constVal);
779 }
780
GetCoStubOffset(Expr glue,int index) const781 Expr LiteCGIRBuilder::GetCoStubOffset(Expr glue, int index) const
782 {
783 int offset =
784 JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) + static_cast<size_t>(index * slotSize_);
785 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(offset));
786 return lmirBuilder_->ConstVal(constVal);
787 }
788
HandleRuntimeCall(GateRef gate)789 void LiteCGIRBuilder::HandleRuntimeCall(GateRef gate)
790 {
791 std::vector<GateRef> ins;
792 acc_.GetIns(gate, ins);
793 VisitRuntimeCall(gate, ins);
794 };
795
ConvertLiteCGTypeFromVariableType(VariableType type) const796 LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromVariableType(VariableType type) const
797 {
798 std::map<VariableType, LiteCGType *> machineTypeMap = {
799 {VariableType::VOID(), lmirBuilder_->voidType},
800 {VariableType::BOOL(), lmirBuilder_->u1Type},
801 {VariableType::INT8(), lmirBuilder_->i8Type},
802 {VariableType::INT16(), lmirBuilder_->i16Type},
803 {VariableType::INT32(), lmirBuilder_->i32Type},
804 {VariableType::INT64(), lmirBuilder_->i64Type},
805 {VariableType::FLOAT32(), lmirBuilder_->f32Type},
806 {VariableType::FLOAT64(), lmirBuilder_->f64Type},
807 {VariableType::NATIVE_POINTER(), lmirBuilder_->i64Type},
808 {VariableType::JS_POINTER(), lmirBuilder_->i64RefType},
809 {VariableType::JS_ANY(), lmirBuilder_->i64RefType},
810 };
811 return machineTypeMap[type];
812 }
813
GenerateFuncType(const std::vector<Expr> & params,const CallSignature * stubDescriptor)814 LiteCGType *LiteCGIRBuilder::GenerateFuncType(const std::vector<Expr> ¶ms, const CallSignature *stubDescriptor)
815 {
816 LiteCGType *retType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType());
817 std::vector<LiteCGType *> paramTys;
818 for (auto value : params) {
819 paramTys.emplace_back(value.GetType());
820 }
821 LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, retType, false);
822 return functionType;
823 }
824
GetFuncType(const CallSignature * stubDescriptor) const825 LiteCGType *LiteCGIRBuilder::GetFuncType(const CallSignature *stubDescriptor) const
826 {
827 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType());
828 std::vector<LiteCGType *> paramTys;
829 auto paramCount = stubDescriptor->GetParametersCount();
830 auto paramsType = stubDescriptor->GetParametersType();
831 if (paramsType != nullptr) {
832 LiteCGType *glueType = ConvertLiteCGTypeFromVariableType(paramsType[0]);
833 paramTys.push_back(glueType);
834
835 for (size_t i = 1; i < paramCount; i++) {
836 paramTys.push_back(ConvertLiteCGTypeFromVariableType(paramsType[i]));
837 }
838 }
839 auto funcType = lmirBuilder_->CreateFuncType(paramTys, returnType, stubDescriptor->IsVariadicArgs());
840 return funcType;
841 }
842
GetFunction(BB & bb,Expr glue,const CallSignature * signature,Expr rtbaseoffset,const std::string & realName) const843 Expr LiteCGIRBuilder::GetFunction(BB &bb, Expr glue, const CallSignature *signature, Expr rtbaseoffset,
844 const std::string &realName) const
845 {
846 LiteCGType *rtfuncType = GetFuncType(signature);
847 LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType);
848 LiteCGType *rtFuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr);
849 LiteCGType *glueType = (glue.GetType());
850 LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType);
851 Expr rtbaseAddr = lmirBuilder_->Cvt(rtbaseoffset.GetType(), glueTypePtr, rtbaseoffset);
852
853 Expr funcAddr = lmirBuilder_->Iread(glueType, rtbaseAddr, glueTypePtr);
854 Expr callee = lmirBuilder_->Cvt(glueType, rtFuncTypePtrPtr, funcAddr);
855
856 std::string name = realName.empty() ? signature->GetName() : realName;
857 Stmt &comment = lmirBuilder_->Comment("function: " + name);
858 lmirBuilder_->AppendStmt(bb, comment);
859 PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType());
860 Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx);
861 lmirBuilder_->AppendStmt(bb, funcAddrNode);
862
863 return lmirBuilder_->Regread(funcPregIdx);
864 }
865
IsOptimizedJSFunction() const866 bool LiteCGIRBuilder::IsOptimizedJSFunction() const
867 {
868 return circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME;
869 }
870
IsOptimized() const871 bool LiteCGIRBuilder::IsOptimized() const
872 {
873 return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME;
874 }
875
GetCallExceptionKind(size_t index,OpCode op) const876 CallExceptionKind LiteCGIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const
877 {
878 bool hasPcOffset = IsOptimizedJSFunction() &&
879 ((op == OpCode::NOGC_RUNTIME_CALL && (kungfu::RuntimeStubCSigns::IsAsmStub(index))) ||
880 (op == OpCode::CALL) || (op == OpCode::RUNTIME_CALL));
881 return hasPcOffset ? CallExceptionKind::HAS_PC_OFFSET : CallExceptionKind::NO_PC_OFFSET;
882 }
883
VisitRuntimeCall(GateRef gate,const std::vector<GateRef> & inList)884 void LiteCGIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList)
885 {
886 StubIdType stubId = RTSTUB_ID(CallRuntime);
887 Expr glue = GetGlue(inList);
888 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
889 Expr rtoffset = GetRTStubOffset(glue, stubIndex);
890 Expr rtbaseOffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
891 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
892
893 CallExceptionKind kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL);
894 bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET);
895 size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size(); // 2: pcOffset and frameArgs
896
897 std::vector<Expr> params;
898 params.push_back(glue); // glue
899
900 const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)]));
901 Expr indexValue =
902 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(index)));
903 params.push_back(indexValue); // target
904
905 const int64_t argc = actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER);
906 Expr argcValue =
907 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(argc)));
908 params.push_back(argcValue); // argc
909
910 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) {
911 GateRef gateTmp = inList[paraIdx];
912 params.push_back(GetExprFromGate(gateTmp));
913 }
914
915 std::string targetName = RuntimeStubCSigns::GetRTName(index);
916 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
917 std::string name = targetName.empty() ? signature->GetName() : targetName;
918 Expr callee = GetFunction(bb, glue, signature, rtbaseOffset, name);
919
920 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType());
921 bool returnVoid = (returnType == lmirBuilder_->voidType);
922 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
923 Stmt &callNode =
924 returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx);
925
926 if (kind == CallExceptionKind::HAS_PC_OFFSET) {
927 std::unordered_map<int, LiteCGValue> deoptBundleInfo;
928 auto frameArgs = inList.at(actualNumArgs);
929 Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1]))
930 : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0));
931 CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs);
932 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
933 }
934 lmirBuilder_->SetStmtCallConv(callNode, maple::litecg::Web_Kit_JS_Call);
935 lmirBuilder_->AppendStmt(bb, callNode);
936 if (!returnVoid) {
937 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
938 }
939 }
940
HandleZExtInt(GateRef gate)941 void LiteCGIRBuilder::HandleZExtInt(GateRef gate)
942 {
943 std::vector<GateRef> ins;
944 acc_.GetIns(gate, ins);
945 VisitZExtInt(gate, ins[0]);
946 }
947
VisitZExtInt(GateRef gate,GateRef e1)948 void LiteCGIRBuilder::VisitZExtInt(GateRef gate, GateRef e1)
949 {
950 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
951 GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
952 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
953 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate, false);
954 Expr result = lmirBuilder_->ZExt(fromType, toType, GetExprFromGate(e1));
955 SaveGate2Expr(gate, result);
956 }
957
HandleIntDiv(GateRef gate)958 void LiteCGIRBuilder::HandleIntDiv(GateRef gate)
959 {
960 auto g0 = acc_.GetIn(gate, 0);
961 auto g1 = acc_.GetIn(gate, 1);
962 VisitIntDiv(gate, g0, g1);
963 }
964
VisitIntDiv(GateRef gate,GateRef e1,GateRef e2)965 void LiteCGIRBuilder::VisitIntDiv(GateRef gate, GateRef e1, GateRef e2)
966 {
967 Expr e1Value = GetExprFromGate(e1);
968 Expr e2Value = GetExprFromGate(e2);
969 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
970 Expr result = lmirBuilder_->SDiv(type, e1Value, e2Value);
971 SaveGate2Expr(gate, result);
972 }
973
GetCallee(maple::litecg::BB & bb,const std::vector<GateRef> & inList,const CallSignature * signature,const std::string & realName)974 Expr LiteCGIRBuilder::GetCallee(maple::litecg::BB &bb, const std::vector<GateRef> &inList,
975 const CallSignature *signature, const std::string &realName)
976 {
977 LiteCGType *rtfuncType = GetFuncType(signature);
978 LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType);
979 LiteCGType *rtfuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr);
980 Expr code = GetExprFromGate(inList[static_cast<size_t>(CallInputs::TARGET)]);
981 Expr callee = lmirBuilder_->Cvt(code.GetType(), rtfuncTypePtrPtr, code);
982
983 std::string name = realName.empty() ? signature->GetName() : realName;
984 Stmt &comment = lmirBuilder_->Comment("function: " + name);
985 lmirBuilder_->AppendStmt(bb, comment);
986
987 PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType());
988 Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx);
989 lmirBuilder_->AppendStmt(bb, funcAddrNode);
990 return lmirBuilder_->Regread(funcPregIdx);
991 }
992
HandleRuntimeCallWithArgv(GateRef gate)993 void LiteCGIRBuilder::HandleRuntimeCallWithArgv(GateRef gate)
994 {
995 std::vector<GateRef> ins;
996 acc_.GetIns(gate, ins);
997 VisitRuntimeCallWithArgv(gate, ins);
998 }
999
VisitRuntimeCallWithArgv(GateRef gate,const std::vector<GateRef> & inList)1000 void LiteCGIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList)
1001 {
1002 ASSERT(IsOptimized() == true);
1003 StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv);
1004 Expr glue = GetGlue(inList);
1005 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
1006 Expr rtoffset = GetRTStubOffset(glue, stubIndex);
1007 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1008 const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
1009
1010 std::vector<Expr> params;
1011 params.push_back(glue); // glue
1012
1013 uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]);
1014 auto targetId = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, index));
1015 params.push_back(targetId); // target
1016 for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
1017 GateRef gateTmp = inList[paraIdx];
1018 params.push_back(GetExprFromGate(gateTmp));
1019 }
1020
1021 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1022 std::string targetName = RuntimeStubCSigns::GetRTName(index);
1023 std::string name = targetName.empty() ? signature->GetName() : targetName;
1024 Expr callee = GetFunction(bb, glue, signature, rtbaseoffset, name);
1025
1026 static uint32_t val = 0;
1027 std::string returnCallValName = name + "Ret" + std::to_string(val++);
1028 LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType());
1029 Var *returnVar = (returnType == lmirBuilder_->voidType)
1030 ? nullptr
1031 : &(lmirBuilder_->CreateLocalVar(returnType, returnCallValName));
1032 Stmt &callNode = lmirBuilder_->ICall(callee, params, returnVar);
1033 lmirBuilder_->AppendStmt(bb, callNode);
1034 if (returnVar != nullptr) {
1035 SaveGate2Expr(gate, lmirBuilder_->Dread(*returnVar));
1036 }
1037 }
1038
HandleCall(GateRef gate)1039 void LiteCGIRBuilder::HandleCall(GateRef gate)
1040 {
1041 std::vector<GateRef> ins;
1042 acc_.GetIns(gate, ins);
1043 OpCode callOp = acc_.GetOpCode(gate);
1044 if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL || callOp == OpCode::BUILTINS_CALL ||
1045 callOp == OpCode::BUILTINS_CALL_WITH_ARGV || callOp == OpCode::CALL_OPTIMIZED ||
1046 callOp == OpCode::FAST_CALL_OPTIMIZED) {
1047 VisitCall(gate, ins, callOp);
1048 } else {
1049 LOG_ECMA(FATAL) << "this branch is unreachable";
1050 UNREACHABLE();
1051 }
1052 }
1053
VisitCall(GateRef gate,const std::vector<GateRef> & inList,OpCode op)1054 void LiteCGIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
1055 {
1056 size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
1057 static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3);
1058 const CallSignature *calleeDescriptor = nullptr;
1059 Expr glue = GetGlue(inList);
1060 Expr callee;
1061 CallExceptionKind kind = CallExceptionKind::NO_PC_OFFSET;
1062 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1063 if (op == OpCode::CALL) {
1064 const size_t index = acc_.GetConstantValue(inList[targetIndex]);
1065 calleeDescriptor = CommonStubCSigns::Get(index);
1066 Expr rtoffset = GetCoStubOffset(glue, index);
1067 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1068 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1069 kind = GetCallExceptionKind(index, op);
1070 } else if (op == OpCode::NOGC_RUNTIME_CALL) {
1071 UpdateLeaveFrame(glue);
1072 const size_t index = acc_.GetConstantValue(inList[targetIndex]);
1073 calleeDescriptor = RuntimeStubCSigns::Get(index);
1074 Expr rtoffset = GetRTStubOffset(glue, index);
1075 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1076 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1077 kind = GetCallExceptionKind(index, op);
1078 } else if (op == OpCode::CALL_OPTIMIZED) {
1079 calleeDescriptor = RuntimeStubCSigns::GetOptimizedCallSign();
1080 callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName());
1081 if (IsOptimizedJSFunction()) {
1082 kind = CallExceptionKind::HAS_PC_OFFSET;
1083 } else {
1084 kind = CallExceptionKind::NO_PC_OFFSET;
1085 }
1086 } else if (op == OpCode::FAST_CALL_OPTIMIZED) {
1087 calleeDescriptor = RuntimeStubCSigns::GetOptimizedFastCallSign();
1088 callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName());
1089 if (IsOptimizedJSFunction()) {
1090 kind = CallExceptionKind::HAS_PC_OFFSET;
1091 } else {
1092 kind = CallExceptionKind::NO_PC_OFFSET;
1093 }
1094 } else {
1095 ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV);
1096 Expr opcodeOffset = GetExprFromGate(inList[targetIndex]);
1097 Expr rtoffset = GetBuiltinsStubOffset(glue);
1098 Expr offset = lmirBuilder_->Add(rtoffset.GetType(), rtoffset, opcodeOffset);
1099 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, offset);
1100 if (op == OpCode::BUILTINS_CALL) {
1101 calleeDescriptor = BuiltinsStubCSigns::BuiltinsCSign();
1102 } else {
1103 calleeDescriptor = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
1104 }
1105 callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1106 }
1107
1108 std::vector<Expr> params;
1109 const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
1110 GateRef glueGate = inList[firstArg];
1111 params.push_back(GetExprFromGate(glueGate));
1112
1113 LiteCGType *calleeFuncType = lmirBuilder_->LiteCGGetPointedType(callee.GetType());
1114 std::vector<LiteCGType *> paramTypes = lmirBuilder_->LiteCGGetFuncParamTypes(calleeFuncType);
1115
1116 bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET);
1117 size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size(); // 2: pcOffset and frameArgs
1118
1119 // then push the actual parameter for js function call
1120 for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
1121 GateRef gateTmp = inList[paraIdx];
1122 Expr gateExpr = GetExprFromGate(gateTmp);
1123 const auto gateTmpType = gateExpr.GetType();
1124 if (params.size() < paramTypes.size()) { // this condition will be false for variadic arguments
1125 const auto paramType = paramTypes.at(params.size());
1126 // match parameter types and function signature types
1127 if (lmirBuilder_->IsHeapPointerType(paramType) && !lmirBuilder_->IsHeapPointerType(gateTmpType)) {
1128 Expr cvtI64Expr = lmirBuilder_->Cvt(gateTmpType, lmirBuilder_->i64Type, gateExpr);
1129 params.push_back(lmirBuilder_->Cvt(lmirBuilder_->i64Type, paramType, cvtI64Expr));
1130 } else {
1131 params.push_back(lmirBuilder_->Cvt(gateTmpType, paramType, gateExpr));
1132 }
1133 } else {
1134 params.push_back(gateExpr);
1135 }
1136 }
1137
1138 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(calleeFuncType);
1139 bool returnVoid = (returnType == lmirBuilder_->voidType);
1140 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
1141 Stmt &callNode =
1142 returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx);
1143 if (kind == CallExceptionKind::HAS_PC_OFFSET) {
1144 std::unordered_map<int, LiteCGValue> deoptBundleInfo;
1145 auto frameArgs = inList.at(actualNumArgs);
1146 Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1]))
1147 : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0));
1148 CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs);
1149 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
1150 }
1151 lmirBuilder_->SetStmtCallConv(callNode, ConvertCallAttr(calleeDescriptor->GetCallConv()));
1152 lmirBuilder_->AppendStmt(bb, callNode);
1153 if (!returnVoid) {
1154 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
1155 }
1156 }
1157
CollectExraCallSiteInfo(std::unordered_map<int,maple::litecg::LiteCGValue> & deoptBundleInfo,maple::litecg::Expr pcOffset,GateRef frameArgs)1158 void LiteCGIRBuilder::CollectExraCallSiteInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo,
1159 maple::litecg::Expr pcOffset, GateRef frameArgs)
1160 {
1161 // pc offset
1162 auto pcIndex = static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX);
1163 ASSERT(pcOffset.IsConstValue());
1164 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(
1165 pcIndex, {0, nullptr, lmirBuilder_->GetConstFromExpr(pcOffset), LiteCGValueKind::kConstKind}));
1166
1167 if (!enableOptInlining_) {
1168 return;
1169 }
1170
1171 if (frameArgs == Circuit::NullGate()) {
1172 return;
1173 }
1174 if (acc_.GetOpCode(frameArgs) != OpCode::FRAME_ARGS) {
1175 return;
1176 }
1177 uint32_t maxDepth = acc_.GetFrameDepth(frameArgs, OpCode::FRAME_ARGS);
1178 if (maxDepth == 0) {
1179 return;
1180 }
1181
1182 maxDepth = std::min(maxDepth, MAX_METHOD_OFFSET_NUM);
1183 size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM);
1184 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
1185 for (int32_t curDepth = static_cast<int32_t>(maxDepth - 1); curDepth >= 0; curDepth--) {
1186 ASSERT(acc_.GetOpCode(frameArgs) == OpCode::FRAME_ARGS);
1187 // method id
1188 uint32_t methodOffset = acc_.TryGetMethodOffset(frameArgs);
1189 frameArgs = acc_.GetFrameState(frameArgs);
1190 if (methodOffset == FrameStateOutput::INVALID_INDEX) {
1191 methodOffset = 0;
1192 }
1193 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - curDepth;
1194 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specCallTargetIndex, curDepth, shift);
1195 auto constMethodOffset = lmirBuilder_->GetConstFromExpr(
1196 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, methodOffset)));
1197 deoptBundleInfo.insert(
1198 std::pair<int, LiteCGValue>(encodeIndex, {0, nullptr, constMethodOffset, LiteCGValueKind::kConstKind}));
1199 }
1200 }
1201
ConvertCallAttr(const CallSignature::CallConv callConv)1202 maple::litecg::ConvAttr LiteCGIRBuilder::ConvertCallAttr(const CallSignature::CallConv callConv)
1203 {
1204 switch (callConv) {
1205 case CallSignature::CallConv::GHCCallConv: {
1206 return maple::litecg::GHC_Call;
1207 }
1208 case CallSignature::CallConv::WebKitJSCallConv: {
1209 return maple::litecg::Web_Kit_JS_Call;
1210 }
1211 default: {
1212 return maple::litecg::CCall;
1213 }
1214 }
1215 }
1216
GetBuiltinsStubOffset(Expr glue)1217 Expr LiteCGIRBuilder::GetBuiltinsStubOffset(Expr glue)
1218 {
1219 Const &constVal = lmirBuilder_->CreateIntConst(
1220 glue.GetType(), JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()));
1221 return lmirBuilder_->ConstVal(constVal);
1222 }
1223
UpdateLeaveFrame(Expr glue)1224 void LiteCGIRBuilder::UpdateLeaveFrame(Expr glue)
1225 {
1226 Expr leaveFrameOffset = GetLeaveFrameOffset(glue);
1227 Expr leaveFrameValue = lmirBuilder_->Add(glue.GetType(), glue, leaveFrameOffset);
1228 LiteCGType *glueType = glue.GetType();
1229 LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType);
1230 Expr leaveFrameAddr = lmirBuilder_->Cvt(leaveFrameValue.GetType(), glueTypePtr, leaveFrameValue);
1231 Expr fpAddr = CallingFp(true);
1232 Expr fp = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
1233
1234 lmirBuilder_->Iassign(fp, leaveFrameAddr, fp.GetType());
1235 }
1236
IsInterpreted() const1237 bool LiteCGIRBuilder::IsInterpreted() const
1238 {
1239 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
1240 }
1241
CallingFp(bool)1242 Expr LiteCGIRBuilder::CallingFp(bool /*isCaller*/)
1243 {
1244 ASSERT(!IsInterpreted());
1245 /* 0:calling 1:its caller */
1246 Function &func = lmirBuilder_->GetCurFunction();
1247 return lmirBuilder_->LiteCGGetPregFP(func);
1248 }
1249
GetLeaveFrameOffset(Expr glue)1250 Expr LiteCGIRBuilder::GetLeaveFrameOffset(Expr glue)
1251 {
1252 size_t slotOffset = JSThread::GlueData::GetLeaveFrameOffset(compCfg_->Is32Bit());
1253 Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int>(slotOffset));
1254 return lmirBuilder_->ConstVal(constVal);
1255 }
1256
HandleUDiv(GateRef gate)1257 void LiteCGIRBuilder::HandleUDiv(GateRef gate)
1258 {
1259 auto g0 = acc_.GetIn(gate, 0);
1260 auto g1 = acc_.GetIn(gate, 1);
1261 VisitUDiv(gate, g0, g1);
1262 }
1263
VisitUDiv(GateRef gate,GateRef e1,GateRef e2)1264 void LiteCGIRBuilder::VisitUDiv(GateRef gate, GateRef e1, GateRef e2)
1265 {
1266 Expr e1Value = GetExprFromGate(e1);
1267 Expr e2Value = GetExprFromGate(e2);
1268 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1269 Expr result = lmirBuilder_->UDiv(type, e1Value, e2Value);
1270 SaveGate2Expr(gate, result);
1271 }
1272
HandleIntAnd(GateRef gate)1273 void LiteCGIRBuilder::HandleIntAnd(GateRef gate)
1274 {
1275 auto g0 = acc_.GetIn(gate, 0);
1276 auto g1 = acc_.GetIn(gate, 1);
1277 VisitIntAnd(gate, g0, g1);
1278 }
1279
VisitIntAnd(GateRef gate,GateRef e1,GateRef e2)1280 void LiteCGIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2)
1281 {
1282 Expr e1Value = GetExprFromGate(e1);
1283 Expr e2Value = GetExprFromGate(e2);
1284 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1285 Expr result = lmirBuilder_->And(type, e1Value, e2Value);
1286 SaveGate2Expr(gate, result);
1287 }
1288
HandleIntOr(GateRef gate)1289 void LiteCGIRBuilder::HandleIntOr(GateRef gate)
1290 {
1291 auto g0 = acc_.GetIn(gate, 0);
1292 auto g1 = acc_.GetIn(gate, 1);
1293 VisitIntOr(gate, g0, g1);
1294 }
1295
VisitIntOr(GateRef gate,GateRef e1,GateRef e2)1296 void LiteCGIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2)
1297 {
1298 Expr e1Value = GetExprFromGate(e1);
1299 Expr e2Value = GetExprFromGate(e2);
1300 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1301 Expr result = lmirBuilder_->Or(type, e1Value, e2Value);
1302 SaveGate2Expr(gate, result);
1303 }
1304
HandleIntXor(GateRef gate)1305 void LiteCGIRBuilder::HandleIntXor(GateRef gate)
1306 {
1307 auto g0 = acc_.GetIn(gate, 0);
1308 auto g1 = acc_.GetIn(gate, 1);
1309 VisitIntXor(gate, g0, g1);
1310 }
1311
VisitIntXor(GateRef gate,GateRef e1,GateRef e2)1312 void LiteCGIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2)
1313 {
1314 Expr e1Value = GetExprFromGate(e1);
1315 Expr e2Value = GetExprFromGate(e2);
1316 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1317 Expr result = lmirBuilder_->Xor(type, e1Value, e2Value);
1318 SaveGate2Expr(gate, result);
1319 }
1320
HandleIntLsr(GateRef gate)1321 void LiteCGIRBuilder::HandleIntLsr(GateRef gate)
1322 {
1323 auto g0 = acc_.GetIn(gate, 0);
1324 auto g1 = acc_.GetIn(gate, 1);
1325 VisitIntLsr(gate, g0, g1);
1326 }
1327
VisitIntLsr(GateRef gate,GateRef e1,GateRef e2)1328 void LiteCGIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2)
1329 {
1330 Expr e1Value = GetExprFromGate(e1);
1331 Expr e2Value = GetExprFromGate(e2);
1332 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1333 Expr result = lmirBuilder_->LShr(type, e1Value, e2Value);
1334 SaveGate2Expr(gate, result);
1335 }
1336
HandleIntAsr(GateRef gate)1337 void LiteCGIRBuilder::HandleIntAsr(GateRef gate)
1338 {
1339 auto g0 = acc_.GetIn(gate, 0);
1340 auto g1 = acc_.GetIn(gate, 1);
1341 VisitIntAsr(gate, g0, g1);
1342 }
1343
VisitIntAsr(GateRef gate,GateRef e1,GateRef e2)1344 void LiteCGIRBuilder::VisitIntAsr(GateRef gate, GateRef e1, GateRef e2)
1345 {
1346 Expr e1Value = GetExprFromGate(e1);
1347 Expr e2Value = GetExprFromGate(e2);
1348 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1349 Expr result = lmirBuilder_->AShr(type, e1Value, e2Value);
1350 SaveGate2Expr(gate, result);
1351 }
1352
HandleBitCast(GateRef gate)1353 void LiteCGIRBuilder::HandleBitCast(GateRef gate)
1354 {
1355 VisitBitCast(gate, acc_.GetIn(gate, 0));
1356 }
1357
VisitBitCast(GateRef gate,GateRef e1)1358 void LiteCGIRBuilder::VisitBitCast(GateRef gate, GateRef e1)
1359 {
1360 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(gate)) ==
1361 GetBitWidthFromMachineType(acc_.GetMachineType(e1)));
1362 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
1363 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate);
1364 Expr e1Value = GetExprFromGate(e1);
1365 Expr result = lmirBuilder_->BitCast(fromType, toType, e1Value);
1366 SaveGate2Expr(gate, result);
1367 }
1368
HandleIntLsl(GateRef gate)1369 void LiteCGIRBuilder::HandleIntLsl(GateRef gate)
1370 {
1371 auto g0 = acc_.GetIn(gate, 0);
1372 auto g1 = acc_.GetIn(gate, 1);
1373 VisitIntLsl(gate, g0, g1);
1374 }
1375
VisitIntLsl(GateRef gate,GateRef e1,GateRef e2)1376 void LiteCGIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2)
1377 {
1378 Expr e1Value = GetExprFromGate(e1);
1379 Expr e2Value = GetExprFromGate(e2);
1380 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1381 Expr result = lmirBuilder_->Shl(type, e1Value, e2Value);
1382 SaveGate2Expr(gate, result);
1383 }
1384
HandleMod(GateRef gate)1385 void LiteCGIRBuilder::HandleMod(GateRef gate)
1386 {
1387 auto g0 = acc_.GetIn(gate, 0);
1388 auto g1 = acc_.GetIn(gate, 1);
1389 VisitMod(gate, g0, g1);
1390 }
1391
VisitMod(GateRef gate,GateRef e1,GateRef e2)1392 void LiteCGIRBuilder::VisitMod(GateRef gate, GateRef e1, GateRef e2)
1393 {
1394 Expr e1Value = GetExprFromGate(e1);
1395 Expr e2Value = GetExprFromGate(e2);
1396 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1397 ASSERT(type == ConvertLiteCGTypeFromGate(e1));
1398 ASSERT(type == ConvertLiteCGTypeFromGate(e2));
1399 auto machineType = acc_.GetMachineType(gate);
1400 Expr result;
1401 if (machineType == MachineType::I32) {
1402 result = lmirBuilder_->SRem(type, e1Value, e2Value);
1403 } else if (machineType != MachineType::F64) {
1404 LOG_ECMA(FATAL) << "this branch is unreachable";
1405 UNREACHABLE();
1406 }
1407 SaveGate2Expr(gate, result);
1408 }
1409
HandleCastIntXToIntY(GateRef gate)1410 void LiteCGIRBuilder::HandleCastIntXToIntY(GateRef gate)
1411 {
1412 VisitCastIntXToIntY(gate, acc_.GetIn(gate, 0));
1413 }
1414
VisitCastIntXToIntY(GateRef gate,GateRef e1)1415 void LiteCGIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1)
1416 {
1417 Expr e1Value = GetExprFromGate(e1);
1418 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
1419 GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1420 auto e1Type = ConvertLiteCGTypeFromGate(e1);
1421 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1422 SaveGate2Expr(gate, result);
1423 }
1424
HandleChangeInt32ToDouble(GateRef gate)1425 void LiteCGIRBuilder::HandleChangeInt32ToDouble(GateRef gate)
1426 {
1427 VisitChangeInt32ToDouble(gate, acc_.GetIn(gate, 0));
1428 }
1429
VisitChangeInt32ToDouble(GateRef gate,GateRef e1)1430 void LiteCGIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1)
1431 {
1432 Expr e1Value = GetExprFromGate(e1);
1433 auto e1Type = ConvertLiteCGTypeFromGate(e1);
1434 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1435 SaveGate2Expr(gate, result);
1436 }
1437
HandleChangeUInt32ToDouble(GateRef gate)1438 void LiteCGIRBuilder::HandleChangeUInt32ToDouble(GateRef gate)
1439 {
1440 VisitChangeUInt32ToDouble(gate, acc_.GetIn(gate, 0));
1441 }
1442
VisitChangeUInt32ToDouble(GateRef gate,GateRef e1)1443 void LiteCGIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1)
1444 {
1445 Expr e1Value = GetExprFromGate(e1);
1446 auto e1Type = ConvertLiteCGTypeFromGate(e1);
1447 if (e1Type == lmirBuilder_->i32Type) {
1448 e1Value = lmirBuilder_->Cvt(e1Type, lmirBuilder_->u32Type, e1Value);
1449 }
1450 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1451 SaveGate2Expr(gate, result);
1452 }
1453
HandleChangeDoubleToInt32(GateRef gate)1454 void LiteCGIRBuilder::HandleChangeDoubleToInt32(GateRef gate)
1455 {
1456 VisitChangeDoubleToInt32(gate, acc_.GetIn(gate, 0));
1457 }
1458
VisitChangeDoubleToInt32(GateRef gate,GateRef e1)1459 void LiteCGIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1)
1460 {
1461 Expr e1Value = GetExprFromGate(e1);
1462 auto e1Type = ConvertLiteCGTypeFromGate(e1);
1463 Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1464 SaveGate2Expr(gate, result);
1465 }
1466
HandleChangeTaggedPointerToInt64(GateRef gate)1467 void LiteCGIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate)
1468 {
1469 VisitChangeTaggedPointerToInt64(gate, acc_.GetIn(gate, 0));
1470 }
1471
VisitChangeTaggedPointerToInt64(GateRef gate,GateRef e1)1472 void LiteCGIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1)
1473 {
1474 Expr result = CanonicalizeToInt(e1);
1475 SaveGate2Expr(gate, result);
1476 }
1477
CanonicalizeToInt(GateRef gate)1478 Expr LiteCGIRBuilder::CanonicalizeToInt(GateRef gate)
1479 {
1480 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1481 Expr opnd = GetExprFromGate(gate);
1482 if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) {
1483 return lmirBuilder_->Cvt(type, lmirBuilder_->i64Type, opnd);
1484 } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) {
1485 return opnd;
1486 } else {
1487 LOG_COMPILER(FATAL) << "can't Canonicalize to Int64: ";
1488 UNREACHABLE();
1489 }
1490 }
1491
HandleChangeInt64ToTagged(GateRef gate)1492 void LiteCGIRBuilder::HandleChangeInt64ToTagged(GateRef gate)
1493 {
1494 VisitChangeInt64ToTagged(gate, acc_.GetIn(gate, 0));
1495 }
1496
VisitChangeInt64ToTagged(GateRef gate,GateRef e1)1497 void LiteCGIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1)
1498 {
1499 Expr e1Value = GetExprFromGate(e1);
1500 ASSERT(lmirBuilder_->LiteCGGetTypeKind(ConvertLiteCGTypeFromGate(e1)) == maple::litecg::kLiteCGTypeScalar);
1501 Expr result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, e1Value);
1502 SaveGate2Expr(gate, result);
1503 }
1504
HandleSub(GateRef gate)1505 void LiteCGIRBuilder::HandleSub(GateRef gate)
1506 {
1507 auto g0 = acc_.GetIn(gate, 0);
1508 auto g1 = acc_.GetIn(gate, 1);
1509 VisitSub(gate, g0, g1);
1510 }
1511
VisitSub(GateRef gate,GateRef e1,GateRef e2)1512 void LiteCGIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2)
1513 {
1514 Expr e1Value = GetExprFromGate(e1);
1515 Expr e2Value = GetExprFromGate(e2);
1516 Expr result;
1517 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1518 auto machineType = acc_.GetMachineType(gate);
1519 if (machineType == MachineType::I16 || machineType == MachineType::I32 || machineType == MachineType::I64 ||
1520 machineType == MachineType::ARCH || machineType == MachineType::F64) {
1521 result = lmirBuilder_->Sub(returnType, e1Value, e2Value);
1522 } else {
1523 LOG_ECMA(FATAL) << "this branch is unreachable";
1524 UNREACHABLE();
1525 }
1526 SaveGate2Expr(gate, result);
1527 }
1528
HandleMul(GateRef gate)1529 void LiteCGIRBuilder::HandleMul(GateRef gate)
1530 {
1531 auto g0 = acc_.GetIn(gate, 0);
1532 auto g1 = acc_.GetIn(gate, 1);
1533 VisitMul(gate, g0, g1);
1534 }
1535
VisitMul(GateRef gate,GateRef e1,GateRef e2)1536 void LiteCGIRBuilder::VisitMul(GateRef gate, GateRef e1, GateRef e2)
1537 {
1538 Expr e1Value = GetExprFromGate(e1);
1539 Expr e2Value = GetExprFromGate(e2);
1540 Expr result;
1541 LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1542 auto machineType = acc_.GetMachineType(gate);
1543 if (IsMulIntergerType(machineType)) {
1544 result = lmirBuilder_->Mul(returnType, e1Value, e2Value);
1545 } else if (machineType == MachineType::F64) {
1546 result = lmirBuilder_->Mul(returnType, e1Value, e2Value);
1547 } else {
1548 LOG_ECMA(FATAL) << "this branch is unreachable";
1549 UNREACHABLE();
1550 }
1551 SaveGate2Expr(gate, result);
1552 }
1553
HandleIntRev(GateRef gate)1554 void LiteCGIRBuilder::HandleIntRev(GateRef gate)
1555 {
1556 std::vector<GateRef> ins;
1557 acc_.GetIns(gate, ins);
1558 VisitIntRev(gate, ins[0]);
1559 }
1560
VisitIntRev(GateRef gate,GateRef e1)1561 void LiteCGIRBuilder::VisitIntRev(GateRef gate, GateRef e1)
1562 {
1563 Expr e1Value = GetExprFromGate(e1);
1564 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1565 ASSERT(type == ConvertLiteCGTypeFromGate(e1));
1566 Expr result;
1567 auto machineType = acc_.GetMachineType(gate);
1568 if (machineType <= MachineType::I64 && machineType >= MachineType::I1) {
1569 if (machineType == MachineType::I1) {
1570 result = lmirBuilder_->Lnot(type, e1Value);
1571 } else {
1572 result = lmirBuilder_->Bnot(type, e1Value);
1573 }
1574 } else {
1575 LOG_ECMA(FATAL) << "this branch is unreachable";
1576 UNREACHABLE();
1577 }
1578 SaveGate2Expr(gate, result);
1579 }
1580
HandleFloatDiv(GateRef gate)1581 void LiteCGIRBuilder::HandleFloatDiv(GateRef gate)
1582 {
1583 auto g0 = acc_.GetIn(gate, 0);
1584 auto g1 = acc_.GetIn(gate, 1);
1585 VisitFloatDiv(gate, g0, g1);
1586 }
1587
VisitFloatDiv(GateRef gate,GateRef e1,GateRef e2)1588 void LiteCGIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2)
1589 {
1590 Expr e1Value = GetExprFromGate(e1);
1591 Expr e2Value = GetExprFromGate(e2);
1592 Expr result = lmirBuilder_->SDiv(ConvertLiteCGTypeFromGate(gate), e1Value, e2Value);
1593 SaveGate2Expr(gate, result);
1594 }
1595
HandleTruncFloatToInt(GateRef gate)1596 void LiteCGIRBuilder::HandleTruncFloatToInt(GateRef gate)
1597 {
1598 auto g0 = acc_.GetIn(gate, 0);
1599 VisitTruncFloatToInt(gate, g0);
1600 }
1601
VisitTruncFloatToInt(GateRef gate,GateRef e1)1602 void LiteCGIRBuilder::VisitTruncFloatToInt(GateRef gate, GateRef e1)
1603 {
1604 Expr e1Value = GetExprFromGate(e1);
1605 auto machineType = acc_.GetMachineType(e1);
1606 Expr result;
1607 if (machineType <= MachineType::F64 && machineType >= MachineType::F32) {
1608 result = lmirBuilder_->Trunc(ConvertLiteCGTypeFromGate(e1), lmirBuilder_->i64Type, e1Value);
1609 } else {
1610 LOG_ECMA(FATAL) << "this branch is unreachable";
1611 UNREACHABLE();
1612 }
1613 SaveGate2Expr(gate, result);
1614 }
1615
HandleAddWithOverflow(GateRef gate)1616 void LiteCGIRBuilder::HandleAddWithOverflow(GateRef gate)
1617 {
1618 auto in0 = acc_.GetIn(gate, 0);
1619 auto in1 = acc_.GetIn(gate, 1);
1620 ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
1621 ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
1622 VisitAddWithOverflow(gate, in0, in1);
1623 }
1624
VisitAddWithOverflow(GateRef gate,GateRef e1,GateRef e2)1625 void LiteCGIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2)
1626 {
1627 // need use different symbol name?
1628 // get return type {i32 res, u1 carry}
1629 auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
1630 retType = retType ? retType
1631 : lmirBuilder_->CreateStructType("overflow_internal@i32")
1632 .Field("res", lmirBuilder_->i32Type)
1633 .Field("carry", lmirBuilder_->u1Type)
1634 .Done();
1635 static uint32_t val = 0;
1636 std::string retVarName = "add_overflow_ret@i32" + std::to_string(val++);
1637 Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
1638
1639 // generate function call
1640 Expr e1Value = GetExprFromGate(e1);
1641 Expr e2Value = GetExprFromGate(e2);
1642 std::vector<Expr> args = {e1Value, e2Value};
1643 auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_ADD_WITH_OVERFLOW, args, &retVar);
1644 SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
1645 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
1646 }
1647
HandleSubWithOverflow(GateRef gate)1648 void LiteCGIRBuilder::HandleSubWithOverflow(GateRef gate)
1649 {
1650 auto in0 = acc_.GetIn(gate, 0);
1651 auto in1 = acc_.GetIn(gate, 1);
1652 ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
1653 ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
1654 VisitSubWithOverflow(gate, in0, in1);
1655 }
1656
VisitSubWithOverflow(GateRef gate,GateRef e1,GateRef e2)1657 void LiteCGIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2)
1658 {
1659 // need use different symbol name?
1660 // get return type {i32 res, u1 carry}
1661 auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
1662 retType = retType ? retType
1663 : lmirBuilder_->CreateStructType("overflow_internal@i32")
1664 .Field("res", lmirBuilder_->i32Type)
1665 .Field("carry", lmirBuilder_->u1Type)
1666 .Done();
1667 static uint32_t val = 0;
1668 std::string retVarName = "sub_overflow_ret@i32" + std::to_string(val++);
1669 Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
1670
1671 // generate function call
1672 Expr e1Value = GetExprFromGate(e1);
1673 Expr e2Value = GetExprFromGate(e2);
1674 std::vector<Expr> args = {e1Value, e2Value};
1675 auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_SUB_WITH_OVERFLOW, args, &retVar);
1676 SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
1677 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
1678 }
1679
HandleMulWithOverflow(GateRef gate)1680 void LiteCGIRBuilder::HandleMulWithOverflow(GateRef gate)
1681 {
1682 auto in0 = acc_.GetIn(gate, 0);
1683 auto in1 = acc_.GetIn(gate, 1);
1684 ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
1685 ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
1686 VisitMulWithOverflow(gate, in0, in1);
1687 }
1688
VisitMulWithOverflow(GateRef gate,GateRef e1,GateRef e2)1689 void LiteCGIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2)
1690 {
1691 // need use different symbol name?
1692 // get return type {i32 res, u1 carry}
1693 auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
1694 retType = retType ? retType
1695 : lmirBuilder_->CreateStructType("overflow_internal@i32")
1696 .Field("res", lmirBuilder_->i32Type)
1697 .Field("carry", lmirBuilder_->u1Type)
1698 .Done();
1699 static uint32_t val = 0;
1700 std::string retVarName = "mul_overflow_ret@i32" + std::to_string(val++);
1701 Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
1702
1703 // generate function call
1704 Expr e1Value = GetExprFromGate(e1);
1705 Expr e2Value = GetExprFromGate(e2);
1706 std::vector<Expr> args = {e1Value, e2Value};
1707 auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_MUL_WITH_OVERFLOW, args, &retVar);
1708 SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
1709 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
1710 }
1711
HandleSExtInt(GateRef gate)1712 void LiteCGIRBuilder::HandleSExtInt(GateRef gate)
1713 {
1714 std::vector<GateRef> ins;
1715 acc_.GetIns(gate, ins);
1716 VisitSExtInt(gate, ins[0]);
1717 }
1718
VisitSExtInt(GateRef gate,GateRef e1)1719 void LiteCGIRBuilder::VisitSExtInt(GateRef gate, GateRef e1)
1720 {
1721 Expr e1Value = GetExprFromGate(e1);
1722 LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
1723 LiteCGType *toType = ConvertLiteCGTypeFromGate(gate);
1724 Expr result = lmirBuilder_->SExt(fromType, toType, e1Value);
1725 SaveGate2Expr(gate, result);
1726 }
1727
HandleSqrt(GateRef gate)1728 void LiteCGIRBuilder::HandleSqrt(GateRef gate)
1729 {
1730 GateRef param = acc_.GetIn(gate, 0);
1731 VisitSqrt(gate, param);
1732 }
1733
VisitSqrt(GateRef gate,GateRef e1)1734 void LiteCGIRBuilder::VisitSqrt(GateRef gate, GateRef e1)
1735 {
1736 Expr e1Value = GetExprFromGate(e1);
1737 LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
1738 Expr result;
1739 if (type == lmirBuilder_->f32Type || type == lmirBuilder_->f64Type) {
1740 result = lmirBuilder_->Sqrt(type, e1Value);
1741 } else {
1742 result = lmirBuilder_->Sqrt(lmirBuilder_->f64Type, lmirBuilder_->Cvt(type, lmirBuilder_->f64Type, e1Value));
1743 }
1744 SaveGate2Expr(gate, result);
1745 }
1746
HandleReadSp(GateRef gate)1747 void LiteCGIRBuilder::HandleReadSp(GateRef gate)
1748 {
1749 ASSERT(acc_.GetOpCode(gate) == OpCode::READSP);
1750 VisitReadSp(gate);
1751 }
1752
VisitReadSp(GateRef gate)1753 void LiteCGIRBuilder::VisitReadSp(GateRef gate)
1754 {
1755 Expr result = lmirBuilder_->LiteCGGetPregSP();
1756 SaveGate2Expr(gate, result);
1757 }
1758
HandleFPTrunc(GateRef gate)1759 void LiteCGIRBuilder::HandleFPTrunc(GateRef gate)
1760 {
1761 VisitFPTrunc(gate, acc_.GetIn(gate, 0));
1762 }
1763
VisitFPTrunc(GateRef gate,GateRef e1)1764 void LiteCGIRBuilder::VisitFPTrunc(GateRef gate, GateRef e1)
1765 {
1766 Expr e1Value = GetExprFromGate(e1);
1767 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
1768 GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1769 Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value);
1770 SaveGate2Expr(gate, result);
1771 }
1772
HandleFPExt(GateRef gate)1773 void LiteCGIRBuilder::HandleFPExt(GateRef gate)
1774 {
1775 VisitFPExt(gate, acc_.GetIn(gate, 0));
1776 }
1777
VisitFPExt(GateRef gate,GateRef e1)1778 void LiteCGIRBuilder::VisitFPExt(GateRef gate, GateRef e1)
1779 {
1780 Expr e1Value = GetExprFromGate(e1);
1781 ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
1782 GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1783 Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value);
1784 SaveGate2Expr(gate, result);
1785 }
1786
HandleExtractValue(GateRef gate)1787 void LiteCGIRBuilder::HandleExtractValue(GateRef gate)
1788 {
1789 GateRef pointer = acc_.GetIn(gate, 0);
1790 GateRef index = acc_.GetIn(gate, 1);
1791 VisitExtractValue(gate, pointer, index);
1792 }
1793
VisitExtractValue(GateRef gate,GateRef e1,GateRef e2)1794 void LiteCGIRBuilder::VisitExtractValue(GateRef gate, GateRef e1, GateRef e2)
1795 {
1796 Expr e1Value = GetExprFromGate(e1);
1797 ASSERT((acc_.GetOpCode(e2) == OpCode::CONSTANT) && acc_.GetMachineType(e2) == MachineType::I32);
1798 uint32_t index = static_cast<uint32_t>(acc_.GetConstantValue(e2));
1799 Var *baseVar = lmirBuilder_->GetLocalVarFromExpr(e1Value);
1800 ASSERT(baseVar != nullptr);
1801 // in maple type system, field 0 means the agg itself and field index start from 1
1802 Expr rhs = lmirBuilder_->DreadWithField(*baseVar, index + 1);
1803 PregIdx pregIdx = lmirBuilder_->CreatePreg(rhs.GetType());
1804 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), lmirBuilder_->Regassign(rhs, pregIdx));
1805 SaveGate2Expr(gate, lmirBuilder_->Regread(pregIdx));
1806 }
1807
HandleStore(GateRef gate)1808 void LiteCGIRBuilder::HandleStore(GateRef gate)
1809 {
1810 VisitStore(gate, acc_.GetIn(gate, 2), acc_.GetIn(gate, 1)); // 2:baseAddr gate, 1:data gate
1811 }
1812
VisitStore(GateRef gate,GateRef base,GateRef value)1813 void LiteCGIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef value)
1814 {
1815 Expr baseAddr = GetExprFromGate(base);
1816 Expr data = GetExprFromGate(value);
1817
1818 LiteCGType *returnType = ConvertLiteCGTypeFromGate(value);
1819 LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(baseAddr.GetType()))
1820 ? lmirBuilder_->CreateRefType(returnType)
1821 : lmirBuilder_->CreatePtrType(returnType);
1822 baseAddr = CanonicalizeToPtr(baseAddr, memType);
1823
1824 Stmt &store = lmirBuilder_->Iassign(data, baseAddr, memType);
1825 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), store);
1826 }
1827
HandlePhi(GateRef gate)1828 void LiteCGIRBuilder::HandlePhi(GateRef gate)
1829 {
1830 std::vector<GateRef> ins;
1831 acc_.GetIns(gate, ins);
1832 VisitPhi(gate, ins);
1833 }
1834
AddPhiDesc(int bbID,PhiDesc & desc)1835 void LiteCGIRBuilder::AddPhiDesc(int bbID, PhiDesc &desc)
1836 {
1837 auto it = bbID2unmergedPhis_.find(bbID);
1838 if (it == bbID2unmergedPhis_.end()) {
1839 std::vector<PhiDesc> vec;
1840 vec.push_back(std::move(desc));
1841 bbID2unmergedPhis_.insert(std::make_pair(bbID, vec));
1842 } else {
1843 it->second.push_back(std::move(desc));
1844 }
1845 }
1846
VisitPhi(GateRef gate,const std::vector<GateRef> & phiIns)1847 void LiteCGIRBuilder::VisitPhi(GateRef gate, const std::vector<GateRef> &phiIns)
1848 {
1849 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1850 PregIdx phiPregIdx = lmirBuilder_->CreatePreg(type);
1851
1852 if (phiIns.size() > 1) {
1853 SaveGate2Expr(gate, lmirBuilder_->Regread(phiPregIdx));
1854 }
1855 // Collect the states merges of this phi and note the 1-in is the merged states.
1856 std::vector<GateRef> phiStates;
1857 acc_.GetIns(phiIns[0], phiStates);
1858 ASSERT(phiStates.size() + 1 == phiIns.size());
1859 int curBBId = instID2bbID_[acc_.GetId(gate)];
1860 for (int i = 1; i < static_cast<int>(phiIns.size()); i++) {
1861 int preBBId = LookupPredBB(phiStates[i - 1], curBBId);
1862 // if bbID2BB_.count(preBBId) = 0 means bb with current bbIdx hasn't been created
1863 if (bbID2BB_.count(preBBId) != 0) {
1864 BB *preBB = bbID2BB_[preBBId];
1865 if (preBB == nullptr) {
1866 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed BasicBlock nullptr";
1867 return;
1868 }
1869 PhiDesc desc = {preBBId, phiIns[i], phiPregIdx};
1870 AddPhiDesc(curBBId, desc);
1871 } else {
1872 PhiDesc desc = {preBBId, phiIns[i], phiPregIdx};
1873 AddPhiDesc(curBBId, desc);
1874 }
1875 }
1876 }
1877
HandleSwitch(GateRef gate)1878 void LiteCGIRBuilder::HandleSwitch(GateRef gate)
1879 {
1880 std::vector<GateRef> ins;
1881 acc_.GetIns(gate, ins);
1882 std::vector<GateRef> outs;
1883 acc_.GetOutStates(gate, outs);
1884 VisitSwitch(gate, ins[1], outs);
1885 }
1886
VisitSwitch(GateRef gate,GateRef input,const std::vector<GateRef> & outList)1887 void LiteCGIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<GateRef> &outList)
1888 {
1889 Expr cond = GetExprFromGate(input);
1890 int caseNum = static_cast<int>(outList.size());
1891 BB *defaultOutBB = nullptr;
1892 for (int i = 0; i < caseNum; i++) {
1893 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
1894 defaultOutBB = &GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]);
1895 }
1896 }
1897
1898 LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1899 SwitchBuilder builder = lmirBuilder_->Switch(type, cond, *defaultOutBB);
1900 for (int i = 0; i < caseNum; i++) {
1901 if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
1902 continue;
1903 }
1904 BB &curOutBB = GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]);
1905 builder.Case(i, curOutBB);
1906 }
1907 Stmt &switchStmt = builder.Done();
1908 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), switchStmt);
1909 lmirBuilder_->AppendBB(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]));
1910 }
1911
HandleBytecodeCall(GateRef gate)1912 void LiteCGIRBuilder::HandleBytecodeCall(GateRef gate)
1913 {
1914 std::vector<GateRef> ins;
1915 acc_.GetIns(gate, ins);
1916 VisitBytecodeCall(gate, ins);
1917 }
1918
GetBaseOffset(GateRef gate,Expr glue)1919 Expr LiteCGIRBuilder::GetBaseOffset(GateRef gate, Expr glue)
1920 {
1921 switch (acc_.GetOpCode(gate)) {
1922 case OpCode::BYTECODE_CALL:
1923 return GetBCStubOffset(glue);
1924 case OpCode::DEBUGGER_BYTECODE_CALL:
1925 return GetBCDebugStubOffset(glue);
1926 default:
1927 LOG_ECMA(FATAL) << "this branch is unreachable";
1928 UNREACHABLE();
1929 }
1930 }
1931
GetBCStubOffset(Expr glue)1932 Expr LiteCGIRBuilder::GetBCStubOffset(Expr glue)
1933 {
1934 return lmirBuilder_->ConstVal(
1935 lmirBuilder_->CreateIntConst(glue.GetType(), JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit())));
1936 }
1937
GetBCDebugStubOffset(Expr glue)1938 Expr LiteCGIRBuilder::GetBCDebugStubOffset(Expr glue)
1939 {
1940 return lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(
1941 glue.GetType(), JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit())));
1942 }
1943
VisitBytecodeCall(GateRef gate,const std::vector<GateRef> & inList)1944 void LiteCGIRBuilder::VisitBytecodeCall(GateRef gate, const std::vector<GateRef> &inList)
1945 {
1946 size_t paraStartIndex = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
1947 size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
1948 size_t glueIndex = static_cast<size_t>(CallInputs::GLUE);
1949 Expr opcodeOffset = GetExprFromGate(inList[targetIndex]);
1950
1951 // start index of bytecode handler csign
1952 Expr glue = GetExprFromGate(inList[glueIndex]);
1953 Expr baseOffset = GetBaseOffset(gate, glue);
1954 Expr offset = lmirBuilder_->Add(baseOffset.GetType(), baseOffset, opcodeOffset);
1955 Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, offset);
1956 const CallSignature *signature = BytecodeStubCSigns::BCHandler();
1957 BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1958 Expr callee = GetFunction(bb, glue, signature, rtbaseoffset);
1959
1960 std::vector<Expr> params;
1961 for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) {
1962 GateRef gateTmp = inList[paraIdx];
1963 params.push_back(GetExprFromGate(gateTmp));
1964 }
1965
1966 LiteCGType *funcType = GenerateFuncType(params, signature);
1967 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
1968 static uint32_t retNo = 0;
1969 std::string retName = signature->GetName() + "Ret" + std::to_string(retNo++);
1970 Var *returnVar =
1971 (returnType == lmirBuilder_->voidType) ? nullptr : &(lmirBuilder_->CreateLocalVar(returnType, retName));
1972 Stmt &callNode = lmirBuilder_->ICall(callee, params, returnVar);
1973 lmirBuilder_->AppendStmt(bb, callNode);
1974 if (returnVar != nullptr) {
1975 SaveGate2Expr(gate, lmirBuilder_->Dread(*returnVar));
1976 }
1977
1978 lmirBuilder_->SetStmtCallConv(callNode, maple::litecg::GHC_Call);
1979 }
1980
HandleDeoptCheck(GateRef gate)1981 void LiteCGIRBuilder::HandleDeoptCheck(GateRef gate)
1982 {
1983 int block = instID2bbID_[acc_.GetId(gate)];
1984 std::vector<GateRef> outs;
1985 acc_.GetOutStates(gate, outs);
1986 int bbOut = instID2bbID_[acc_.GetId(outs[0])]; // 0: output
1987
1988 BB &trueBB = GetOrCreateBB(bbOut);
1989 BB &falseBB = lmirBuilder_->CreateBB();
1990 GateRef cmp = acc_.GetValueIn(gate, 0); // 0: cond
1991 Expr cond = GetExprFromGate(cmp);
1992 BB &curBB = GetOrCreateBB(block);
1993 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->CondGoto(cond, falseBB, false));
1994 lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Goto(trueBB));
1995 lmirBuilder_->AppendBB(curBB);
1996 // deopt branch is not expected to be token as often,
1997 // just put them to the end of the function
1998 lmirBuilder_->AppendToLast(falseBB);
1999
2000 VisitDeoptCheck(gate);
2001 Expr returnValue = GetExprFromGate(gate);
2002 lmirBuilder_->AppendStmt(falseBB, lmirBuilder_->Return(returnValue));
2003 }
2004
GetExperimentalDeoptTy()2005 LiteCGType *LiteCGIRBuilder::GetExperimentalDeoptTy()
2006 {
2007 std::vector<LiteCGType *> paramTys = {lmirBuilder_->i64Type, lmirBuilder_->i64RefType, lmirBuilder_->i64RefType};
2008 LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, lmirBuilder_->i64RefType, false);
2009 return functionType;
2010 }
2011
SaveFrameTypeOnFrame(BB & bb,FrameType frameType)2012 void LiteCGIRBuilder::SaveFrameTypeOnFrame(BB &bb, FrameType frameType)
2013 {
2014 Expr llvmFpAddr = CallingFp(false);
2015 Expr frameAddr = lmirBuilder_->Cvt(llvmFpAddr.GetType(), slotType_, llvmFpAddr);
2016 Expr frameTypeSlotAddr = lmirBuilder_->Sub(
2017 slotType_, frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_)));
2018 LiteCGType *slotTypePtr = lmirBuilder_->CreatePtrType(slotType_);
2019 Expr addr = lmirBuilder_->Cvt(frameTypeSlotAddr.GetType(), slotTypePtr, frameTypeSlotAddr);
2020 Expr llvmFrameType =
2021 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, static_cast<uintptr_t>(frameType)));
2022 Stmt &stmt = lmirBuilder_->Iassign(llvmFrameType, addr, slotTypePtr);
2023 lmirBuilder_->AppendStmt(bb, stmt);
2024 }
2025
GenDeoptEntry(std::string funcName)2026 void LiteCGIRBuilder::GenDeoptEntry(std::string funcName)
2027 {
2028 BB &bb = CreateBB();
2029 auto reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
2030 lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
2031 SaveFrameTypeOnFrame(bb, FrameType::OPTIMIZED_FRAME);
2032 Function &func = lmirBuilder_->GetCurFunction();
2033 lmirModule_->SetFunction(LMIRModule::kDeoptEntryOffset, funcName, false);
2034
2035 Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 0));
2036 Expr check = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 1));
2037 Expr depth = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 2));
2038
2039 StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm);
2040 int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
2041 Expr rtoffset = lmirBuilder_->Add(glue.GetType(), glue, GetRTStubOffset(glue, stubIndex));
2042 Expr patchAddr = lmirBuilder_->Cvt(glue.GetType(), lmirBuilder_->i64PtrType, rtoffset);
2043 Expr funcAddr = lmirBuilder_->Iread(rtoffset.GetType(), patchAddr, lmirBuilder_->i64PtrType);
2044
2045 LiteCGType *funcType = GetExperimentalDeoptTy();
2046 LiteCGType *funcTypePtr = lmirBuilder_->CreatePtrType(funcType);
2047 LiteCGType *funcTypePtrPtr = lmirBuilder_->CreatePtrType(funcTypePtr);
2048 Expr callee = lmirBuilder_->Cvt(glue.GetType(), funcTypePtrPtr, funcAddr);
2049
2050 Var &funcVar = lmirBuilder_->CreateLocalVar(callee.GetType(), "DeoptimizeSubFunc");
2051 Stmt &funcAddrNode = lmirBuilder_->Dassign(callee, funcVar);
2052 lmirBuilder_->AppendStmt(bb, funcAddrNode);
2053
2054 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
2055 PregIdx pregIdx = lmirBuilder_->CreatePreg(returnType);
2056 std::vector<Expr> params = {glue, check, depth};
2057 Stmt &callNode = lmirBuilder_->ICall(lmirBuilder_->Dread(funcVar), params, pregIdx);
2058 lmirBuilder_->AppendStmt(bb, callNode);
2059 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Return(lmirBuilder_->Regread(pregIdx)));
2060 lmirBuilder_->AppendBB(bb);
2061 }
2062
GetExperimentalDeopt()2063 Function *LiteCGIRBuilder::GetExperimentalDeopt()
2064 {
2065 /* 0:calling 1:its caller */
2066 std::string funcName = "litecg.experimental.deoptimize.p1i64";
2067 auto fn = lmirBuilder_->GetFunc(funcName);
2068 if (!fn) {
2069 // save previous func for restore env
2070 Function &preFunc = lmirBuilder_->GetCurFunction();
2071 auto fnTy = GetExperimentalDeoptTy();
2072 FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName);
2073 // glue type depth
2074 funcBuilder.Param(lmirBuilder_->i64Type, "glue")
2075 .Param(lmirBuilder_->i64RefType, "deopt_type")
2076 .Param(lmirBuilder_->i64RefType, "max_depth");
2077 Function &curFunc = funcBuilder.Return(lmirBuilder_->LiteCGGetFuncReturnType(fnTy)).Done();
2078 funcBuilder.CallConvAttribute(maple::litecg::CCall);
2079 lmirBuilder_->SetCurFunc(curFunc);
2080 GenDeoptEntry(funcName);
2081 fn = &curFunc;
2082
2083 lmirBuilder_->SetCurFunc(preFunc);
2084 }
2085 return fn;
2086 }
2087
ConvertToTagged(GateRef gate)2088 Expr LiteCGIRBuilder::ConvertToTagged(GateRef gate)
2089 {
2090 auto machineType = acc_.GetMachineType(gate);
2091 switch (machineType) {
2092 case MachineType::I1:
2093 return ConvertBoolToTaggedBoolean(gate);
2094 case MachineType::I32:
2095 return ConvertInt32ToTaggedInt(GetExprFromGate(gate));
2096 case MachineType::F64:
2097 return ConvertFloat64ToTaggedDouble(gate);
2098 case MachineType::I64:
2099 break;
2100 default:
2101 LOG_COMPILER(FATAL) << "unexpected machineType!";
2102 UNREACHABLE();
2103 break;
2104 }
2105 return GetExprFromGate(gate);
2106 }
2107
ConvertInt32ToTaggedInt(Expr value)2108 Expr LiteCGIRBuilder::ConvertInt32ToTaggedInt(Expr value)
2109 {
2110 Expr e1Value = lmirBuilder_->SExt(value.GetType(), lmirBuilder_->i64Type, value);
2111 Expr tagMask = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_INT));
2112 Expr result = lmirBuilder_->Or(lmirBuilder_->i64Type, e1Value, tagMask);
2113 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result);
2114 }
2115
ConvertBoolToTaggedBoolean(GateRef gate)2116 Expr LiteCGIRBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
2117 {
2118 Expr value = GetExprFromGate(gate);
2119 Expr e1Value = lmirBuilder_->ZExt(value.GetType(), lmirBuilder_->u64Type, value);
2120 Expr tagMask =
2121 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_BOOLEAN_MASK));
2122 Expr result = lmirBuilder_->Or(lmirBuilder_->u64Type, e1Value, tagMask);
2123 return lmirBuilder_->Cvt(lmirBuilder_->u64Type, lmirBuilder_->i64RefType, result);
2124 }
2125
ConvertFloat64ToTaggedDouble(GateRef gate)2126 Expr LiteCGIRBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
2127 {
2128 Expr value = GetExprFromGate(gate);
2129 Expr e1Value = lmirBuilder_->BitCast(value.GetType(), lmirBuilder_->i64Type, value);
2130 Expr offset = lmirBuilder_->ConstVal(
2131 lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::DOUBLE_ENCODE_OFFSET));
2132 Expr result = lmirBuilder_->Add(lmirBuilder_->i64Type, e1Value, offset);
2133 return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result);
2134 }
2135
SaveDeoptVregInfo(std::unordered_map<int,LiteCGValue> & deoptBundleInfo,BB & bb,int32_t index,size_t curDepth,size_t shift,GateRef gate)2136 void LiteCGIRBuilder::SaveDeoptVregInfo(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb, int32_t index,
2137 size_t curDepth, size_t shift, GateRef gate)
2138 {
2139 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
2140 Expr value = ConvertToTagged(gate);
2141 PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType());
2142 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx));
2143 LiteCGValue deoptVal;
2144 deoptVal.kind = LiteCGValueKind::kPregKind;
2145 deoptVal.pregIdx = pregIdx;
2146 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, deoptVal));
2147 }
SaveDeoptVregInfoWithI64(std::unordered_map<int,LiteCGValue> & deoptBundleInfo,BB & bb,int32_t index,size_t curDepth,size_t shift,GateRef gate)2148 void LiteCGIRBuilder::SaveDeoptVregInfoWithI64(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb,
2149 int32_t index, size_t curDepth, size_t shift, GateRef gate)
2150 {
2151 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
2152 Expr expr = GetExprFromGate(gate);
2153 Expr value = ConvertInt32ToTaggedInt(lmirBuilder_->Cvt(expr.GetType(), lmirBuilder_->i32Type, expr));
2154 PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType());
2155 lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx));
2156 LiteCGValue deoptVal;
2157 deoptVal.kind = LiteCGValueKind::kPregKind;
2158 deoptVal.pregIdx = pregIdx;
2159 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, deoptVal));
2160 }
2161
VisitDeoptCheck(GateRef gate)2162 void LiteCGIRBuilder::VisitDeoptCheck(GateRef gate)
2163 {
2164 BB &bb = lmirBuilder_->GetLastAppendedBB(); // falseBB of deopt check
2165 Expr glue = GetExprFromGate(acc_.GetGlueFromArgList());
2166 GateRef deoptFrameState = acc_.GetValueIn(gate, 1); // 1: frame state
2167 ASSERT(acc_.GetOpCode(deoptFrameState) == OpCode::FRAME_STATE);
2168 std::vector<Expr> params;
2169 params.push_back(glue); // glue
2170 GateRef deoptType = acc_.GetValueIn(gate, 2); // 2: deopt type
2171 uint64_t v = acc_.GetConstantValue(deoptType);
2172 Expr constV = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(v)));
2173 params.push_back(ConvertInt32ToTaggedInt(constV)); // deoptType
2174 Function *callee = GetExperimentalDeopt();
2175 LiteCGType *funcType = GetExperimentalDeoptTy();
2176
2177 std::unordered_map<int, LiteCGValue> deoptBundleInfo;
2178 size_t maxDepth = 0;
2179 GateRef frameState = acc_.GetFrameState(deoptFrameState);
2180 while ((acc_.GetOpCode(frameState) == OpCode::FRAME_STATE)) {
2181 maxDepth++;
2182 frameState = acc_.GetFrameState(frameState);
2183 }
2184 Expr constMaxDepth =
2185 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(maxDepth)));
2186 params.push_back(ConvertInt32ToTaggedInt(constMaxDepth));
2187 size_t shift = Deoptimizier::ComputeShift(maxDepth);
2188 frameState = deoptFrameState;
2189 ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
2190 for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) {
2191 ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
2192 GateRef frameValues = acc_.GetValueIn(frameState, 1); // 1: frame values
2193 const size_t numValueIn = acc_.GetNumValueIn(frameValues);
2194 const size_t envIndex = numValueIn - 2; // 2: env valueIn index
2195 const size_t accIndex = numValueIn - 1; // 1: acc valueIn index
2196 GateRef env = acc_.GetValueIn(frameValues, envIndex);
2197 GateRef acc = acc_.GetValueIn(frameValues, accIndex);
2198 auto pc = acc_.TryGetPcOffset(frameState);
2199 GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
2200 GateRef newTarget = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::NEW_TARGET);
2201 GateRef thisObj = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::THIS_OBJECT);
2202 GateRef actualArgc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::ACTUAL_ARGC);
2203 // vreg
2204 for (size_t i = 0; i < envIndex; i++) {
2205 GateRef vregValue = acc_.GetValueIn(frameValues, i);
2206 if (acc_.IsConstantValue(vregValue, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
2207 continue;
2208 }
2209 SaveDeoptVregInfo(deoptBundleInfo, bb, i, curDepth, shift, vregValue);
2210 }
2211 // env
2212 if (!acc_.IsConstantValue(env, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
2213 int32_t specEnvVregIndex = static_cast<int32_t>(SpecVregIndex::ENV_INDEX);
2214 SaveDeoptVregInfo(deoptBundleInfo, bb, specEnvVregIndex, curDepth, shift, env);
2215 }
2216 // acc
2217 if (!acc_.IsConstantValue(acc, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
2218 int32_t specAccVregIndex = static_cast<int32_t>(SpecVregIndex::ACC_INDEX);
2219 SaveDeoptVregInfo(deoptBundleInfo, bb, specAccVregIndex, curDepth, shift, acc);
2220 }
2221 // pc offset
2222 int32_t specPcOffsetIndex = static_cast<int32_t>(SpecVregIndex::PC_OFFSET_INDEX);
2223 int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specPcOffsetIndex, curDepth, shift);
2224 Const &pcConst = lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, pc);
2225 LiteCGValue deoptVal;
2226 deoptVal.kind = LiteCGValueKind::kConstKind;
2227 deoptVal.constVal = &pcConst;
2228 deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, deoptVal));
2229
2230 // func
2231 int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FUNC_INDEX);
2232 SaveDeoptVregInfo(deoptBundleInfo, bb, specCallTargetIndex, curDepth, shift, jsFunc);
2233 // newTarget
2234 int32_t specNewTargetIndex = static_cast<int32_t>(SpecVregIndex::NEWTARGET_INDEX);
2235 SaveDeoptVregInfo(deoptBundleInfo, bb, specNewTargetIndex, curDepth, shift, newTarget);
2236 // this object
2237 int32_t specThisIndex = static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX);
2238 SaveDeoptVregInfo(deoptBundleInfo, bb, specThisIndex, curDepth, shift, thisObj);
2239 int32_t specArgcIndex = static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX);
2240 SaveDeoptVregInfoWithI64(deoptBundleInfo, bb, specArgcIndex, curDepth, shift, actualArgc);
2241 frameState = acc_.GetFrameState(frameState);
2242 }
2243 LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
2244
2245 bool returnVoid = (returnType == lmirBuilder_->voidType);
2246 PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
2247
2248 Stmt &callNode = lmirBuilder_->Call(*callee, params, returnPregIdx);
2249 lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
2250
2251 lmirBuilder_->AppendStmt(bb, callNode);
2252 if (!returnVoid) {
2253 SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
2254 }
2255 }
2256
HandleConstString(GateRef gate)2257 void LiteCGIRBuilder::HandleConstString(GateRef gate)
2258 {
2259 const ChunkVector<char> &str = acc_.GetConstantString(gate); // 64: bit width
2260 VisitConstString(gate, str);
2261 }
2262
VisitConstString(GateRef gate,const ChunkVector<char> & str)2263 void LiteCGIRBuilder::VisitConstString(GateRef gate, const ChunkVector<char> &str) // 64: bit width
2264 {
2265 ASSERT(acc_.GetMachineType(gate) == MachineType::ARCH);
2266
2267 Expr value = lmirBuilder_->ConstVal(lmirBuilder_->CreateStrConst(std::string(str.data(), str.size())));
2268 static uint32_t val = 0;
2269 std::string name = "ConstStringVar" + std::to_string(val++);
2270 Var &var = lmirBuilder_->CreateLocalVar(value.GetType(), name);
2271 Stmt &stmt = lmirBuilder_->Dassign(value, var);
2272 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), stmt);
2273 SaveGate2Expr(gate, lmirBuilder_->Addrof(var));
2274 }
2275
HandleRelocatableData(GateRef gate)2276 void LiteCGIRBuilder::HandleRelocatableData(GateRef gate)
2277 {
2278 uint64_t value = acc_.TryGetValue(gate);
2279 VisitRelocatableData(gate, value);
2280 }
2281
VisitRelocatableData(GateRef gate,uint64_t value)2282 void LiteCGIRBuilder::VisitRelocatableData(GateRef gate, uint64_t value)
2283 {
2284 Var &var = lmirBuilder_->CreateGlobalVar(lmirBuilder_->i64Type, "G", maple::litecg::GlobalVarAttr::VAR_internal);
2285 Expr constVal = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, value));
2286 Stmt &stmt = lmirBuilder_->Dassign(constVal, var);
2287 lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), stmt);
2288 SaveGate2Expr(gate, lmirBuilder_->Dread(var));
2289 }
2290
HandleAlloca(GateRef gate)2291 void LiteCGIRBuilder::HandleAlloca(GateRef gate)
2292 {
2293 return VisitAlloca(gate);
2294 }
2295
VisitAlloca(GateRef gate)2296 void LiteCGIRBuilder::VisitAlloca(GateRef gate)
2297 {
2298 uint64_t machineRep = acc_.TryGetValue(gate);
2299 LiteCGType *dataType = GetMachineRepType(static_cast<MachineRep>(machineRep));
2300
2301 static uint32_t val = 0;
2302 std::string name = "AllocaVar" + std::to_string(val++);
2303 Var &var = lmirBuilder_->CreateLocalVar(dataType, name);
2304 Expr addr = lmirBuilder_->Addrof(var);
2305 Expr addrCvt = lmirBuilder_->Cvt(addr.GetType(), ConvertLiteCGTypeFromGate(gate), addr);
2306 SaveGate2Expr(gate, addrCvt);
2307 }
2308
GetMachineRepType(MachineRep rep) const2309 LiteCGType *LiteCGIRBuilder::GetMachineRepType(MachineRep rep) const
2310 {
2311 LiteCGType *dstType;
2312 switch (rep) {
2313 case MachineRep::K_BIT:
2314 dstType = lmirBuilder_->u1Type;
2315 break;
2316 case MachineRep::K_WORD8:
2317 dstType = lmirBuilder_->i8Type;
2318 break;
2319 case MachineRep::K_WORD16:
2320 dstType = lmirBuilder_->i16Type;
2321 break;
2322 case MachineRep::K_WORD32:
2323 dstType = lmirBuilder_->i32Type;
2324 break;
2325 case MachineRep::K_FLOAT64:
2326 dstType = lmirBuilder_->f64Type;
2327 break;
2328 case MachineRep::K_WORD64:
2329 dstType = lmirBuilder_->i64Type;
2330 break;
2331 case MachineRep::K_PTR_1:
2332 dstType = lmirBuilder_->i64RefType;
2333 break;
2334 case MachineRep::K_META:
2335 LOG_ECMA(FATAL) << "this branch is unreachable";
2336 UNREACHABLE();
2337 break;
2338 default:
2339 LOG_ECMA(FATAL) << "this branch is unreachable";
2340 UNREACHABLE();
2341 break;
2342 }
2343 return dstType;
2344 }
2345
GetBitWidthFromMachineType(MachineType machineType) const2346 int64_t LiteCGIRBuilder::GetBitWidthFromMachineType(MachineType machineType) const
2347 {
2348 switch (machineType) {
2349 case NOVALUE:
2350 return 0;
2351 case ARCH:
2352 return 48; // 48: Pointer representation in different architectures
2353 case I1:
2354 return 1;
2355 case I8:
2356 return 8; // 8: bit width
2357 case I16:
2358 return 16; // 16: bit width
2359 case I32:
2360 return 32; // 32: bit width
2361 case I64:
2362 return 64; // 64: bit width
2363 case F32:
2364 return 32; // 32: bit width
2365 case F64:
2366 return 64; // 64: bit width
2367 case FLEX:
2368 case ANYVALUE:
2369 LOG_ECMA(FATAL) << "this branch is unreachable";
2370 UNREACHABLE();
2371 default:
2372 LOG_ECMA(FATAL) << "this branch is unreachable";
2373 UNREACHABLE();
2374 }
2375 }
2376
LookupPredBB(GateRef start,int bbID)2377 int LiteCGIRBuilder::LookupPredBB(GateRef start, int bbID)
2378 {
2379 GateId gateId = acc_.GetId(start);
2380 int owner = instID2bbID_[gateId];
2381 if (owner != bbID) {
2382 return owner;
2383 }
2384 GateRef pred = start;
2385 while (owner == bbID) {
2386 pred = acc_.GetState(pred);
2387 auto id = acc_.GetId(pred);
2388 owner = instID2bbID_[id];
2389 }
2390 return owner;
2391 }
2392
2393 } // namespace panda::ecmascript::kungfu
2394