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