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