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