• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pandagen.h"
17 
18 #include "varbinder/varbinder.h"
19 #include "checker/checker.h"
20 #include "checker/types/globalTypesHolder.h"
21 #include "util/helpers.h"
22 #include "varbinder/scope.h"
23 #include "varbinder/variable.h"
24 #include "compiler/base/catchTable.h"
25 #include "compiler/base/lexenv.h"
26 #include "compiler/base/literals.h"
27 #include "public/public.h"
28 #include "compiler/core/labelTarget.h"
29 #include "compiler/core/regAllocator.h"
30 #include "compiler/function/asyncFunctionBuilder.h"
31 #include "compiler/function/asyncGeneratorFunctionBuilder.h"
32 #include "compiler/function/functionBuilder.h"
33 #include "compiler/function/generatorFunctionBuilder.h"
34 #include "es2panda.h"
35 #include "generated/isa.h"
36 #include "ir/base/scriptFunction.h"
37 #include "ir/base/spreadElement.h"
38 #include "ir/statement.h"
39 #include "ir/expressions/identifier.h"
40 #include "ir/expressions/literals/numberLiteral.h"
41 #include "ir/expressions/literals/stringLiteral.h"
42 
43 namespace ark::es2panda::compiler {
44 
45 #ifndef PANDA_WITH_ECMASCRIPT
46 class EcmaDisabled : public IRNode {
47 public:
48     template <typename... Args>
EcmaDisabled(const ir::AstNode * node,Args &&...args)49     explicit EcmaDisabled(const ir::AstNode *node, [[maybe_unused]] Args &&...args) : IRNode(node)
50     {
51         UNREACHABLE();
52     }
53 
GetFormats() const54     Formats GetFormats() const override
55     {
56         UNREACHABLE();
57     }
58 
Registers(std::array<VReg *,MAX_REG_OPERAND> * regs)59     size_t Registers([[maybe_unused]] std::array<VReg *, MAX_REG_OPERAND> *regs) override
60     {
61         UNREACHABLE();
62     }
63 
Registers(std::array<const VReg *,MAX_REG_OPERAND> * regs) const64     size_t Registers([[maybe_unused]] std::array<const VReg *, MAX_REG_OPERAND> *regs) const override
65     {
66         UNREACHABLE();
67     }
68 
OutRegisters(std::array<OutVReg,MAX_REG_OPERAND> * regs) const69     size_t OutRegisters([[maybe_unused]] std::array<OutVReg, MAX_REG_OPERAND> *regs) const override
70     {
71         UNREACHABLE();
72     }
73 
Transform(pandasm::Ins * ins,ProgramElement * programElement,uint32_t totalRegs) const74     void Transform([[maybe_unused]] pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement,
75                    [[maybe_unused]] uint32_t totalRegs) const override
76     {
77         UNREACHABLE();
78     }
79 };
80 
81 using EcmaLdhole = EcmaDisabled;
82 using EcmaLdnan = EcmaDisabled;
83 using EcmaLdinfinity = EcmaDisabled;
84 using EcmaLdglobal = EcmaDisabled;
85 using EcmaLdundefined = EcmaDisabled;
86 using EcmaLdsymbol = EcmaDisabled;
87 using EcmaLdnull = EcmaDisabled;
88 using EcmaLdtrue = EcmaDisabled;
89 using EcmaLdfalse = EcmaDisabled;
90 using EcmaTryldglobalbyname = EcmaDisabled;
91 using EcmaTrystglobalbyname = EcmaDisabled;
92 using EcmaLdobjbyname = EcmaDisabled;
93 using EcmaStobjbyname = EcmaDisabled;
94 using EcmaLdobjbyindex = EcmaDisabled;
95 using EcmaLdobjbyvalue = EcmaDisabled;
96 using EcmaStobjbyvalue = EcmaDisabled;
97 using EcmaStobjbyindex = EcmaDisabled;
98 using EcmaStownbyname = EcmaDisabled;
99 using EcmaStownbyvalue = EcmaDisabled;
100 using EcmaStownbyindex = EcmaDisabled;
101 using EcmaDelobjprop = EcmaDisabled;
102 using EcmaLdglobalvar = EcmaDisabled;
103 using EcmaStglobalvar = EcmaDisabled;
104 using EcmaLdbigint = EcmaDisabled;
105 using EcmaEqdyn = EcmaDisabled;
106 using EcmaNoteqdyn = EcmaDisabled;
107 using EcmaStricteqdyn = EcmaDisabled;
108 using EcmaStrictnoteqdyn = EcmaDisabled;
109 using EcmaLessdyn = EcmaDisabled;
110 using EcmaLesseqdyn = EcmaDisabled;
111 using EcmaGreaterdyn = EcmaDisabled;
112 using EcmaGreatereqdyn = EcmaDisabled;
113 using EcmaTonumber = EcmaDisabled;
114 using EcmaNegdyn = EcmaDisabled;
115 using EcmaNotdyn = EcmaDisabled;
116 using EcmaNegate = EcmaDisabled;
117 using EcmaIncdyn = EcmaDisabled;
118 using EcmaDecdyn = EcmaDisabled;
119 using EcmaEqdyn = EcmaDisabled;
120 using EcmaNoteqdyn = EcmaDisabled;
121 using EcmaStricteqdyn = EcmaDisabled;
122 using EcmaStrictnoteqdyn = EcmaDisabled;
123 using EcmaLessdyn = EcmaDisabled;
124 using EcmaLesseqdyn = EcmaDisabled;
125 using EcmaGreaterdyn = EcmaDisabled;
126 using EcmaGreatereqdyn = EcmaDisabled;
127 using EcmaAdd2dyn = EcmaDisabled;
128 using EcmaSub2dyn = EcmaDisabled;
129 using EcmaMul2dyn = EcmaDisabled;
130 using EcmaDiv2dyn = EcmaDisabled;
131 using EcmaMod2dyn = EcmaDisabled;
132 using EcmaExpdyn = EcmaDisabled;
133 using EcmaShl2dyn = EcmaDisabled;
134 using EcmaShr2dyn = EcmaDisabled;
135 using EcmaAshr2dyn = EcmaDisabled;
136 using EcmaAnd2dyn = EcmaDisabled;
137 using EcmaOr2dyn = EcmaDisabled;
138 using EcmaXor2dyn = EcmaDisabled;
139 using EcmaIsindyn = EcmaDisabled;
140 using EcmaInstanceofdyn = EcmaDisabled;
141 using EcmaIsundefined = EcmaDisabled;
142 using EcmaIsundefined = EcmaDisabled;
143 using EcmaJtrue = EcmaDisabled;
144 using EcmaIstrue = EcmaDisabled;
145 using EcmaJfalse = EcmaDisabled;
146 using EcmaIscoercible = EcmaDisabled;
147 using EcmaThrowdyn = EcmaDisabled;
148 using EcmaRethrowdyn = EcmaDisabled;
149 using EcmaReturnDyn = EcmaDisabled;
150 using EcmaReturnundefined = EcmaDisabled;
151 using EcmaCall0thisdyn = EcmaDisabled;
152 using EcmaCall1thisdyn = EcmaDisabled;
153 using EcmaCall0dyn = EcmaDisabled;
154 using EcmaCall1thisdyn = EcmaDisabled;
155 using EcmaCall1dyn = EcmaDisabled;
156 using EcmaCall2thisdyn = EcmaDisabled;
157 using EcmaCall2dyn = EcmaDisabled;
158 using EcmaCall3thisdyn = EcmaDisabled;
159 using EcmaCall3dyn = EcmaDisabled;
160 using EcmaCallithisrangedyn = EcmaDisabled;
161 using EcmaCallirangedyn = EcmaDisabled;
162 using EcmaCall1thisdyn = EcmaDisabled;
163 using EcmaCall1dyn = EcmaDisabled;
164 using EcmaCall2thisdyn = EcmaDisabled;
165 using EcmaCall2dyn = EcmaDisabled;
166 using EcmaCall3thisdyn = EcmaDisabled;
167 using EcmaCall3dyn = EcmaDisabled;
168 using EcmaCallithisrangedyn = EcmaDisabled;
169 using EcmaCallirangedyn = EcmaDisabled;
170 using EcmaSupercall = EcmaDisabled;
171 using EcmaSupercallspread = EcmaDisabled;
172 using EcmaNewobjdynrange = EcmaDisabled;
173 using EcmaLdhomeobject = EcmaDisabled;
174 using EcmaDefinemethod = EcmaDisabled;
175 using EcmaDefineasyncgeneratorfunc = EcmaDisabled;
176 using EcmaDefineasyncfunc = EcmaDisabled;
177 using EcmaDefinegeneratorfunc = EcmaDisabled;
178 using EcmaDefinencfuncdyn = EcmaDisabled;
179 using EcmaDefinefuncdyn = EcmaDisabled;
180 using EcmaTypeofdyn = EcmaDisabled;
181 using EcmaCallspreaddyn = EcmaDisabled;
182 using EcmaNewobjspreaddyn = EcmaDisabled;
183 using EcmaGetunmappedargs = EcmaDisabled;
184 using EcmaNegate = EcmaDisabled;
185 using EcmaToboolean = EcmaDisabled;
186 using EcmaTonumber = EcmaDisabled;
187 using EcmaGetmethod = EcmaDisabled;
188 using EcmaCreategeneratorobj = EcmaDisabled;
189 using EcmaCreateasyncgeneratorobj = EcmaDisabled;
190 using EcmaCreateiterresultobj = EcmaDisabled;
191 using EcmaSuspendgenerator = EcmaDisabled;
192 using EcmaSuspendasyncgenerator = EcmaDisabled;
193 using EcmaSetgeneratorstate = EcmaDisabled;
194 using EcmaSetgeneratorstate = EcmaDisabled;
195 using EcmaResumegenerator = EcmaDisabled;
196 using EcmaGetresumemode = EcmaDisabled;
197 using EcmaAsyncfunctionenter = EcmaDisabled;
198 using EcmaAsyncfunctionawait = EcmaDisabled;
199 using EcmaAsyncfunctionresolve = EcmaDisabled;
200 using EcmaAsyncfunctionreject = EcmaDisabled;
201 using EcmaAsyncgeneratorresolve = EcmaDisabled;
202 using EcmaAsyncgeneratorreject = EcmaDisabled;
203 using EcmaGettemplateobject = EcmaDisabled;
204 using EcmaCopyrestargs = EcmaDisabled;
205 using EcmaGetpropiterator = EcmaDisabled;
206 using EcmaGetnextpropname = EcmaDisabled;
207 using EcmaCreateemptyobject = EcmaDisabled;
208 using EcmaCreateobjectwithbuffer = EcmaDisabled;
209 using EcmaCreateobjecthavingmethod = EcmaDisabled;
210 using EcmaSetobjectwithproto = EcmaDisabled;
211 using EcmaCopydataproperties = EcmaDisabled;
212 using EcmaDefinegettersetterbyvalue = EcmaDisabled;
213 using EcmaCreateemptyarray = EcmaDisabled;
214 using EcmaCreatearraywithbuffer = EcmaDisabled;
215 using EcmaStarrayspread = EcmaDisabled;
216 using EcmaCreateregexpwithliteral = EcmaDisabled;
217 using EcmaThrowifnotobject = EcmaDisabled;
218 using EcmaThrowthrownotexists = EcmaDisabled;
219 using EcmaGetiterator = EcmaDisabled;
220 using EcmaGetasynciterator = EcmaDisabled;
221 using EcmaCreateobjectwithexcludedkeys = EcmaDisabled;
222 using EcmaThrowpatternnoncoercible = EcmaDisabled;
223 using EcmaCloseiterator = EcmaDisabled;
224 using EcmaImportmodule = EcmaDisabled;
225 using EcmaSetclasscomputedfields = EcmaDisabled;
226 using EcmaDefineclasswithbuffer = EcmaDisabled;
227 using EcmaLoadclasscomputedinstancefields = EcmaDisabled;
228 using EcmaDefineclassprivatefields = EcmaDisabled;
229 using EcmaClassfieldadd = EcmaDisabled;
230 using EcmaClassprivatefieldadd = EcmaDisabled;
231 using EcmaClassprivatemethodoraccessoradd = EcmaDisabled;
232 using EcmaClassprivatefieldget = EcmaDisabled;
233 using EcmaClassprivatefieldset = EcmaDisabled;
234 using EcmaClassprivatefieldin = EcmaDisabled;
235 using EcmaLdmodvarbyname = EcmaDisabled;
236 using EcmaStmodulevar = EcmaDisabled;
237 using EcmaCopymodule = EcmaDisabled;
238 using EcmaStsuperbyname = EcmaDisabled;
239 using EcmaLdsuperbyname = EcmaDisabled;
240 using EcmaStsuperbyvalue = EcmaDisabled;
241 using EcmaLdsuperbyvalue = EcmaDisabled;
242 using EcmaLdlexvardyn = EcmaDisabled;
243 using EcmaLdlexdyn = EcmaDisabled;
244 using EcmaStlexvardyn = EcmaDisabled;
245 using EcmaStlexdyn = EcmaDisabled;
246 using EcmaThrowifsupernotcorrectcall = EcmaDisabled;
247 using EcmaThrowtdz = EcmaDisabled;
248 using EcmaThrowconstassignment = EcmaDisabled;
249 using EcmaPoplexenvdyn = EcmaDisabled;
250 using EcmaCopylexenvdyn = EcmaDisabled;
251 using EcmaNewlexenvdyn = EcmaDisabled;
252 using EcmaLdlexenvdyn = EcmaDisabled;
253 using EcmaLdevalvar = EcmaDisabled;
254 using EcmaStevalvar = EcmaDisabled;
255 using EcmaLdevalbindings = EcmaDisabled;
256 using EcmaDirecteval = EcmaDisabled;
257 #endif
258 
PandaGen(ArenaAllocator * const allocator,RegSpiller * const spiller,public_lib::Context * const context,std::tuple<varbinder::FunctionScope *,ProgramElement *,AstCompiler * > toCompile)259 PandaGen::PandaGen(ArenaAllocator *const allocator, RegSpiller *const spiller, public_lib::Context *const context,
260                    std::tuple<varbinder::FunctionScope *, ProgramElement *, AstCompiler *> toCompile)
261     : CodeGen(allocator, spiller, context, toCompile)
262 {
263     Function::Compile(this);
264 }
265 
FuncBuilder() const266 FunctionBuilder *PandaGen::FuncBuilder() const noexcept
267 {
268     return builder_;
269 }
270 
GetEnvScope() const271 EnvScope *PandaGen::GetEnvScope() const noexcept
272 {
273     return envScope_;
274 }
275 
OptionalChainCheck(const bool optional,const VReg obj) const276 void PandaGen::OptionalChainCheck(const bool optional, const VReg obj) const
277 {
278     if (optional && optionalChain_ != nullptr) {
279         optionalChain_->Check(obj);
280     }
281 }
282 
FunctionInit(CatchTable * catchTable)283 void PandaGen::FunctionInit(CatchTable *catchTable)
284 {
285     if (RootNode()->IsProgram()) {
286         builder_ = Allocator()->New<FunctionBuilder>(this, catchTable);
287         return;
288     }
289 
290     const ir::ScriptFunction *func = RootNode()->AsScriptFunction();
291 
292     if (func->IsAsyncFunc()) {
293         if (func->IsGenerator()) {
294             builder_ = Allocator()->New<AsyncGeneratorFunctionBuilder>(this, catchTable);
295             return;
296         }
297 
298         builder_ = Allocator()->New<AsyncFunctionBuilder>(this, catchTable);
299         return;
300     }
301 
302     if (func->IsGenerator()) {
303         builder_ = Allocator()->New<GeneratorFunctionBuilder>(this, catchTable);
304         return;
305     }
306 
307     builder_ = Allocator()->New<FunctionBuilder>(this, catchTable);
308 }
309 
FunctionHasFinalizer() const310 bool PandaGen::FunctionHasFinalizer() const
311 {
312     if (RootNode()->IsProgram()) {
313         return false;
314     }
315 
316     const ir::ScriptFunction *func = RootNode()->AsScriptFunction();
317 
318     return func->IsAsyncFunc() || func->IsGenerator();
319 }
320 
FunctionEnter()321 void PandaGen::FunctionEnter()
322 {
323     builder_->Prepare(RootNode()->AsScriptFunction());
324 }
325 
FunctionExit()326 void PandaGen::FunctionExit()
327 {
328     builder_->CleanUp(RootNode()->AsScriptFunction());
329 }
330 
StoreAccumulator(const ir::AstNode * node,VReg vreg)331 void PandaGen::StoreAccumulator(const ir::AstNode *node, VReg vreg)
332 {
333     Ra().Emit<StaDyn>(node, vreg);
334 }
335 
LoadAccumulator(const ir::AstNode * node,VReg reg)336 void PandaGen::LoadAccumulator(const ir::AstNode *node, VReg reg)
337 {
338     Ra().Emit<LdaDyn>(node, reg);
339 }
340 
AllocMov(const ir::AstNode * node,const VReg vd,const VReg vs)341 IRNode *PandaGen::AllocMov(const ir::AstNode *node, const VReg vd, const VReg vs)
342 {
343     return Allocator()->New<MovDyn>(node, vd, vs);
344 }
345 
AllocMov(const ir::AstNode * node,OutVReg vd,const VReg vs)346 IRNode *PandaGen::AllocMov(const ir::AstNode *node, OutVReg vd, const VReg vs)
347 {
348     ASSERT(vd.type == OperandType::ANY);
349     return Allocator()->New<MovDyn>(node, *vd.reg, vs);
350 }
351 
MoveVreg(const ir::AstNode * node,VReg vd,VReg vs)352 void PandaGen::MoveVreg(const ir::AstNode *node, VReg vd, VReg vs)
353 {
354     Ra().Emit<MovDyn>(node, vd, vs);
355 }
356 
LoadAccumulatorDouble(const ir::AstNode * node,double num)357 void PandaGen::LoadAccumulatorDouble(const ir::AstNode *node, double num)
358 {
359     Sa().Emit<FldaiDyn>(node, num);
360 }
361 
LoadAccumulatorInt(const ir::AstNode * node,size_t num)362 void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num)
363 {
364     Sa().Emit<LdaiDyn>(node, static_cast<int64_t>(num));
365 }
366 
StoreConst(const ir::AstNode * node,VReg reg,Constant id)367 void PandaGen::StoreConst(const ir::AstNode *node, VReg reg, Constant id)
368 {
369     LoadConst(node, id);
370     StoreAccumulator(node, reg);
371 }
372 
LoadConst(const ir::AstNode * node,Constant id)373 void PandaGen::LoadConst(const ir::AstNode *node, Constant id)
374 {
375     switch (id) {
376         case Constant::JS_HOLE: {
377             Sa().Emit<EcmaLdhole>(node);
378             break;
379         }
380         case Constant::JS_NAN: {
381             Sa().Emit<EcmaLdnan>(node);
382             break;
383         }
384         case Constant::JS_INFINITY: {
385             Sa().Emit<EcmaLdinfinity>(node);
386             break;
387         }
388         case Constant::JS_GLOBAL: {
389             Sa().Emit<EcmaLdglobal>(node);
390             break;
391         }
392         case Constant::JS_UNDEFINED: {
393             Sa().Emit<EcmaLdundefined>(node);
394             break;
395         }
396         case Constant::JS_SYMBOL: {
397             Sa().Emit<EcmaLdsymbol>(node);
398             break;
399         }
400         case Constant::JS_NULL: {
401             Sa().Emit<EcmaLdnull>(node);
402             break;
403         }
404         case Constant::JS_TRUE: {
405             Sa().Emit<EcmaLdtrue>(node);
406             break;
407         }
408         case Constant::JS_FALSE: {
409             Sa().Emit<EcmaLdfalse>(node);
410             break;
411         }
412         default: {
413             UNREACHABLE();
414         }
415     }
416 }
417 
GetFunctionObject(const ir::AstNode * node)418 void PandaGen::GetFunctionObject(const ir::AstNode *node)
419 {
420     LoadAccFromLexEnv(node, Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_FUNC));
421 }
422 
GetNewTarget(const ir::AstNode * node)423 void PandaGen::GetNewTarget(const ir::AstNode *node)
424 {
425     LoadAccFromLexEnv(node, Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_NEW_TARGET));
426 }
427 
GetThis(const ir::AstNode * node)428 void PandaGen::GetThis(const ir::AstNode *node)
429 {
430     LoadAccFromLexEnv(node, Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS));
431 }
432 
SetThis(const ir::AstNode * node)433 void PandaGen::SetThis(const ir::AstNode *node)
434 {
435     StoreAccToLexEnv(node, Scope()->Find(varbinder::VarBinder::MANDATORY_PARAM_THIS), true);
436 }
437 
LoadVar(const ir::Identifier * node,const varbinder::ConstScopeFindResult & result)438 void PandaGen::LoadVar(const ir::Identifier *node, const varbinder::ConstScopeFindResult &result)
439 {
440     auto *var = result.variable;
441 
442     if (var == nullptr) {
443         TryLoadGlobalByName(node, result.name);
444         return;
445     }
446 
447     if (var->IsGlobalVariable()) {
448         LoadGlobalVar(node, var->Name());
449         return;
450     }
451 
452     if (var->IsModuleVariable()) {
453         LoadModuleVariable(node, var->AsModuleVariable()->ModuleReg(), var->AsModuleVariable()->ExoticName());
454         return;
455     }
456 
457     ASSERT(var->IsLocalVariable());
458     LoadAccFromLexEnv(node, result);
459 }
460 
StoreVar(const ir::AstNode * node,const varbinder::ConstScopeFindResult & result,bool isDeclaration)461 void PandaGen::StoreVar(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, bool isDeclaration)
462 {
463     varbinder::Variable *var = result.variable;
464 
465     if (var == nullptr) {
466         if (IsDirectEval()) {
467             StoreEvalVariable(node, result.name);
468         } else {
469             TryStoreGlobalByName(node, result.name);
470         }
471         return;
472     }
473 
474     if (var->IsGlobalVariable()) {
475         StoreGlobalVar(node, var->Name());
476         return;
477     }
478 
479     if (var->IsModuleVariable()) {
480         ThrowConstAssignment(node, var->Name());
481         return;
482     }
483 
484     ASSERT(var->IsLocalVariable());
485     StoreAccToLexEnv(node, result, isDeclaration);
486 }
487 
LoadAccFromArgs(const ir::AstNode * node)488 void PandaGen::LoadAccFromArgs(const ir::AstNode *node)
489 {
490     if (!Scope()->HasFlag(varbinder::ScopeFlags::USE_ARGS)) {
491         return;
492     }
493 
494     auto res = Scope()->Find(varbinder::VarBinder::FUNCTION_ARGUMENTS);
495     ASSERT(res.scope);
496 
497     GetUnmappedArgs(node);
498     StoreAccToLexEnv(node, res, true);
499 }
500 
LoadObjProperty(const ir::AstNode * node,const Operand & prop)501 void PandaGen::LoadObjProperty(const ir::AstNode *node, const Operand &prop)
502 {
503     if (std::holds_alternative<VReg>(prop)) {
504         LoadObjByValue(node, std::get<VReg>(prop));
505         return;
506     }
507 
508     if (std::holds_alternative<int64_t>(prop)) {
509         LoadObjByIndex(node, std::get<int64_t>(prop));
510         return;
511     }
512 
513     ASSERT(std::holds_alternative<util::StringView>(prop));
514     LoadObjByName(node, std::get<util::StringView>(prop));
515 }
516 
StoreObjProperty(const ir::AstNode * node,VReg obj,const Operand & prop)517 void PandaGen::StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
518 {
519     if (std::holds_alternative<VReg>(prop)) {
520         StoreObjByValue(node, obj, std::get<VReg>(prop));
521         return;
522     }
523 
524     if (std::holds_alternative<int64_t>(prop)) {
525         StoreObjByIndex(node, obj, std::get<int64_t>(prop));
526         return;
527     }
528 
529     ASSERT(std::holds_alternative<util::StringView>(prop));
530     StoreObjByName(node, obj, std::get<util::StringView>(prop));
531 }
532 
StoreOwnProperty(const ir::AstNode * node,VReg obj,const Operand & prop)533 void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
534 {
535     if (std::holds_alternative<VReg>(prop)) {
536         StOwnByValue(node, obj, std::get<VReg>(prop));
537         return;
538     }
539 
540     if (std::holds_alternative<int64_t>(prop)) {
541         StOwnByIndex(node, obj, std::get<int64_t>(prop));
542         return;
543     }
544 
545     ASSERT(std::holds_alternative<util::StringView>(prop));
546     StOwnByName(node, obj, std::get<util::StringView>(prop));
547 }
548 
TryLoadGlobalByName(const ir::AstNode * node,const util::StringView & name)549 void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name)
550 {
551     Sa().Emit<EcmaTryldglobalbyname>(node, name);
552 }
553 
TryStoreGlobalByName(const ir::AstNode * node,const util::StringView & name)554 void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringView &name)
555 {
556     Sa().Emit<EcmaTrystglobalbyname>(node, name);
557 }
558 
LoadObjByName(const ir::AstNode * node,const util::StringView & prop)559 void PandaGen::LoadObjByName(const ir::AstNode *node, const util::StringView &prop)
560 {
561     Ra().Emit<EcmaLdobjbyname>(node, prop);
562 }
563 
StoreObjByName(const ir::AstNode * node,VReg obj,const util::StringView & prop)564 void PandaGen::StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop)
565 {
566     Ra().Emit<EcmaStobjbyname>(node, prop, obj);
567 }
568 
LoadObjByIndex(const ir::AstNode * node,int64_t index)569 void PandaGen::LoadObjByIndex(const ir::AstNode *node, int64_t index)
570 {
571     Ra().Emit<EcmaLdobjbyindex>(node, index);
572 }
573 
LoadObjByValue(const ir::AstNode * node,VReg obj)574 void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj)
575 {
576     Ra().Emit<EcmaLdobjbyvalue>(node, obj);
577 }
578 
StoreObjByValue(const ir::AstNode * node,VReg obj,VReg prop)579 void PandaGen::StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop)
580 {
581     Ra().Emit<EcmaStobjbyvalue>(node, obj, prop);
582 }
583 
StoreObjByIndex(const ir::AstNode * node,VReg obj,int64_t index)584 void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index)
585 {
586     Ra().Emit<EcmaStobjbyindex>(node, index, obj);
587 }
588 
StOwnByName(const ir::AstNode * node,VReg obj,const util::StringView & prop)589 void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop)
590 {
591     Ra().Emit<EcmaStownbyname>(node, prop, obj);
592 }
593 
StOwnByValue(const ir::AstNode * node,VReg obj,VReg prop)594 void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop)
595 {
596     Ra().Emit<EcmaStownbyvalue>(node, obj, prop);
597 }
598 
StOwnByIndex(const ir::AstNode * node,VReg obj,int64_t index)599 void PandaGen::StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index)
600 {
601     Ra().Emit<EcmaStownbyindex>(node, index, obj);
602 }
603 
DeleteObjProperty(const ir::AstNode * node,VReg obj,VReg prop)604 void PandaGen::DeleteObjProperty(const ir::AstNode *node, VReg obj, VReg prop)
605 {
606     Ra().Emit<EcmaDelobjprop>(node, obj, prop);
607 }
608 
LoadGlobalVar(const ir::AstNode * node,const util::StringView & name)609 void PandaGen::LoadGlobalVar(const ir::AstNode *node, const util::StringView &name)
610 {
611     Sa().Emit<EcmaLdglobalvar>(node, name);
612 }
613 
StoreGlobalVar(const ir::AstNode * node,const util::StringView & name)614 void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &name)
615 {
616     Sa().Emit<EcmaStglobalvar>(node, name);
617 }
618 
LexEnv() const619 VReg PandaGen::LexEnv() const noexcept
620 {
621     return envScope_->LexEnv();
622 }
623 
LoadAccFromLexEnv(const ir::AstNode * node,const varbinder::ConstScopeFindResult & result)624 void PandaGen::LoadAccFromLexEnv(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result)
625 {
626     VirtualLoadVar::Expand(this, node, result);
627 }
628 
StoreAccToLexEnv(const ir::AstNode * node,const varbinder::ConstScopeFindResult & result,bool isDeclaration)629 void PandaGen::StoreAccToLexEnv(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result,
630                                 bool isDeclaration)
631 {
632     VirtualStoreVar::Expand(this, node, result, isDeclaration);
633 }
634 
LoadAccumulatorBigInt(const ir::AstNode * node,const util::StringView & bigInt)635 void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &bigInt)
636 {
637     Sa().Emit<EcmaLdbigint>(node, bigInt);
638 }
639 
Condition(const ir::AstNode * node,lexer::TokenType op,VReg lhs,Label * ifFalse)640 void PandaGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, Label *ifFalse)
641 {
642     switch (op) {
643         case lexer::TokenType::PUNCTUATOR_EQUAL: {
644             Ra().Emit<EcmaEqdyn>(node, lhs);
645             break;
646         }
647         case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: {
648             Ra().Emit<EcmaNoteqdyn>(node, lhs);
649             break;
650         }
651         case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: {
652             Ra().Emit<EcmaStricteqdyn>(node, lhs);
653             break;
654         }
655         case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
656             Ra().Emit<EcmaStrictnoteqdyn>(node, lhs);
657             break;
658         }
659         case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
660             Ra().Emit<EcmaLessdyn>(node, lhs);
661             break;
662         }
663         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: {
664             Ra().Emit<EcmaLesseqdyn>(node, lhs);
665             break;
666         }
667         case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
668             Ra().Emit<EcmaGreaterdyn>(node, lhs);
669             break;
670         }
671         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
672             Ra().Emit<EcmaGreatereqdyn>(node, lhs);
673             break;
674         }
675         default: {
676             UNREACHABLE();
677         }
678     }
679 
680     BranchIfFalse(node, ifFalse);
681 }
682 
Unary(const ir::AstNode * node,lexer::TokenType op,VReg operand)683 void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand)
684 {
685     switch (op) {
686         case lexer::TokenType::PUNCTUATOR_PLUS: {
687             Ra().Emit<EcmaTonumber>(node, operand);
688             break;
689         }
690         case lexer::TokenType::PUNCTUATOR_MINUS: {
691             Ra().Emit<EcmaNegdyn>(node, operand);
692             break;
693         }
694         case lexer::TokenType::PUNCTUATOR_TILDE: {
695             Ra().Emit<EcmaNotdyn>(node, operand);
696             break;
697         }
698         case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
699             Sa().Emit<EcmaNegate>(node);
700             break;
701         }
702         case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: {
703             Ra().Emit<EcmaIncdyn>(node, operand);
704             break;
705         }
706         case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: {
707             Ra().Emit<EcmaDecdyn>(node, operand);
708             break;
709         }
710         case lexer::TokenType::KEYW_VOID:
711         case lexer::TokenType::KEYW_DELETE: {
712             LoadConst(node, Constant::JS_UNDEFINED);
713             break;
714         }
715         default: {
716             UNREACHABLE();
717         }
718     }
719 }
720 
Binary(const ir::AstNode * node,lexer::TokenType op,VReg lhs)721 void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs)
722 {
723     switch (op) {
724         case lexer::TokenType::PUNCTUATOR_EQUAL: {
725             Ra().Emit<EcmaEqdyn>(node, lhs);
726             break;
727         }
728         case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: {
729             Ra().Emit<EcmaNoteqdyn>(node, lhs);
730             break;
731         }
732         case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: {
733             Ra().Emit<EcmaStricteqdyn>(node, lhs);
734             break;
735         }
736         case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
737             Ra().Emit<EcmaStrictnoteqdyn>(node, lhs);
738             break;
739         }
740         case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
741             Ra().Emit<EcmaLessdyn>(node, lhs);
742             break;
743         }
744         case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: {
745             Ra().Emit<EcmaLesseqdyn>(node, lhs);
746             break;
747         }
748         case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
749             Ra().Emit<EcmaGreaterdyn>(node, lhs);
750             break;
751         }
752         case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
753             Ra().Emit<EcmaGreatereqdyn>(node, lhs);
754             break;
755         }
756         case lexer::TokenType::PUNCTUATOR_PLUS:
757         case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: {
758             Ra().Emit<EcmaAdd2dyn>(node, lhs);
759             break;
760         }
761         case lexer::TokenType::PUNCTUATOR_MINUS:
762         case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: {
763             Ra().Emit<EcmaSub2dyn>(node, lhs);
764             break;
765         }
766         case lexer::TokenType::PUNCTUATOR_MULTIPLY:
767         case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: {
768             Ra().Emit<EcmaMul2dyn>(node, lhs);
769             break;
770         }
771         case lexer::TokenType::PUNCTUATOR_DIVIDE:
772         case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
773             Ra().Emit<EcmaDiv2dyn>(node, lhs);
774             break;
775         }
776         case lexer::TokenType::PUNCTUATOR_MOD:
777         case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: {
778             Ra().Emit<EcmaMod2dyn>(node, lhs);
779             break;
780         }
781         case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL:
782         case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
783             Ra().Emit<EcmaExpdyn>(node, lhs);
784             break;
785         }
786         case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
787         case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: {
788             Ra().Emit<EcmaShl2dyn>(node, lhs);
789             break;
790         }
791         case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
792         case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: {
793             Ra().Emit<EcmaShr2dyn>(node, lhs);
794             break;
795         }
796         case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
797         case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: {
798             Ra().Emit<EcmaAshr2dyn>(node, lhs);
799             break;
800         }
801         case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
802         case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: {
803             Ra().Emit<EcmaAnd2dyn>(node, lhs);
804             break;
805         }
806         case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
807         case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: {
808             Ra().Emit<EcmaOr2dyn>(node, lhs);
809             break;
810         }
811         case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
812         case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: {
813             Ra().Emit<EcmaXor2dyn>(node, lhs);
814             break;
815         }
816         case lexer::TokenType::KEYW_IN: {
817             Ra().Emit<EcmaIsindyn>(node, lhs);
818             break;
819         }
820         case lexer::TokenType::KEYW_INSTANCEOF: {
821             Ra().Emit<EcmaInstanceofdyn>(node, lhs);
822             break;
823         }
824         case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
825         case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: {
826             Unimplemented();
827             break;
828         }
829         default: {
830             UNREACHABLE();
831         }
832     }
833 }
834 
BranchIfUndefined(const ir::AstNode * node,Label * target)835 void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target)
836 {
837     Sa().Emit<EcmaIsundefined>(node);
838     BranchIfTrue(node, target);
839 }
840 
BranchIfNotUndefined(const ir::AstNode * node,Label * target)841 void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target)
842 {
843     Sa().Emit<EcmaIsundefined>(node);
844     BranchIfFalse(node, target);
845 }
846 
BranchIfTrue(const ir::AstNode * node,Label * target)847 void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target)
848 {
849     Sa().Emit<EcmaJtrue>(node, target);
850 }
851 
BranchIfNotTrue(const ir::AstNode * node,Label * target)852 void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target)
853 {
854     Sa().Emit<EcmaIstrue>(node);
855     BranchIfFalse(node, target);
856 }
857 
BranchIfFalse(const ir::AstNode * node,Label * target)858 void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target)
859 {
860     Sa().Emit<EcmaJfalse>(node, target);
861 }
862 
BranchIfCoercible(const ir::AstNode * node,Label * target)863 void PandaGen::BranchIfCoercible(const ir::AstNode *node, Label *target)
864 {
865     Sa().Emit<EcmaIscoercible>(node);
866     BranchIfTrue(node, target);
867 }
868 
EmitThrow(const ir::AstNode * node)869 void PandaGen::EmitThrow(const ir::AstNode *node)
870 {
871     Sa().Emit<EcmaThrowdyn>(node);
872 }
873 
EmitRethrow(const ir::AstNode * node)874 void PandaGen::EmitRethrow(const ir::AstNode *node)
875 {
876     Sa().Emit<EcmaRethrowdyn>(node);
877 }
878 
EmitReturn(const ir::AstNode * node)879 void PandaGen::EmitReturn(const ir::AstNode *node)
880 {
881     Sa().Emit<EcmaReturnDyn>(node);
882 }
883 
EmitReturnUndefined(const ir::AstNode * node)884 void PandaGen::EmitReturnUndefined(const ir::AstNode *node)
885 {
886     Sa().Emit<EcmaReturnundefined>(node);
887 }
888 
ImplicitReturn(const ir::AstNode * node)889 void PandaGen::ImplicitReturn(const ir::AstNode *node)
890 {
891     builder_->ImplicitReturn(node);
892 }
893 
DirectReturn(const ir::AstNode * node)894 void PandaGen::DirectReturn(const ir::AstNode *node)
895 {
896     builder_->DirectReturn(node);
897 }
898 
ValidateClassDirectReturn(const ir::AstNode * node)899 void PandaGen::ValidateClassDirectReturn(const ir::AstNode *node)
900 {
901     const ir::ScriptFunction *func = util::Helpers::GetContainingFunction(node);
902 
903     if (func == nullptr || !func->IsConstructor()) {
904         return;
905     }
906 
907     RegScope rs(this);
908     VReg value = AllocReg();
909     StoreAccumulator(node, value);
910 
911     auto *notUndefined = AllocLabel();
912     auto *condEnd = AllocLabel();
913 
914     BranchIfNotUndefined(node, notUndefined);
915     GetThis(func);
916     ThrowIfSuperNotCorrectCall(func, 0);
917     Branch(node, condEnd);
918 
919     SetLabel(node, notUndefined);
920     LoadAccumulator(node, value);
921 
922     SetLabel(node, condEnd);
923 }
924 
EmitAwait(const ir::AstNode * node)925 void PandaGen::EmitAwait(const ir::AstNode *node)
926 {
927     builder_->Await(node);
928 }
929 
Call0This(const ir::AstNode * node,VReg callee,VReg thisReg)930 void PandaGen::Call0This(const ir::AstNode *node, VReg callee, VReg thisReg)
931 {
932     LoadAccumulator(node, thisReg);
933     Ra().Emit<EcmaCall0thisdyn>(node, callee);
934 }
935 
Call1This(const ir::AstNode * node,VReg callee,VReg thisReg,VReg arg0)936 void PandaGen::Call1This(const ir::AstNode *node, VReg callee, VReg thisReg, VReg arg0)
937 {
938     LoadAccumulator(node, arg0);
939     Ra().Emit<EcmaCall1thisdyn>(node, callee, thisReg);
940 }
941 
Call0Args(const ir::AstNode * n,VReg c,VReg thisR,bool hasThis)942 void PandaGen::Call0Args(const ir::AstNode *n, VReg c, VReg thisR, bool hasThis)
943 {
944     if (hasThis) {
945         Call0This(n, c, thisR);
946     } else {
947         Sa().Emit<EcmaCall0dyn>(n);
948     }
949 }
950 
Call1Arg(const ir::AstNode * n,VReg c,VReg thisR,const ArenaVector<ir::Expression * > & args,bool hasThis)951 void PandaGen::Call1Arg(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args,
952                         bool hasThis)
953 {
954     const auto *arg0 = args[0];
955     arg0->Compile(this);
956 
957     if (hasThis) {
958         Ra().Emit<EcmaCall1thisdyn>(n, c, thisR);
959     } else {
960         Ra().Emit<EcmaCall1dyn>(n, c);
961     }
962 }
963 
Call2Args(const ir::AstNode * n,VReg c,VReg thisR,const ArenaVector<ir::Expression * > & args,bool hasThis)964 void PandaGen::Call2Args(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args,
965                          bool hasThis)
966 {
967     const auto *arg0 = args[0];
968     arg0->Compile(this);
969     compiler::VReg arg0Reg = AllocReg();
970     StoreAccumulator(arg0, arg0Reg);
971 
972     const auto *arg1 = args[1];
973     arg1->Compile(this);
974 
975     if (hasThis) {
976         Ra().Emit<EcmaCall2thisdyn>(n, c, thisR, arg0Reg);
977     } else {
978         Ra().Emit<EcmaCall2dyn>(n, c, arg0Reg);
979     }
980 }
981 
Call3Args(const ir::AstNode * n,VReg c,VReg thisR,const ArenaVector<ir::Expression * > & args,bool hasThis)982 void PandaGen::Call3Args(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args,
983                          bool hasThis)
984 {
985     const auto *arg0 = args[0];
986     arg0->Compile(this);
987     compiler::VReg arg0Reg = AllocReg();
988     StoreAccumulator(arg0, arg0Reg);
989 
990     const auto *arg1 = args[1];
991     arg1->Compile(this);
992     compiler::VReg arg1Reg = AllocReg();
993     StoreAccumulator(arg1, arg1Reg);
994 
995     const auto *arg2 = args[2];
996     arg2->Compile(this);
997 
998     if (hasThis) {
999         Ra().Emit<EcmaCall3thisdyn>(n, c, thisR, arg0Reg, arg1Reg);
1000     } else {
1001         Ra().Emit<EcmaCall3dyn>(n, c, arg0Reg, arg1Reg);
1002     }
1003 }
1004 
Call(const ir::AstNode * node,VReg callee,VReg thisReg,const ArenaVector<ir::Expression * > & arguments)1005 void PandaGen::Call(const ir::AstNode *node, VReg callee, VReg thisReg, const ArenaVector<ir::Expression *> &arguments)
1006 {
1007     bool hasThis = !thisReg.IsInvalid();
1008 
1009     switch (arguments.size()) {
1010         case 0: {  // 0 args
1011             Call0Args(node, callee, thisReg, hasThis);
1012             return;
1013         }
1014         case 1: {  // 1 arg
1015             Call1Arg(node, callee, thisReg, arguments, hasThis);
1016             return;
1017         }
1018         case 2: {  // 2 args
1019             Call2Args(node, callee, thisReg, arguments, hasThis);
1020             return;
1021         }
1022         case 3: {  // 3 args
1023             Call3Args(node, callee, thisReg, arguments, hasThis);
1024             return;
1025         }
1026         default: {
1027             break;
1028         }
1029     }
1030 
1031     for (const auto *it : arguments) {
1032         it->Compile(this);
1033         compiler::VReg arg = AllocReg();
1034         StoreAccumulator(it, arg);
1035     }
1036 
1037     if (hasThis) {
1038         size_t argCount = arguments.size() + 1;
1039         auto constexpr EXTRA_ARGS = 2;
1040         Rra().Emit<EcmaCallithisrangedyn>(node, callee, argCount + EXTRA_ARGS, static_cast<int64_t>(argCount), callee);
1041     } else {
1042         size_t argCount = arguments.size();
1043         Rra().Emit<EcmaCallirangedyn>(node, callee, argCount + 1, static_cast<int64_t>(argCount), callee);
1044     }
1045 }
1046 
CallArgsTagged(const ir::AstNode * node,VReg callee,VReg thisReg,const ArenaVector<ir::Expression * > & arguments,bool hasThis)1047 bool PandaGen::CallArgsTagged(const ir::AstNode *node, VReg callee, VReg thisReg,
1048                               const ArenaVector<ir::Expression *> &arguments, bool hasThis)
1049 {
1050     VReg arg0Reg = AllocReg();
1051     StoreAccumulator(node, arg0Reg);
1052 
1053     const auto call1 = [this, hasThis, arg0Reg](const ir::AstNode *n, VReg c, VReg thisR,
1054                                                 const ArenaVector<ir::Expression *> &args) {
1055         const auto *arg = args[0];
1056         arg->Compile(this);
1057 
1058         if (hasThis) {
1059             Ra().Emit<EcmaCall2thisdyn>(n, c, thisR, arg0Reg);
1060         } else {
1061             Ra().Emit<EcmaCall2dyn>(n, c, arg0Reg);
1062         }
1063     };
1064     const auto call2 = [this, hasThis, arg0Reg](const ir::AstNode *n, VReg c, VReg thisR,
1065                                                 const ArenaVector<ir::Expression *> &args) {
1066         const auto *arg1 = args[0];
1067         arg1->Compile(this);
1068         compiler::VReg arg1Reg = AllocReg();
1069         StoreAccumulator(arg1, arg1Reg);
1070 
1071         const auto *arg2 = args[1];
1072         arg2->Compile(this);
1073 
1074         if (hasThis) {
1075             Ra().Emit<EcmaCall3thisdyn>(n, c, thisR, arg0Reg, arg1Reg);
1076         } else {
1077             Ra().Emit<EcmaCall3dyn>(n, c, arg0Reg, arg1Reg);
1078         }
1079     };
1080 
1081     switch (arguments.size()) {
1082         case 1: {
1083             call1(node, callee, thisReg, arguments);
1084             return true;
1085         }
1086         case 2: {  // 2:2 args
1087             call2(node, callee, thisReg, arguments);
1088             return true;
1089         }
1090         default: {
1091             break;
1092         }
1093     }
1094     return false;
1095 }
1096 
CallTagged(const ir::AstNode * node,VReg callee,VReg thisReg,const ArenaVector<ir::Expression * > & arguments)1097 void PandaGen::CallTagged(const ir::AstNode *node, VReg callee, VReg thisReg,
1098                           const ArenaVector<ir::Expression *> &arguments)
1099 {
1100     bool hasThis = !thisReg.IsInvalid();
1101 
1102     StoreAccumulator(node, callee);
1103     Literals::GetTemplateObject(this, node->AsTaggedTemplateExpression());
1104 
1105     if (arguments.empty()) {
1106         if (hasThis) {
1107             Ra().Emit<EcmaCall1thisdyn>(node, callee, thisReg);
1108         } else {
1109             Sa().Emit<EcmaCall1dyn>(node, callee);
1110         }
1111         return;
1112     }
1113 
1114     if (CallArgsTagged(node, callee, thisReg, arguments, hasThis)) {
1115         return;
1116     }
1117 
1118     for (const auto *it : arguments) {
1119         it->Compile(this);
1120         compiler::VReg arg = AllocReg();
1121         StoreAccumulator(it, arg);
1122     }
1123 
1124     if (hasThis) {
1125         auto constexpr EXTRA_ARGS = 2;
1126         size_t argCount = arguments.size() + EXTRA_ARGS;
1127         Rra().Emit<EcmaCallithisrangedyn>(node, callee, argCount + EXTRA_ARGS, static_cast<int64_t>(argCount), callee);
1128     } else {
1129         size_t argCount = arguments.size() + 1;
1130         Rra().Emit<EcmaCallirangedyn>(node, callee, argCount + 1, static_cast<int64_t>(argCount), callee);
1131     }
1132 }
1133 
SuperCall(const ir::AstNode * node,VReg startReg,size_t argCount)1134 void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount)
1135 {
1136     Rra().Emit<EcmaSupercall>(node, startReg, argCount, static_cast<int64_t>(argCount), startReg);
1137 }
1138 
SuperCallSpread(const ir::AstNode * node,VReg vs)1139 void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs)
1140 {
1141     Ra().Emit<EcmaSupercallspread>(node, vs);
1142 }
1143 
NewObject(const ir::AstNode * node,VReg startReg,size_t argCount)1144 void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount)
1145 {
1146     Rra().Emit<EcmaNewobjdynrange>(node, startReg, argCount, static_cast<int64_t>(argCount), startReg);
1147 }
1148 
LoadHomeObject(const ir::AstNode * node)1149 void PandaGen::LoadHomeObject(const ir::AstNode *node)
1150 {
1151     Sa().Emit<EcmaLdhomeobject>(node);
1152 }
1153 
DefineMethod(const ir::AstNode * node,const util::StringView & name)1154 void PandaGen::DefineMethod(const ir::AstNode *node, const util::StringView &name)
1155 {
1156     Ra().Emit<EcmaDefinemethod>(node, name, LexEnv());
1157 }
1158 
DefineFunction(const ir::AstNode * node,const ir::ScriptFunction * realNode,const util::StringView & name)1159 void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name)
1160 {
1161     if (realNode->IsAsyncFunc()) {
1162         if (realNode->IsGenerator()) {
1163             Ra().Emit<EcmaDefineasyncgeneratorfunc>(node, name, LexEnv());
1164         } else {
1165             Ra().Emit<EcmaDefineasyncfunc>(node, name, LexEnv());
1166         }
1167     } else if (realNode->IsGenerator()) {
1168         Ra().Emit<EcmaDefinegeneratorfunc>(node, name, LexEnv());
1169     } else if (realNode->IsArrow()) {
1170         LoadHomeObject(node);
1171         Ra().Emit<EcmaDefinencfuncdyn>(node, name, LexEnv());
1172     } else if (realNode->IsMethod()) {
1173         DefineMethod(node, name);
1174     } else {
1175         Ra().Emit<EcmaDefinefuncdyn>(node, name, LexEnv());
1176     }
1177 }
1178 
TypeOf(const ir::AstNode * node)1179 void PandaGen::TypeOf(const ir::AstNode *node)
1180 {
1181     Sa().Emit<EcmaTypeofdyn>(node);
1182 }
1183 
CallSpread(const ir::AstNode * node,VReg func,VReg thisReg,VReg args)1184 void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args)
1185 {
1186     Ra().Emit<EcmaCallspreaddyn>(node, func, thisReg, args);
1187 }
1188 
NewObjSpread(const ir::AstNode * node,VReg obj,VReg target)1189 void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj, VReg target)
1190 {
1191     Ra().Emit<EcmaNewobjspreaddyn>(node, obj, target);
1192 }
1193 
GetUnmappedArgs(const ir::AstNode * node)1194 void PandaGen::GetUnmappedArgs(const ir::AstNode *node)
1195 {
1196     Sa().Emit<EcmaGetunmappedargs>(node);
1197 }
1198 
Negate(const ir::AstNode * node)1199 void PandaGen::Negate(const ir::AstNode *node)
1200 {
1201     Sa().Emit<EcmaNegate>(node);
1202 }
1203 
ToBoolean(const ir::AstNode * node)1204 void PandaGen::ToBoolean(const ir::AstNode *node)
1205 {
1206     Sa().Emit<EcmaToboolean>(node);
1207 }
1208 
ToNumber(const ir::AstNode * node,VReg arg)1209 void PandaGen::ToNumber(const ir::AstNode *node, VReg arg)
1210 {
1211     Ra().Emit<EcmaTonumber>(node, arg);
1212 }
1213 
GetMethod(const ir::AstNode * node,VReg obj,const util::StringView & name)1214 void PandaGen::GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name)
1215 {
1216     Ra().Emit<EcmaGetmethod>(node, name, obj);
1217 }
1218 
CreateGeneratorObj(const ir::AstNode * node,VReg funcObj)1219 void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj)
1220 {
1221     Ra().Emit<EcmaCreategeneratorobj>(node, funcObj);
1222 }
1223 
CreateAsyncGeneratorObj(const ir::AstNode * node,VReg funcObj)1224 void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj)
1225 {
1226     Ra().Emit<EcmaCreateasyncgeneratorobj>(node, funcObj);
1227 }
1228 
CreateIterResultObject(const ir::AstNode * node,bool done)1229 void PandaGen::CreateIterResultObject(const ir::AstNode *node, bool done)
1230 {
1231     Ra().Emit<EcmaCreateiterresultobj>(node, static_cast<int32_t>(done));
1232 }
1233 
SuspendGenerator(const ir::AstNode * node,VReg genObj)1234 void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj)
1235 {
1236     Ra().Emit<EcmaSuspendgenerator>(node, genObj);
1237 }
1238 
SuspendAsyncGenerator(const ir::AstNode * node,VReg asyncGenObj)1239 void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj)
1240 {
1241     Ra().Emit<EcmaSuspendasyncgenerator>(node, asyncGenObj);
1242 }
1243 
GeneratorYield(const ir::AstNode * node,VReg genObj)1244 void PandaGen::GeneratorYield(const ir::AstNode *node, VReg genObj)
1245 {
1246     Ra().Emit<EcmaSetgeneratorstate>(node, genObj, static_cast<int32_t>(GeneratorState::SUSPENDED_YIELD));
1247 }
1248 
GeneratorComplete(const ir::AstNode * node,VReg genObj)1249 void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj)
1250 {
1251     Ra().Emit<EcmaSetgeneratorstate>(node, genObj, static_cast<int32_t>(GeneratorState::COMPLETED));
1252 }
1253 
ResumeGenerator(const ir::AstNode * node,VReg genObj)1254 void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj)
1255 {
1256     Ra().Emit<EcmaResumegenerator>(node, genObj);
1257 }
1258 
GetResumeMode(const ir::AstNode * node,VReg genObj)1259 void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj)
1260 {
1261     Ra().Emit<EcmaGetresumemode>(node, genObj);
1262 }
1263 
AsyncFunctionEnter(const ir::AstNode * node)1264 void PandaGen::AsyncFunctionEnter(const ir::AstNode *node)
1265 {
1266     Sa().Emit<EcmaAsyncfunctionenter>(node);
1267 }
1268 
AsyncFunctionAwait(const ir::AstNode * node,VReg asyncFuncObj)1269 void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj)
1270 {
1271     Ra().Emit<EcmaAsyncfunctionawait>(node, asyncFuncObj);
1272 }
1273 
AsyncFunctionResolve(const ir::AstNode * node,VReg asyncFuncObj)1274 void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj)
1275 {
1276     Ra().Emit<EcmaAsyncfunctionresolve>(node, asyncFuncObj);
1277 }
1278 
AsyncFunctionReject(const ir::AstNode * node,VReg asyncFuncObj)1279 void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj)
1280 {
1281     Ra().Emit<EcmaAsyncfunctionreject>(node, asyncFuncObj);
1282 }
1283 
AsyncGeneratorResolve(const ir::AstNode * node,VReg asyncGenObj)1284 void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj)
1285 {
1286     Ra().Emit<EcmaAsyncgeneratorresolve>(node, asyncGenObj);
1287 }
1288 
AsyncGeneratorReject(const ir::AstNode * node,VReg asyncGenObj)1289 void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj)
1290 {
1291     Ra().Emit<EcmaAsyncgeneratorreject>(node, asyncGenObj);
1292 }
1293 
GetTemplateObject(const ir::AstNode * node,VReg value)1294 void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value)
1295 {
1296     Ra().Emit<EcmaGettemplateobject>(node, value);
1297 }
1298 
CopyRestArgs(const ir::AstNode * node,uint32_t index)1299 void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index)
1300 {
1301     Sa().Emit<EcmaCopyrestargs>(node, index);
1302 }
1303 
GetPropIterator(const ir::AstNode * node)1304 void PandaGen::GetPropIterator(const ir::AstNode *node)
1305 {
1306     Sa().Emit<EcmaGetpropiterator>(node);
1307 }
1308 
GetNextPropName(const ir::AstNode * node,VReg iter)1309 void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter)
1310 {
1311     Ra().Emit<EcmaGetnextpropname>(node, iter);
1312 }
1313 
CreateEmptyObject(const ir::AstNode * node)1314 void PandaGen::CreateEmptyObject(const ir::AstNode *node)
1315 {
1316     Sa().Emit<EcmaCreateemptyobject>(node);
1317 }
1318 
CreateObjectWithBuffer(const ir::AstNode * node,uint32_t idx)1319 void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx)
1320 {
1321     ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1322     Sa().Emit<EcmaCreateobjectwithbuffer>(node, util::Helpers::ToStringView(Allocator(), idx));
1323 }
1324 
CreateObjectHavingMethod(const ir::AstNode * node,uint32_t idx)1325 void PandaGen::CreateObjectHavingMethod(const ir::AstNode *node, uint32_t idx)
1326 {
1327     ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1328     LoadAccumulator(node, LexEnv());
1329     Sa().Emit<EcmaCreateobjecthavingmethod>(node, util::Helpers::ToStringView(Allocator(), idx));
1330 }
1331 
SetObjectWithProto(const ir::AstNode * node,VReg proto,VReg obj)1332 void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj)
1333 {
1334     Ra().Emit<EcmaSetobjectwithproto>(node, proto, obj);
1335 }
1336 
CopyDataProperties(const ir::AstNode * node,VReg dst,VReg src)1337 void PandaGen::CopyDataProperties(const ir::AstNode *node, VReg dst, VReg src)
1338 {
1339     Ra().Emit<EcmaCopydataproperties>(node, dst, src);
1340 }
1341 
DefineGetterSetterByValue(const ir::AstNode * node,std::tuple<VReg,VReg,VReg,VReg> registers,bool setName)1342 void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, std::tuple<VReg, VReg, VReg, VReg> registers,
1343                                          bool setName)
1344 {
1345     const auto [obj, name, getter, setter] = registers;
1346     LoadConst(node, setName ? Constant::JS_TRUE : Constant::JS_FALSE);
1347     Ra().Emit<EcmaDefinegettersetterbyvalue>(node, obj, name, getter, setter);
1348 }
1349 
CreateEmptyArray(const ir::AstNode * node)1350 void PandaGen::CreateEmptyArray(const ir::AstNode *node)
1351 {
1352     Sa().Emit<EcmaCreateemptyarray>(node);
1353 }
1354 
CreateArrayWithBuffer(const ir::AstNode * node,uint32_t idx)1355 void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx)
1356 {
1357     ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1358     Sa().Emit<EcmaCreatearraywithbuffer>(node, util::Helpers::ToStringView(Allocator(), idx));
1359 }
1360 
HandleArrayLiterals(const ir::AstNode * node,const ArenaVector<ir::Expression * > & elements)1361 size_t PandaGen::HandleArrayLiterals(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements)
1362 {
1363     LiteralBuffer buf {};
1364 
1365     size_t i = 0;
1366     // This loop handles constant literal data by collecting it into a literal buffer
1367     // until a non-constant element is encountered.
1368     while (i < elements.size()) {
1369         Literal lit = util::Helpers::ToConstantLiteral(elements[i]);
1370         if (lit.IsInvalid()) {
1371             break;
1372         }
1373 
1374         buf.emplace_back(std::move(lit));
1375         i++;
1376     }
1377 
1378     if (buf.empty()) {
1379         CreateEmptyArray(node);
1380     } else {
1381         uint32_t bufIdx = AddLiteralBuffer(std::move(buf));
1382         CreateArrayWithBuffer(node, bufIdx);
1383     }
1384     return i;
1385 }
1386 
HandleArraySpread(const ir::AstNode * node,const ArenaVector<ir::Expression * > & elements,VReg obj)1387 void PandaGen::HandleArraySpread(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj)
1388 {
1389     size_t i = 0;
1390     bool hasSpread = false;
1391 
1392     // This loop handles array elements until a spread element is encountered
1393     for (; i < elements.size(); i++) {
1394         const ir::Expression *elem = elements[i];
1395 
1396         if (elem->IsOmittedExpression()) {
1397             continue;
1398         }
1399 
1400         if (elem->IsSpreadElement()) {
1401             // The next loop will handle arrays that have a spread element
1402             hasSpread = true;
1403             break;
1404         }
1405 
1406         elem->Compile(this);
1407         StOwnByIndex(elem, obj, i);
1408     }
1409 
1410     RegScope rs(this);
1411     VReg idxReg {};
1412 
1413     if (hasSpread) {
1414         idxReg = AllocReg();
1415         LoadAccumulatorInt(node, i);
1416         StoreAccumulator(node, idxReg);
1417     }
1418 
1419     // This loop handles arrays that contain spread elements
1420     for (; i < elements.size(); i++) {
1421         const ir::Expression *elem = elements[i];
1422 
1423         if (elem->IsSpreadElement()) {
1424             elem->AsSpreadElement()->Argument()->Compile(this);
1425 
1426             StoreArraySpread(elem, obj, idxReg);
1427             StoreAccumulator(elem, idxReg);
1428             continue;
1429         }
1430 
1431         if (!elem->IsOmittedExpression()) {
1432             elem->Compile(this);
1433             StOwnByValue(elem, obj, idxReg);
1434         }
1435 
1436         Unary(elem, lexer::TokenType::PUNCTUATOR_PLUS_PLUS, idxReg);
1437         StoreAccumulator(elem, idxReg);
1438     }
1439 
1440     // If the last element is omitted, we also have to update the length property
1441     if (elements.back()->IsOmittedExpression()) {
1442         // if there was a spread value then acc already contains the length
1443         if (!hasSpread) {
1444             LoadAccumulatorInt(node, i);
1445         }
1446 
1447         StOwnByName(node, obj, "length");
1448     }
1449 }
1450 
CreateArray(const ir::AstNode * node,const ArenaVector<ir::Expression * > & elements,VReg obj)1451 void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj)
1452 {
1453     if (elements.empty()) {
1454         CreateEmptyArray(node);
1455         StoreAccumulator(node, obj);
1456         return;
1457     }
1458 
1459     const auto i = HandleArrayLiterals(node, elements);
1460 
1461     StoreAccumulator(node, obj);
1462 
1463     if (i == elements.size()) {
1464         return;
1465     }
1466 
1467     HandleArraySpread(node, elements, obj);
1468 
1469     LoadAccumulator(node, obj);
1470 }
1471 
StoreArraySpread(const ir::AstNode * node,VReg array,VReg index)1472 void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index)
1473 {
1474     Ra().Emit<EcmaStarrayspread>(node, array, index);
1475 }
1476 
CreateRegExpWithLiteral(const ir::AstNode * node,const util::StringView & pattern,uint8_t flags)1477 void PandaGen::CreateRegExpWithLiteral(const ir::AstNode *node, const util::StringView &pattern, uint8_t flags)
1478 {
1479     Sa().Emit<EcmaCreateregexpwithliteral>(node, pattern, flags);
1480 }
1481 
ThrowIfNotObject(const ir::AstNode * node)1482 void PandaGen::ThrowIfNotObject(const ir::AstNode *node)
1483 {
1484     Ra().Emit<EcmaThrowifnotobject>(node);
1485 }
1486 
ThrowThrowNotExist(const ir::AstNode * node)1487 void PandaGen::ThrowThrowNotExist(const ir::AstNode *node)
1488 {
1489     Sa().Emit<EcmaThrowthrownotexists>(node);
1490 }
1491 
GetIterator(const ir::AstNode * node)1492 void PandaGen::GetIterator(const ir::AstNode *node)
1493 {
1494     Sa().Emit<EcmaGetiterator>(node);
1495 }
1496 
GetAsyncIterator(const ir::AstNode * node)1497 void PandaGen::GetAsyncIterator(const ir::AstNode *node)
1498 {
1499     Sa().Emit<EcmaGetasynciterator>(node);
1500 }
1501 
CreateObjectWithExcludedKeys(const ir::AstNode * node,VReg obj,VReg argStart,size_t argCount)1502 void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount)
1503 {
1504     ASSERT(argStart.GetIndex() == obj.GetIndex() - 1);
1505     if (argCount == 0) {  // Do not emit undefined register
1506         argStart = obj;
1507     }
1508 
1509     Rra().Emit<EcmaCreateobjectwithexcludedkeys>(node, argStart, argCount, static_cast<int64_t>(argCount), obj,
1510                                                  argStart);
1511 }
1512 
ThrowObjectNonCoercible(const ir::AstNode * node)1513 void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node)
1514 {
1515     Sa().Emit<EcmaThrowpatternnoncoercible>(node);
1516 }
1517 
CloseIterator(const ir::AstNode * node,VReg iter)1518 void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter)
1519 {
1520     Ra().Emit<EcmaCloseiterator>(node, iter);
1521 }
1522 
ImportModule(const ir::AstNode * node,const util::StringView & name)1523 void PandaGen::ImportModule(const ir::AstNode *node, const util::StringView &name)
1524 {
1525     Sa().Emit<EcmaImportmodule>(node, name);
1526 }
1527 
SetClassComputedFields(const ir::AstNode * node,VReg classReg,VReg computedInstanceFieldArray)1528 void PandaGen::SetClassComputedFields(const ir::AstNode *node, VReg classReg, VReg computedInstanceFieldArray)
1529 {
1530     Ra().Emit<EcmaSetclasscomputedfields>(node, classReg, computedInstanceFieldArray);
1531 }
1532 
DefineClassWithBuffer(const ir::AstNode * node,const util::StringView & ctorId,uint32_t litIdx,VReg lexenv,VReg base)1533 void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, uint32_t litIdx,
1534                                      VReg lexenv, VReg base)
1535 {
1536     Ra().Emit<EcmaDefineclasswithbuffer>(node, ctorId, litIdx, lexenv, base);
1537 }
1538 
LoadClassComputedInstanceFields(const ir::AstNode * node,VReg ctor)1539 void PandaGen::LoadClassComputedInstanceFields(const ir::AstNode *node, VReg ctor)
1540 {
1541     Sa().Emit<EcmaLoadclasscomputedinstancefields>(node, ctor);
1542 }
1543 
DefineClassPrivateFields(const ir::AstNode * node,uint32_t privateBufIdx)1544 void PandaGen::DefineClassPrivateFields(const ir::AstNode *node, uint32_t privateBufIdx)
1545 {
1546     Sa().Emit<EcmaDefineclassprivatefields>(node, util::Helpers::ToStringView(Allocator(), privateBufIdx), LexEnv());
1547 }
1548 
ClassFieldAdd(const ir::AstNode * node,VReg obj,VReg prop)1549 void PandaGen::ClassFieldAdd(const ir::AstNode *node, VReg obj, VReg prop)
1550 {
1551     Ra().Emit<EcmaClassfieldadd>(node, obj, prop);
1552 }
1553 
ClassPrivateFieldAdd(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1554 void PandaGen::ClassPrivateFieldAdd(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1555 {
1556     Ra().Emit<EcmaClassprivatefieldadd>(node, prop, ctor, obj);
1557 }
1558 
ClassPrivateMethodOrAccessorAdd(const ir::AstNode * node,VReg ctor,VReg obj)1559 void PandaGen::ClassPrivateMethodOrAccessorAdd(const ir::AstNode *node, VReg ctor, VReg obj)
1560 {
1561     Ra().Emit<EcmaClassprivatemethodoraccessoradd>(node, ctor, obj);
1562 }
1563 
ClassPrivateFieldGet(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1564 void PandaGen::ClassPrivateFieldGet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1565 {
1566     Ra().Emit<EcmaClassprivatefieldget>(node, prop, ctor, obj);
1567 }
1568 
ClassPrivateFieldSet(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1569 void PandaGen::ClassPrivateFieldSet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1570 {
1571     Ra().Emit<EcmaClassprivatefieldset>(node, prop, ctor, obj);
1572 }
1573 
ClassPrivateFieldIn(const ir::AstNode * node,VReg ctor,const util::StringView & prop)1574 void PandaGen::ClassPrivateFieldIn(const ir::AstNode *node, VReg ctor, const util::StringView &prop)
1575 {
1576     Ra().Emit<EcmaClassprivatefieldin>(node, prop, ctor);
1577 }
1578 
LoadModuleVariable(const ir::AstNode * node,VReg module,const util::StringView & name)1579 void PandaGen::LoadModuleVariable(const ir::AstNode *node, VReg module, const util::StringView &name)
1580 {
1581     Ra().Emit<EcmaLdmodvarbyname>(node, name, module);
1582 }
1583 
StoreModuleVar(const ir::AstNode * node,const util::StringView & name)1584 void PandaGen::StoreModuleVar(const ir::AstNode *node, const util::StringView &name)
1585 {
1586     Sa().Emit<EcmaStmodulevar>(node, name);
1587 }
1588 
CopyModule(const ir::AstNode * node,VReg module)1589 void PandaGen::CopyModule(const ir::AstNode *node, VReg module)
1590 {
1591     Ra().Emit<EcmaCopymodule>(node, module);
1592 }
1593 
StSuperByName(const ir::AstNode * node,VReg obj,const util::StringView & key)1594 void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key)
1595 {
1596     Ra().Emit<EcmaStsuperbyname>(node, key, obj);
1597 }
1598 
LdSuperByName(const ir::AstNode * node,const util::StringView & key)1599 void PandaGen::LdSuperByName(const ir::AstNode *node, const util::StringView &key)
1600 {
1601     Ra().Emit<EcmaLdsuperbyname>(node, key);
1602 }
1603 
StSuperByValue(const ir::AstNode * node,VReg obj,VReg prop)1604 void PandaGen::StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop)
1605 {
1606     Ra().Emit<EcmaStsuperbyvalue>(node, obj, prop);
1607 }
1608 
LdSuperByValue(const ir::AstNode * node,VReg obj)1609 void PandaGen::LdSuperByValue(const ir::AstNode *node, VReg obj)
1610 {
1611     Ra().Emit<EcmaLdsuperbyvalue>(node, obj);
1612 }
1613 
StoreSuperProperty(const ir::AstNode * node,VReg obj,const Operand & prop)1614 void PandaGen::StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
1615 {
1616     if (std::holds_alternative<util::StringView>(prop)) {
1617         StSuperByName(node, obj, std::get<util::StringView>(prop));
1618         return;
1619     }
1620 
1621     ASSERT(std::holds_alternative<VReg>(prop));
1622     StSuperByValue(node, obj, std::get<VReg>(prop));
1623 }
1624 
LoadSuperProperty(const ir::AstNode * node,const Operand & prop)1625 void PandaGen::LoadSuperProperty(const ir::AstNode *node, const Operand &prop)
1626 {
1627     if (std::holds_alternative<util::StringView>(prop)) {
1628         LdSuperByName(node, std::get<util::StringView>(prop));
1629         return;
1630     }
1631 
1632     ASSERT(std::holds_alternative<VReg>(prop));
1633     LdSuperByValue(node, std::get<VReg>(prop));
1634 }
1635 
LoadLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1636 void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1637 {
1638     Sa().Emit<EcmaLdlexvardyn>(node, level, slot);
1639 }
1640 
LoadLexical(const ir::AstNode * node,const util::StringView & name,uint32_t level,uint32_t slot)1641 void PandaGen::LoadLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot)
1642 {
1643     Sa().Emit<EcmaLdlexdyn>(node, name, level, slot);
1644 }
1645 
StoreLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1646 void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1647 {
1648     Ra().Emit<EcmaStlexvardyn>(node, level, slot);
1649 }
1650 
StoreLexical(const ir::AstNode * node,const util::StringView & name,uint32_t level,uint32_t slot)1651 void PandaGen::StoreLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot)
1652 {
1653     Ra().Emit<EcmaStlexdyn>(node, name, level, slot);
1654 }
1655 
ThrowIfSuperNotCorrectCall(const ir::AstNode * node,int64_t num)1656 void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num)
1657 {
1658     Sa().Emit<EcmaThrowifsupernotcorrectcall>(node, num);
1659 }
1660 
ThrowTdz(const ir::AstNode * node,const util::StringView & name)1661 void PandaGen::ThrowTdz(const ir::AstNode *node, const util::StringView &name)
1662 {
1663     Sa().Emit<EcmaThrowtdz>(node, name);
1664 }
1665 
ThrowConstAssignment(const ir::AstNode * node,const util::StringView & name)1666 void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name)
1667 {
1668     Ra().Emit<EcmaThrowconstassignment>(node, name);
1669 }
1670 
PopLexEnv(const ir::AstNode * node)1671 void PandaGen::PopLexEnv(const ir::AstNode *node)
1672 {
1673     Sa().Emit<EcmaPoplexenvdyn>(node);
1674 }
1675 
CopyLexEnv(const ir::AstNode * node)1676 void PandaGen::CopyLexEnv(const ir::AstNode *node)
1677 {
1678     Sa().Emit<EcmaCopylexenvdyn>(node);
1679 }
1680 
NewLexEnv(const ir::AstNode * node,uint32_t num)1681 void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num)
1682 {
1683     Sa().Emit<EcmaNewlexenvdyn>(node, num);
1684 }
1685 
LdLexEnv(const ir::AstNode * node)1686 void PandaGen::LdLexEnv(const ir::AstNode *node)
1687 {
1688     Sa().Emit<EcmaLdlexenvdyn>(node);
1689 }
1690 
ToNamedPropertyKey(const ir::Expression * prop,bool isComputed)1691 Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed)
1692 {
1693     VReg res {VReg::REG_START};
1694 
1695     if (!isComputed) {
1696         if (prop->IsIdentifier()) {
1697             return prop->AsIdentifier()->Name();
1698         }
1699         return res;
1700     }
1701 
1702     if (prop->IsStringLiteral()) {
1703         const util::StringView &str = prop->AsStringLiteral()->Str();
1704 
1705         /* NOTE: dbatyai. remove this when runtime handles __proto__ as property name correctly */
1706         if (str.Is("__proto__")) {
1707             return res;
1708         }
1709 
1710         int64_t index = util::Helpers::GetIndex(str);
1711         if (index != util::Helpers::INVALID_INDEX) {
1712             return index;
1713         }
1714 
1715         return str;
1716     }
1717 
1718     if (prop->IsNumberLiteral()) {
1719         auto num = prop->AsNumberLiteral()->Number().GetDouble();
1720         if (util::Helpers::IsIndex(num)) {
1721             return static_cast<int64_t>(num);
1722         }
1723 
1724         return prop->AsNumberLiteral()->Str();
1725     }
1726 
1727     return res;
1728 }
1729 
ToPropertyKey(const ir::Expression * prop,bool isComputed,bool isSuperExpression)1730 Operand PandaGen::ToPropertyKey(const ir::Expression *prop, bool isComputed, bool isSuperExpression)
1731 {
1732     Operand op = ToNamedPropertyKey(prop, isComputed);
1733     if (std::holds_alternative<util::StringView>(op)) {
1734         return op;
1735     }
1736 
1737     if (std::holds_alternative<int64_t>(op) && !isSuperExpression) {
1738         return op;
1739     }
1740 
1741     VReg objReg = AllocReg();
1742     StoreAccumulator(prop, objReg);
1743     prop->Compile(this);
1744 
1745     return objReg;
1746 }
1747 
ToOwnPropertyKey(const ir::Expression * prop,bool isComputed)1748 Operand PandaGen::ToOwnPropertyKey(const ir::Expression *prop, bool isComputed)
1749 {
1750     Operand op = ToNamedPropertyKey(prop, isComputed);
1751     if (std::holds_alternative<util::StringView>(op)) {
1752         ASSERT(std::holds_alternative<util::StringView>(op) || std::holds_alternative<int64_t>(op));
1753         return op;
1754     }
1755 
1756     if (std::holds_alternative<int64_t>(op)) {
1757         return op;
1758     }
1759 
1760     VReg propReg = AllocReg();
1761     prop->Compile(this);
1762     StoreAccumulator(prop, propReg);
1763 
1764     return propReg;
1765 }
1766 
LoadPropertyKeyAcc(const ir::Expression * prop,bool isComputed)1767 void PandaGen::LoadPropertyKeyAcc(const ir::Expression *prop, bool isComputed)
1768 {
1769     Operand op = ToNamedPropertyKey(prop, isComputed);
1770     if (std::holds_alternative<util::StringView>(op)) {
1771         LoadAccumulatorString(prop, std::get<util::StringView>(op));
1772     } else if (std::holds_alternative<int64_t>(op)) {
1773         LoadAccumulatorInt(prop, static_cast<size_t>(std::get<int64_t>(op)));
1774     } else {
1775         prop->Compile(this);
1776     }
1777 }
1778 
LoadPropertyKey(const ir::Expression * prop,bool isComputed)1779 VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed)
1780 {
1781     LoadPropertyKeyAcc(prop, isComputed);
1782 
1783     VReg propReg = AllocReg();
1784     StoreAccumulator(prop, propReg);
1785 
1786     return propReg;
1787 }
1788 
LoadEvalVariable(const ir::AstNode * node,const util::StringView & name)1789 void PandaGen::LoadEvalVariable(const ir::AstNode *node, const util::StringView &name)
1790 {
1791     RegScope rs(this);
1792     LoadLexicalContext(node);
1793     Ra().Emit<EcmaLdevalvar>(node, name);
1794 }
1795 
StoreEvalVariable(const ir::AstNode * node,const util::StringView & name)1796 void PandaGen::StoreEvalVariable(const ir::AstNode *node, const util::StringView &name)
1797 {
1798     RegScope rs(this);
1799     VReg value = AllocReg();
1800     StoreAccumulator(node, value);
1801     LoadLexicalContext(node);
1802     Ra().Emit<EcmaStevalvar>(node, name, value);
1803 }
1804 
DirectEval(const ir::AstNode * node,uint32_t parserStatus)1805 void PandaGen::DirectEval(const ir::AstNode *node, uint32_t parserStatus)
1806 {
1807     RegScope rs(this);
1808 
1809     uint32_t index = 0;
1810     uint32_t evalBindingsIndex = 0;
1811     VReg arg0 = AllocReg();
1812     StoreAccumulator(node, arg0);
1813     VReg bindings = AllocReg();
1814     CreateEmptyArray(node);
1815     StoreAccumulator(node, bindings);
1816 
1817     GetFunctionObject(node);
1818     StOwnByIndex(node, bindings, index++);
1819     GetNewTarget(node);
1820     StOwnByIndex(node, bindings, index++);
1821     GetThis(node);
1822     StOwnByIndex(node, bindings, index++);
1823 
1824     VReg evalBindings = AllocReg();
1825     CreateEmptyArray(node);
1826     StoreAccumulator(node, evalBindings);
1827 
1828     LoadAccumulator(node, LexEnv());
1829     StOwnByIndex(node, evalBindings, evalBindingsIndex++);
1830 
1831     const auto *iter = Scope()->EnclosingVariableScope();
1832 
1833     while (true) {
1834         uint32_t scopeBindingsBuf = iter->EvalBindings();
1835         if (scopeBindingsBuf != INVALID_LITERAL_BUFFER_ID) {
1836             Sa().Emit<EcmaLdevalbindings>(node, util::Helpers::ToStringView(Allocator(), scopeBindingsBuf));
1837             StOwnByIndex(node, evalBindings, evalBindingsIndex++);
1838         }
1839 
1840         if (iter->Parent() == nullptr) {
1841             break;
1842         }
1843 
1844         iter = iter->Parent()->EnclosingVariableScope();
1845     }
1846 
1847     LoadAccumulator(node, evalBindings);
1848     StOwnByIndex(node, bindings, index++);
1849 
1850     Sa().Emit<EcmaDirecteval>(node, static_cast<int64_t>(parserStatus), arg0, bindings);
1851 }
1852 
LoadLexicalContext(const ir::AstNode * node)1853 void PandaGen::LoadLexicalContext(const ir::AstNode *node)
1854 {
1855     auto result = Scope()->Find(varbinder::VarBinder::LEXICAL_CONTEXT_PARAM);
1856     LoadLexicalVar(node, result.lexLevel, result.variable->AsLocalVariable()->LexIdx());
1857 }
1858 
IsDirectEval() const1859 bool PandaGen::IsDirectEval() const
1860 {
1861     return Context()->config->options->CompilerOptions().isDirectEval;
1862 }
1863 
IsEval() const1864 bool PandaGen::IsEval() const
1865 {
1866     return Context()->config->options->CompilerOptions().isEval;
1867 }
1868 
GetVRegType(VReg vreg) const1869 const checker::Type *PandaGen::GetVRegType(VReg vreg) const
1870 {
1871     // We assume that all used regs have any type
1872     if (vreg.GetIndex() > NextReg().GetIndex()) {
1873         return Context()->checker->GetGlobalTypesHolder()->GlobalAnyType();
1874     }
1875 
1876     return nullptr;
1877 }
1878 
1879 }  // namespace ark::es2panda::compiler
1880