• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/codegen/maple/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/baseline/baseline_call_signature.h"
24 #include "ecmascript/compiler/circuit.h"
25 #include "ecmascript/compiler/call_signature.h"
26 #include "ecmascript/compiler/common_stub_csigns.h"
27 #include "ecmascript/compiler/debug_info.h"
28 #include "ecmascript/compiler/gate.h"
29 #include "ecmascript/compiler/rt_call_signature.h"
30 #include "ecmascript/deoptimizer/deoptimizer.h"
31 #include "ecmascript/frames.h"
32 #include "ecmascript/js_function.h"
33 #include "ecmascript/js_thread.h"
34 #include "ecmascript/method.h"
35 #include "triple.h"
36 #include "lmir_builder.h"
37 
38 namespace panda::ecmascript::kungfu {
39 using FunctionBuilder = maple::litecg::LMIRBuilder::FunctionBuilder;
40 using SwitchBuilder = maple::litecg::LMIRBuilder::SwitchBuilder;
41 using Function = maple::litecg::Function;
42 using LMIRBuilder = maple::litecg::LMIRBuilder;
43 using BB = maple::litecg::BB;
44 using Expr = maple::litecg::Expr;
45 using Stmt = maple::litecg::Stmt;
46 using Const = maple::litecg::Const;
47 using LiteCGType = maple::litecg::Type;
48 using IntCmpCondition = maple::litecg::IntCmpCondition;
49 using FloatCmpCondition = maple::litecg::FloatCmpCondition;
50 using Var = maple::litecg::Var;
51 using PregIdx = maple::litecg::PregIdx;
52 using IntrinsicId = maple::litecg::IntrinsicId;
53 using maple::litecg::LiteCGValue;
54 using maple::litecg::LiteCGValueKind;
55 
56 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, Expr>;
57 
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)58 LiteCGIRBuilder::LiteCGIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
59                                  LMIRModule *module, const CompilationConfig *cfg, CallSignature::CallConv callConv,
60                                  bool enableLog, bool enableOptInlining,
61                                  const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile,
62                                  const std::string &funcName)
63     : scheduledGates_(schedule),
64       circuit_(circuit),
65       lmirModule_(module),
66       compCfg_(cfg),
67       callConv_(callConv),
68       enableLog_(enableLog),
69       enableOptInlining_(enableOptInlining),
70       methodLiteral_(methodLiteral),
71       jsPandaFile_(jsPandaFile),
72       funcName_(funcName),
73       acc_(circuit),
74       cf_(*module->GetModule())
75 {
76     lmirBuilder_ = new LMIRBuilder(*module->GetModule());
77     maple::theMIRModule = module->GetModule();
78     ASSERT(compCfg_->Is64Bit());
79     slotSize_ = sizeof(uint64_t);
80     slotType_ = lmirBuilder_->i64Type;
81     InitializeHandlers();
82     if (cfg != nullptr) {
83         maple::Triple::GetTriple().Init(cfg->IsAArch64());
84     }
85 }
86 
~LiteCGIRBuilder()87 LiteCGIRBuilder::~LiteCGIRBuilder()
88 {
89     delete lmirBuilder_;
90 }
91 
BuildInstID2BBIDMap()92 void LiteCGIRBuilder::BuildInstID2BBIDMap()
93 {
94     for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
95         const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx);
96         for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
97             GateId gateId = acc_.GetId(bb[instIdx - 1]);
98             instID2bbID_[gateId] = static_cast<int>(bbIdx);
99         }
100     }
101 }
102 
GetOrCreateBB(int bbID)103 BB &LiteCGIRBuilder::GetOrCreateBB(int bbID)
104 {
105     auto itr = bbID2BB_.find(bbID);
106     if (itr != bbID2BB_.end()) {
107         return *(itr->second);
108     }
109     BB &bb = lmirBuilder_->CreateBB();
110     bbID2BB_[bbID] = &bb;
111     return bb;
112 }
113 
GetFirstBB()114 BB &LiteCGIRBuilder::GetFirstBB()
115 {
116     // Obtain the first BB (i.e. the BB with id zero) for inserting prologue information
117     return GetOrCreateBB(0);
118 }
119 
CreateBB()120 BB &LiteCGIRBuilder::CreateBB()
121 {
122     BB &bb = lmirBuilder_->CreateBB(false);
123     return bb;
124 }
125 
ConvertLiteCGTypeFromGate(GateRef gate,bool isSigned) const126 LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromGate(GateRef gate, bool isSigned) const
127 {
128     if (acc_.IsGCRelated(gate)) {
129         return lmirBuilder_->i64RefType;
130     }
131 
132     MachineType t = acc_.GetMachineType(gate);
133     switch (t) {
134         case MachineType::NOVALUE:
135             return lmirBuilder_->voidType;
136         case MachineType::I1:
137             return lmirBuilder_->u1Type;
138         case MachineType::I8:
139             return isSigned ? lmirBuilder_->i8Type : lmirBuilder_->u8Type;
140         case MachineType::I16:
141             return isSigned ? lmirBuilder_->i16Type : lmirBuilder_->u16Type;
142         case MachineType::I32:
143             return isSigned ? lmirBuilder_->i32Type : lmirBuilder_->u32Type;
144         case MachineType::I64:
145             return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type;
146         case MachineType::F32:
147             return lmirBuilder_->f32Type;
148         case MachineType::F64:
149             return lmirBuilder_->f64Type;
150         case MachineType::ARCH:
151             return isSigned ? lmirBuilder_->i64Type : lmirBuilder_->u64Type;
152         default:
153             LOG_ECMA(FATAL) << "this branch is unreachable";
154             UNREACHABLE();
155     }
156 }
157 
AddFunc()158 void LiteCGIRBuilder::AddFunc()
159 {
160     // setup function type
161     std::string funcName = lmirModule_->GetFuncName(methodLiteral_, jsPandaFile_);
162     FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName);
163     funcBuilder.Param(lmirBuilder_->i64Type, "glue");
164     if (circuit_->IsOsr()) {
165         funcBuilder.Param(lmirBuilder_->i64PtrType, "interpSp");
166     } else if (!methodLiteral_->IsFastCall()) {
167         funcBuilder.Param(lmirBuilder_->i64Type, "actualArgc")
168             .Param(lmirBuilder_->i64PtrType, "actualArgv")
169             .Param(lmirBuilder_->i64RefType, "func")
170             .Param(lmirBuilder_->i64RefType, "new_target")
171             .Param(lmirBuilder_->i64RefType, "this_object");
172         for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) {
173             funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i));
174         }
175     } else {
176         funcBuilder.Param(lmirBuilder_->i64RefType, "func").Param(lmirBuilder_->i64RefType, "this_object");
177         for (uint32_t i = 0; i < methodLiteral_->GetNumArgsWithCallField(); ++i) {
178             funcBuilder.Param(lmirBuilder_->i64RefType, "param" + std::to_string(i));
179         }
180     }
181 
182     funcBuilder.CallConvAttribute(ConvertCallAttr(callConv_));
183     Function &function = funcBuilder.Return(lmirBuilder_->i64RefType).Done();
184     lmirBuilder_->SetCurFunc(function);
185     lmirBuilder_->RenameFormal2Preg(function);
186     GenPrologue(function);
187     auto offsetInPandaFile = methodLiteral_->GetMethodId().GetOffset();
188     lmirModule_->SetFunction(offsetInPandaFile, funcName, methodLiteral_->IsFastCall());
189 }
190 
191 // deal with derived reference
CollectDerivedRefInfo()192 void LiteCGIRBuilder::CollectDerivedRefInfo()
193 {
194     auto GetPregFromGate = [&](GateRef gate)->PregIdx {
195         LiteCGValue value = gate2Expr_[gate];
196         ASSERT(value.kind == LiteCGValueKind::kPregKind);
197         return std::get<PregIdx>(value.data);
198     };
199 
200     // collect base references for derived phi reference
201     for (auto &pair : bbID2basePhis_) {
202         for (auto &desc : pair.second) {
203             Expr expr = GetExprFromGate(desc.operand);
204             if (derivedPhiGate2BasePhiPreg_.find(desc.operand) != derivedPhiGate2BasePhiPreg_.end()) {
205                 expr = lmirBuilder_->Regread(derivedPhiGate2BasePhiPreg_[desc.operand]);
206             }
207             Stmt &tmpPhiAssign = lmirBuilder_->Regassign(expr, desc.phi);
208             lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(desc.predBBId), tmpPhiAssign);
209         }
210     }
211 
212     std::set<PregIdx> baseRefSet;
213     // set common derived reference
214     for (auto it : derivedGate2BaseGate_) {
215         if (GetExprFromGate(it.second).IsConstValue() || GetExprFromGate(it.first).IsConstValue()) {
216             continue;
217         }
218         ASSERT(!GetExprFromGate(it.second).IsDread());
219         PregIdx derivedIdx = GetPregFromGate(it.first);
220         PregIdx baseIdx = GetPregFromGate(it.second);
221         baseRefSet.insert(baseIdx);
222         lmirBuilder_->SetFunctionDerived2BaseRef(derivedIdx, baseIdx);
223     }
224 
225     // set phi derived reference
226     for (auto it : derivedPhiGate2BasePhiPreg_) {
227         PregIdx derivedIdx = GetPregFromGate(it.first);
228         PregIdx baseIdx = it.second;
229         if (baseRefSet.find(derivedIdx) != baseRefSet.end()) {
230             LOG_COMPILER(FATAL) << "shouldn't occur nested derived reference" << std::endl;
231             UNREACHABLE();
232         }
233         lmirBuilder_->SetFunctionDerived2BaseRef(derivedIdx, baseIdx);
234     }
235 
236     bbID2basePhis_.clear();
237     derivedPhiGate2BasePhiPreg_.clear();
238     derivedGate2BaseGate_.clear();
239     derivedGateCache_.clear();
240 }
241 
HandleBB(const std::vector<GateRef> & bb,std::unordered_set<OpCode> & usedOpcodeSet)242 void LiteCGIRBuilder::HandleBB(const std::vector<GateRef> &bb, std::unordered_set<OpCode> &usedOpcodeSet)
243 {
244     for (size_t instIdx = bb.size(); instIdx > 0; instIdx--) {
245         GateRef gate = bb[instIdx - 1];
246         OpCode opcode = acc_.GetOpCode(gate);
247         if (IsLogEnabled()) {
248             lmirBuilder_->SetCurrentDebugComment(acc_.ToString(gate));
249         }
250         switch (opcode) {
251             case OpCode::STATE_ENTRY:
252                 HandleGoto(gate);
253                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::STATE_ENTRY);
254                 break;
255             case OpCode::RETURN:
256                 HandleReturn(gate);
257                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RETURN);
258                 break;
259             case OpCode::RETURN_VOID:
260                 HandleReturnVoid(gate);
261                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RETURN_VOID);
262                 break;
263             case OpCode::IF_BRANCH:
264                 HandleBranch(gate);
265                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_BRANCH);
266                 break;
267             case OpCode::ORDINARY_BLOCK:
268                 HandleGoto(gate);
269                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ORDINARY_BLOCK);
270                 break;
271             case OpCode::IF_TRUE:
272                 HandleGoto(gate);
273                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_TRUE);
274                 break;
275             case OpCode::IF_FALSE:
276                 HandleGoto(gate);
277                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::IF_FALSE);
278                 break;
279             case OpCode::SWITCH_BRANCH:
280                 HandleSwitch(gate);
281                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SWITCH_BRANCH);
282                 break;
283             case OpCode::SWITCH_CASE:
284                 HandleGoto(gate);
285                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SWITCH_CASE);
286                 break;
287             case OpCode::MERGE:
288                 HandleGoto(gate);
289                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MERGE);
290                 break;
291             case OpCode::DEFAULT_CASE:
292                 HandleGoto(gate);
293                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DEFAULT_CASE);
294                 break;
295             case OpCode::LOOP_BEGIN:
296                 HandleGoto(gate);
297                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOOP_BACK);
298                 break;
299             case OpCode::LOOP_BACK:
300                 HandleGoto(gate);
301                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOOP_BEGIN);
302                 break;
303             case OpCode::VALUE_SELECTOR:
304                 HandlePhi(gate);
305                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::VALUE_SELECTOR);
306                 break;
307             case OpCode::RUNTIME_CALL:
308                 HandleRuntimeCall(gate);
309                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RUNTIME_CALL);
310                 break;
311             case OpCode::RUNTIME_CALL_WITH_ARGV:
312                 HandleRuntimeCallWithArgv(gate);
313                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::RUNTIME_CALL_WITH_ARGV);
314                 break;
315             case OpCode::NOGC_RUNTIME_CALL:
316                 HandleCall(gate);
317                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::NOGC_RUNTIME_CALL);
318                 break;
319             case OpCode::CALL_OPTIMIZED:
320                 HandleCall(gate);
321                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CALL_OPTIMIZED);
322                 break;
323             case OpCode::FAST_CALL_OPTIMIZED:
324                 HandleCall(gate);
325                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FAST_CALL_OPTIMIZED);
326                 break;
327             case OpCode::CALL:
328                 HandleCall(gate);
329                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CALL);
330                 break;
331             case OpCode::BASELINE_CALL:
332                 HandleCall(gate);
333                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BASELINE_CALL);
334                 break;
335             case OpCode::BUILTINS_CALL:
336                 HandleCall(gate);
337                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BUILTINS_CALL);
338                 break;
339             case OpCode::BUILTINS_CALL_WITH_ARGV:
340                 HandleCall(gate);
341                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BUILTINS_CALL_WITH_ARGV);
342                 break;
343             case OpCode::ARG:
344                 HandleParameter(gate);
345                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ARG);
346                 break;
347             case OpCode::CONSTANT:
348                 HandleConstant(gate);
349                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CONSTANT);
350                 break;
351             case OpCode::ZEXT:
352                 HandleZExtInt(gate);
353                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ZEXT);
354                 break;
355             case OpCode::SEXT:
356                 HandleSExtInt(gate);
357                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SEXT);
358                 break;
359             case OpCode::TRUNC:
360                 HandleCastIntXToIntY(gate);
361                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC);
362                 break;
363             case OpCode::FEXT:
364                 HandleFPExt(gate);
365                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FEXT);
366                 break;
367             case OpCode::FTRUNC:
368                 HandleFPTrunc(gate);
369                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FTRUNC);
370                 break;
371             case OpCode::REV:
372                 HandleIntRev(gate);
373                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::REV);
374                 break;
375             case OpCode::ADD:
376                 HandleAdd(gate);
377                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ADD);
378                 break;
379             case OpCode::SUB:
380                 HandleSub(gate);
381                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SUB);
382                 break;
383             case OpCode::MUL:
384                 HandleMul(gate);
385                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MUL);
386                 break;
387             case OpCode::FDIV:
388                 HandleFloatDiv(gate);
389                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FDIV);
390                 break;
391             case OpCode::SDIV:
392                 HandleIntDiv(gate);
393                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SDIV);
394                 break;
395             case OpCode::UDIV:
396                 HandleUDiv(gate);
397                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::UDIV);
398                 break;
399             case OpCode::AND:
400                 HandleIntAnd(gate);
401                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::AND);
402                 break;
403             case OpCode::OR:
404                 HandleIntOr(gate);
405                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::OR);
406                 break;
407             case OpCode::XOR:
408                 HandleIntXor(gate);
409                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::XOR);
410                 break;
411             case OpCode::LSR:
412                 HandleIntLsr(gate);
413                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LSR);
414                 break;
415             case OpCode::ASR:
416                 HandleIntAsr(gate);
417                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ASR);
418                 break;
419             case OpCode::ICMP:
420                 HandleCmp(gate);
421                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ICMP);
422                 break;
423             case OpCode::FCMP:
424                 HandleCmp(gate);
425                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FCMP);
426                 break;
427             case OpCode::LOAD:
428                 HandleLoad(gate);
429                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LOAD);
430                 break;
431             case OpCode::STORE_WITHOUT_BARRIER:
432                 HandleStore(gate);
433                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::STORE_WITHOUT_BARRIER);
434                 break;
435             case OpCode::SIGNED_INT_TO_FLOAT:
436                 HandleChangeInt32ToDouble(gate);
437                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SIGNED_INT_TO_FLOAT);
438                 break;
439             case OpCode::UNSIGNED_INT_TO_FLOAT:
440                 HandleChangeUInt32ToDouble(gate);
441                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::UNSIGNED_INT_TO_FLOAT);
442                 break;
443             case OpCode::FLOAT_TO_SIGNED_INT:
444                 HandleChangeDoubleToInt32(gate);
445                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FLOAT_TO_SIGNED_INT);
446                 break;
447             case OpCode::TAGGED_TO_INT64:
448                 HandleChangeTaggedPointerToInt64(gate);
449                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TAGGED_TO_INT64);
450                 break;
451             case OpCode::INT64_TO_TAGGED:
452                 HandleChangeInt64ToTagged(gate);
453                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::INT64_TO_TAGGED);
454                 break;
455             case OpCode::BITCAST:
456                 HandleBitCast(gate);
457                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::BITCAST);
458                 break;
459             case OpCode::LSL:
460                 HandleIntLsl(gate);
461                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::LSL);
462                 break;
463             case OpCode::SMOD:
464                 HandleMod(gate);
465                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SMOD);
466                 break;
467             case OpCode::FMOD:
468                 HandleMod(gate);
469                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FMOD);
470                 break;
471             case OpCode::DEOPT_CHECK:
472                 HandleDeoptCheck(gate);
473                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DEOPT_CHECK);
474                 break;
475             case OpCode::TRUNC_FLOAT_TO_INT64:
476                 HandleTruncFloatToInt(gate);
477                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC_FLOAT_TO_INT64);
478                 break;
479             case OpCode::TRUNC_FLOAT_TO_INT32:
480                 HandleTruncFloatToInt(gate);
481                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::TRUNC_FLOAT_TO_INT32);
482                 break;
483             case OpCode::ADD_WITH_OVERFLOW:
484                 HandleAddWithOverflow(gate);
485                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ADD_WITH_OVERFLOW);
486                 break;
487             case OpCode::SUB_WITH_OVERFLOW:
488                 HandleSubWithOverflow(gate);
489                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SUB_WITH_OVERFLOW);
490                 break;
491             case OpCode::MUL_WITH_OVERFLOW:
492                 HandleMulWithOverflow(gate);
493                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MUL_WITH_OVERFLOW);
494                 break;
495             case OpCode::EXP:
496                 HandleExp(gate);
497                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::EXP);
498                 break;
499             case OpCode::ABS:
500                 HandleAbs(gate);
501                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::ABS);
502                 break;
503             case OpCode::MIN:
504                 HandleMin(gate);
505                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MIN);
506                 break;
507             case OpCode::MAX:
508                 HandleMax(gate);
509                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::MAX);
510                 break;
511             case OpCode::CLZ32:
512                 HandleClz32(gate);
513                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CLZ32);
514                 break;
515             case OpCode::DOUBLE_TRUNC:
516                 HandleDoubleTrunc(gate);
517                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::DOUBLE_TRUNC);
518                 break;
519             case OpCode::CEIL:
520                 HandleCeil(gate);
521                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::CEIL);
522                 break;
523             case OpCode::FLOOR:
524                 HandleFloor(gate);
525                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FLOOR);
526                 break;
527             case OpCode::EXTRACT_VALUE:
528                 HandleExtractValue(gate);
529                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::EXTRACT_VALUE);
530                 break;
531             case OpCode::SQRT:
532                 HandleSqrt(gate);
533                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::SQRT);
534                 break;
535             case OpCode::READSP:
536                 HandleReadSp(gate);
537                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::READSP);
538                 break;
539             case OpCode::FINISH_ALLOCATE:
540                 HandleFinishAllocate(gate);
541                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::FINISH_ALLOCATE);
542                 break;
543             case OpCode::INITVREG:
544                 HandleInitVreg(gate);
545                 InsertUsedOpcodeSet(usedOpcodeSet, OpCode::INITVREG);
546                 break;
547             default:
548                 if (illegalOpHandlers_.find(acc_.GetOpCode(gate)) == illegalOpHandlers_.end()) {
549                     LOG_COMPILER(FATAL) << "can't process opcode: " << acc_.GetOpCode(gate) << std::endl;
550                 }
551         }
552         if (IsLogEnabled()) {
553             lmirBuilder_->ClearCurrentDebugComment();
554         }
555     }
556 }
Build()557 void LiteCGIRBuilder::Build()
558 {
559     BuildInstID2BBIDMap();
560     AddFunc();
561     LOG_COMPILER(INFO) << "============== building litecg ir=======" << std::endl;
562 
563     std::unordered_set<OpCode> usedOpcodeSet;
564     for (size_t bbIdx = 0; bbIdx < scheduledGates_->size(); bbIdx++) {
565         const std::vector<GateRef> &bb = scheduledGates_->at(bbIdx);
566         HandleBB(bb, usedOpcodeSet);
567     }
568 
569     if (enableLog_) {
570         for (auto &opcode : usedOpcodeSet) {
571             LOG_COMPILER(INFO) << "OPCODE: " << opcode << std::endl;
572         }
573     }
574 
575     CollectDerivedRefInfo();
576 
577     std::map<int, std::vector<std::pair<PregIdx, PregIdx>>> bbID2phiAssign;
578     for (auto &pair : bbID2unmergedPhis_) {
579         for (auto &desc : pair.second) {
580             Expr value = GetExprFromGate(desc.operand);
581             PregIdx tmpPhiPregIdx = lmirBuilder_->CreatePreg(value.GetType());
582             Stmt &tmpPhiAssign = lmirBuilder_->Regassign(value, tmpPhiPregIdx);
583             lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(desc.predBBId), tmpPhiAssign);
584             bbID2phiAssign[desc.predBBId].emplace_back(std::make_pair(tmpPhiPregIdx, desc.phi));
585         }
586     }
587 
588     for (auto &pair: bbID2phiAssign) {
589         for (auto &expr: pair.second) {
590             auto &stmt =  lmirBuilder_->Regassign(lmirBuilder_->Regread(expr.first), expr.second);
591             lmirBuilder_->AppendStmtBeforeBranch(GetOrCreateBB(pair.first), stmt);
592         }
593     }
594     bbID2unmergedPhis_.clear();
595     bbID2phiAssign.clear();
596 
597     lmirBuilder_->AppendBB(lmirBuilder_->GetLastPosBB());
598 }
599 
AssistGenPrologue(const size_t reservedSlotsSize,FrameType frameType,maple::litecg::Function & function)600 void LiteCGIRBuilder::AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType,
601                                         maple::litecg::Function &function)
602 {
603     lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
604     if (circuit_->IsOsr()) {
605         SaveFrameTypeOnFrame(methodLiteral_->IsFastCall() ? FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME :
606             frameType);
607         return;
608     }
609     auto ArgList = circuit_->GetArgRoot();
610     auto uses = acc_.Uses(ArgList);
611     for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
612         int argth = static_cast<int>(acc_.TryGetValue(*useIt));
613         Var &value = lmirBuilder_->GetParam(function, argth);
614         int funcIndex = 0;
615         if (methodLiteral_->IsFastCall()) {
616             frameType = FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
617             funcIndex = static_cast<int>(FastCallArgIdx::FUNC);
618         } else {
619             funcIndex = static_cast<int>(CommonArgIdx::FUNC);
620         }
621         if (argth == funcIndex) {
622             SaveByteCodePcOnOptJSFuncFrame(value);
623             SaveJSFuncOnOptJSFuncFrame(value);
624             SaveFrameTypeOnFrame(frameType);
625         }
626     }
627 }
628 
GenPrologue(maple::litecg::Function & function)629 void LiteCGIRBuilder::GenPrologue(maple::litecg::Function &function)
630 {
631     auto frameType = circuit_->GetFrameType();
632     if (IsInterpreted() || IsBaselineBuiltin()) {
633         return;
634     }
635     lmirBuilder_->SetFuncFramePointer("all");
636     size_t reservedSlotsSize = 0;
637     if (frameType == FrameType::OPTIMIZED_FRAME) {
638         reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
639         lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
640         SaveFrameTypeOnFrame(frameType);
641     } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
642         reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
643         lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
644         if (circuit_->IsOsr()) {
645             SaveFrameTypeOnFrame(methodLiteral_->IsFastCall() ? FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME :
646                 frameType);
647             return;
648         }
649         auto ArgList = circuit_->GetArgRoot();
650         auto uses = acc_.Uses(ArgList);
651         for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
652             int argth = static_cast<int>(acc_.TryGetValue(*useIt));
653             Var &value = lmirBuilder_->GetParam(function, argth);
654             int funcIndex = 0;
655             if (methodLiteral_->IsFastCall()) {
656                 frameType = FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME;
657                 funcIndex = static_cast<int>(FastCallArgIdx::FUNC);
658             } else {
659                 funcIndex = static_cast<int>(CommonArgIdx::FUNC);
660             }
661             if (argth == funcIndex) {
662                 SaveJSFuncOnOptJSFuncFrame(value);
663                 SaveFrameTypeOnFrame(frameType);
664             }
665         }
666     } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) {
667         reservedSlotsSize = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_);
668         AssistGenPrologue(reservedSlotsSize, frameType, function);
669     } else {
670         LOG_COMPILER(FATAL) << "frameType interpret type error !";
671         ASSERT_PRINT(static_cast<uintptr_t>(frameType), "is not support !");
672     }
673 }
674 
SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var & value)675 void LiteCGIRBuilder::SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value)
676 {
677     ASSERT(circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME);
678     // load method
679     Expr func = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value));
680     Expr offsetMethod = lmirBuilder_->ConstVal(
681         lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, JSFunctionBase::METHOD_OFFSET));
682     Expr addrMethod = lmirBuilder_->Add(lmirBuilder_->i64PtrType, func, offsetMethod);
683     Expr method = lmirBuilder_->Iread(
684         lmirBuilder_->i64PtrType, addrMethod, lmirBuilder_->CreatePtrType(lmirBuilder_->i64PtrType));
685     // load byteCodePc
686     Expr offsetByteCodePc = lmirBuilder_->ConstVal(
687         lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
688     Expr addrByteCodePc = lmirBuilder_->Add(lmirBuilder_->i64PtrType, method, offsetByteCodePc);
689     Expr byteCodePc = lmirBuilder_->Iread(
690         lmirBuilder_->i64PtrType, addrByteCodePc, lmirBuilder_->CreatePtrType(lmirBuilder_->i64PtrType));
691     // push byteCodePc
692     Expr fpAddr = CallingFp(false);
693     Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
694     size_t reservedOffset = FASTJITFunctionFrame::ComputeReservedPcOffset(slotSize_);
695     Expr frameByteCodePcSlotAddr =
696         lmirBuilder_->Sub(frameAddr.GetType(), frameAddr,
697                           lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset)));
698     Expr byteCodePcAddr =
699         lmirBuilder_->Cvt(frameByteCodePcSlotAddr.GetType(),
700                           lmirBuilder_->CreatePtrType(slotType_), frameByteCodePcSlotAddr);
701     auto &stmt = lmirBuilder_->Iassign(byteCodePc, byteCodePcAddr, byteCodePcAddr.GetType());
702     lmirBuilder_->AppendStmt(GetFirstBB(), stmt);
703 }
704 
SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var & value)705 void LiteCGIRBuilder::SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var &value)
706 {
707     ASSERT(IsOptimizedJSFunction());
708     Expr fpAddr = CallingFp(false);
709     Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
710     size_t reservedOffset = 0;
711     if (circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) {
712         reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
713     } else {
714         reservedOffset = FASTJITFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
715     }
716 
717     Expr frameJSFuncSlotAddr =
718         lmirBuilder_->Sub(frameAddr.GetType(), frameAddr,
719                           lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset)));
720     Expr jsFuncAddr =
721         lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr);
722     Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value));
723     auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType());
724     lmirBuilder_->AppendStmt(GetFirstBB(), stmt);
725 }
726 
SaveFrameTypeOnFrame(FrameType frameType)727 void LiteCGIRBuilder::SaveFrameTypeOnFrame(FrameType frameType)
728 {
729     Expr fpAddr = CallingFp(false);
730     Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
731     Expr frameJSFuncSlotAddr = lmirBuilder_->Sub(
732         frameAddr.GetType(), frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_)));
733     Expr jsFuncAddr =
734         lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr);
735     Expr liteFramType =
736         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<uintptr_t>(frameType)));
737     auto &stmt = lmirBuilder_->Iassign(liteFramType, jsFuncAddr, jsFuncAddr.GetType());
738     lmirBuilder_->AppendStmt(GetFirstBB(), stmt);
739 }
740 
GetGlue(const std::vector<GateRef> & inList)741 Expr LiteCGIRBuilder::GetGlue(const std::vector<GateRef> &inList)
742 {
743     GateRef glueGate = inList[static_cast<size_t>(CallInputs::GLUE)];
744     auto itr = gate2Expr_.find(glueGate);
745     if (itr != gate2Expr_.end()) {
746         return GetExprFromGate(glueGate);
747     }
748     Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetLocalVar("glue"));
749     SaveGate2Expr(glueGate, glue);
750     return glue;
751 }
752 
SaveGate2Expr(GateRef gate,Expr expr,bool isGlueAdd)753 void LiteCGIRBuilder::SaveGate2Expr(GateRef gate, Expr expr, bool isGlueAdd)
754 {
755     if (isGlueAdd) {
756         gate2Expr_[gate] = {LiteCGValueKind::kGlueAdd, lmirBuilder_->GetConstFromExpr(expr)};
757         return;
758     } else if (expr.IsDread()) {
759         gate2Expr_[gate] = {LiteCGValueKind::kSymbolKind, lmirBuilder_->GetLocalVarFromExpr(expr)};
760         return;
761     } else if (expr.IsRegread()) {
762         gate2Expr_[gate] = {LiteCGValueKind::kPregKind, lmirBuilder_->GetPregIdxFromExpr(expr)};
763         return;
764     } else if (expr.IsConstValue()) {
765         gate2Expr_[gate] = {LiteCGValueKind::kConstKind, lmirBuilder_->GetConstFromExpr(expr)};
766         return;
767     }
768     auto *newNode = cf_.Fold(expr.GetNode());
769     if (newNode == nullptr || !newNode->IsConstval()) {
770         // check expr is not agg
771         BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
772         PregIdx pregIdx = lmirBuilder_->CreatePreg(expr.GetType());
773         lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Regassign(expr, pregIdx));
774         gate2Expr_[gate] = {LiteCGValueKind::kPregKind, pregIdx};
775         return;
776     }
777     gate2Expr_[gate] = {LiteCGValueKind::kConstKind, static_cast<maple::ConstvalNode*>(newNode)->GetConstVal()};
778 }
779 
GetConstant(GateRef gate)780 Expr LiteCGIRBuilder::GetConstant(GateRef gate)
781 {
782     std::bitset<64> value = acc_.GetConstantValue(gate); // 64 for bit width
783     auto machineType = acc_.GetMachineType(gate);
784     if (machineType == MachineType::ARCH) {
785         ASSERT(compCfg_->Is64Bit());
786         machineType = MachineType::I64;
787     }
788 
789     Const *constVal = nullptr;
790     if (machineType == MachineType::I32) {
791         constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, static_cast<int64_t>(value.to_ulong())));
792     } else if (machineType == MachineType::I64) {
793         constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, static_cast<int64_t>(value.to_ulong())));
794         LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
795         if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) {
796             Expr constExpr = lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, lmirBuilder_->ConstVal(*constVal));
797             return constExpr;
798         } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) {
799             // do nothing
800         } else {
801             LOG_ECMA(FATAL) << "this branch is unreachable";
802             UNREACHABLE();
803         }
804     } else if (machineType == MachineType::F64) {
805         auto doubleValue = base::bit_cast<double>(value.to_ullong());  // actual double value
806         constVal = &(lmirBuilder_->CreateDoubleConst(static_cast<double>(doubleValue)));
807     } else if (machineType == MachineType::I8) {
808         constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u8Type, static_cast<int64_t>(value.to_ulong())));
809     } else if (machineType == MachineType::I16) {
810         constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u16Type, static_cast<int64_t>(value.to_ulong())));
811     } else if (machineType == MachineType::I1) {
812         constVal = &(lmirBuilder_->CreateIntConst(lmirBuilder_->u1Type, static_cast<int64_t>(value.to_ulong())));
813     } else {
814         LOG_ECMA(FATAL) << "this branch is unreachable";
815         UNREACHABLE();
816     }
817     return lmirBuilder_->ConstVal(*constVal);
818 }
819 
GetExprFromGate(GateRef gate)820 Expr LiteCGIRBuilder::GetExprFromGate(GateRef gate)
821 {
822     if (acc_.GetOpCode(gate) == OpCode::CONSTANT) {
823         return GetConstant(gate);
824     }
825     LiteCGValue value = gate2Expr_[gate];
826     if (value.kind == LiteCGValueKind::kSymbolKind) {
827         return lmirBuilder_->Dread(*std::get<maple::MIRSymbol*>(value.data));
828     } else if (value.kind == LiteCGValueKind::kConstKind) {
829         return lmirBuilder_->ConstVal(*std::get<maple::MIRConst*>(value.data));
830     } else if (value.kind == LiteCGValueKind::kGlueAdd) {
831         auto glue = acc_.GetGlueFromArgList();
832         return lmirBuilder_->Add(ConvertLiteCGTypeFromGate(glue), GetExprFromGate(glue),
833             lmirBuilder_->ConstVal(*std::get<maple::MIRConst*>(value.data)));
834     }
835     ASSERT(value.kind == LiteCGValueKind::kPregKind);
836     return lmirBuilder_->Regread(std::get<PregIdx>(value.data));
837 }
838 
InitializeHandlers()839 void LiteCGIRBuilder::InitializeHandlers()
840 {
841     illegalOpHandlers_ = {OpCode::NOP,
842                           OpCode::CIRCUIT_ROOT,
843                           OpCode::DEPEND_ENTRY,
844                           OpCode::DEAD,
845                           OpCode::RETURN_LIST,
846                           OpCode::ARG_LIST,
847                           OpCode::THROW,
848                           OpCode::DEPEND_SELECTOR,
849                           OpCode::DEPEND_RELAY,
850                           OpCode::FRAME_STATE,
851                           OpCode::STATE_SPLIT,
852                           OpCode::FRAME_ARGS,
853                           OpCode::LOOP_EXIT_DEPEND,
854                           OpCode::LOOP_EXIT,
855                           OpCode::START_ALLOCATE,
856                           OpCode::FINISH_ALLOCATE,
857                           OpCode::FRAME_VALUES,
858                           OpCode::ASM_CALL_BARRIER};
859 }
860 
HandleReturnVoid(GateRef gate)861 void LiteCGIRBuilder::HandleReturnVoid([[maybe_unused]] GateRef gate)
862 {
863     return;
864 }
865 
HandleGoto(GateRef gate)866 void LiteCGIRBuilder::HandleGoto(GateRef gate)
867 {
868     std::vector<GateRef> outs;
869     acc_.GetOutStates(gate, outs);
870     int block = instID2bbID_[acc_.GetId(gate)];
871     int bbOut = instID2bbID_[acc_.GetId(outs[0])];
872     switch (acc_.GetOpCode(gate)) {
873         case OpCode::MERGE:
874         case OpCode::LOOP_BEGIN: {
875             for (const auto &out : outs) {
876                 bbOut = instID2bbID_[acc_.GetId(out)];
877                 VisitGoto(block, bbOut);
878             }
879             break;
880         }
881         default: {
882             VisitGoto(block, bbOut);
883             break;
884         }
885     }
886 }
887 
VisitGoto(int block,int bbOut)888 void LiteCGIRBuilder::VisitGoto(int block, int bbOut)
889 {
890     if (block == bbOut) {
891         return;
892     }
893     BB &srcBB = GetOrCreateBB(block);
894     BB &destBB = GetOrCreateBB(bbOut);
895 
896     lmirBuilder_->AppendStmt(srcBB, lmirBuilder_->Goto(destBB));
897     lmirBuilder_->AppendBB(srcBB);
898 }
899 
HandleParameter(GateRef gate)900 void LiteCGIRBuilder::HandleParameter(GateRef gate)
901 {
902     return VisitParameter(gate);
903 }
904 
VisitParameter(GateRef gate)905 void LiteCGIRBuilder::VisitParameter(GateRef gate)
906 {
907     std::vector<GateRef> outs;
908     acc_.GetOuts(gate, outs);
909     if (outs.empty()) {
910         return;
911     }
912     size_t argth = static_cast<size_t>(acc_.TryGetValue(gate));
913     Var &param = lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), argth);
914     SaveGate2Expr(gate, lmirBuilder_->GenExprFromVar(param));
915 }
916 
HandleConstant(GateRef gate)917 void LiteCGIRBuilder::HandleConstant(GateRef gate)
918 {
919     // no need to deal with constant separately
920     (void)gate;
921     return;
922 }
923 
HandleAdd(GateRef gate)924 void LiteCGIRBuilder::HandleAdd(GateRef gate)
925 {
926     auto g0 = acc_.GetIn(gate, 0);
927     auto g1 = acc_.GetIn(gate, 1);
928     VisitAdd(gate, g0, g1);
929 }
930 
CanonicalizeToPtr(Expr expr,LiteCGType * type)931 Expr LiteCGIRBuilder::CanonicalizeToPtr(Expr expr, LiteCGType *type)
932 {
933     if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypePointer) {
934         if (expr.GetType() == type) {
935             return expr;
936         }
937         return lmirBuilder_->Cvt(expr.GetType(), type, expr);
938     } else if (lmirBuilder_->LiteCGGetTypeKind(expr.GetType()) == maple::litecg::kLiteCGTypeScalar) {
939         return lmirBuilder_->Cvt(lmirBuilder_->i64Type, type, expr);
940     } else {
941         LOG_COMPILER(FATAL) << "can't Canonicalize to Ptr: ";
942         UNREACHABLE();
943     }
944     return expr;
945 }
946 
VisitAdd(GateRef gate,GateRef e1,GateRef e2)947 void LiteCGIRBuilder::VisitAdd(GateRef gate, GateRef e1, GateRef e2)
948 {
949     Expr e1Value = GetExprFromGate(e1);
950     Expr e2Value = GetExprFromGate(e2);
951     // save glue + offset
952     if (e1 == acc_.GetGlueFromArgList() && acc_.GetOpCode(e2) == OpCode::CONSTANT) {
953         SaveGate2Expr(gate, e2Value, true);
954         return;
955     }
956 
957     Expr result;
958     /*
959      *  If the first operand is pointer, special treatment is needed
960      *  1) add, pointer, int
961      *  2) add, vector{i8* x 2}, int
962      */
963     LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
964     auto machineType = acc_.GetMachineType(gate);
965     if (IsAddIntergerType(machineType)) {
966         auto e1Type = ConvertLiteCGTypeFromGate(e1);
967         auto e1TypeKind = lmirBuilder_->LiteCGGetTypeKind(e1Type);
968         auto e2Type = ConvertLiteCGTypeFromGate(e2);
969         if (e1TypeKind == maple::litecg::kLiteCGTypePointer) {
970             Expr tmp1 = lmirBuilder_->Cvt(e1Type, lmirBuilder_->i64Type, e1Value);
971             Expr tmp2 =
972                 (e2Type == lmirBuilder_->i64Type) ? e2Value : lmirBuilder_->Cvt(e2Type, lmirBuilder_->i64Type, e2Value);
973             Expr tmp3 = lmirBuilder_->Add(lmirBuilder_->i64Type, tmp1, tmp2);
974             result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, returnType, tmp3);
975             SaveGate2Expr(gate, result);
976             // set the base reference of derived reference
977             if (e1Type == lmirBuilder_->i64RefType) {
978                 ASSERT(!e1Value.IsDread());
979                 auto e1BaseIter = derivedGate2BaseGate_.find(e1);
980                 derivedGate2BaseGate_[gate] = (e1BaseIter == derivedGate2BaseGate_.end() ? e1 : e1BaseIter->second);
981             }
982             return;
983         } else {
984             Expr tmp1Expr = (e1Type == returnType) ? e1Value : lmirBuilder_->Cvt(e1Type, returnType, e1Value);
985             Expr tmp2Expr = (e2Type == returnType) ? e2Value : lmirBuilder_->Cvt(e2Type, returnType, e2Value);
986             result = lmirBuilder_->Add(returnType, tmp1Expr, tmp2Expr);
987         }
988     } else if (machineType == MachineType::F64) {
989         result = lmirBuilder_->Add(lmirBuilder_->f64Type, e1Value, e2Value);
990     } else {
991         LOG_ECMA(FATAL) << "this branch is unreachable";
992         UNREACHABLE();
993     }
994     SaveGate2Expr(gate, result);
995 }
996 
HandleLoad(GateRef gate)997 void LiteCGIRBuilder::HandleLoad(GateRef gate)
998 {
999     VisitLoad(gate, acc_.GetIn(gate, 1));
1000 }
1001 
VisitLoad(GateRef gate,GateRef base)1002 void LiteCGIRBuilder::VisitLoad(GateRef gate, GateRef base)
1003 {
1004     Expr baseAddr = GetExprFromGate(base);
1005 
1006     LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1007     LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(returnType)) ? lmirBuilder_->CreateRefType(returnType)
1008                                                                         : lmirBuilder_->CreatePtrType(returnType);
1009     baseAddr = CanonicalizeToPtr(baseAddr, memType);
1010     Expr result = lmirBuilder_->Iread(returnType, baseAddr, memType);
1011     SaveGate2Expr(gate, result);
1012 }
1013 
HandleCmp(GateRef gate)1014 void LiteCGIRBuilder::HandleCmp(GateRef gate)
1015 {
1016     GateRef left = acc_.GetIn(gate, 0);
1017     GateRef right = acc_.GetIn(gate, 1);
1018     VisitCmp(gate, left, right);
1019 }
1020 
ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const1021 IntCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromICMP(ICmpCondition cond) const
1022 {
1023     switch (cond) {
1024         case ICmpCondition::SLT:
1025             return IntCmpCondition::kSLT;
1026         case ICmpCondition::SLE:
1027             return IntCmpCondition::kSLE;
1028         case ICmpCondition::SGT:
1029             return IntCmpCondition::kSGT;
1030         case ICmpCondition::SGE:
1031             return IntCmpCondition::kSGE;
1032         case ICmpCondition::ULT:
1033             return IntCmpCondition::kULT;
1034         case ICmpCondition::ULE:
1035             return IntCmpCondition::kULE;
1036         case ICmpCondition::UGT:
1037             return IntCmpCondition::kUGT;
1038         case ICmpCondition::UGE:
1039             return IntCmpCondition::kUGE;
1040         case ICmpCondition::NE:
1041             return IntCmpCondition::kNE;
1042         case ICmpCondition::EQ:
1043             return IntCmpCondition::kEQ;
1044         default:
1045             LOG_COMPILER(FATAL) << "unexpected cond!";
1046             UNREACHABLE();
1047     }
1048     return IntCmpCondition::kEQ;
1049 }
1050 
ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const1051 FloatCmpCondition LiteCGIRBuilder::ConvertLiteCGPredicateFromFCMP(FCmpCondition cond) const
1052 {
1053     switch (cond) {
1054         case FCmpCondition::OLT:
1055             return FloatCmpCondition::kOLT;
1056         case FCmpCondition::OLE:
1057             return FloatCmpCondition::kOLE;
1058         case FCmpCondition::OGT:
1059             return FloatCmpCondition::kOGT;
1060         case FCmpCondition::OGE:
1061             return FloatCmpCondition::kOGE;
1062         case FCmpCondition::ONE:
1063             return FloatCmpCondition::kONE;
1064         case FCmpCondition::OEQ:
1065             return FloatCmpCondition::kOEQ;
1066         default:
1067             LOG_COMPILER(FATAL) << "unexpected cond!";
1068             UNREACHABLE();
1069     }
1070     return FloatCmpCondition::kOEQ;
1071 }
1072 
VisitCmp(GateRef gate,GateRef e1,GateRef e2)1073 void LiteCGIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
1074 {
1075     Expr e1Value = GetExprFromGate(e1);
1076     Expr e2Value = GetExprFromGate(e2);
1077     LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1078 
1079     [[maybe_unused]] auto e1ValCode = acc_.GetMachineType(e1);
1080     [[maybe_unused]] auto e2ValCode = acc_.GetMachineType(e2);
1081     ASSERT((e1ValCode == e2ValCode) ||
1082            (compCfg_->Is64Bit() && (e1ValCode == MachineType::ARCH) && (e2ValCode == MachineType::I64)) ||
1083            (compCfg_->Is64Bit() && (e2ValCode == MachineType::ARCH) && (e1ValCode == MachineType::I64)));
1084     auto op = acc_.GetOpCode(gate);
1085     if (op == OpCode::ICMP) {
1086         auto cond = acc_.GetICmpCondition(gate);
1087         auto litecgCond = ConvertLiteCGPredicateFromICMP(cond);
1088         Expr result = lmirBuilder_->ICmp(returnType, e1Value, e2Value, litecgCond);
1089         SaveGate2Expr(gate, result);
1090     } else if (op == OpCode::FCMP) {
1091         auto cond = acc_.GetFCmpCondition(gate);
1092         auto litecgCond = ConvertLiteCGPredicateFromFCMP(cond);
1093         Expr result = lmirBuilder_->FCmp(returnType, e1Value, e2Value, litecgCond);
1094         SaveGate2Expr(gate, result);
1095     } else {
1096         LOG_ECMA(FATAL) << "this branch is unreachable";
1097         UNREACHABLE();
1098     }
1099 }
1100 
HandleBranch(GateRef gate)1101 void LiteCGIRBuilder::HandleBranch(GateRef gate)
1102 {
1103     std::vector<GateRef> ins;
1104     acc_.GetIns(gate, ins);
1105     std::vector<GateRef> outs;
1106     acc_.GetOutStates(gate, outs);
1107     GateRef bTrue = (acc_.GetOpCode(outs[0]) == OpCode::IF_TRUE) ? outs[0] : outs[1];
1108     GateRef bFalse = (acc_.GetOpCode(outs[0]) == OpCode::IF_FALSE) ? outs[0] : outs[1];
1109     int bbTrue = instID2bbID_[acc_.GetId(bTrue)];
1110     int bbFalse = instID2bbID_[acc_.GetId(bFalse)];
1111     VisitBranch(gate, ins[1], bbTrue, bbFalse);
1112 }
1113 
VisitBranch(GateRef gate,GateRef cmp,int btrue,int bfalse)1114 void LiteCGIRBuilder::VisitBranch(GateRef gate, GateRef cmp, int btrue, int bfalse)
1115 {
1116     if ((gate2Expr_.count(cmp) == 0) && (acc_.GetOpCode(cmp) != OpCode::CONSTANT)) {
1117         OPTIONAL_LOG_COMPILER(ERROR) << "Branch condition gate is nullptr!";
1118         return;
1119     }
1120     uint32_t trueWeight = 0;
1121     uint32_t falseWeight = 0;
1122     if (acc_.HasBranchWeight(gate)) {
1123         trueWeight = acc_.GetTrueWeight(gate);
1124         falseWeight = acc_.GetFalseWeight(gate);
1125     }
1126     BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1127     lmirBuilder_->AppendBB(curBB);
1128     BB &bb = CreateBB();
1129     BB &trueBB = GetOrCreateBB(btrue);
1130     BB &falseBB = GetOrCreateBB(bfalse);
1131     // we hope that branch with higher probability can be placed immediatly behind
1132     if (trueWeight < falseWeight) {
1133         Stmt &stmt = lmirBuilder_->Goto(falseBB);
1134         lmirBuilder_->AppendStmt(bb, stmt);
1135         lmirBuilder_->AppendBB(bb);
1136         Expr cond = GetExprFromGate(cmp);
1137         Stmt &condBR = lmirBuilder_->CondGoto(cond, trueBB, true);
1138         lmirBuilder_->AppendStmt(curBB, condBR);
1139         return;
1140     }
1141     Stmt &stmt = lmirBuilder_->Goto(trueBB);
1142     lmirBuilder_->AppendStmt(bb, stmt);
1143     lmirBuilder_->AppendBB(bb);
1144     Expr cond = GetExprFromGate(cmp);
1145     Stmt &condBR = lmirBuilder_->CondGoto(cond, falseBB, false);
1146     lmirBuilder_->AppendStmt(curBB, condBR);
1147 }
1148 
HandleReturn(GateRef gate)1149 void LiteCGIRBuilder::HandleReturn(GateRef gate)
1150 {
1151     std::vector<GateRef> ins;
1152     acc_.GetIns(gate, ins);
1153     VisitReturn(gate, 1, ins);
1154 }
1155 
VisitReturn(GateRef gate,GateRef popCount,const std::vector<GateRef> & operands)1156 void LiteCGIRBuilder::VisitReturn([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef popCount,
1157                                   const std::vector<GateRef> &operands)
1158 {
1159     // [STATE] [DEPEND] [VALUE] [RETURN_LIST]
1160     GateRef operand = operands[2];  // 2: skip 2 in gate that are not data gate
1161     Expr returnValue = GetExprFromGate(operand);
1162     Stmt &returnNode = lmirBuilder_->Return(returnValue);
1163     BB &curBB = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1164     lmirBuilder_->AppendStmt(curBB, returnNode);
1165     lmirBuilder_->AppendBB(curBB);
1166 }
1167 
GetRTStubOffset(Expr glue,int index)1168 Expr LiteCGIRBuilder::GetRTStubOffset(Expr glue, int index)
1169 {
1170     size_t slotOffset = JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit()) + index * slotSize_;
1171     Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(slotOffset));
1172     return lmirBuilder_->ConstVal(constVal);
1173 }
1174 
GetCoStubOffset(Expr glue,int index) const1175 Expr LiteCGIRBuilder::GetCoStubOffset(Expr glue, int index) const
1176 {
1177     size_t offset =
1178         JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) + static_cast<size_t>(index * slotSize_);
1179     Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(offset));
1180     return lmirBuilder_->ConstVal(constVal);
1181 }
1182 
GetBaselineStubOffset(Expr glue,int index) const1183 Expr LiteCGIRBuilder::GetBaselineStubOffset(Expr glue, int index) const
1184 {
1185     size_t offset =
1186         JSThread::GlueData::GetBaselineStubEntriesOffset(compCfg_->Is32Bit()) + static_cast<size_t>(index * slotSize_);
1187     Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int64_t>(offset));
1188     return lmirBuilder_->ConstVal(constVal);
1189 }
1190 
HandleRuntimeCall(GateRef gate)1191 void LiteCGIRBuilder::HandleRuntimeCall(GateRef gate)
1192 {
1193     std::vector<GateRef> ins;
1194     acc_.GetIns(gate, ins);
1195     VisitRuntimeCall(gate, ins);
1196 };
1197 
ConvertLiteCGTypeFromVariableType(VariableType type) const1198 LiteCGType *LiteCGIRBuilder::ConvertLiteCGTypeFromVariableType(VariableType type) const
1199 {
1200     std::map<VariableType, LiteCGType *> machineTypeMap = {
1201         {VariableType::VOID(), lmirBuilder_->voidType},
1202         {VariableType::BOOL(), lmirBuilder_->u1Type},
1203         {VariableType::INT8(), lmirBuilder_->i8Type},
1204         {VariableType::INT16(), lmirBuilder_->i16Type},
1205         {VariableType::INT32(), lmirBuilder_->i32Type},
1206         {VariableType::INT64(), lmirBuilder_->i64Type},
1207         {VariableType::FLOAT32(), lmirBuilder_->f32Type},
1208         {VariableType::FLOAT64(), lmirBuilder_->f64Type},
1209         {VariableType::NATIVE_POINTER(), lmirBuilder_->i64Type},
1210         {VariableType::JS_POINTER(), lmirBuilder_->i64RefType},
1211         {VariableType::JS_ANY(), lmirBuilder_->i64RefType},
1212     };
1213     return machineTypeMap[type];
1214 }
1215 
GenerateFuncType(const std::vector<Expr> & params,const CallSignature * stubDescriptor)1216 LiteCGType *LiteCGIRBuilder::GenerateFuncType(const std::vector<Expr> &params, const CallSignature *stubDescriptor)
1217 {
1218     LiteCGType *retType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType());
1219     std::vector<LiteCGType *> paramTys;
1220     for (auto value : params) {
1221         paramTys.emplace_back(value.GetType());
1222     }
1223     LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, retType, false);
1224     return functionType;
1225 }
1226 
GetFuncType(const CallSignature * stubDescriptor) const1227 LiteCGType *LiteCGIRBuilder::GetFuncType(const CallSignature *stubDescriptor) const
1228 {
1229     LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(stubDescriptor->GetReturnType());
1230     std::vector<LiteCGType *> paramTys;
1231     auto paramCount = stubDescriptor->GetParametersCount();
1232     auto paramsType = stubDescriptor->GetParametersType();
1233     if (paramsType != nullptr) {
1234         LiteCGType *glueType = ConvertLiteCGTypeFromVariableType(paramsType[0]);
1235         paramTys.push_back(glueType);
1236 
1237         for (size_t i = 1; i < paramCount; i++) {
1238             paramTys.push_back(ConvertLiteCGTypeFromVariableType(paramsType[i]));
1239         }
1240     }
1241     auto funcType = lmirBuilder_->CreateFuncType(paramTys, returnType, stubDescriptor->IsVariadicArgs());
1242     return funcType;
1243 }
1244 
GetFunction(BB & bb,Expr glue,const CallSignature * signature,Expr rtbaseoffset,const std::string & realName) const1245 Expr LiteCGIRBuilder::GetFunction(BB &bb, Expr glue, const CallSignature *signature, Expr rtbaseoffset,
1246                                   const std::string &realName) const
1247 {
1248     LiteCGType *rtfuncType = GetFuncType(signature);
1249     LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType);
1250     LiteCGType *rtFuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr);
1251     LiteCGType *glueType = (glue.GetType());
1252     LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType);
1253     Expr rtbaseAddr = lmirBuilder_->Cvt(rtbaseoffset.GetType(), glueTypePtr, rtbaseoffset);
1254 
1255     Expr funcAddr = lmirBuilder_->Iread(glueType, rtbaseAddr, glueTypePtr);
1256     Expr callee = lmirBuilder_->Cvt(glueType, rtFuncTypePtrPtr, funcAddr);
1257 
1258     std::string name = realName.empty() ? signature->GetName() : realName;
1259     Stmt &comment = lmirBuilder_->Comment("function: " + name);
1260     lmirBuilder_->AppendStmt(bb, comment);
1261     PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType());
1262     Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx);
1263     lmirBuilder_->AppendStmt(bb, funcAddrNode);
1264 
1265     return lmirBuilder_->Regread(funcPregIdx);
1266 }
1267 
IsOptimizedJSFunction() const1268 bool LiteCGIRBuilder::IsOptimizedJSFunction() const
1269 {
1270     return circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
1271         circuit_->GetFrameType() == FrameType::FASTJIT_FUNCTION_FRAME;
1272 }
1273 
IsOptimized() const1274 bool LiteCGIRBuilder::IsOptimized() const
1275 {
1276     return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME;
1277 }
1278 
GetCallExceptionKind(size_t index,OpCode op) const1279 CallExceptionKind LiteCGIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const
1280 {
1281     bool hasPcOffset = IsOptimizedJSFunction() &&
1282                        ((op == OpCode::NOGC_RUNTIME_CALL && (kungfu::RuntimeStubCSigns::IsAsmStub(index))) ||
1283                         (op == OpCode::CALL) || (op == OpCode::RUNTIME_CALL));
1284     return hasPcOffset ? CallExceptionKind::HAS_PC_OFFSET : CallExceptionKind::NO_PC_OFFSET;
1285 }
1286 
VisitRuntimeCall(GateRef gate,const std::vector<GateRef> & inList)1287 void LiteCGIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList)
1288 {
1289     StubIdType stubId = RTSTUB_ID(CallRuntime);
1290     Expr glue = GetGlue(inList);
1291     int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
1292     Expr rtoffset = GetRTStubOffset(glue, stubIndex);
1293     Expr rtbaseOffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1294     const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
1295 
1296     CallExceptionKind kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL);
1297     bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET);
1298     size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size();  // 2: pcOffset and frameArgs
1299 
1300     std::vector<Expr> params;
1301     params.push_back(glue);  // glue
1302 
1303     const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)]));
1304     Expr indexValue =
1305         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(index)));
1306     params.push_back(indexValue);  // target
1307 
1308     const int64_t argc = actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER);
1309     Expr argcValue =
1310         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u64Type, static_cast<uint64_t>(argc)));
1311     params.push_back(argcValue);  // argc
1312 
1313     for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) {
1314         GateRef gateTmp = inList[paraIdx];
1315         params.push_back(GetExprFromGate(gateTmp));
1316     }
1317 
1318     std::string targetName = RuntimeStubCSigns::GetRTName(index);
1319     BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1320     std::string name = targetName.empty() ? signature->GetName() : targetName;
1321     Expr callee = GetFunction(bb, glue, signature, rtbaseOffset, name);
1322 
1323     LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType());
1324     bool returnVoid = (returnType == lmirBuilder_->voidType);
1325     PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
1326     Stmt &callNode =
1327         returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx);
1328 
1329     if (kind == CallExceptionKind::HAS_PC_OFFSET) {
1330         std::unordered_map<int, LiteCGValue> deoptBundleInfo;
1331         auto frameArgs = inList.at(actualNumArgs);
1332         Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1]))
1333                                     : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0));
1334         CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs);
1335         lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
1336     }
1337     lmirBuilder_->SetStmtCallConv(callNode, maple::litecg::Web_Kit_JS_Call);
1338     lmirBuilder_->AppendStmt(bb, callNode);
1339     if (!returnVoid) {
1340         SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
1341     }
1342 }
1343 
HandleZExtInt(GateRef gate)1344 void LiteCGIRBuilder::HandleZExtInt(GateRef gate)
1345 {
1346     std::vector<GateRef> ins;
1347     acc_.GetIns(gate, ins);
1348     VisitZExtInt(gate, ins[0]);
1349 }
1350 
VisitZExtInt(GateRef gate,GateRef e1)1351 void LiteCGIRBuilder::VisitZExtInt(GateRef gate, GateRef e1)
1352 {
1353     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
1354            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1355     LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
1356     LiteCGType *toType = ConvertLiteCGTypeFromGate(gate, false);
1357     Expr result = lmirBuilder_->ZExt(fromType, toType, GetExprFromGate(e1));
1358     SaveGate2Expr(gate, result);
1359 }
1360 
HandleIntDiv(GateRef gate)1361 void LiteCGIRBuilder::HandleIntDiv(GateRef gate)
1362 {
1363     auto g0 = acc_.GetIn(gate, 0);
1364     auto g1 = acc_.GetIn(gate, 1);
1365     VisitIntDiv(gate, g0, g1);
1366 }
1367 
VisitIntDiv(GateRef gate,GateRef e1,GateRef e2)1368 void LiteCGIRBuilder::VisitIntDiv(GateRef gate, GateRef e1, GateRef e2)
1369 {
1370     Expr e1Value = GetExprFromGate(e1);
1371     Expr e2Value = GetExprFromGate(e2);
1372     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1373     Expr result = lmirBuilder_->SDiv(type, e1Value, e2Value);
1374     SaveGate2Expr(gate, result);
1375 }
1376 
GetCallee(maple::litecg::BB & bb,const std::vector<GateRef> & inList,const CallSignature * signature,const std::string & realName)1377 Expr LiteCGIRBuilder::GetCallee(maple::litecg::BB &bb, const std::vector<GateRef> &inList,
1378                                 const CallSignature *signature, const std::string &realName)
1379 {
1380     LiteCGType *rtfuncType = GetFuncType(signature);
1381     LiteCGType *rtfuncTypePtr = lmirBuilder_->CreatePtrType(rtfuncType);
1382     LiteCGType *rtfuncTypePtrPtr = lmirBuilder_->CreatePtrType(rtfuncTypePtr);
1383     Expr code = GetExprFromGate(inList[static_cast<size_t>(CallInputs::TARGET)]);
1384     Expr callee = lmirBuilder_->Cvt(code.GetType(), rtfuncTypePtrPtr, code);
1385 
1386     std::string name = realName.empty() ? signature->GetName() : realName;
1387     Stmt &comment = lmirBuilder_->Comment("function: " + name);
1388     lmirBuilder_->AppendStmt(bb, comment);
1389 
1390     PregIdx funcPregIdx = lmirBuilder_->CreatePreg(callee.GetType());
1391     Stmt &funcAddrNode = lmirBuilder_->Regassign(callee, funcPregIdx);
1392     lmirBuilder_->AppendStmt(bb, funcAddrNode);
1393     return lmirBuilder_->Regread(funcPregIdx);
1394 }
1395 
HandleRuntimeCallWithArgv(GateRef gate)1396 void LiteCGIRBuilder::HandleRuntimeCallWithArgv(GateRef gate)
1397 {
1398     std::vector<GateRef> ins;
1399     acc_.GetIns(gate, ins);
1400     VisitRuntimeCallWithArgv(gate, ins);
1401 }
1402 
VisitRuntimeCallWithArgv(GateRef gate,const std::vector<GateRef> & inList)1403 void LiteCGIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList)
1404 {
1405     ASSERT(IsOptimized() == true);
1406     StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv);
1407     Expr glue = GetGlue(inList);
1408     int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
1409     Expr rtoffset = GetRTStubOffset(glue, stubIndex);
1410     Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1411     const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
1412 
1413     std::vector<Expr> params;
1414     params.push_back(glue);  // glue
1415 
1416     uint64_t index = acc_.GetConstantValue(inList[static_cast<size_t>(CallInputs::TARGET)]);
1417     auto targetId = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, index));
1418     params.push_back(targetId);  // target
1419     for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
1420         GateRef gateTmp = inList[paraIdx];
1421         params.push_back(GetExprFromGate(gateTmp));
1422     }
1423 
1424     BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1425     std::string targetName = RuntimeStubCSigns::GetRTName(index);
1426     std::string name = targetName.empty() ? signature->GetName() : targetName;
1427     Expr callee = GetFunction(bb, glue, signature, rtbaseoffset, name);
1428 
1429     static uint32_t val = 0;
1430     std::string returnCallValName = name + "Ret" + std::to_string(val++);
1431     LiteCGType *returnType = ConvertLiteCGTypeFromVariableType(signature->GetReturnType());
1432     Var *returnVar = (returnType == lmirBuilder_->voidType)
1433                          ? nullptr
1434                          : &(lmirBuilder_->CreateLocalVar(returnType, returnCallValName));
1435     Stmt &callNode = lmirBuilder_->ICall(callee, params, returnVar);
1436     lmirBuilder_->AppendStmt(bb, callNode);
1437     if (returnVar != nullptr) {
1438         SaveGate2Expr(gate, lmirBuilder_->Dread(*returnVar));
1439     }
1440 }
1441 
HandleCall(GateRef gate)1442 void LiteCGIRBuilder::HandleCall(GateRef gate)
1443 {
1444     std::vector<GateRef> ins;
1445     acc_.GetIns(gate, ins);
1446     OpCode callOp = acc_.GetOpCode(gate);
1447     if (callOp == OpCode::CALL || callOp == OpCode::NOGC_RUNTIME_CALL || callOp == OpCode::BUILTINS_CALL ||
1448         callOp == OpCode::BUILTINS_CALL_WITH_ARGV || callOp == OpCode::CALL_OPTIMIZED ||
1449         callOp == OpCode::FAST_CALL_OPTIMIZED || callOp == OpCode::BASELINE_CALL) {
1450         VisitCall(gate, ins, callOp);
1451     } else {
1452         LOG_ECMA(FATAL) << "this branch is unreachable";
1453         UNREACHABLE();
1454     }
1455 }
1456 
VisitCall(GateRef gate,const std::vector<GateRef> & inList,OpCode op)1457 void LiteCGIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
1458 {
1459     size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
1460     static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3);
1461     const CallSignature *calleeDescriptor = nullptr;
1462     Expr glue = GetGlue(inList);
1463     Expr callee;
1464     CallExceptionKind kind = CallExceptionKind::NO_PC_OFFSET;
1465     BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
1466     if (op == OpCode::CALL) {
1467         const size_t index = acc_.GetConstantValue(inList[targetIndex]);
1468         calleeDescriptor = CommonStubCSigns::Get(index);
1469         Expr rtoffset = GetCoStubOffset(glue, index);
1470         Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1471         callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1472         kind = GetCallExceptionKind(index, op);
1473     } else if (op == OpCode::NOGC_RUNTIME_CALL) {
1474         UpdateLeaveFrame(glue);
1475         const size_t index = acc_.GetConstantValue(inList[targetIndex]);
1476         calleeDescriptor = RuntimeStubCSigns::Get(index);
1477         Expr rtoffset = GetRTStubOffset(glue, index);
1478         Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1479         callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1480         kind = GetCallExceptionKind(index, op);
1481     } else if (op == OpCode::CALL_OPTIMIZED) {
1482         calleeDescriptor = RuntimeStubCSigns::GetOptimizedCallSign();
1483         callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName());
1484         if (IsOptimizedJSFunction()) {
1485             kind = CallExceptionKind::HAS_PC_OFFSET;
1486         } else {
1487             kind = CallExceptionKind::NO_PC_OFFSET;
1488         }
1489     } else if (op == OpCode::FAST_CALL_OPTIMIZED) {
1490         calleeDescriptor = RuntimeStubCSigns::GetOptimizedFastCallSign();
1491         callee = GetCallee(bb, inList, calleeDescriptor, calleeDescriptor->GetName());
1492         if (IsOptimizedJSFunction()) {
1493             kind = CallExceptionKind::HAS_PC_OFFSET;
1494         } else {
1495             kind = CallExceptionKind::NO_PC_OFFSET;
1496         }
1497     } else if (op == OpCode::BASELINE_CALL) {
1498         const size_t index = acc_.GetConstantValue(inList[targetIndex]);
1499         calleeDescriptor = BaselineStubCSigns::Get(index);
1500         Expr rtoffset = GetBaselineStubOffset(glue, index);
1501         Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, rtoffset);
1502         callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1503         kind = GetCallExceptionKind(index, op);
1504     } else {
1505         ASSERT(op == OpCode::BUILTINS_CALL || op == OpCode::BUILTINS_CALL_WITH_ARGV);
1506         Expr opcodeOffset = GetExprFromGate(inList[targetIndex]);
1507         Expr rtoffset = GetBuiltinsStubOffset(glue);
1508         Expr offset = lmirBuilder_->Add(rtoffset.GetType(), rtoffset, opcodeOffset);
1509         Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, offset);
1510         if (op == OpCode::BUILTINS_CALL) {
1511             calleeDescriptor = BuiltinsStubCSigns::BuiltinsCSign();
1512         } else {
1513             calleeDescriptor = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
1514         }
1515         callee = GetFunction(bb, glue, calleeDescriptor, rtbaseoffset);
1516     }
1517 
1518     std::vector<Expr> params;
1519     const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
1520     GateRef glueGate = inList[firstArg];
1521     params.push_back(GetExprFromGate(glueGate));
1522 
1523     LiteCGType *calleeFuncType = lmirBuilder_->LiteCGGetPointedType(callee.GetType());
1524     std::vector<LiteCGType *> paramTypes = lmirBuilder_->LiteCGGetFuncParamTypes(calleeFuncType);
1525 
1526     bool hasPCOffset = (kind == CallExceptionKind::HAS_PC_OFFSET);
1527     size_t actualNumArgs = hasPCOffset ? (inList.size() - 2) : inList.size();  // 2: pcOffset and frameArgs
1528 
1529     // then push the actual parameter for js function call
1530     for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
1531         GateRef gateTmp = inList[paraIdx];
1532         Expr gateExpr = GetExprFromGate(gateTmp);
1533         const auto gateTmpType = gateExpr.GetType();
1534         if (params.size() < paramTypes.size()) {  // this condition will be false for variadic arguments
1535             const auto paramType = paramTypes.at(params.size());
1536             // match parameter types and function signature types
1537             if (lmirBuilder_->IsHeapPointerType(paramType) && !lmirBuilder_->IsHeapPointerType(gateTmpType)) {
1538                 Expr cvtI64Expr = lmirBuilder_->Cvt(gateTmpType, lmirBuilder_->i64Type, gateExpr);
1539                 params.push_back(lmirBuilder_->Cvt(lmirBuilder_->i64Type, paramType, cvtI64Expr));
1540             } else {
1541                 params.push_back(lmirBuilder_->Cvt(gateTmpType, paramType, gateExpr));
1542             }
1543         } else {
1544             params.push_back(gateExpr);
1545         }
1546     }
1547 
1548     LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(calleeFuncType);
1549     bool returnVoid = (returnType == lmirBuilder_->voidType);
1550     PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
1551     Stmt &callNode =
1552         returnVoid ? lmirBuilder_->ICall(callee, params) : lmirBuilder_->ICall(callee, params, returnPregIdx);
1553     if (kind == CallExceptionKind::HAS_PC_OFFSET) {
1554         std::unordered_map<int, LiteCGValue> deoptBundleInfo;
1555         auto frameArgs = inList.at(actualNumArgs);
1556         Expr pcOffset = hasPCOffset ? (GetExprFromGate(inList[actualNumArgs + 1]))
1557                                     : lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, 0));
1558         CollectExraCallSiteInfo(deoptBundleInfo, pcOffset, frameArgs);
1559         lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
1560     }
1561     lmirBuilder_->SetStmtCallConv(callNode, ConvertCallAttr(calleeDescriptor->GetCallConv()));
1562     lmirBuilder_->AppendStmt(bb, callNode);
1563     if (!returnVoid) {
1564         SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
1565     }
1566 }
1567 
CollectExraCallSiteInfo(std::unordered_map<int,maple::litecg::LiteCGValue> & deoptBundleInfo,maple::litecg::Expr pcOffset,GateRef frameArgs)1568 void LiteCGIRBuilder::CollectExraCallSiteInfo(std::unordered_map<int, maple::litecg::LiteCGValue> &deoptBundleInfo,
1569                                               maple::litecg::Expr pcOffset, GateRef frameArgs)
1570 {
1571     // pc offset
1572     auto pcIndex = static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX);
1573     ASSERT(pcOffset.IsConstValue());
1574     deoptBundleInfo.insert(std::pair<int, LiteCGValue>(
1575         pcIndex, {LiteCGValueKind::kConstKind, lmirBuilder_->GetConstFromExpr(pcOffset)}));
1576 
1577     if (!enableOptInlining_) {
1578         return;
1579     }
1580 
1581     if (frameArgs == Circuit::NullGate()) {
1582         return;
1583     }
1584     if (acc_.GetOpCode(frameArgs) != OpCode::FRAME_ARGS) {
1585         return;
1586     }
1587     uint32_t maxDepth = acc_.GetFrameDepth(frameArgs, OpCode::FRAME_ARGS);
1588     if (maxDepth == 0) {
1589         return;
1590     }
1591 
1592     maxDepth = std::min(maxDepth, MAX_METHOD_OFFSET_NUM);
1593     size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM);
1594     ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
1595     for (int32_t curDepth = static_cast<int32_t>(maxDepth - 1); curDepth >= 0; curDepth--) {
1596         ASSERT(acc_.GetOpCode(frameArgs) == OpCode::FRAME_ARGS);
1597         // method id
1598         uint32_t methodOffset = acc_.TryGetMethodOffset(frameArgs);
1599         frameArgs = acc_.GetFrameState(frameArgs);
1600         if (methodOffset == FrameStateOutput::INVALID_INDEX) {
1601             methodOffset = 0;
1602         }
1603         int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - curDepth;
1604         int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specCallTargetIndex, curDepth, shift);
1605         auto constMethodOffset = lmirBuilder_->GetConstFromExpr(
1606             lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i32Type, methodOffset)));
1607         deoptBundleInfo.insert(
1608             std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kConstKind, constMethodOffset}));
1609     }
1610 }
1611 
ConvertCallAttr(const CallSignature::CallConv callConv)1612 maple::litecg::ConvAttr LiteCGIRBuilder::ConvertCallAttr(const CallSignature::CallConv callConv)
1613 {
1614     switch (callConv) {
1615         case CallSignature::CallConv::GHCCallConv: {
1616             return maple::litecg::GHC_Call;
1617         }
1618         case CallSignature::CallConv::WebKitJSCallConv: {
1619             return maple::litecg::Web_Kit_JS_Call;
1620         }
1621         default: {
1622             return maple::litecg::CCall;
1623         }
1624     }
1625 }
1626 
GetBuiltinsStubOffset(Expr glue)1627 Expr LiteCGIRBuilder::GetBuiltinsStubOffset(Expr glue)
1628 {
1629     Const &constVal = lmirBuilder_->CreateIntConst(
1630         glue.GetType(), JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()));
1631     return lmirBuilder_->ConstVal(constVal);
1632 }
1633 
UpdateLeaveFrame(Expr glue)1634 void LiteCGIRBuilder::UpdateLeaveFrame(Expr glue)
1635 {
1636     Expr leaveFrameOffset = GetLeaveFrameOffset(glue);
1637     Expr leaveFrameValue = lmirBuilder_->Add(glue.GetType(), glue, leaveFrameOffset);
1638     LiteCGType *glueType = glue.GetType();
1639     LiteCGType *glueTypePtr = lmirBuilder_->CreatePtrType(glueType);
1640     Expr leaveFrameAddr = lmirBuilder_->Cvt(leaveFrameValue.GetType(), glueTypePtr, leaveFrameValue);
1641     Expr fpAddr = CallingFp(true);
1642     Expr fp = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
1643 
1644     lmirBuilder_->Iassign(fp, leaveFrameAddr, fp.GetType());
1645 }
1646 
IsInterpreted() const1647 bool LiteCGIRBuilder::IsInterpreted() const
1648 {
1649     return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
1650 }
1651 
IsBaselineBuiltin() const1652 bool LiteCGIRBuilder::IsBaselineBuiltin() const
1653 {
1654     return circuit_->GetFrameType() == FrameType::BASELINE_BUILTIN_FRAME;
1655 }
1656 
CallingFp(bool)1657 Expr LiteCGIRBuilder::CallingFp(bool /*isCaller*/)
1658 {
1659     ASSERT(!IsInterpreted() && !IsBaselineBuiltin());
1660     /* 0:calling 1:its caller */
1661     Function &func = lmirBuilder_->GetCurFunction();
1662     return lmirBuilder_->LiteCGGetPregFP(func);
1663 }
1664 
GetLeaveFrameOffset(Expr glue)1665 Expr LiteCGIRBuilder::GetLeaveFrameOffset(Expr glue)
1666 {
1667     size_t slotOffset = JSThread::GlueData::GetLeaveFrameOffset(compCfg_->Is32Bit());
1668     Const &constVal = lmirBuilder_->CreateIntConst(glue.GetType(), static_cast<int>(slotOffset));
1669     return lmirBuilder_->ConstVal(constVal);
1670 }
1671 
HandleUDiv(GateRef gate)1672 void LiteCGIRBuilder::HandleUDiv(GateRef gate)
1673 {
1674     auto g0 = acc_.GetIn(gate, 0);
1675     auto g1 = acc_.GetIn(gate, 1);
1676     VisitUDiv(gate, g0, g1);
1677 }
1678 
VisitUDiv(GateRef gate,GateRef e1,GateRef e2)1679 void LiteCGIRBuilder::VisitUDiv(GateRef gate, GateRef e1, GateRef e2)
1680 {
1681     Expr e1Value = GetExprFromGate(e1);
1682     Expr e2Value = GetExprFromGate(e2);
1683     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1684     Expr result = lmirBuilder_->UDiv(type, e1Value, e2Value);
1685     SaveGate2Expr(gate, result);
1686 }
1687 
HandleIntAnd(GateRef gate)1688 void LiteCGIRBuilder::HandleIntAnd(GateRef gate)
1689 {
1690     auto g0 = acc_.GetIn(gate, 0);
1691     auto g1 = acc_.GetIn(gate, 1);
1692     VisitIntAnd(gate, g0, g1);
1693 }
1694 
VisitIntAnd(GateRef gate,GateRef e1,GateRef e2)1695 void LiteCGIRBuilder::VisitIntAnd(GateRef gate, GateRef e1, GateRef e2)
1696 {
1697     Expr e1Value = GetExprFromGate(e1);
1698     Expr e2Value = GetExprFromGate(e2);
1699     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1700     Expr result = lmirBuilder_->And(type, e1Value, e2Value);
1701     SaveGate2Expr(gate, result);
1702 }
1703 
HandleIntOr(GateRef gate)1704 void LiteCGIRBuilder::HandleIntOr(GateRef gate)
1705 {
1706     auto g0 = acc_.GetIn(gate, 0);
1707     auto g1 = acc_.GetIn(gate, 1);
1708     VisitIntOr(gate, g0, g1);
1709 }
1710 
VisitIntOr(GateRef gate,GateRef e1,GateRef e2)1711 void LiteCGIRBuilder::VisitIntOr(GateRef gate, GateRef e1, GateRef e2)
1712 {
1713     Expr e1Value = GetExprFromGate(e1);
1714     Expr e2Value = GetExprFromGate(e2);
1715     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1716     Expr result = lmirBuilder_->Or(type, e1Value, e2Value);
1717     SaveGate2Expr(gate, result);
1718 }
1719 
HandleIntXor(GateRef gate)1720 void LiteCGIRBuilder::HandleIntXor(GateRef gate)
1721 {
1722     auto g0 = acc_.GetIn(gate, 0);
1723     auto g1 = acc_.GetIn(gate, 1);
1724     VisitIntXor(gate, g0, g1);
1725 }
1726 
VisitIntXor(GateRef gate,GateRef e1,GateRef e2)1727 void LiteCGIRBuilder::VisitIntXor(GateRef gate, GateRef e1, GateRef e2)
1728 {
1729     Expr e1Value = GetExprFromGate(e1);
1730     Expr e2Value = GetExprFromGate(e2);
1731     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1732     Expr result = lmirBuilder_->Xor(type, e1Value, e2Value);
1733     SaveGate2Expr(gate, result);
1734 }
1735 
HandleIntLsr(GateRef gate)1736 void LiteCGIRBuilder::HandleIntLsr(GateRef gate)
1737 {
1738     auto g0 = acc_.GetIn(gate, 0);
1739     auto g1 = acc_.GetIn(gate, 1);
1740     VisitIntLsr(gate, g0, g1);
1741 }
1742 
VisitIntLsr(GateRef gate,GateRef e1,GateRef e2)1743 void LiteCGIRBuilder::VisitIntLsr(GateRef gate, GateRef e1, GateRef e2)
1744 {
1745     Expr e1Value = GetExprFromGate(e1);
1746     Expr e2Value = GetExprFromGate(e2);
1747     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1748     Expr result = lmirBuilder_->LShr(type, e1Value, e2Value);
1749     SaveGate2Expr(gate, result);
1750 }
1751 
HandleIntAsr(GateRef gate)1752 void LiteCGIRBuilder::HandleIntAsr(GateRef gate)
1753 {
1754     auto g0 = acc_.GetIn(gate, 0);
1755     auto g1 = acc_.GetIn(gate, 1);
1756     VisitIntAsr(gate, g0, g1);
1757 }
1758 
VisitIntAsr(GateRef gate,GateRef e1,GateRef e2)1759 void LiteCGIRBuilder::VisitIntAsr(GateRef gate, GateRef e1, GateRef e2)
1760 {
1761     Expr e1Value = GetExprFromGate(e1);
1762     Expr e2Value = GetExprFromGate(e2);
1763     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1764     Expr result = lmirBuilder_->AShr(type, e1Value, e2Value);
1765     SaveGate2Expr(gate, result);
1766 }
1767 
HandleBitCast(GateRef gate)1768 void LiteCGIRBuilder::HandleBitCast(GateRef gate)
1769 {
1770     VisitBitCast(gate, acc_.GetIn(gate, 0));
1771 }
1772 
VisitBitCast(GateRef gate,GateRef e1)1773 void LiteCGIRBuilder::VisitBitCast(GateRef gate, GateRef e1)
1774 {
1775     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(gate)) ==
1776            GetBitWidthFromMachineType(acc_.GetMachineType(e1)));
1777     LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
1778     LiteCGType *toType = ConvertLiteCGTypeFromGate(gate);
1779     Expr e1Value = GetExprFromGate(e1);
1780     Expr result = lmirBuilder_->BitCast(fromType, toType, e1Value);
1781     SaveGate2Expr(gate, result);
1782 }
1783 
HandleIntLsl(GateRef gate)1784 void LiteCGIRBuilder::HandleIntLsl(GateRef gate)
1785 {
1786     auto g0 = acc_.GetIn(gate, 0);
1787     auto g1 = acc_.GetIn(gate, 1);
1788     VisitIntLsl(gate, g0, g1);
1789 }
1790 
VisitIntLsl(GateRef gate,GateRef e1,GateRef e2)1791 void LiteCGIRBuilder::VisitIntLsl(GateRef gate, GateRef e1, GateRef e2)
1792 {
1793     Expr e1Value = GetExprFromGate(e1);
1794     Expr e2Value = GetExprFromGate(e2);
1795     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1796     Expr result = lmirBuilder_->Shl(type, e1Value, e2Value);
1797     SaveGate2Expr(gate, result);
1798 }
1799 
HandleMod(GateRef gate)1800 void LiteCGIRBuilder::HandleMod(GateRef gate)
1801 {
1802     auto g0 = acc_.GetIn(gate, 0);
1803     auto g1 = acc_.GetIn(gate, 1);
1804     VisitMod(gate, g0, g1);
1805 }
1806 
VisitMod(GateRef gate,GateRef e1,GateRef e2)1807 void LiteCGIRBuilder::VisitMod(GateRef gate, GateRef e1, GateRef e2)
1808 {
1809     Expr e1Value = GetExprFromGate(e1);
1810     Expr e2Value = GetExprFromGate(e2);
1811     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1812     ASSERT(type == ConvertLiteCGTypeFromGate(e1));
1813     ASSERT(type == ConvertLiteCGTypeFromGate(e2));
1814     auto machineType = acc_.GetMachineType(gate);
1815     Expr result;
1816     if (machineType == MachineType::I32) {
1817         result = lmirBuilder_->SRem(type, e1Value, e2Value);
1818     } else if (machineType != MachineType::F64) {
1819         LOG_ECMA(FATAL) << "this branch is unreachable";
1820         UNREACHABLE();
1821     }
1822     SaveGate2Expr(gate, result);
1823 }
1824 
HandleFinishAllocate(GateRef gate)1825 void LiteCGIRBuilder::HandleFinishAllocate(GateRef gate)
1826 {
1827     GateRef g0 = acc_.GetValueIn(gate, 0);
1828     VisitFinishAllocate(gate, g0);
1829 }
1830 
VisitFinishAllocate(GateRef gate,GateRef e1)1831 void LiteCGIRBuilder::VisitFinishAllocate(GateRef gate, GateRef e1)
1832 {
1833     Expr result = GetExprFromGate(e1);
1834     SaveGate2Expr(gate, result);
1835 }
1836 
HandleCastIntXToIntY(GateRef gate)1837 void LiteCGIRBuilder::HandleCastIntXToIntY(GateRef gate)
1838 {
1839     VisitCastIntXToIntY(gate, acc_.GetIn(gate, 0));
1840 }
1841 
VisitCastIntXToIntY(GateRef gate,GateRef e1)1842 void LiteCGIRBuilder::VisitCastIntXToIntY(GateRef gate, GateRef e1)
1843 {
1844     Expr e1Value = GetExprFromGate(e1);
1845     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
1846            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
1847     auto e1Type = ConvertLiteCGTypeFromGate(e1);
1848     Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1849     SaveGate2Expr(gate, result);
1850 }
1851 
HandleChangeInt32ToDouble(GateRef gate)1852 void LiteCGIRBuilder::HandleChangeInt32ToDouble(GateRef gate)
1853 {
1854     VisitChangeInt32ToDouble(gate, acc_.GetIn(gate, 0));
1855 }
1856 
VisitChangeInt32ToDouble(GateRef gate,GateRef e1)1857 void LiteCGIRBuilder::VisitChangeInt32ToDouble(GateRef gate, GateRef e1)
1858 {
1859     Expr e1Value = GetExprFromGate(e1);
1860     auto e1Type = ConvertLiteCGTypeFromGate(e1);
1861     Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1862     SaveGate2Expr(gate, result);
1863 }
1864 
HandleChangeUInt32ToDouble(GateRef gate)1865 void LiteCGIRBuilder::HandleChangeUInt32ToDouble(GateRef gate)
1866 {
1867     VisitChangeUInt32ToDouble(gate, acc_.GetIn(gate, 0));
1868 }
1869 
VisitChangeUInt32ToDouble(GateRef gate,GateRef e1)1870 void LiteCGIRBuilder::VisitChangeUInt32ToDouble(GateRef gate, GateRef e1)
1871 {
1872     Expr e1Value = GetExprFromGate(e1);
1873     auto e1Type = ConvertLiteCGTypeFromGate(e1);
1874     if (e1Type != lmirBuilder_->u32Type) {
1875         e1Value = lmirBuilder_->Cvt(e1Type, lmirBuilder_->u32Type, e1Value);
1876     }
1877     Expr result = lmirBuilder_->Cvt(lmirBuilder_->u32Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1878     SaveGate2Expr(gate, result);
1879 }
1880 
HandleChangeDoubleToInt32(GateRef gate)1881 void LiteCGIRBuilder::HandleChangeDoubleToInt32(GateRef gate)
1882 {
1883     VisitChangeDoubleToInt32(gate, acc_.GetIn(gate, 0));
1884 }
1885 
VisitChangeDoubleToInt32(GateRef gate,GateRef e1)1886 void LiteCGIRBuilder::VisitChangeDoubleToInt32(GateRef gate, GateRef e1)
1887 {
1888     Expr e1Value = GetExprFromGate(e1);
1889     auto e1Type = ConvertLiteCGTypeFromGate(e1);
1890     Expr result = lmirBuilder_->Cvt(e1Type, ConvertLiteCGTypeFromGate(gate), e1Value);
1891     SaveGate2Expr(gate, result);
1892 }
1893 
HandleChangeTaggedPointerToInt64(GateRef gate)1894 void LiteCGIRBuilder::HandleChangeTaggedPointerToInt64(GateRef gate)
1895 {
1896     VisitChangeTaggedPointerToInt64(gate, acc_.GetIn(gate, 0));
1897 }
1898 
VisitChangeTaggedPointerToInt64(GateRef gate,GateRef e1)1899 void LiteCGIRBuilder::VisitChangeTaggedPointerToInt64(GateRef gate, GateRef e1)
1900 {
1901     Expr result = CanonicalizeToInt(e1);
1902     SaveGate2Expr(gate, result);
1903 }
1904 
CanonicalizeToInt(GateRef gate)1905 Expr LiteCGIRBuilder::CanonicalizeToInt(GateRef gate)
1906 {
1907     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1908     Expr opnd = GetExprFromGate(gate);
1909     if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypePointer) {
1910         return lmirBuilder_->Cvt(type, lmirBuilder_->i64Type, opnd);
1911     } else if (lmirBuilder_->LiteCGGetTypeKind(type) == maple::litecg::kLiteCGTypeScalar) {
1912         return opnd;
1913     } else {
1914         LOG_COMPILER(FATAL) << "can't Canonicalize to Int64: ";
1915         UNREACHABLE();
1916     }
1917 }
1918 
HandleChangeInt64ToTagged(GateRef gate)1919 void LiteCGIRBuilder::HandleChangeInt64ToTagged(GateRef gate)
1920 {
1921     VisitChangeInt64ToTagged(gate, acc_.GetIn(gate, 0));
1922 }
1923 
VisitChangeInt64ToTagged(GateRef gate,GateRef e1)1924 void LiteCGIRBuilder::VisitChangeInt64ToTagged(GateRef gate, GateRef e1)
1925 {
1926     Expr e1Value = GetExprFromGate(e1);
1927     ASSERT(lmirBuilder_->LiteCGGetTypeKind(ConvertLiteCGTypeFromGate(e1)) == maple::litecg::kLiteCGTypeScalar);
1928     Expr result = lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, e1Value);
1929     SaveGate2Expr(gate, result);
1930 }
1931 
HandleDoubleTrunc(GateRef gate)1932 void LiteCGIRBuilder::HandleDoubleTrunc(GateRef gate)
1933 {
1934     GateRef param = acc_.GetIn(gate, 0);
1935     VisitDoubleTrunc(gate, param);
1936 }
1937 
VisitDoubleTrunc(GateRef gate,GateRef e1)1938 void LiteCGIRBuilder::VisitDoubleTrunc(GateRef gate, GateRef e1)
1939 {
1940     Expr e1Value = GetExprFromGate(e1);
1941     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
1942     ASSERT(acc_.GetMachineType(e1) == acc_.GetMachineType(gate));
1943     Expr result = lmirBuilder_->Trunc(type, type, e1Value);
1944     SaveGate2Expr(gate, result);
1945 }
1946 
HandleSub(GateRef gate)1947 void LiteCGIRBuilder::HandleSub(GateRef gate)
1948 {
1949     auto g0 = acc_.GetIn(gate, 0);
1950     auto g1 = acc_.GetIn(gate, 1);
1951     VisitSub(gate, g0, g1);
1952 }
1953 
VisitSub(GateRef gate,GateRef e1,GateRef e2)1954 void LiteCGIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2)
1955 {
1956     Expr e1Value = GetExprFromGate(e1);
1957     Expr e2Value = GetExprFromGate(e2);
1958     Expr result;
1959     LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1960     auto machineType = acc_.GetMachineType(gate);
1961     if (machineType == MachineType::I16 || machineType == MachineType::I32 || machineType == MachineType::I64 ||
1962         machineType == MachineType::ARCH || machineType == MachineType::F64) {
1963         result = lmirBuilder_->Sub(returnType, e1Value, e2Value);
1964     } else {
1965         LOG_ECMA(FATAL) << "this branch is unreachable";
1966         UNREACHABLE();
1967     }
1968     SaveGate2Expr(gate, result);
1969 }
1970 
HandleMul(GateRef gate)1971 void LiteCGIRBuilder::HandleMul(GateRef gate)
1972 {
1973     auto g0 = acc_.GetIn(gate, 0);
1974     auto g1 = acc_.GetIn(gate, 1);
1975     VisitMul(gate, g0, g1);
1976 }
1977 
VisitMul(GateRef gate,GateRef e1,GateRef e2)1978 void LiteCGIRBuilder::VisitMul(GateRef gate, GateRef e1, GateRef e2)
1979 {
1980     Expr e1Value = GetExprFromGate(e1);
1981     Expr e2Value = GetExprFromGate(e2);
1982     Expr result;
1983     LiteCGType *returnType = ConvertLiteCGTypeFromGate(gate);
1984     auto machineType = acc_.GetMachineType(gate);
1985     if (IsMulIntergerType(machineType)) {
1986         result = lmirBuilder_->Mul(returnType, e1Value, e2Value);
1987     } else if (machineType == MachineType::F64) {
1988         result = lmirBuilder_->Mul(returnType, e1Value, e2Value);
1989     } else {
1990         LOG_ECMA(FATAL) << "this branch is unreachable";
1991         UNREACHABLE();
1992     }
1993     SaveGate2Expr(gate, result);
1994 }
1995 
HandleIntRev(GateRef gate)1996 void LiteCGIRBuilder::HandleIntRev(GateRef gate)
1997 {
1998     std::vector<GateRef> ins;
1999     acc_.GetIns(gate, ins);
2000     VisitIntRev(gate, ins[0]);
2001 }
2002 
VisitIntRev(GateRef gate,GateRef e1)2003 void LiteCGIRBuilder::VisitIntRev(GateRef gate, GateRef e1)
2004 {
2005     Expr e1Value = GetExprFromGate(e1);
2006     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
2007     ASSERT(type == ConvertLiteCGTypeFromGate(e1));
2008     Expr result;
2009     auto machineType = acc_.GetMachineType(gate);
2010     if (machineType <= MachineType::I64 && machineType >= MachineType::I1) {
2011         if (machineType == MachineType::I1) {
2012             result = lmirBuilder_->Lnot(type, e1Value);
2013         } else {
2014             result = lmirBuilder_->Bnot(type, e1Value);
2015         }
2016     } else {
2017         LOG_ECMA(FATAL) << "this branch is unreachable";
2018         UNREACHABLE();
2019     }
2020     SaveGate2Expr(gate, result);
2021 }
2022 
HandleFloatDiv(GateRef gate)2023 void LiteCGIRBuilder::HandleFloatDiv(GateRef gate)
2024 {
2025     auto g0 = acc_.GetIn(gate, 0);
2026     auto g1 = acc_.GetIn(gate, 1);
2027     VisitFloatDiv(gate, g0, g1);
2028 }
2029 
VisitFloatDiv(GateRef gate,GateRef e1,GateRef e2)2030 void LiteCGIRBuilder::VisitFloatDiv(GateRef gate, GateRef e1, GateRef e2)
2031 {
2032     Expr e1Value = GetExprFromGate(e1);
2033     Expr e2Value = GetExprFromGate(e2);
2034     Expr result = lmirBuilder_->SDiv(ConvertLiteCGTypeFromGate(gate), e1Value, e2Value);
2035     SaveGate2Expr(gate, result);
2036 }
2037 
HandleTruncFloatToInt(GateRef gate)2038 void LiteCGIRBuilder::HandleTruncFloatToInt(GateRef gate)
2039 {
2040     auto g0 = acc_.GetIn(gate, 0);
2041     VisitTruncFloatToInt(gate, g0);
2042 }
2043 
VisitTruncFloatToInt(GateRef gate,GateRef e1)2044 void LiteCGIRBuilder::VisitTruncFloatToInt(GateRef gate, GateRef e1)
2045 {
2046     Expr e1Value = GetExprFromGate(e1);
2047     auto machineType = acc_.GetMachineType(e1);
2048     Expr result;
2049     if (machineType <= MachineType::F64 && machineType >= MachineType::F32) {
2050         result = lmirBuilder_->Trunc(ConvertLiteCGTypeFromGate(e1), lmirBuilder_->i64Type, e1Value);
2051     } else {
2052         LOG_ECMA(FATAL) << "this branch is unreachable";
2053         UNREACHABLE();
2054     }
2055     SaveGate2Expr(gate, result);
2056 }
2057 
HandleAddWithOverflow(GateRef gate)2058 void LiteCGIRBuilder::HandleAddWithOverflow(GateRef gate)
2059 {
2060     auto in0 = acc_.GetIn(gate, 0);
2061     auto in1 = acc_.GetIn(gate, 1);
2062     ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
2063     ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
2064     VisitAddWithOverflow(gate, in0, in1);
2065 }
2066 
VisitAddWithOverflow(GateRef gate,GateRef e1,GateRef e2)2067 void LiteCGIRBuilder::VisitAddWithOverflow(GateRef gate, GateRef e1, GateRef e2)
2068 {
2069     // need use different symbol name?
2070     // get return type {i32 res, u1 carry}
2071     auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
2072     retType = retType ? retType
2073                       : lmirBuilder_->CreateStructType("overflow_internal@i32")
2074                             .Field("res", lmirBuilder_->i32Type)
2075                             .Field("carry", lmirBuilder_->u1Type)
2076                             .Done();
2077     static uint32_t val = 0;
2078     std::string retVarName = "add_overflow_ret@i32" + std::to_string(val++);
2079     Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
2080 
2081     // generate function call
2082     Expr e1Value = GetExprFromGate(e1);
2083     Expr e2Value = GetExprFromGate(e2);
2084     std::vector<Expr> args = {e1Value, e2Value};
2085     auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_ADD_WITH_OVERFLOW, args, &retVar);
2086     SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
2087     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
2088 }
2089 
HandleSubWithOverflow(GateRef gate)2090 void LiteCGIRBuilder::HandleSubWithOverflow(GateRef gate)
2091 {
2092     auto in0 = acc_.GetIn(gate, 0);
2093     auto in1 = acc_.GetIn(gate, 1);
2094     ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
2095     ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
2096     VisitSubWithOverflow(gate, in0, in1);
2097 }
2098 
VisitSubWithOverflow(GateRef gate,GateRef e1,GateRef e2)2099 void LiteCGIRBuilder::VisitSubWithOverflow(GateRef gate, GateRef e1, GateRef e2)
2100 {
2101     // need use different symbol name?
2102     // get return type {i32 res, u1 carry}
2103     auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
2104     retType = retType ? retType
2105                       : lmirBuilder_->CreateStructType("overflow_internal@i32")
2106                             .Field("res", lmirBuilder_->i32Type)
2107                             .Field("carry", lmirBuilder_->u1Type)
2108                             .Done();
2109     static uint32_t val = 0;
2110     std::string retVarName = "sub_overflow_ret@i32" + std::to_string(val++);
2111     Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
2112 
2113     // generate function call
2114     Expr e1Value = GetExprFromGate(e1);
2115     Expr e2Value = GetExprFromGate(e2);
2116     std::vector<Expr> args = {e1Value, e2Value};
2117     auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_SUB_WITH_OVERFLOW, args, &retVar);
2118     SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
2119     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
2120 }
2121 
HandleMulWithOverflow(GateRef gate)2122 void LiteCGIRBuilder::HandleMulWithOverflow(GateRef gate)
2123 {
2124     auto in0 = acc_.GetIn(gate, 0);
2125     auto in1 = acc_.GetIn(gate, 1);
2126     ASSERT(acc_.GetMachineType(in0) == MachineType::I32);
2127     ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
2128     VisitMulWithOverflow(gate, in0, in1);
2129 }
2130 
VisitMulWithOverflow(GateRef gate,GateRef e1,GateRef e2)2131 void LiteCGIRBuilder::VisitMulWithOverflow(GateRef gate, GateRef e1, GateRef e2)
2132 {
2133     // need use different symbol name?
2134     // get return type {i32 res, u1 carry}
2135     auto *retType = lmirBuilder_->GetStructType("overflow_internal@i32");
2136     retType = retType ? retType
2137                       : lmirBuilder_->CreateStructType("overflow_internal@i32")
2138                             .Field("res", lmirBuilder_->i32Type)
2139                             .Field("carry", lmirBuilder_->u1Type)
2140                             .Done();
2141     static uint32_t val = 0;
2142     std::string retVarName = "mul_overflow_ret@i32" + std::to_string(val++);
2143     Var &retVar = lmirBuilder_->CreateLocalVar(retType, retVarName);
2144 
2145     // generate function call
2146     Expr e1Value = GetExprFromGate(e1);
2147     Expr e2Value = GetExprFromGate(e2);
2148     std::vector<Expr> args = {e1Value, e2Value};
2149     auto &call = lmirBuilder_->IntrinsicCall(IntrinsicId::INTRN_MUL_WITH_OVERFLOW, args, &retVar);
2150     SaveGate2Expr(gate, lmirBuilder_->Dread(retVar));
2151     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), call);
2152 }
2153 
HandleSExtInt(GateRef gate)2154 void LiteCGIRBuilder::HandleSExtInt(GateRef gate)
2155 {
2156     std::vector<GateRef> ins;
2157     acc_.GetIns(gate, ins);
2158     VisitSExtInt(gate, ins[0]);
2159 }
2160 
VisitSExtInt(GateRef gate,GateRef e1)2161 void LiteCGIRBuilder::VisitSExtInt(GateRef gate, GateRef e1)
2162 {
2163     Expr e1Value = GetExprFromGate(e1);
2164     LiteCGType *fromType = ConvertLiteCGTypeFromGate(e1);
2165     LiteCGType *toType = ConvertLiteCGTypeFromGate(gate);
2166     Expr result = lmirBuilder_->SExt(fromType, toType, e1Value);
2167     SaveGate2Expr(gate, result);
2168 }
2169 
HandleSqrt(GateRef gate)2170 void LiteCGIRBuilder::HandleSqrt(GateRef gate)
2171 {
2172     GateRef param = acc_.GetIn(gate, 0);
2173     VisitSqrt(gate, param);
2174 }
2175 
VisitSqrt(GateRef gate,GateRef e1)2176 void LiteCGIRBuilder::VisitSqrt(GateRef gate, GateRef e1)
2177 {
2178     Expr e1Value = GetExprFromGate(e1);
2179     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2180     Expr result;
2181     if (type == lmirBuilder_->f32Type || type == lmirBuilder_->f64Type) {
2182         result = lmirBuilder_->Sqrt(type, e1Value);
2183     } else {
2184         result = lmirBuilder_->Sqrt(lmirBuilder_->f64Type, lmirBuilder_->Cvt(type, lmirBuilder_->f64Type, e1Value));
2185     }
2186     SaveGate2Expr(gate, result);
2187 }
2188 
HandleExp(GateRef gate)2189 void LiteCGIRBuilder::HandleExp(GateRef gate)
2190 {
2191     (void)gate;
2192     CHECK_FATAL(false, "not support exp !");
2193 }
2194 
HandleCeil(GateRef gate)2195 void LiteCGIRBuilder::HandleCeil(GateRef gate)
2196 {
2197     VisitCeil(gate, acc_.GetIn(gate, 0));
2198 }
2199 
VisitCeil(GateRef gate,GateRef e1)2200 void LiteCGIRBuilder::VisitCeil(GateRef gate, GateRef e1)
2201 {
2202     Expr e1Value = GetExprFromGate(e1);
2203     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2204     Expr result = lmirBuilder_->Ceil(type, type, e1Value);
2205     SaveGate2Expr(gate, result);
2206 }
2207 
HandleAbs(GateRef gate)2208 void LiteCGIRBuilder::HandleAbs(GateRef gate)
2209 {
2210     VisitAbs(gate, acc_.GetIn(gate, 0));
2211 }
2212 
VisitAbs(GateRef gate,GateRef e1)2213 void LiteCGIRBuilder::VisitAbs(GateRef gate, GateRef e1)
2214 {
2215     auto machineType = acc_.GetMachineType(gate);
2216     ASSERT(acc_.GetMachineType(e1) == machineType);
2217     Expr result;
2218     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2219     Expr e1Value = GetExprFromGate(e1);
2220     if (machineType == MachineType::I32 || machineType == MachineType::F64) {
2221         result = lmirBuilder_->Abs(type, e1Value);
2222     } else {
2223         LOG_ECMA(FATAL) << "`Abs` type should be untagged double or signed int";
2224         UNREACHABLE();
2225     }
2226     SaveGate2Expr(gate, result);
2227     return;
2228 }
2229 
HandleMin(GateRef gate)2230 void LiteCGIRBuilder::HandleMin(GateRef gate)
2231 {
2232     VisitMin(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U));
2233 }
2234 
VisitMin(GateRef gate,GateRef e1,GateRef e2)2235 void LiteCGIRBuilder::VisitMin(GateRef gate, GateRef e1, GateRef e2)
2236 {
2237     auto machineType = acc_.GetMachineType(gate);
2238     ASSERT(acc_.GetMachineType(e1) == machineType);
2239     ASSERT(acc_.GetMachineType(e2) == machineType);
2240     Expr result;
2241     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2242     Expr e1Value = GetExprFromGate(e1);
2243     Expr e2Value = GetExprFromGate(e2);
2244     if (machineType == MachineType::I32 || machineType == MachineType::F64) {
2245         result = lmirBuilder_->Min(type, e1Value, e2Value);
2246     } else {
2247         LOG_ECMA(FATAL) << "`Min` type should be untagged double or signed int";
2248         UNREACHABLE();
2249     }
2250     SaveGate2Expr(gate, result);
2251     return;
2252 }
2253 
HandleMax(GateRef gate)2254 void LiteCGIRBuilder::HandleMax(GateRef gate)
2255 {
2256     VisitMax(gate, acc_.GetIn(gate, 0), acc_.GetIn(gate, 1U));
2257 }
2258 
VisitMax(GateRef gate,GateRef e1,GateRef e2)2259 void LiteCGIRBuilder::VisitMax(GateRef gate, GateRef e1, GateRef e2)
2260 {
2261     auto machineType = acc_.GetMachineType(gate);
2262     ASSERT(acc_.GetMachineType(e1) == machineType);
2263     ASSERT(acc_.GetMachineType(e2) == machineType);
2264     Expr result;
2265     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2266     Expr e1Value = GetExprFromGate(e1);
2267     Expr e2Value = GetExprFromGate(e2);
2268     if (machineType == MachineType::I32 || machineType == MachineType::F64) {
2269         result = lmirBuilder_->Max(type, e1Value, e2Value);
2270     } else {
2271         LOG_ECMA(FATAL) << "`Max` type should be untagged double or signed int";
2272         UNREACHABLE();
2273     }
2274     SaveGate2Expr(gate, result);
2275     return;
2276 }
2277 
HandleFloor(GateRef gate)2278 void LiteCGIRBuilder::HandleFloor(GateRef gate)
2279 {
2280     VisitFloor(gate, acc_.GetIn(gate, 0));
2281 }
2282 
VisitFloor(GateRef gate,GateRef e1)2283 void LiteCGIRBuilder::VisitFloor(GateRef gate, GateRef e1)
2284 {
2285     Expr e1Value = GetExprFromGate(e1);
2286     LiteCGType *type = ConvertLiteCGTypeFromGate(e1);
2287     Expr result = lmirBuilder_->Floor(type, type, e1Value);
2288     SaveGate2Expr(gate, result);
2289 }
2290 
HandleClz32(GateRef gate)2291 void LiteCGIRBuilder::HandleClz32(GateRef gate)
2292 {
2293     VisitClz32(gate, acc_.GetIn(gate, 0));
2294 }
2295 
VisitClz32(GateRef gate,GateRef param)2296 void LiteCGIRBuilder::VisitClz32(GateRef gate,  GateRef param)
2297 {
2298     std::vector<Expr> params;
2299     params.push_back(GetExprFromGate(param));
2300     LiteCGType *type = ConvertLiteCGTypeFromGate(param);
2301     Expr result = lmirBuilder_->IntrinsicOp(IntrinsicId::INTRN_C_clz32, type, params);
2302     SaveGate2Expr(gate, result);
2303 }
2304 
2305 
HandleReadSp(GateRef gate)2306 void LiteCGIRBuilder::HandleReadSp(GateRef gate)
2307 {
2308     ASSERT(acc_.GetOpCode(gate) == OpCode::READSP);
2309     VisitReadSp(gate);
2310 }
2311 
VisitReadSp(GateRef gate)2312 void LiteCGIRBuilder::VisitReadSp(GateRef gate)
2313 {
2314     Expr result = lmirBuilder_->LiteCGGetPregSP();
2315     SaveGate2Expr(gate, result);
2316 }
2317 
HandleInitVreg(GateRef gate)2318 void LiteCGIRBuilder::HandleInitVreg(GateRef gate)
2319 {
2320     ASSERT(acc_.GetOpCode(gate) == OpCode::INITVREG);
2321     VisitInitVreg(gate);
2322 }
2323 
VisitInitVreg(GateRef gate)2324 void LiteCGIRBuilder::VisitInitVreg(GateRef gate)
2325 {
2326     size_t vregNumber = acc_.GetInitOffset(gate);
2327     BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
2328     LiteCGType *i64 = lmirBuilder_->i64Type;
2329     LiteCGType *i64Ptr = lmirBuilder_->i64PtrType;
2330     LiteCGType *i64Ref = lmirBuilder_->i64RefType;
2331     LiteCGType *i32 = lmirBuilder_->i32Type;
2332     switch (vregNumber) {
2333         case INIT_VRGE_GLUE: {
2334             // init glue
2335             Expr glue = lmirBuilder_->GenExprFromVar(
2336                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 0));  // 0 : osr first param - glue
2337             SaveGate2Expr(gate, glue);
2338             return;
2339         }
2340         case INIT_VRGE_ARGS: {
2341             // init argc
2342             SaveGate2Expr(gate, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0)));
2343             return;
2344         }
2345         case INIT_VRGE_FUNCTION: {
2346             // init func
2347             PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref);
2348             // load from frame
2349             Expr sp = lmirBuilder_->GenExprFromVar(
2350                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1));  // 1 : osr second param - sp
2351             Expr offsetFrame = lmirBuilder_->ConstVal(
2352                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64())));
2353             Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame);
2354             Expr offsetFunc = lmirBuilder_->ConstVal(
2355                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetFunctionOffset(!circuit_->IsArch64())));
2356             Expr addrFunc = lmirBuilder_->Add(i64Ptr, frame, offsetFunc);
2357             Expr ldrFunc = lmirBuilder_->Iread(i64Ref, addrFunc, lmirBuilder_->CreatePtrType(i64Ptr));
2358             lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrFunc, vreg));
2359             if (IsOptimizedJSFunction()) {
2360                 // reset jsfunc on OptJSFuncFrame
2361                 Expr fpAddr = CallingFp(false);
2362                 Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr);
2363                 size_t reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_);
2364                 Expr frameJSFuncSlotAddr =
2365                     lmirBuilder_->Sub(frameAddr.GetType(), frameAddr,
2366                                       lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset)));
2367                 Expr jsFuncAddr = lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(),
2368                                                     lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr);
2369                 Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->Regread(vreg));
2370                 auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType());
2371                 lmirBuilder_->AppendStmt(bb, stmt);
2372             }
2373             SaveGate2Expr(gate, lmirBuilder_->Regread(vreg));
2374             return;
2375         }
2376         case INIT_VRGE_NEW_TARGET: {
2377             // init new_target
2378             PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref);
2379             // load func from interpreter sp
2380             Expr sp = lmirBuilder_->GenExprFromVar(
2381                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1));  // 1 : osr second param - sp
2382             Expr offsetFrame = lmirBuilder_->ConstVal(
2383                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64())));
2384             Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame);
2385             Expr offsetFunc = lmirBuilder_->ConstVal(
2386                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetFunctionOffset(!circuit_->IsArch64())));
2387             Expr addrFunc = lmirBuilder_->Add(i64Ptr, frame, offsetFunc);
2388             Expr func = lmirBuilder_->Iread(i64Ref, addrFunc, lmirBuilder_->CreatePtrType(i64Ptr));
2389             // load method from func
2390             Expr offsetMethod = lmirBuilder_->ConstVal(
2391                 lmirBuilder_->CreateIntConst(lmirBuilder_->i64PtrType, JSFunctionBase::METHOD_OFFSET));
2392             Expr addrMethod = lmirBuilder_->Add(i64Ptr, func, offsetMethod);
2393             Expr method = lmirBuilder_->Iread(i64Ptr, addrMethod, lmirBuilder_->CreatePtrType(i64Ptr));
2394             // load callField from method
2395             Expr offsetCF = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, Method::CALL_FIELD_OFFSET));
2396             Expr addrCF = lmirBuilder_->Add(i64Ptr, method, offsetCF);
2397             Expr cf = lmirBuilder_->Iread(i64, addrCF, lmirBuilder_->CreatePtrType(i64));
2398             // cal new target offset from callField
2399             Expr offsetNVSB =
2400                 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, MethodLiteral::NumVregsBits::START_BIT));
2401             Expr offsetNVSZ = lmirBuilder_->ConstVal(
2402                 lmirBuilder_->CreateIntConst(i64, (1LLU << MethodLiteral::NumVregsBits::SIZE) - 1));
2403             Expr offsetHFSB =
2404                 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, MethodLiteral::HaveFuncBit::START_BIT));
2405             Expr offsetHFSZ = lmirBuilder_->ConstVal(
2406                 lmirBuilder_->CreateIntConst(i64, (1LLU << MethodLiteral::HaveFuncBit::SIZE) - 1));
2407             Expr const0 = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0));
2408             Expr numVregs = lmirBuilder_->Cvt(
2409                 i64, i32, lmirBuilder_->And(i64, lmirBuilder_->LShr(i64, cf, offsetNVSB), offsetNVSZ));
2410             Expr haveFunc = lmirBuilder_->Cvt(
2411                 i64, i32,
2412                 lmirBuilder_->ICmp(i64, lmirBuilder_->And(i64, lmirBuilder_->LShr(i64, cf, offsetHFSB), offsetHFSZ),
2413                                    const0, IntCmpCondition::kNE));
2414             Expr size = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, JSTaggedValue::TaggedTypeSize()));
2415             Expr offsetNewTarget = lmirBuilder_->Mul(
2416                 i64Ptr, lmirBuilder_->ZExt(i32, i64Ptr, lmirBuilder_->Add(i32, numVregs, haveFunc)), size);
2417             // load new target from sp
2418             Expr addrNewTarget = lmirBuilder_->Add(i64Ptr, sp, offsetNewTarget);
2419             Expr ldrNewTarget = lmirBuilder_->Iread(i64Ref, addrNewTarget, lmirBuilder_->CreatePtrType(i64Ptr));
2420             lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrNewTarget, vreg));
2421             SaveGate2Expr(gate, lmirBuilder_->Regread(vreg));
2422             return;
2423         }
2424         case INIT_VRGE_THIS_OBJECT: {
2425             // init this
2426             PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref);
2427             // load from frame
2428             Expr sp = lmirBuilder_->GenExprFromVar(
2429                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1));  // 1 : osr second param - sp
2430             Expr offsetFrame = lmirBuilder_->ConstVal(
2431                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64())));
2432             Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame);
2433             Expr offsetThis = lmirBuilder_->ConstVal(
2434                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetThisOffset(!circuit_->IsArch64())));
2435             Expr addrThis = lmirBuilder_->Add(i64Ptr, frame, offsetThis);
2436             Expr ldrThis = lmirBuilder_->Iread(i64Ref, addrThis, lmirBuilder_->CreatePtrType(i64Ptr));
2437             lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrThis, vreg));
2438             SaveGate2Expr(gate, lmirBuilder_->Regread(vreg));
2439             return;
2440         }
2441         case INIT_VRGE_NUM_ARGS: {
2442             // init numargs
2443             SaveGate2Expr(gate, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64, 0)));
2444             return;
2445         }
2446         case INIT_VRGE_ENV: {
2447             // init env
2448             PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref);
2449             // load from frame
2450             Expr sp = lmirBuilder_->GenExprFromVar(
2451                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1));  // 1 : osr second param - sp
2452             Expr offsetFrame = lmirBuilder_->ConstVal(
2453                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetSize(!circuit_->IsArch64())));
2454             Expr frame = lmirBuilder_->Sub(i64Ptr, sp, offsetFrame);
2455             Expr offsetEnv = lmirBuilder_->ConstVal(
2456                 lmirBuilder_->CreateIntConst(i64Ptr, AsmInterpretedFrame::GetEnvOffset(!circuit_->IsArch64())));
2457             Expr addrEnv = lmirBuilder_->Add(i64Ptr, frame, offsetEnv);
2458             Expr ldrEnv = lmirBuilder_->Iread(i64Ref, addrEnv, lmirBuilder_->CreatePtrType(i64Ptr));
2459             lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrEnv, vreg));
2460             SaveGate2Expr(gate, lmirBuilder_->Regread(vreg));
2461             return;
2462         }
2463         default: {
2464             // init vregs
2465             PregIdx vreg = lmirBuilder_->CreatePreg(i64Ref);
2466             // load from sp
2467             Expr sp = lmirBuilder_->GenExprFromVar(
2468                 lmirBuilder_->GetParam(lmirBuilder_->GetCurFunction(), 1));  // 1 : osr second param - sp
2469             Expr offset =
2470                 lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(i64Ptr, vregNumber * sizeof(JSTaggedType)));
2471             Expr addr = lmirBuilder_->Add(i64Ptr, sp, offset);
2472             Expr ldrVreg = lmirBuilder_->Iread(i64Ref, addr, lmirBuilder_->CreatePtrType(i64Ptr));
2473             lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(ldrVreg, vreg));
2474             SaveGate2Expr(gate, lmirBuilder_->Regread(vreg));
2475             return;
2476         }
2477     }
2478 }
2479 
HandleFPTrunc(GateRef gate)2480 void LiteCGIRBuilder::HandleFPTrunc(GateRef gate)
2481 {
2482     VisitFPTrunc(gate, acc_.GetIn(gate, 0));
2483 }
2484 
VisitFPTrunc(GateRef gate,GateRef e1)2485 void LiteCGIRBuilder::VisitFPTrunc(GateRef gate, GateRef e1)
2486 {
2487     Expr e1Value = GetExprFromGate(e1);
2488     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) >=
2489            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
2490     Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value);
2491     SaveGate2Expr(gate, result);
2492 }
2493 
HandleFPExt(GateRef gate)2494 void LiteCGIRBuilder::HandleFPExt(GateRef gate)
2495 {
2496     VisitFPExt(gate, acc_.GetIn(gate, 0));
2497 }
2498 
VisitFPExt(GateRef gate,GateRef e1)2499 void LiteCGIRBuilder::VisitFPExt(GateRef gate, GateRef e1)
2500 {
2501     Expr e1Value = GetExprFromGate(e1);
2502     ASSERT(GetBitWidthFromMachineType(acc_.GetMachineType(e1)) <=
2503            GetBitWidthFromMachineType(acc_.GetMachineType(gate)));
2504     Expr result = lmirBuilder_->Cvt(ConvertLiteCGTypeFromGate(e1), ConvertLiteCGTypeFromGate(gate), e1Value);
2505     SaveGate2Expr(gate, result);
2506 }
2507 
HandleExtractValue(GateRef gate)2508 void LiteCGIRBuilder::HandleExtractValue(GateRef gate)
2509 {
2510     GateRef pointer = acc_.GetIn(gate, 0);
2511     GateRef index = acc_.GetIn(gate, 1);
2512     VisitExtractValue(gate, pointer, index);
2513 }
2514 
VisitExtractValue(GateRef gate,GateRef e1,GateRef e2)2515 void LiteCGIRBuilder::VisitExtractValue(GateRef gate, GateRef e1, GateRef e2)
2516 {
2517     Expr e1Value = GetExprFromGate(e1);
2518     ASSERT((acc_.GetOpCode(e2) == OpCode::CONSTANT) && acc_.GetMachineType(e2) == MachineType::I32);
2519     uint32_t index = static_cast<uint32_t>(acc_.GetConstantValue(e2));
2520     Var *baseVar = lmirBuilder_->GetLocalVarFromExpr(e1Value);
2521     ASSERT(baseVar != nullptr);
2522     // in maple type system, field 0 means the agg itself and field index start from 1
2523     Expr rhs = lmirBuilder_->DreadWithField(*baseVar, index + 1);
2524     PregIdx pregIdx = lmirBuilder_->CreatePreg(rhs.GetType());
2525     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), lmirBuilder_->Regassign(rhs, pregIdx));
2526     SaveGate2Expr(gate, lmirBuilder_->Regread(pregIdx));
2527 }
2528 
HandleStore(GateRef gate)2529 void LiteCGIRBuilder::HandleStore(GateRef gate)
2530 {
2531     GateRef addr = acc_.GetValueIn(gate, 0);
2532     GateRef value = acc_.GetValueIn(gate, 1);
2533     VisitStore(gate, addr, value);
2534 }
2535 
VisitStore(GateRef gate,GateRef base,GateRef value)2536 void LiteCGIRBuilder::VisitStore(GateRef gate, GateRef base, GateRef value)
2537 {
2538     Expr baseAddr = GetExprFromGate(base);
2539     Expr data = GetExprFromGate(value);
2540 
2541     LiteCGType *returnType = ConvertLiteCGTypeFromGate(value);
2542     LiteCGType *memType = (lmirBuilder_->IsHeapPointerType(baseAddr.GetType()))
2543                               ? lmirBuilder_->CreateRefType(returnType)
2544                               : lmirBuilder_->CreatePtrType(returnType);
2545     baseAddr = CanonicalizeToPtr(baseAddr, memType);
2546 
2547     Stmt &store = lmirBuilder_->Iassign(data, baseAddr, memType);
2548     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), store);
2549 }
2550 
HandlePhi(GateRef gate)2551 void LiteCGIRBuilder::HandlePhi(GateRef gate)
2552 {
2553     std::vector<GateRef> ins;
2554     acc_.GetIns(gate, ins);
2555     VisitPhi(gate, ins);
2556 }
2557 
AddPhiDesc(int bbID,PhiDesc & desc,std::map<int,std::vector<PhiDesc>> & bbID2Phis)2558 void LiteCGIRBuilder::AddPhiDesc(int bbID, PhiDesc &desc, std::map<int, std::vector<PhiDesc>> &bbID2Phis)
2559 {
2560     auto it = bbID2Phis.find(bbID);
2561     if (it == bbID2Phis.end()) {
2562         std::vector<PhiDesc> vec;
2563         vec.push_back(std::move(desc));
2564         bbID2Phis.insert(std::make_pair(bbID, vec));
2565     } else {
2566         it->second.push_back(std::move(desc));
2567     }
2568 }
2569 
CheckDerivedPhi(GateRef gate,std::set<GateRef> & vis)2570 LiteCGIRBuilder::DerivedStatus LiteCGIRBuilder::CheckDerivedPhi(GateRef gate, std::set<GateRef> &vis)
2571 {
2572     // if the gate status is cached with derived or base, doesn't need to go forward
2573     if (derivedGateCache_.find(gate) != derivedGateCache_.end()) {
2574         if (derivedGateCache_[gate]) {
2575             return DerivedStatus::IS_DERIVED;
2576         } else {
2577             return DerivedStatus::IS_BASE;
2578         }
2579     }
2580     // for the visited gate in the dfs, if not cached, its status is unknow
2581     if (vis.find(gate) != vis.end()) {
2582         return DerivedStatus::UNKNOW;
2583     }
2584     // cached gate doesn't need insert to visited set
2585     vis.insert(gate);
2586     DerivedStatus derivedStatus = DerivedStatus::IS_BASE;
2587     std::vector<GateRef> phiIns;
2588     acc_.GetIns(gate, phiIns);
2589     std::vector<GateRef> phiStates;
2590     acc_.GetIns(phiIns[0], phiStates);
2591     ASSERT(phiStates.size() + 1 == phiIns.size());
2592     for (int i = 1; i < static_cast<int>(phiIns.size()); i++) {
2593         auto op = acc_.GetOpCode(phiIns[i]);
2594         if (op == OpCode::ADD) {
2595             derivedStatus = DerivedStatus::IS_DERIVED;
2596             break;
2597         } else if (op == OpCode::VALUE_SELECTOR) {
2598             DerivedStatus status = CheckDerivedPhi(phiIns[i], vis);
2599             if (status == DerivedStatus::IS_DERIVED) {
2600                 derivedStatus = DerivedStatus::IS_DERIVED;
2601                 break;
2602             }
2603             if (status == DerivedStatus::UNKNOW) {
2604                 derivedStatus = DerivedStatus::UNKNOW;
2605             }
2606         }
2607     }
2608     if (derivedStatus == DerivedStatus::IS_DERIVED) {
2609         derivedGateCache_[gate] = true;
2610     } else if (derivedStatus == DerivedStatus::IS_BASE) {
2611         derivedGateCache_[gate] = false;
2612     }
2613 
2614     return derivedStatus;
2615 }
2616 
FindBaseRefForPhi(GateRef gate,const std::vector<GateRef> & phiIns)2617 void LiteCGIRBuilder::FindBaseRefForPhi(GateRef gate, const std::vector<GateRef> &phiIns)
2618 {
2619     int curBBId = instID2bbID_[acc_.GetId(gate)];
2620     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
2621     PregIdx basePregIdx = 0;
2622     bool isDerived = false;
2623     std::set<GateRef> baseIns;
2624     std::vector<PhiDesc> phiDescs;
2625     std::vector<GateRef> phiStates;
2626     acc_.GetIns(phiIns[0], phiStates);
2627     ASSERT(phiStates.size() + 1 == phiIns.size());
2628     for (int i = 1; i < static_cast<int>(phiIns.size()); i++) {
2629         int preBBId = LookupPredBB(phiStates[i - 1], curBBId);
2630         if (bbID2BB_.count(preBBId) != 0) {
2631             BB *preBB = bbID2BB_[preBBId];
2632             if (preBB == nullptr) {
2633                 OPTIONAL_LOG_COMPILER(ERROR) << "FindBaseRef failed BasicBlock nullptr";
2634                 return;
2635             }
2636         }
2637         auto op = acc_.GetOpCode(phiIns[i]);
2638         if (op == OpCode::ADD) {
2639             auto g0 = acc_.GetIn(phiIns[i], 0);
2640             baseIns.insert(g0);
2641             PhiDesc desc = {preBBId, g0, basePregIdx};
2642             phiDescs.push_back(desc);
2643             isDerived = true;
2644             ASSERT(ConvertLiteCGTypeFromGate(g0) == lmirBuilder_->i64RefType);
2645         } else if (op == OpCode::VALUE_SELECTOR) {
2646             std::set<GateRef> vis;
2647             if (CheckDerivedPhi(phiIns[i], vis) == DerivedStatus::IS_DERIVED) {
2648                 isDerived = true;
2649             }
2650             baseIns.insert(phiIns[i]);
2651             PhiDesc desc = {preBBId, phiIns[i], basePregIdx};
2652             phiDescs.push_back(desc);
2653             ASSERT(ConvertLiteCGTypeFromGate(phiIns[i]) == lmirBuilder_->i64RefType);
2654         } else {
2655             baseIns.insert(phiIns[i]);
2656             PhiDesc desc = {preBBId, phiIns[i], basePregIdx};
2657             phiDescs.push_back(desc);
2658             ASSERT(ConvertLiteCGTypeFromGate(phiIns[i]) == lmirBuilder_->i64RefType);
2659         }
2660     }
2661 
2662     // use to catch the situation that the phi is derived
2663     if (isDerived) {
2664         LOG_COMPILER(FATAL) << "catch derived case!" << phiDescs.size() << std::endl;
2665         UNREACHABLE();
2666     }
2667 
2668     derivedGateCache_[gate] = isDerived;
2669 
2670     if (!isDerived) {
2671         return;
2672     }
2673 
2674     if (baseIns.size() == 1) {
2675         // only one base gate for the derived phi reference, doesn't need to insert a new phi
2676         derivedGate2BaseGate_[gate] = *baseIns.begin();
2677     } else {
2678         basePregIdx = lmirBuilder_->CreatePreg(type);
2679         derivedPhiGate2BasePhiPreg_[gate] = basePregIdx;
2680         for (PhiDesc desc : phiDescs) {
2681             desc.phi = basePregIdx;
2682             AddPhiDesc(curBBId, desc, bbID2basePhis_);
2683         }
2684     }
2685 }
2686 
VisitPhi(GateRef gate,const std::vector<GateRef> & phiIns)2687 void LiteCGIRBuilder::VisitPhi(GateRef gate, const std::vector<GateRef> &phiIns)
2688 {
2689     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
2690     PregIdx phiPregIdx = lmirBuilder_->CreatePreg(type);
2691 
2692     if (phiIns.size() > 1) {
2693         SaveGate2Expr(gate, lmirBuilder_->Regread(phiPregIdx));
2694     }
2695     // Collect the states merges of this phi and note the 1-in is the merged states.
2696     std::vector<GateRef> phiStates;
2697     acc_.GetIns(phiIns[0], phiStates);
2698     ASSERT(phiStates.size() + 1 == phiIns.size());
2699     int curBBId = instID2bbID_[acc_.GetId(gate)];
2700     for (int i = 1; i < static_cast<int>(phiIns.size()); i++) {
2701         int preBBId = LookupPredBB(phiStates[i - 1], curBBId);
2702         // if bbID2BB_.count(preBBId) = 0 means bb with current bbIdx hasn't been created
2703         if (bbID2BB_.count(preBBId) != 0) {
2704             BB *preBB = bbID2BB_[preBBId];
2705             if (preBB == nullptr) {
2706                 OPTIONAL_LOG_COMPILER(ERROR) << "VisitPhi failed BasicBlock nullptr";
2707                 return;
2708             }
2709             PhiDesc desc = {preBBId, phiIns[i], phiPregIdx};
2710             AddPhiDesc(curBBId, desc, bbID2unmergedPhis_);
2711         } else {
2712             PhiDesc desc = {preBBId, phiIns[i], phiPregIdx};
2713             AddPhiDesc(curBBId, desc, bbID2unmergedPhis_);
2714         }
2715     }
2716 
2717     if (type == lmirBuilder_->i64RefType) {
2718         FindBaseRefForPhi(gate, phiIns);
2719     }
2720 }
2721 
HandleSwitch(GateRef gate)2722 void LiteCGIRBuilder::HandleSwitch(GateRef gate)
2723 {
2724     std::vector<GateRef> ins;
2725     acc_.GetIns(gate, ins);
2726     std::vector<GateRef> outs;
2727     acc_.GetOutStates(gate, outs);
2728     VisitSwitch(gate, ins[1], outs);
2729 }
2730 
VisitSwitch(GateRef gate,GateRef input,const std::vector<GateRef> & outList)2731 void LiteCGIRBuilder::VisitSwitch(GateRef gate, GateRef input, const std::vector<GateRef> &outList)
2732 {
2733     Expr cond = GetExprFromGate(input);
2734     int caseNum = static_cast<int>(outList.size());
2735     BB *defaultOutBB = nullptr;
2736     for (int i = 0; i < caseNum; i++) {
2737         if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
2738             defaultOutBB = &GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]);
2739         }
2740     }
2741 
2742     LiteCGType *type = ConvertLiteCGTypeFromGate(gate);
2743     CHECK_NULL_FATAL(defaultOutBB);
2744     SwitchBuilder builder = lmirBuilder_->Switch(type, cond, *defaultOutBB);
2745     for (int i = 0; i < caseNum; i++) {
2746         if (acc_.GetOpCode(outList[i]) == OpCode::DEFAULT_CASE) {
2747             continue;
2748         }
2749         BB &curOutBB = GetOrCreateBB(instID2bbID_[acc_.GetId(outList[i])]);
2750         builder.Case(acc_.TryGetValue(outList[i]), curOutBB);
2751     }
2752     Stmt &switchStmt = builder.Done();
2753     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), switchStmt);
2754     lmirBuilder_->AppendBB(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]));
2755 }
2756 
HandleBytecodeCall(GateRef gate)2757 void LiteCGIRBuilder::HandleBytecodeCall(GateRef gate)
2758 {
2759     std::vector<GateRef> ins;
2760     acc_.GetIns(gate, ins);
2761     VisitBytecodeCall(gate, ins);
2762 }
2763 
GetBaseOffset(GateRef gate,Expr glue)2764 Expr LiteCGIRBuilder::GetBaseOffset(GateRef gate, Expr glue)
2765 {
2766     switch (acc_.GetOpCode(gate)) {
2767         case OpCode::BYTECODE_CALL:
2768             return GetBCStubOffset(glue);
2769         case OpCode::DEBUGGER_BYTECODE_CALL:
2770             return GetBCDebugStubOffset(glue);
2771         default:
2772             LOG_ECMA(FATAL) << "this branch is unreachable";
2773             UNREACHABLE();
2774     }
2775 }
2776 
GetBCStubOffset(Expr glue)2777 Expr LiteCGIRBuilder::GetBCStubOffset(Expr glue)
2778 {
2779     return lmirBuilder_->ConstVal(
2780         lmirBuilder_->CreateIntConst(glue.GetType(), JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit())));
2781 }
2782 
GetBCDebugStubOffset(Expr glue)2783 Expr LiteCGIRBuilder::GetBCDebugStubOffset(Expr glue)
2784 {
2785     return lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(
2786         glue.GetType(), JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit())));
2787 }
2788 
VisitBytecodeCall(GateRef gate,const std::vector<GateRef> & inList)2789 void LiteCGIRBuilder::VisitBytecodeCall(GateRef gate, const std::vector<GateRef> &inList)
2790 {
2791     size_t paraStartIndex = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
2792     size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
2793     size_t glueIndex = static_cast<size_t>(CallInputs::GLUE);
2794     Expr opcodeOffset = GetExprFromGate(inList[targetIndex]);
2795 
2796     // start index of bytecode handler csign
2797     Expr glue = GetExprFromGate(inList[glueIndex]);
2798     Expr baseOffset = GetBaseOffset(gate, glue);
2799     Expr offset = lmirBuilder_->Add(baseOffset.GetType(), baseOffset, opcodeOffset);
2800     Expr rtbaseoffset = lmirBuilder_->Add(glue.GetType(), glue, offset);
2801     const CallSignature *signature = BytecodeStubCSigns::BCHandler();
2802     BB &bb = GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]);
2803     Expr callee = GetFunction(bb, glue, signature, rtbaseoffset);
2804 
2805     std::vector<Expr> params;
2806     for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) {
2807         GateRef gateTmp = inList[paraIdx];
2808         params.push_back(GetExprFromGate(gateTmp));
2809     }
2810 
2811     LiteCGType *funcType = GenerateFuncType(params, signature);
2812     LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
2813     static uint32_t retNo = 0;
2814     std::string retName = signature->GetName() + "Ret" + std::to_string(retNo++);
2815     Var *returnVar =
2816         (returnType == lmirBuilder_->voidType) ? nullptr : &(lmirBuilder_->CreateLocalVar(returnType, retName));
2817     Stmt &callNode = lmirBuilder_->ICall(callee, params, returnVar);
2818     lmirBuilder_->AppendStmt(bb, callNode);
2819     if (returnVar != nullptr) {
2820         SaveGate2Expr(gate, lmirBuilder_->Dread(*returnVar));
2821     }
2822 
2823     lmirBuilder_->SetStmtCallConv(callNode, maple::litecg::GHC_Call);
2824 }
2825 
HandleDeoptCheck(GateRef gate)2826 void LiteCGIRBuilder::HandleDeoptCheck(GateRef gate)
2827 {
2828     int block = instID2bbID_[acc_.GetId(gate)];
2829     std::vector<GateRef> outs;
2830     acc_.GetOutStates(gate, outs);
2831     int bbOut = instID2bbID_[acc_.GetId(outs[0])];  // 0: output
2832 
2833     BB &trueBB = GetOrCreateBB(bbOut);
2834     BB &falseBB = lmirBuilder_->CreateBB();
2835     GateRef cmp = acc_.GetValueIn(gate, 0);  // 0: cond
2836     Expr cond = GetExprFromGate(cmp);
2837     BB &curBB = GetOrCreateBB(block);
2838     lmirBuilder_->AppendStmt(curBB, lmirBuilder_->CondGoto(cond, falseBB, false));
2839     lmirBuilder_->AppendStmt(curBB, lmirBuilder_->Goto(trueBB));
2840     lmirBuilder_->AppendBB(curBB);
2841     // deopt branch is not expected to be token as often,
2842     // just put them to the end of the function
2843     lmirBuilder_->AppendToLast(falseBB);
2844 
2845     VisitDeoptCheck(gate);
2846     Expr returnValue = GetExprFromGate(gate);
2847     lmirBuilder_->AppendStmt(falseBB, lmirBuilder_->Return(returnValue));
2848 }
2849 
GetExperimentalDeoptTy()2850 LiteCGType *LiteCGIRBuilder::GetExperimentalDeoptTy()
2851 {
2852     std::vector<LiteCGType *> paramTys = {lmirBuilder_->i64Type, lmirBuilder_->i64RefType, lmirBuilder_->i64RefType};
2853     LiteCGType *functionType = lmirBuilder_->CreateFuncType(paramTys, lmirBuilder_->i64RefType, false);
2854     return functionType;
2855 }
2856 
SaveFrameTypeOnFrame(BB & bb,FrameType frameType)2857 void LiteCGIRBuilder::SaveFrameTypeOnFrame(BB &bb, FrameType frameType)
2858 {
2859     Expr llvmFpAddr = CallingFp(false);
2860     Expr frameAddr = lmirBuilder_->Cvt(llvmFpAddr.GetType(), slotType_, llvmFpAddr);
2861     Expr frameTypeSlotAddr = lmirBuilder_->Sub(
2862         slotType_, frameAddr, lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, slotSize_)));
2863     LiteCGType *slotTypePtr = lmirBuilder_->CreatePtrType(slotType_);
2864     Expr addr = lmirBuilder_->Cvt(frameTypeSlotAddr.GetType(), slotTypePtr, frameTypeSlotAddr);
2865     Expr llvmFrameType =
2866         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, static_cast<uintptr_t>(frameType)));
2867     Stmt &stmt = lmirBuilder_->Iassign(llvmFrameType, addr, slotTypePtr);
2868     lmirBuilder_->AppendStmt(bb, stmt);
2869 }
2870 
GenDeoptEntry(std::string funcName)2871 void LiteCGIRBuilder::GenDeoptEntry(std::string funcName)
2872 {
2873     BB &bb = CreateBB();
2874     auto reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_);
2875     lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize);
2876     SaveFrameTypeOnFrame(bb, FrameType::OPTIMIZED_FRAME);
2877     Function &func = lmirBuilder_->GetCurFunction();
2878     lmirModule_->SetFunction(LMIRModule::kDeoptEntryOffset, funcName, false);
2879 
2880     Expr glue = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 0));
2881     Expr check = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 1));
2882     Expr depth = lmirBuilder_->Dread(lmirBuilder_->GetParam(func, 2));
2883 
2884     StubIdType stubId = RTSTUB_ID(DeoptHandlerAsm);
2885     int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
2886     Expr rtoffset = lmirBuilder_->Add(glue.GetType(), glue, GetRTStubOffset(glue, stubIndex));
2887     Expr patchAddr = lmirBuilder_->Cvt(glue.GetType(), lmirBuilder_->i64PtrType, rtoffset);
2888     Expr funcAddr = lmirBuilder_->Iread(rtoffset.GetType(), patchAddr, lmirBuilder_->i64PtrType);
2889 
2890     LiteCGType *funcType = GetExperimentalDeoptTy();
2891     LiteCGType *funcTypePtr = lmirBuilder_->CreatePtrType(funcType);
2892     LiteCGType *funcTypePtrPtr = lmirBuilder_->CreatePtrType(funcTypePtr);
2893     Expr callee = lmirBuilder_->Cvt(glue.GetType(), funcTypePtrPtr, funcAddr);
2894 
2895     Var &funcVar = lmirBuilder_->CreateLocalVar(callee.GetType(), "DeoptimizeSubFunc");
2896     Stmt &funcAddrNode = lmirBuilder_->Dassign(callee, funcVar);
2897     lmirBuilder_->AppendStmt(bb, funcAddrNode);
2898 
2899     LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
2900     PregIdx pregIdx = lmirBuilder_->CreatePreg(returnType);
2901     std::vector<Expr> params = {glue, check, depth};
2902     Stmt &callNode = lmirBuilder_->ICall(lmirBuilder_->Dread(funcVar), params, pregIdx);
2903     lmirBuilder_->AppendStmt(bb, callNode);
2904     lmirBuilder_->AppendStmt(bb, lmirBuilder_->Return(lmirBuilder_->Regread(pregIdx)));
2905     lmirBuilder_->AppendBB(bb);
2906 }
2907 
GetExperimentalDeopt()2908 Function *LiteCGIRBuilder::GetExperimentalDeopt()
2909 {
2910     /* 0:calling 1:its caller */
2911     std::string funcName = "litecg.experimental.deoptimize.p1i64";
2912     auto fn = lmirBuilder_->GetFunc(funcName);
2913     if (!fn) {
2914         // save previous func for restore env
2915         Function &preFunc = lmirBuilder_->GetCurFunction();
2916         auto fnTy = GetExperimentalDeoptTy();
2917         FunctionBuilder funcBuilder = lmirBuilder_->DefineFunction(funcName);
2918         // glue type depth
2919         funcBuilder.Param(lmirBuilder_->i64Type, "glue")
2920             .Param(lmirBuilder_->i64RefType, "deopt_type")
2921             .Param(lmirBuilder_->i64RefType, "max_depth");
2922         Function &curFunc = funcBuilder.Return(lmirBuilder_->LiteCGGetFuncReturnType(fnTy)).Done();
2923         funcBuilder.CallConvAttribute(maple::litecg::CCall);
2924         lmirBuilder_->SetCurFunc(curFunc);
2925         GenDeoptEntry(funcName);
2926         fn = &curFunc;
2927 
2928         lmirBuilder_->SetCurFunc(preFunc);
2929     }
2930     return fn;
2931 }
2932 
ConvertToTagged(GateRef gate)2933 Expr LiteCGIRBuilder::ConvertToTagged(GateRef gate)
2934 {
2935     auto machineType = acc_.GetMachineType(gate);
2936     switch (machineType) {
2937         case MachineType::I1:
2938             return ConvertBoolToTaggedBoolean(gate);
2939         case MachineType::I32:
2940             return ConvertInt32ToTaggedInt(GetExprFromGate(gate));
2941         case MachineType::F64:
2942             return ConvertFloat64ToTaggedDouble(gate);
2943         case MachineType::I64:
2944             break;
2945         default:
2946             LOG_COMPILER(FATAL) << "unexpected machineType!";
2947             UNREACHABLE();
2948             break;
2949     }
2950     return GetExprFromGate(gate);
2951 }
2952 
ConvertInt32ToTaggedInt(Expr value)2953 Expr LiteCGIRBuilder::ConvertInt32ToTaggedInt(Expr value)
2954 {
2955     Expr e1Value = lmirBuilder_->SExt(value.GetType(), lmirBuilder_->i64Type, value);
2956     Expr tagMask = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_INT));
2957     Expr result = lmirBuilder_->Or(lmirBuilder_->i64Type, e1Value, tagMask);
2958     return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result);
2959 }
2960 
ConvertBoolToTaggedBoolean(GateRef gate)2961 Expr LiteCGIRBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
2962 {
2963     Expr value = GetExprFromGate(gate);
2964     Expr e1Value = lmirBuilder_->ZExt(value.GetType(), lmirBuilder_->u64Type, value);
2965     Expr tagMask =
2966         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::TAG_BOOLEAN_MASK));
2967     Expr result = lmirBuilder_->Or(lmirBuilder_->u64Type, e1Value, tagMask);
2968     return lmirBuilder_->Cvt(lmirBuilder_->u64Type, lmirBuilder_->i64RefType, result);
2969 }
2970 
ConvertFloat64ToTaggedDouble(GateRef gate)2971 Expr LiteCGIRBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
2972 {
2973     Expr value = GetExprFromGate(gate);
2974     Expr e1Value = lmirBuilder_->BitCast(value.GetType(), lmirBuilder_->i64Type, value);
2975     Expr offset = lmirBuilder_->ConstVal(
2976         lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, JSTaggedValue::DOUBLE_ENCODE_OFFSET));
2977     Expr result = lmirBuilder_->Add(lmirBuilder_->i64Type, e1Value, offset);
2978     return lmirBuilder_->Cvt(lmirBuilder_->i64Type, lmirBuilder_->i64RefType, result);
2979 }
2980 
SaveDeoptVregInfo(std::unordered_map<int,LiteCGValue> & deoptBundleInfo,BB & bb,int32_t index,size_t curDepth,size_t shift,GateRef gate)2981 void LiteCGIRBuilder::SaveDeoptVregInfo(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb, int32_t index,
2982                                         size_t curDepth, size_t shift, GateRef gate)
2983 {
2984     int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
2985     Expr value = ConvertToTagged(gate);
2986     PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType());
2987     lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx));
2988     deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kPregKind, pregIdx}));
2989 }
2990 
SaveDeoptVregInfoWithI64(std::unordered_map<int,LiteCGValue> & deoptBundleInfo,BB & bb,int32_t index,size_t curDepth,size_t shift,GateRef gate)2991 void LiteCGIRBuilder::SaveDeoptVregInfoWithI64(std::unordered_map<int, LiteCGValue> &deoptBundleInfo, BB &bb,
2992                                                int32_t index, size_t curDepth, size_t shift, GateRef gate)
2993 {
2994     int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(index, curDepth, shift);
2995     Expr expr = GetExprFromGate(gate);
2996     Expr value = ConvertInt32ToTaggedInt(lmirBuilder_->Cvt(expr.GetType(), lmirBuilder_->i32Type, expr));
2997     PregIdx pregIdx = lmirBuilder_->CreatePreg(value.GetType());
2998     lmirBuilder_->AppendStmt(bb, lmirBuilder_->Regassign(value, pregIdx));
2999     deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kPregKind, pregIdx}));
3000 }
3001 
VisitDeoptCheck(GateRef gate)3002 void LiteCGIRBuilder::VisitDeoptCheck(GateRef gate)
3003 {
3004     BB &bb = lmirBuilder_->GetLastAppendedBB();  // falseBB of deopt check
3005     Expr glue = GetExprFromGate(acc_.GetGlueFromArgList());
3006     GateRef deoptFrameState = acc_.GetValueIn(gate, 1);  // 1: frame state
3007     ASSERT(acc_.GetOpCode(deoptFrameState) == OpCode::FRAME_STATE);
3008     std::vector<Expr> params;
3009     params.push_back(glue);                        // glue
3010     GateRef deoptType = acc_.GetValueIn(gate, 2);  // 2: deopt type
3011     uint64_t v = acc_.GetConstantValue(deoptType);
3012     Expr constV = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(v)));
3013     params.push_back(ConvertInt32ToTaggedInt(constV));  // deoptType
3014     Function *callee = GetExperimentalDeopt();
3015     LiteCGType *funcType = GetExperimentalDeoptTy();
3016 
3017     std::unordered_map<int, LiteCGValue> deoptBundleInfo;
3018     size_t maxDepth = 0;
3019     GateRef frameState = acc_.GetFrameState(deoptFrameState);
3020     while ((acc_.GetOpCode(frameState) == OpCode::FRAME_STATE)) {
3021         maxDepth++;
3022         frameState = acc_.GetFrameState(frameState);
3023     }
3024     Expr constMaxDepth =
3025         lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, static_cast<uint32_t>(maxDepth)));
3026     params.push_back(ConvertInt32ToTaggedInt(constMaxDepth));
3027     size_t shift = Deoptimizier::ComputeShift(maxDepth);
3028     frameState = deoptFrameState;
3029     ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
3030     for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) {
3031         ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
3032         GateRef frameValues = acc_.GetValueIn(frameState, 1);  // 1: frame values
3033         const size_t numValueIn = acc_.GetNumValueIn(frameValues);
3034         const size_t envIndex = numValueIn - 2;  // 2: env valueIn index
3035         CHECK_FATAL(numValueIn > 0, "must not be zero");
3036         const size_t accIndex = numValueIn - 1;  // 1: acc valueIn index
3037         GateRef env = acc_.GetValueIn(frameValues, envIndex);
3038         GateRef acc = acc_.GetValueIn(frameValues, accIndex);
3039         auto pc = acc_.TryGetPcOffset(frameState);
3040         GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
3041         GateRef newTarget = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::NEW_TARGET);
3042         GateRef thisObj = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::THIS_OBJECT);
3043         GateRef actualArgc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::ACTUAL_ARGC);
3044         // vreg
3045         for (size_t i = 0; i < envIndex; i++) {
3046             GateRef vregValue = acc_.GetValueIn(frameValues, i);
3047             if (acc_.IsConstantTaggedValue(vregValue, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
3048                 continue;
3049             }
3050             SaveDeoptVregInfo(deoptBundleInfo, bb, i, curDepth, shift, vregValue);
3051         }
3052         // env
3053         if (!acc_.IsConstantTaggedValue(env, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
3054             int32_t specEnvVregIndex = static_cast<int32_t>(SpecVregIndex::ENV_INDEX);
3055             SaveDeoptVregInfo(deoptBundleInfo, bb, specEnvVregIndex, curDepth, shift, env);
3056         }
3057         // acc
3058         if (!acc_.IsConstantTaggedValue(acc, JSTaggedValue::VALUE_OPTIMIZED_OUT)) {
3059             int32_t specAccVregIndex = static_cast<int32_t>(SpecVregIndex::ACC_INDEX);
3060             SaveDeoptVregInfo(deoptBundleInfo, bb, specAccVregIndex, curDepth, shift, acc);
3061         }
3062         // pc offset
3063         int32_t specPcOffsetIndex = static_cast<int32_t>(SpecVregIndex::PC_OFFSET_INDEX);
3064         int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specPcOffsetIndex, curDepth, shift);
3065         Const &pcConst = lmirBuilder_->CreateIntConst(lmirBuilder_->u32Type, pc);
3066         deoptBundleInfo.insert(std::pair<int, LiteCGValue>(encodeIndex, {LiteCGValueKind::kConstKind, &pcConst}));
3067 
3068         // func
3069         int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FUNC_INDEX);
3070         SaveDeoptVregInfo(deoptBundleInfo, bb, specCallTargetIndex, curDepth, shift, jsFunc);
3071         // newTarget
3072         int32_t specNewTargetIndex = static_cast<int32_t>(SpecVregIndex::NEWTARGET_INDEX);
3073         SaveDeoptVregInfo(deoptBundleInfo, bb, specNewTargetIndex, curDepth, shift, newTarget);
3074         // this object
3075         int32_t specThisIndex = static_cast<int32_t>(SpecVregIndex::THIS_OBJECT_INDEX);
3076         SaveDeoptVregInfo(deoptBundleInfo, bb, specThisIndex, curDepth, shift, thisObj);
3077         int32_t specArgcIndex = static_cast<int32_t>(SpecVregIndex::ACTUAL_ARGC_INDEX);
3078         SaveDeoptVregInfoWithI64(deoptBundleInfo, bb, specArgcIndex, curDepth, shift, actualArgc);
3079         frameState = acc_.GetFrameState(frameState);
3080     }
3081     LiteCGType *returnType = lmirBuilder_->LiteCGGetFuncReturnType(funcType);
3082 
3083     bool returnVoid = (returnType == lmirBuilder_->voidType);
3084     PregIdx returnPregIdx = returnVoid ? -1 : lmirBuilder_->CreatePreg(returnType);
3085 
3086     Stmt &callNode = lmirBuilder_->Call(*callee, params, returnPregIdx);
3087     lmirBuilder_->SetCallStmtDeoptBundleInfo(callNode, deoptBundleInfo);
3088 
3089     lmirBuilder_->AppendStmt(bb, callNode);
3090     if (!returnVoid) {
3091         SaveGate2Expr(gate, lmirBuilder_->Regread(returnPregIdx));
3092     }
3093 }
3094 
HandleConstString(GateRef gate)3095 void LiteCGIRBuilder::HandleConstString(GateRef gate)
3096 {
3097     const ChunkVector<char> &str = acc_.GetConstantString(gate);  // 64: bit width
3098     VisitConstString(gate, str);
3099 }
3100 
VisitConstString(GateRef gate,const ChunkVector<char> & str)3101 void LiteCGIRBuilder::VisitConstString(GateRef gate, const ChunkVector<char> &str)  // 64: bit width
3102 {
3103     ASSERT(acc_.GetMachineType(gate) == MachineType::ARCH);
3104 
3105     Expr value = lmirBuilder_->ConstVal(lmirBuilder_->CreateStrConst(std::string(str.data(), str.size())));
3106     static uint32_t val = 0;
3107     std::string name = "ConstStringVar" + std::to_string(val++);
3108     Var &var = lmirBuilder_->CreateLocalVar(value.GetType(), name);
3109     Stmt &stmt = lmirBuilder_->Dassign(value, var);
3110     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), stmt);
3111     SaveGate2Expr(gate, lmirBuilder_->Addrof(var));
3112 }
3113 
HandleRelocatableData(GateRef gate)3114 void LiteCGIRBuilder::HandleRelocatableData(GateRef gate)
3115 {
3116     uint64_t value = acc_.TryGetValue(gate);
3117     VisitRelocatableData(gate, value);
3118 }
3119 
VisitRelocatableData(GateRef gate,uint64_t value)3120 void LiteCGIRBuilder::VisitRelocatableData(GateRef gate, uint64_t value)
3121 {
3122     Var &var = lmirBuilder_->CreateGlobalVar(lmirBuilder_->i64Type, "G", maple::litecg::GlobalVarAttr::VAR_internal);
3123     Expr constVal = lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(lmirBuilder_->i64Type, value));
3124     Stmt &stmt = lmirBuilder_->Dassign(constVal, var);
3125     lmirBuilder_->AppendStmt(GetOrCreateBB(instID2bbID_[acc_.GetId(gate)]), stmt);
3126     SaveGate2Expr(gate, lmirBuilder_->Dread(var));
3127 }
3128 
HandleAlloca(GateRef gate)3129 void LiteCGIRBuilder::HandleAlloca(GateRef gate)
3130 {
3131     return VisitAlloca(gate);
3132 }
3133 
VisitAlloca(GateRef gate)3134 void LiteCGIRBuilder::VisitAlloca(GateRef gate)
3135 {
3136     uint64_t machineRep = acc_.TryGetValue(gate);
3137     LiteCGType *dataType = GetMachineRepType(static_cast<MachineRep>(machineRep));
3138 
3139     static uint32_t val = 0;
3140     std::string name = "AllocaVar" + std::to_string(val++);
3141     Var &var = lmirBuilder_->CreateLocalVar(dataType, name);
3142     Expr addr = lmirBuilder_->Addrof(var);
3143     Expr addrCvt = lmirBuilder_->Cvt(addr.GetType(), ConvertLiteCGTypeFromGate(gate), addr);
3144     SaveGate2Expr(gate, addrCvt);
3145 }
3146 
GetMachineRepType(MachineRep rep) const3147 LiteCGType *LiteCGIRBuilder::GetMachineRepType(MachineRep rep) const
3148 {
3149     LiteCGType *dstType;
3150     switch (rep) {
3151         case MachineRep::K_BIT:
3152             dstType = lmirBuilder_->u1Type;
3153             break;
3154         case MachineRep::K_WORD8:
3155             dstType = lmirBuilder_->i8Type;
3156             break;
3157         case MachineRep::K_WORD16:
3158             dstType = lmirBuilder_->i16Type;
3159             break;
3160         case MachineRep::K_WORD32:
3161             dstType = lmirBuilder_->i32Type;
3162             break;
3163         case MachineRep::K_FLOAT64:
3164             dstType = lmirBuilder_->f64Type;
3165             break;
3166         case MachineRep::K_WORD64:
3167             dstType = lmirBuilder_->i64Type;
3168             break;
3169         case MachineRep::K_PTR_1:
3170             dstType = lmirBuilder_->i64RefType;
3171             break;
3172         case MachineRep::K_META:
3173             LOG_ECMA(FATAL) << "this branch is unreachable";
3174             UNREACHABLE();
3175             break;
3176         default:
3177             LOG_ECMA(FATAL) << "this branch is unreachable";
3178             UNREACHABLE();
3179             break;
3180     }
3181     return dstType;
3182 }
3183 
GetBitWidthFromMachineType(MachineType machineType) const3184 int64_t LiteCGIRBuilder::GetBitWidthFromMachineType(MachineType machineType) const
3185 {
3186     switch (machineType) {
3187         case NOVALUE:
3188             return 0;
3189         case ARCH:
3190             return 48;  // 48: Pointer representation in different architectures
3191         case I1:
3192             return 1;
3193         case I8:
3194             return 8;  // 8: bit width
3195         case I16:
3196             return 16;  // 16: bit width
3197         case I32:
3198             return 32;  // 32: bit width
3199         case I64:
3200             return 64;  // 64: bit width
3201         case F32:
3202             return 32;  // 32: bit width
3203         case F64:
3204             return 64;  // 64: bit width
3205         case FLEX:
3206         case ANYVALUE:
3207             LOG_ECMA(FATAL) << "this branch is unreachable";
3208             UNREACHABLE();
3209         default:
3210             LOG_ECMA(FATAL) << "this branch is unreachable";
3211             UNREACHABLE();
3212     }
3213 }
3214 
LookupPredBB(GateRef start,int bbID)3215 int LiteCGIRBuilder::LookupPredBB(GateRef start, int bbID)
3216 {
3217     GateId gateId = acc_.GetId(start);
3218     int owner = instID2bbID_[gateId];
3219     if (owner != bbID) {
3220         return owner;
3221     }
3222     GateRef pred = start;
3223     while (owner == bbID) {
3224         pred = acc_.GetState(pred);
3225         auto id = acc_.GetId(pred);
3226         owner = instID2bbID_[id];
3227     }
3228     return owner;
3229 }
3230 
3231 }  // namespace panda::ecmascript::kungfu
3232