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