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