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