• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param = 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> &params, 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