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