1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "pandagen.h"
17
18 #include "varbinder/varbinder.h"
19 #include "checker/checker.h"
20 #include "checker/types/globalTypesHolder.h"
21 #include "util/helpers.h"
22 #include "varbinder/scope.h"
23 #include "varbinder/variable.h"
24 #include "compiler/base/catchTable.h"
25 #include "compiler/base/lexenv.h"
26 #include "compiler/base/literals.h"
27 #include "compiler/core/compilerContext.h"
28 #include "compiler/core/labelTarget.h"
29 #include "compiler/core/regAllocator.h"
30 #include "compiler/function/asyncFunctionBuilder.h"
31 #include "compiler/function/asyncGeneratorFunctionBuilder.h"
32 #include "compiler/function/functionBuilder.h"
33 #include "compiler/function/generatorFunctionBuilder.h"
34 #include "es2panda.h"
35 #include "generated/isa.h"
36 #include "ir/base/scriptFunction.h"
37 #include "ir/base/spreadElement.h"
38 #include "ir/statement.h"
39 #include "ir/expressions/identifier.h"
40 #include "ir/expressions/literals/numberLiteral.h"
41 #include "ir/expressions/literals/stringLiteral.h"
42
43 namespace panda::es2panda::compiler {
44
45 #ifndef PANDA_WITH_ECMASCRIPT
46 class EcmaDisabled : public IRNode {
47 public:
48 template <typename... Args>
EcmaDisabled(const ir::AstNode * node,Args &&...args)49 explicit EcmaDisabled(const ir::AstNode *node, [[maybe_unused]] Args &&...args) : IRNode(node)
50 {
51 UNREACHABLE();
52 }
53
GetFormats() const54 Formats GetFormats() const override
55 {
56 UNREACHABLE();
57 }
58
Registers(std::array<VReg *,MAX_REG_OPERAND> * regs)59 size_t Registers([[maybe_unused]] std::array<VReg *, MAX_REG_OPERAND> *regs) override
60 {
61 UNREACHABLE();
62 }
63
Registers(std::array<const VReg *,MAX_REG_OPERAND> * regs) const64 size_t Registers([[maybe_unused]] std::array<const VReg *, MAX_REG_OPERAND> *regs) const override
65 {
66 UNREACHABLE();
67 }
68
OutRegisters(std::array<OutVReg,MAX_REG_OPERAND> * regs) const69 size_t OutRegisters([[maybe_unused]] std::array<OutVReg, MAX_REG_OPERAND> *regs) const override
70 {
71 UNREACHABLE();
72 }
73
Transform(pandasm::Ins * ins,ProgramElement * programElement,uint32_t totalRegs) const74 void Transform([[maybe_unused]] pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement,
75 [[maybe_unused]] uint32_t totalRegs) const override
76 {
77 UNREACHABLE();
78 }
79 };
80
81 using EcmaLdhole = EcmaDisabled;
82 using EcmaLdnan = EcmaDisabled;
83 using EcmaLdinfinity = EcmaDisabled;
84 using EcmaLdglobal = EcmaDisabled;
85 using EcmaLdundefined = EcmaDisabled;
86 using EcmaLdsymbol = EcmaDisabled;
87 using EcmaLdnull = EcmaDisabled;
88 using EcmaLdtrue = EcmaDisabled;
89 using EcmaLdfalse = EcmaDisabled;
90 using EcmaTryldglobalbyname = EcmaDisabled;
91 using EcmaTrystglobalbyname = EcmaDisabled;
92 using EcmaLdobjbyname = EcmaDisabled;
93 using EcmaStobjbyname = EcmaDisabled;
94 using EcmaLdobjbyindex = EcmaDisabled;
95 using EcmaLdobjbyvalue = EcmaDisabled;
96 using EcmaStobjbyvalue = EcmaDisabled;
97 using EcmaStobjbyindex = EcmaDisabled;
98 using EcmaStownbyname = EcmaDisabled;
99 using EcmaStownbyvalue = EcmaDisabled;
100 using EcmaStownbyindex = EcmaDisabled;
101 using EcmaDelobjprop = EcmaDisabled;
102 using EcmaLdglobalvar = EcmaDisabled;
103 using EcmaStglobalvar = EcmaDisabled;
104 using EcmaLdbigint = EcmaDisabled;
105 using EcmaEqdyn = EcmaDisabled;
106 using EcmaNoteqdyn = EcmaDisabled;
107 using EcmaStricteqdyn = EcmaDisabled;
108 using EcmaStrictnoteqdyn = EcmaDisabled;
109 using EcmaLessdyn = EcmaDisabled;
110 using EcmaLesseqdyn = EcmaDisabled;
111 using EcmaGreaterdyn = EcmaDisabled;
112 using EcmaGreatereqdyn = EcmaDisabled;
113 using EcmaTonumber = EcmaDisabled;
114 using EcmaNegdyn = EcmaDisabled;
115 using EcmaNotdyn = EcmaDisabled;
116 using EcmaNegate = EcmaDisabled;
117 using EcmaIncdyn = EcmaDisabled;
118 using EcmaDecdyn = EcmaDisabled;
119 using EcmaEqdyn = EcmaDisabled;
120 using EcmaNoteqdyn = EcmaDisabled;
121 using EcmaStricteqdyn = EcmaDisabled;
122 using EcmaStrictnoteqdyn = EcmaDisabled;
123 using EcmaLessdyn = EcmaDisabled;
124 using EcmaLesseqdyn = EcmaDisabled;
125 using EcmaGreaterdyn = EcmaDisabled;
126 using EcmaGreatereqdyn = EcmaDisabled;
127 using EcmaAdd2dyn = EcmaDisabled;
128 using EcmaSub2dyn = EcmaDisabled;
129 using EcmaMul2dyn = EcmaDisabled;
130 using EcmaDiv2dyn = EcmaDisabled;
131 using EcmaMod2dyn = EcmaDisabled;
132 using EcmaExpdyn = EcmaDisabled;
133 using EcmaShl2dyn = EcmaDisabled;
134 using EcmaShr2dyn = EcmaDisabled;
135 using EcmaAshr2dyn = EcmaDisabled;
136 using EcmaAnd2dyn = EcmaDisabled;
137 using EcmaOr2dyn = EcmaDisabled;
138 using EcmaXor2dyn = EcmaDisabled;
139 using EcmaIsindyn = EcmaDisabled;
140 using EcmaInstanceofdyn = EcmaDisabled;
141 using EcmaIsundefined = EcmaDisabled;
142 using EcmaIsundefined = EcmaDisabled;
143 using EcmaJtrue = EcmaDisabled;
144 using EcmaIstrue = EcmaDisabled;
145 using EcmaJfalse = EcmaDisabled;
146 using EcmaIscoercible = EcmaDisabled;
147 using EcmaThrowdyn = EcmaDisabled;
148 using EcmaRethrowdyn = EcmaDisabled;
149 using EcmaReturnDyn = EcmaDisabled;
150 using EcmaReturnundefined = EcmaDisabled;
151 using EcmaCall0thisdyn = EcmaDisabled;
152 using EcmaCall1thisdyn = EcmaDisabled;
153 using EcmaCall0dyn = EcmaDisabled;
154 using EcmaCall1thisdyn = EcmaDisabled;
155 using EcmaCall1dyn = EcmaDisabled;
156 using EcmaCall2thisdyn = EcmaDisabled;
157 using EcmaCall2dyn = EcmaDisabled;
158 using EcmaCall3thisdyn = EcmaDisabled;
159 using EcmaCall3dyn = EcmaDisabled;
160 using EcmaCallithisrangedyn = EcmaDisabled;
161 using EcmaCallirangedyn = EcmaDisabled;
162 using EcmaCall1thisdyn = EcmaDisabled;
163 using EcmaCall1dyn = EcmaDisabled;
164 using EcmaCall2thisdyn = EcmaDisabled;
165 using EcmaCall2dyn = EcmaDisabled;
166 using EcmaCall3thisdyn = EcmaDisabled;
167 using EcmaCall3dyn = EcmaDisabled;
168 using EcmaCallithisrangedyn = EcmaDisabled;
169 using EcmaCallirangedyn = EcmaDisabled;
170 using EcmaSupercall = EcmaDisabled;
171 using EcmaSupercallspread = EcmaDisabled;
172 using EcmaNewobjdynrange = EcmaDisabled;
173 using EcmaLdhomeobject = EcmaDisabled;
174 using EcmaDefinemethod = EcmaDisabled;
175 using EcmaDefineasyncgeneratorfunc = EcmaDisabled;
176 using EcmaDefineasyncfunc = EcmaDisabled;
177 using EcmaDefinegeneratorfunc = EcmaDisabled;
178 using EcmaDefinencfuncdyn = EcmaDisabled;
179 using EcmaDefinefuncdyn = EcmaDisabled;
180 using EcmaTypeofdyn = EcmaDisabled;
181 using EcmaCallspreaddyn = EcmaDisabled;
182 using EcmaNewobjspreaddyn = EcmaDisabled;
183 using EcmaGetunmappedargs = EcmaDisabled;
184 using EcmaNegate = EcmaDisabled;
185 using EcmaToboolean = EcmaDisabled;
186 using EcmaTonumber = EcmaDisabled;
187 using EcmaGetmethod = EcmaDisabled;
188 using EcmaCreategeneratorobj = EcmaDisabled;
189 using EcmaCreateasyncgeneratorobj = EcmaDisabled;
190 using EcmaCreateiterresultobj = EcmaDisabled;
191 using EcmaSuspendgenerator = EcmaDisabled;
192 using EcmaSuspendasyncgenerator = EcmaDisabled;
193 using EcmaSetgeneratorstate = EcmaDisabled;
194 using EcmaSetgeneratorstate = EcmaDisabled;
195 using EcmaResumegenerator = EcmaDisabled;
196 using EcmaGetresumemode = EcmaDisabled;
197 using EcmaAsyncfunctionenter = EcmaDisabled;
198 using EcmaAsyncfunctionawait = EcmaDisabled;
199 using EcmaAsyncfunctionresolve = EcmaDisabled;
200 using EcmaAsyncfunctionreject = EcmaDisabled;
201 using EcmaAsyncgeneratorresolve = EcmaDisabled;
202 using EcmaAsyncgeneratorreject = EcmaDisabled;
203 using EcmaGettemplateobject = EcmaDisabled;
204 using EcmaCopyrestargs = EcmaDisabled;
205 using EcmaGetpropiterator = EcmaDisabled;
206 using EcmaGetnextpropname = EcmaDisabled;
207 using EcmaCreateemptyobject = EcmaDisabled;
208 using EcmaCreateobjectwithbuffer = EcmaDisabled;
209 using EcmaCreateobjecthavingmethod = EcmaDisabled;
210 using EcmaSetobjectwithproto = EcmaDisabled;
211 using EcmaCopydataproperties = EcmaDisabled;
212 using EcmaDefinegettersetterbyvalue = EcmaDisabled;
213 using EcmaCreateemptyarray = EcmaDisabled;
214 using EcmaCreatearraywithbuffer = EcmaDisabled;
215 using EcmaStarrayspread = EcmaDisabled;
216 using EcmaCreateregexpwithliteral = EcmaDisabled;
217 using EcmaThrowifnotobject = EcmaDisabled;
218 using EcmaThrowthrownotexists = EcmaDisabled;
219 using EcmaGetiterator = EcmaDisabled;
220 using EcmaGetasynciterator = EcmaDisabled;
221 using EcmaCreateobjectwithexcludedkeys = EcmaDisabled;
222 using EcmaThrowpatternnoncoercible = EcmaDisabled;
223 using EcmaCloseiterator = EcmaDisabled;
224 using EcmaImportmodule = EcmaDisabled;
225 using EcmaSetclasscomputedfields = EcmaDisabled;
226 using EcmaDefineclasswithbuffer = EcmaDisabled;
227 using EcmaLoadclasscomputedinstancefields = EcmaDisabled;
228 using EcmaDefineclassprivatefields = EcmaDisabled;
229 using EcmaClassfieldadd = EcmaDisabled;
230 using EcmaClassprivatefieldadd = EcmaDisabled;
231 using EcmaClassprivatemethodoraccessoradd = EcmaDisabled;
232 using EcmaClassprivatefieldget = EcmaDisabled;
233 using EcmaClassprivatefieldset = EcmaDisabled;
234 using EcmaClassprivatefieldin = EcmaDisabled;
235 using EcmaLdmodvarbyname = EcmaDisabled;
236 using EcmaStmodulevar = EcmaDisabled;
237 using EcmaCopymodule = EcmaDisabled;
238 using EcmaStsuperbyname = EcmaDisabled;
239 using EcmaLdsuperbyname = EcmaDisabled;
240 using EcmaStsuperbyvalue = EcmaDisabled;
241 using EcmaLdsuperbyvalue = EcmaDisabled;
242 using EcmaLdlexvardyn = EcmaDisabled;
243 using EcmaLdlexdyn = EcmaDisabled;
244 using EcmaStlexvardyn = EcmaDisabled;
245 using EcmaStlexdyn = EcmaDisabled;
246 using EcmaThrowifsupernotcorrectcall = EcmaDisabled;
247 using EcmaThrowtdz = EcmaDisabled;
248 using EcmaThrowconstassignment = EcmaDisabled;
249 using EcmaPoplexenvdyn = EcmaDisabled;
250 using EcmaCopylexenvdyn = EcmaDisabled;
251 using EcmaNewlexenvdyn = EcmaDisabled;
252 using EcmaLdlexenvdyn = EcmaDisabled;
253 using EcmaLdevalvar = EcmaDisabled;
254 using EcmaStevalvar = EcmaDisabled;
255 using EcmaLdevalbindings = EcmaDisabled;
256 using EcmaDirecteval = EcmaDisabled;
257 #endif
258
PandaGen(ArenaAllocator * const allocator,RegSpiller * const spiller,CompilerContext * const context,varbinder::FunctionScope * const scope,ProgramElement * const programElement,AstCompiler * astcompiler)259 PandaGen::PandaGen(ArenaAllocator *const allocator, RegSpiller *const spiller, CompilerContext *const context,
260 varbinder::FunctionScope *const scope, ProgramElement *const programElement,
261 AstCompiler *astcompiler)
262 : CodeGen(allocator, spiller, context, scope, programElement, astcompiler)
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 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 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 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 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 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 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 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 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 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 UNREACHABLE();
718 }
719 }
720 }
721
Binary(const ir::AstNode * node,lexer::TokenType op,VReg lhs)722 void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs)
723 {
724 switch (op) {
725 case lexer::TokenType::PUNCTUATOR_EQUAL: {
726 Ra().Emit<EcmaEqdyn>(node, lhs);
727 break;
728 }
729 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: {
730 Ra().Emit<EcmaNoteqdyn>(node, lhs);
731 break;
732 }
733 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: {
734 Ra().Emit<EcmaStricteqdyn>(node, lhs);
735 break;
736 }
737 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
738 Ra().Emit<EcmaStrictnoteqdyn>(node, lhs);
739 break;
740 }
741 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
742 Ra().Emit<EcmaLessdyn>(node, lhs);
743 break;
744 }
745 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: {
746 Ra().Emit<EcmaLesseqdyn>(node, lhs);
747 break;
748 }
749 case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
750 Ra().Emit<EcmaGreaterdyn>(node, lhs);
751 break;
752 }
753 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
754 Ra().Emit<EcmaGreatereqdyn>(node, lhs);
755 break;
756 }
757 case lexer::TokenType::PUNCTUATOR_PLUS:
758 case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: {
759 Ra().Emit<EcmaAdd2dyn>(node, lhs);
760 break;
761 }
762 case lexer::TokenType::PUNCTUATOR_MINUS:
763 case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: {
764 Ra().Emit<EcmaSub2dyn>(node, lhs);
765 break;
766 }
767 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
768 case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: {
769 Ra().Emit<EcmaMul2dyn>(node, lhs);
770 break;
771 }
772 case lexer::TokenType::PUNCTUATOR_DIVIDE:
773 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
774 Ra().Emit<EcmaDiv2dyn>(node, lhs);
775 break;
776 }
777 case lexer::TokenType::PUNCTUATOR_MOD:
778 case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: {
779 Ra().Emit<EcmaMod2dyn>(node, lhs);
780 break;
781 }
782 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL:
783 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
784 Ra().Emit<EcmaExpdyn>(node, lhs);
785 break;
786 }
787 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
788 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: {
789 Ra().Emit<EcmaShl2dyn>(node, lhs);
790 break;
791 }
792 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
793 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: {
794 Ra().Emit<EcmaShr2dyn>(node, lhs);
795 break;
796 }
797 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
798 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: {
799 Ra().Emit<EcmaAshr2dyn>(node, lhs);
800 break;
801 }
802 case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
803 case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: {
804 Ra().Emit<EcmaAnd2dyn>(node, lhs);
805 break;
806 }
807 case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
808 case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: {
809 Ra().Emit<EcmaOr2dyn>(node, lhs);
810 break;
811 }
812 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
813 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: {
814 Ra().Emit<EcmaXor2dyn>(node, lhs);
815 break;
816 }
817 case lexer::TokenType::KEYW_IN: {
818 Ra().Emit<EcmaIsindyn>(node, lhs);
819 break;
820 }
821 case lexer::TokenType::KEYW_INSTANCEOF: {
822 Ra().Emit<EcmaInstanceofdyn>(node, lhs);
823 break;
824 }
825 case lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING:
826 case lexer::TokenType::PUNCTUATOR_LOGICAL_NULLISH_EQUAL: {
827 Unimplemented();
828 break;
829 }
830 default: {
831 UNREACHABLE();
832 }
833 }
834 }
835
BranchIfUndefined(const ir::AstNode * node,Label * target)836 void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target)
837 {
838 Sa().Emit<EcmaIsundefined>(node);
839 BranchIfTrue(node, target);
840 }
841
BranchIfNotUndefined(const ir::AstNode * node,Label * target)842 void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target)
843 {
844 Sa().Emit<EcmaIsundefined>(node);
845 BranchIfFalse(node, target);
846 }
847
BranchIfTrue(const ir::AstNode * node,Label * target)848 void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target)
849 {
850 Sa().Emit<EcmaJtrue>(node, target);
851 }
852
BranchIfNotTrue(const ir::AstNode * node,Label * target)853 void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target)
854 {
855 Sa().Emit<EcmaIstrue>(node);
856 BranchIfFalse(node, target);
857 }
858
BranchIfFalse(const ir::AstNode * node,Label * target)859 void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target)
860 {
861 Sa().Emit<EcmaJfalse>(node, target);
862 }
863
BranchIfCoercible(const ir::AstNode * node,Label * target)864 void PandaGen::BranchIfCoercible(const ir::AstNode *node, Label *target)
865 {
866 Sa().Emit<EcmaIscoercible>(node);
867 BranchIfTrue(node, target);
868 }
869
EmitThrow(const ir::AstNode * node)870 void PandaGen::EmitThrow(const ir::AstNode *node)
871 {
872 Sa().Emit<EcmaThrowdyn>(node);
873 }
874
EmitRethrow(const ir::AstNode * node)875 void PandaGen::EmitRethrow(const ir::AstNode *node)
876 {
877 Sa().Emit<EcmaRethrowdyn>(node);
878 }
879
EmitReturn(const ir::AstNode * node)880 void PandaGen::EmitReturn(const ir::AstNode *node)
881 {
882 Sa().Emit<EcmaReturnDyn>(node);
883 }
884
EmitReturnUndefined(const ir::AstNode * node)885 void PandaGen::EmitReturnUndefined(const ir::AstNode *node)
886 {
887 Sa().Emit<EcmaReturnundefined>(node);
888 }
889
ImplicitReturn(const ir::AstNode * node)890 void PandaGen::ImplicitReturn(const ir::AstNode *node)
891 {
892 builder_->ImplicitReturn(node);
893 }
894
DirectReturn(const ir::AstNode * node)895 void PandaGen::DirectReturn(const ir::AstNode *node)
896 {
897 builder_->DirectReturn(node);
898 }
899
ValidateClassDirectReturn(const ir::AstNode * node)900 void PandaGen::ValidateClassDirectReturn(const ir::AstNode *node)
901 {
902 const ir::ScriptFunction *func = util::Helpers::GetContainingFunction(node);
903
904 if (func == nullptr || !func->IsConstructor()) {
905 return;
906 }
907
908 RegScope rs(this);
909 VReg value = AllocReg();
910 StoreAccumulator(node, value);
911
912 auto *notUndefined = AllocLabel();
913 auto *condEnd = AllocLabel();
914
915 BranchIfNotUndefined(node, notUndefined);
916 GetThis(func);
917 ThrowIfSuperNotCorrectCall(func, 0);
918 Branch(node, condEnd);
919
920 SetLabel(node, notUndefined);
921 LoadAccumulator(node, value);
922
923 SetLabel(node, condEnd);
924 }
925
EmitAwait(const ir::AstNode * node)926 void PandaGen::EmitAwait(const ir::AstNode *node)
927 {
928 builder_->Await(node);
929 }
930
Call0This(const ir::AstNode * node,VReg callee,VReg thisReg)931 void PandaGen::Call0This(const ir::AstNode *node, VReg callee, VReg thisReg)
932 {
933 LoadAccumulator(node, thisReg);
934 Ra().Emit<EcmaCall0thisdyn>(node, callee);
935 }
936
Call1This(const ir::AstNode * node,VReg callee,VReg thisReg,VReg arg0)937 void PandaGen::Call1This(const ir::AstNode *node, VReg callee, VReg thisReg, VReg arg0)
938 {
939 LoadAccumulator(node, arg0);
940 Ra().Emit<EcmaCall1thisdyn>(node, callee, thisReg);
941 }
942
Call(const ir::AstNode * node,VReg callee,VReg thisReg,const ArenaVector<ir::Expression * > & arguments)943 void PandaGen::Call(const ir::AstNode *node, VReg callee, VReg thisReg, const ArenaVector<ir::Expression *> &arguments)
944 {
945 bool hasThis = !thisReg.IsInvalid();
946
947 switch (arguments.size()) {
948 case 0: { // 0 args
949 if (hasThis) {
950 Call0This(node, callee, thisReg);
951 } else {
952 Sa().Emit<EcmaCall0dyn>(node);
953 }
954 return;
955 }
956 case 1: { // 1 arg
957 const auto *arg0 = arguments[0];
958 arg0->Compile(this);
959
960 if (hasThis) {
961 Ra().Emit<EcmaCall1thisdyn>(node, callee, thisReg);
962 } else {
963 Ra().Emit<EcmaCall1dyn>(node, callee);
964 }
965 return;
966 }
967 case 2: { // 2 args
968 const auto *arg0 = arguments[0];
969 arg0->Compile(this);
970 compiler::VReg arg0Reg = AllocReg();
971 StoreAccumulator(arg0, arg0Reg);
972
973 const auto *arg1 = arguments[1];
974 arg1->Compile(this);
975
976 if (hasThis) {
977 Ra().Emit<EcmaCall2thisdyn>(node, callee, thisReg, arg0Reg);
978 } else {
979 Ra().Emit<EcmaCall2dyn>(node, callee, arg0Reg);
980 }
981 return;
982 }
983 case 3: { // 3 args
984 const auto *arg0 = arguments[0];
985 arg0->Compile(this);
986 compiler::VReg arg0Reg = AllocReg();
987 StoreAccumulator(arg0, arg0Reg);
988
989 const auto *arg1 = arguments[1];
990 arg1->Compile(this);
991 compiler::VReg arg1Reg = AllocReg();
992 StoreAccumulator(arg1, arg1Reg);
993
994 const auto *arg2 = arguments[2];
995 arg2->Compile(this);
996
997 if (hasThis) {
998 Ra().Emit<EcmaCall3thisdyn>(node, callee, thisReg, arg0Reg, arg1Reg);
999 } else {
1000 Ra().Emit<EcmaCall3dyn>(node, callee, arg0Reg, arg1Reg);
1001 }
1002 return;
1003 }
1004 default: {
1005 break;
1006 }
1007 }
1008
1009 for (const auto *it : arguments) {
1010 it->Compile(this);
1011 compiler::VReg arg = AllocReg();
1012 StoreAccumulator(it, arg);
1013 }
1014
1015 if (hasThis) {
1016 size_t argCount = arguments.size() + 1;
1017 auto constexpr EXTRA_ARGS = 2;
1018 Rra().Emit<EcmaCallithisrangedyn>(node, callee, argCount + EXTRA_ARGS, static_cast<int64_t>(argCount), callee);
1019 } else {
1020 size_t argCount = arguments.size();
1021 Rra().Emit<EcmaCallirangedyn>(node, callee, argCount + 1, static_cast<int64_t>(argCount), callee);
1022 }
1023 }
1024
CallTagged(const ir::AstNode * node,VReg callee,VReg thisReg,const ArenaVector<ir::Expression * > & arguments)1025 void PandaGen::CallTagged(const ir::AstNode *node, VReg callee, VReg thisReg,
1026 const ArenaVector<ir::Expression *> &arguments)
1027 {
1028 bool hasThis = !thisReg.IsInvalid();
1029
1030 StoreAccumulator(node, callee);
1031 Literals::GetTemplateObject(this, node->AsTaggedTemplateExpression());
1032
1033 if (arguments.empty()) {
1034 if (hasThis) {
1035 Ra().Emit<EcmaCall1thisdyn>(node, callee, thisReg);
1036 } else {
1037 Sa().Emit<EcmaCall1dyn>(node, callee);
1038 }
1039 return;
1040 }
1041
1042 VReg arg0Reg = AllocReg();
1043 StoreAccumulator(node, arg0Reg);
1044
1045 switch (arguments.size()) {
1046 case 1: {
1047 const auto *arg = arguments[0];
1048 arg->Compile(this);
1049
1050 if (hasThis) {
1051 Ra().Emit<EcmaCall2thisdyn>(node, callee, thisReg, arg0Reg);
1052 } else {
1053 Ra().Emit<EcmaCall2dyn>(node, callee, arg0Reg);
1054 }
1055 return;
1056 }
1057 case 2: { // 2:2 args
1058 const auto *arg1 = arguments[0];
1059 arg1->Compile(this);
1060 compiler::VReg arg1Reg = AllocReg();
1061 StoreAccumulator(arg1, arg1Reg);
1062
1063 const auto *arg2 = arguments[1];
1064 arg2->Compile(this);
1065
1066 if (hasThis) {
1067 Ra().Emit<EcmaCall3thisdyn>(node, callee, thisReg, arg0Reg, arg1Reg);
1068 } else {
1069 Ra().Emit<EcmaCall3dyn>(node, callee, arg0Reg, arg1Reg);
1070 }
1071 return;
1072 }
1073 default: {
1074 break;
1075 }
1076 }
1077
1078 for (const auto *it : arguments) {
1079 it->Compile(this);
1080 compiler::VReg arg = AllocReg();
1081 StoreAccumulator(it, arg);
1082 }
1083
1084 if (hasThis) {
1085 auto constexpr EXTRA_ARGS = 2;
1086 size_t argCount = arguments.size() + EXTRA_ARGS;
1087 Rra().Emit<EcmaCallithisrangedyn>(node, callee, argCount + EXTRA_ARGS, static_cast<int64_t>(argCount), callee);
1088 } else {
1089 size_t argCount = arguments.size() + 1;
1090 Rra().Emit<EcmaCallirangedyn>(node, callee, argCount + 1, static_cast<int64_t>(argCount), callee);
1091 }
1092 }
1093
SuperCall(const ir::AstNode * node,VReg startReg,size_t argCount)1094 void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount)
1095 {
1096 Rra().Emit<EcmaSupercall>(node, startReg, argCount, static_cast<int64_t>(argCount), startReg);
1097 }
1098
SuperCallSpread(const ir::AstNode * node,VReg vs)1099 void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs)
1100 {
1101 Ra().Emit<EcmaSupercallspread>(node, vs);
1102 }
1103
NewObject(const ir::AstNode * node,VReg startReg,size_t argCount)1104 void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount)
1105 {
1106 Rra().Emit<EcmaNewobjdynrange>(node, startReg, argCount, static_cast<int64_t>(argCount), startReg);
1107 }
1108
LoadHomeObject(const ir::AstNode * node)1109 void PandaGen::LoadHomeObject(const ir::AstNode *node)
1110 {
1111 Sa().Emit<EcmaLdhomeobject>(node);
1112 }
1113
DefineMethod(const ir::AstNode * node,const util::StringView & name)1114 void PandaGen::DefineMethod(const ir::AstNode *node, const util::StringView &name)
1115 {
1116 Ra().Emit<EcmaDefinemethod>(node, name, LexEnv());
1117 }
1118
DefineFunction(const ir::AstNode * node,const ir::ScriptFunction * realNode,const util::StringView & name)1119 void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name)
1120 {
1121 if (realNode->IsAsyncFunc()) {
1122 if (realNode->IsGenerator()) {
1123 Ra().Emit<EcmaDefineasyncgeneratorfunc>(node, name, LexEnv());
1124 } else {
1125 Ra().Emit<EcmaDefineasyncfunc>(node, name, LexEnv());
1126 }
1127 } else if (realNode->IsGenerator()) {
1128 Ra().Emit<EcmaDefinegeneratorfunc>(node, name, LexEnv());
1129 } else if (realNode->IsArrow()) {
1130 LoadHomeObject(node);
1131 Ra().Emit<EcmaDefinencfuncdyn>(node, name, LexEnv());
1132 } else if (realNode->IsMethod()) {
1133 DefineMethod(node, name);
1134 } else {
1135 Ra().Emit<EcmaDefinefuncdyn>(node, name, LexEnv());
1136 }
1137 }
1138
TypeOf(const ir::AstNode * node)1139 void PandaGen::TypeOf(const ir::AstNode *node)
1140 {
1141 Sa().Emit<EcmaTypeofdyn>(node);
1142 }
1143
CallSpread(const ir::AstNode * node,VReg func,VReg thisReg,VReg args)1144 void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args)
1145 {
1146 Ra().Emit<EcmaCallspreaddyn>(node, func, thisReg, args);
1147 }
1148
NewObjSpread(const ir::AstNode * node,VReg obj,VReg target)1149 void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj, VReg target)
1150 {
1151 Ra().Emit<EcmaNewobjspreaddyn>(node, obj, target);
1152 }
1153
GetUnmappedArgs(const ir::AstNode * node)1154 void PandaGen::GetUnmappedArgs(const ir::AstNode *node)
1155 {
1156 Sa().Emit<EcmaGetunmappedargs>(node);
1157 }
1158
Negate(const ir::AstNode * node)1159 void PandaGen::Negate(const ir::AstNode *node)
1160 {
1161 Sa().Emit<EcmaNegate>(node);
1162 }
1163
ToBoolean(const ir::AstNode * node)1164 void PandaGen::ToBoolean(const ir::AstNode *node)
1165 {
1166 Sa().Emit<EcmaToboolean>(node);
1167 }
1168
ToNumber(const ir::AstNode * node,VReg arg)1169 void PandaGen::ToNumber(const ir::AstNode *node, VReg arg)
1170 {
1171 Ra().Emit<EcmaTonumber>(node, arg);
1172 }
1173
GetMethod(const ir::AstNode * node,VReg obj,const util::StringView & name)1174 void PandaGen::GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name)
1175 {
1176 Ra().Emit<EcmaGetmethod>(node, name, obj);
1177 }
1178
CreateGeneratorObj(const ir::AstNode * node,VReg funcObj)1179 void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj)
1180 {
1181 Ra().Emit<EcmaCreategeneratorobj>(node, funcObj);
1182 }
1183
CreateAsyncGeneratorObj(const ir::AstNode * node,VReg funcObj)1184 void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj)
1185 {
1186 Ra().Emit<EcmaCreateasyncgeneratorobj>(node, funcObj);
1187 }
1188
CreateIterResultObject(const ir::AstNode * node,bool done)1189 void PandaGen::CreateIterResultObject(const ir::AstNode *node, bool done)
1190 {
1191 Ra().Emit<EcmaCreateiterresultobj>(node, static_cast<int32_t>(done));
1192 }
1193
SuspendGenerator(const ir::AstNode * node,VReg genObj)1194 void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj)
1195 {
1196 Ra().Emit<EcmaSuspendgenerator>(node, genObj);
1197 }
1198
SuspendAsyncGenerator(const ir::AstNode * node,VReg asyncGenObj)1199 void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj)
1200 {
1201 Ra().Emit<EcmaSuspendasyncgenerator>(node, asyncGenObj);
1202 }
1203
GeneratorYield(const ir::AstNode * node,VReg genObj)1204 void PandaGen::GeneratorYield(const ir::AstNode *node, VReg genObj)
1205 {
1206 Ra().Emit<EcmaSetgeneratorstate>(node, genObj, static_cast<int32_t>(GeneratorState::SUSPENDED_YIELD));
1207 }
1208
GeneratorComplete(const ir::AstNode * node,VReg genObj)1209 void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj)
1210 {
1211 Ra().Emit<EcmaSetgeneratorstate>(node, genObj, static_cast<int32_t>(GeneratorState::COMPLETED));
1212 }
1213
ResumeGenerator(const ir::AstNode * node,VReg genObj)1214 void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj)
1215 {
1216 Ra().Emit<EcmaResumegenerator>(node, genObj);
1217 }
1218
GetResumeMode(const ir::AstNode * node,VReg genObj)1219 void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj)
1220 {
1221 Ra().Emit<EcmaGetresumemode>(node, genObj);
1222 }
1223
AsyncFunctionEnter(const ir::AstNode * node)1224 void PandaGen::AsyncFunctionEnter(const ir::AstNode *node)
1225 {
1226 Sa().Emit<EcmaAsyncfunctionenter>(node);
1227 }
1228
AsyncFunctionAwait(const ir::AstNode * node,VReg asyncFuncObj)1229 void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj)
1230 {
1231 Ra().Emit<EcmaAsyncfunctionawait>(node, asyncFuncObj);
1232 }
1233
AsyncFunctionResolve(const ir::AstNode * node,VReg asyncFuncObj)1234 void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj)
1235 {
1236 Ra().Emit<EcmaAsyncfunctionresolve>(node, asyncFuncObj);
1237 }
1238
AsyncFunctionReject(const ir::AstNode * node,VReg asyncFuncObj)1239 void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj)
1240 {
1241 Ra().Emit<EcmaAsyncfunctionreject>(node, asyncFuncObj);
1242 }
1243
AsyncGeneratorResolve(const ir::AstNode * node,VReg asyncGenObj)1244 void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj)
1245 {
1246 Ra().Emit<EcmaAsyncgeneratorresolve>(node, asyncGenObj);
1247 }
1248
AsyncGeneratorReject(const ir::AstNode * node,VReg asyncGenObj)1249 void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj)
1250 {
1251 Ra().Emit<EcmaAsyncgeneratorreject>(node, asyncGenObj);
1252 }
1253
GetTemplateObject(const ir::AstNode * node,VReg value)1254 void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value)
1255 {
1256 Ra().Emit<EcmaGettemplateobject>(node, value);
1257 }
1258
CopyRestArgs(const ir::AstNode * node,uint32_t index)1259 void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index)
1260 {
1261 Sa().Emit<EcmaCopyrestargs>(node, index);
1262 }
1263
GetPropIterator(const ir::AstNode * node)1264 void PandaGen::GetPropIterator(const ir::AstNode *node)
1265 {
1266 Sa().Emit<EcmaGetpropiterator>(node);
1267 }
1268
GetNextPropName(const ir::AstNode * node,VReg iter)1269 void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter)
1270 {
1271 Ra().Emit<EcmaGetnextpropname>(node, iter);
1272 }
1273
CreateEmptyObject(const ir::AstNode * node)1274 void PandaGen::CreateEmptyObject(const ir::AstNode *node)
1275 {
1276 Sa().Emit<EcmaCreateemptyobject>(node);
1277 }
1278
CreateObjectWithBuffer(const ir::AstNode * node,uint32_t idx)1279 void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx)
1280 {
1281 ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1282 Sa().Emit<EcmaCreateobjectwithbuffer>(node, util::Helpers::ToStringView(Allocator(), idx));
1283 }
1284
CreateObjectHavingMethod(const ir::AstNode * node,uint32_t idx)1285 void PandaGen::CreateObjectHavingMethod(const ir::AstNode *node, uint32_t idx)
1286 {
1287 ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1288 LoadAccumulator(node, LexEnv());
1289 Sa().Emit<EcmaCreateobjecthavingmethod>(node, util::Helpers::ToStringView(Allocator(), idx));
1290 }
1291
SetObjectWithProto(const ir::AstNode * node,VReg proto,VReg obj)1292 void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj)
1293 {
1294 Ra().Emit<EcmaSetobjectwithproto>(node, proto, obj);
1295 }
1296
CopyDataProperties(const ir::AstNode * node,VReg dst,VReg src)1297 void PandaGen::CopyDataProperties(const ir::AstNode *node, VReg dst, VReg src)
1298 {
1299 Ra().Emit<EcmaCopydataproperties>(node, dst, src);
1300 }
1301
DefineGetterSetterByValue(const ir::AstNode * node,VReg obj,VReg name,VReg getter,VReg setter,bool setName)1302 void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter,
1303 bool setName)
1304 {
1305 LoadConst(node, setName ? Constant::JS_TRUE : Constant::JS_FALSE);
1306 Ra().Emit<EcmaDefinegettersetterbyvalue>(node, obj, name, getter, setter);
1307 }
1308
CreateEmptyArray(const ir::AstNode * node)1309 void PandaGen::CreateEmptyArray(const ir::AstNode *node)
1310 {
1311 Sa().Emit<EcmaCreateemptyarray>(node);
1312 }
1313
CreateArrayWithBuffer(const ir::AstNode * node,uint32_t idx)1314 void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx)
1315 {
1316 ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1317 Sa().Emit<EcmaCreatearraywithbuffer>(node, util::Helpers::ToStringView(Allocator(), idx));
1318 }
1319
CreateArray(const ir::AstNode * node,const ArenaVector<ir::Expression * > & elements,VReg obj)1320 void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj)
1321 {
1322 if (elements.empty()) {
1323 CreateEmptyArray(node);
1324 StoreAccumulator(node, obj);
1325 return;
1326 }
1327
1328 LiteralBuffer buf {};
1329
1330 size_t i = 0;
1331 // This loop handles constant literal data by collecting it into a literal buffer
1332 // until a non-constant element is encountered.
1333 while (i < elements.size()) {
1334 Literal lit = util::Helpers::ToConstantLiteral(elements[i]);
1335 if (lit.IsInvalid()) {
1336 break;
1337 }
1338
1339 buf.emplace_back(std::move(lit));
1340 i++;
1341 }
1342
1343 if (buf.empty()) {
1344 CreateEmptyArray(node);
1345 } else {
1346 uint32_t bufIdx = AddLiteralBuffer(std::move(buf));
1347 CreateArrayWithBuffer(node, bufIdx);
1348 }
1349
1350 StoreAccumulator(node, obj);
1351
1352 if (i == elements.size()) {
1353 return;
1354 }
1355
1356 bool hasSpread = false;
1357
1358 // This loop handles array elements until a spread element is encountered
1359 for (; i < elements.size(); i++) {
1360 const ir::Expression *elem = elements[i];
1361
1362 if (elem->IsOmittedExpression()) {
1363 continue;
1364 }
1365
1366 if (elem->IsSpreadElement()) {
1367 // The next loop will handle arrays that have a spread element
1368 hasSpread = true;
1369 break;
1370 }
1371
1372 elem->Compile(this);
1373 StOwnByIndex(elem, obj, i);
1374 }
1375
1376 RegScope rs(this);
1377 VReg idxReg {};
1378
1379 if (hasSpread) {
1380 idxReg = AllocReg();
1381 LoadAccumulatorInt(node, i);
1382 StoreAccumulator(node, idxReg);
1383 }
1384
1385 // This loop handles arrays that contain spread elements
1386 for (; i < elements.size(); i++) {
1387 const ir::Expression *elem = elements[i];
1388
1389 if (elem->IsSpreadElement()) {
1390 elem->AsSpreadElement()->Argument()->Compile(this);
1391
1392 StoreArraySpread(elem, obj, idxReg);
1393 StoreAccumulator(elem, idxReg);
1394 continue;
1395 }
1396
1397 if (!elem->IsOmittedExpression()) {
1398 elem->Compile(this);
1399 StOwnByValue(elem, obj, idxReg);
1400 }
1401
1402 Unary(elem, lexer::TokenType::PUNCTUATOR_PLUS_PLUS, idxReg);
1403 StoreAccumulator(elem, idxReg);
1404 }
1405
1406 // If the last element is omitted, we also have to update the length property
1407 if (elements.back()->IsOmittedExpression()) {
1408 // if there was a spread value then acc already contains the length
1409 if (!hasSpread) {
1410 LoadAccumulatorInt(node, i);
1411 }
1412
1413 StOwnByName(node, obj, "length");
1414 }
1415
1416 LoadAccumulator(node, obj);
1417 }
1418
StoreArraySpread(const ir::AstNode * node,VReg array,VReg index)1419 void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index)
1420 {
1421 Ra().Emit<EcmaStarrayspread>(node, array, index);
1422 }
1423
CreateRegExpWithLiteral(const ir::AstNode * node,const util::StringView & pattern,uint8_t flags)1424 void PandaGen::CreateRegExpWithLiteral(const ir::AstNode *node, const util::StringView &pattern, uint8_t flags)
1425 {
1426 Sa().Emit<EcmaCreateregexpwithliteral>(node, pattern, flags);
1427 }
1428
ThrowIfNotObject(const ir::AstNode * node)1429 void PandaGen::ThrowIfNotObject(const ir::AstNode *node)
1430 {
1431 Ra().Emit<EcmaThrowifnotobject>(node);
1432 }
1433
ThrowThrowNotExist(const ir::AstNode * node)1434 void PandaGen::ThrowThrowNotExist(const ir::AstNode *node)
1435 {
1436 Sa().Emit<EcmaThrowthrownotexists>(node);
1437 }
1438
GetIterator(const ir::AstNode * node)1439 void PandaGen::GetIterator(const ir::AstNode *node)
1440 {
1441 Sa().Emit<EcmaGetiterator>(node);
1442 }
1443
GetAsyncIterator(const ir::AstNode * node)1444 void PandaGen::GetAsyncIterator(const ir::AstNode *node)
1445 {
1446 Sa().Emit<EcmaGetasynciterator>(node);
1447 }
1448
CreateObjectWithExcludedKeys(const ir::AstNode * node,VReg obj,VReg argStart,size_t argCount)1449 void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount)
1450 {
1451 ASSERT(argStart.GetIndex() == obj.GetIndex() - 1);
1452 if (argCount == 0) { // Do not emit undefined register
1453 argStart = obj;
1454 }
1455
1456 Rra().Emit<EcmaCreateobjectwithexcludedkeys>(node, argStart, argCount, static_cast<int64_t>(argCount), obj,
1457 argStart);
1458 }
1459
ThrowObjectNonCoercible(const ir::AstNode * node)1460 void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node)
1461 {
1462 Sa().Emit<EcmaThrowpatternnoncoercible>(node);
1463 }
1464
CloseIterator(const ir::AstNode * node,VReg iter)1465 void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter)
1466 {
1467 Ra().Emit<EcmaCloseiterator>(node, iter);
1468 }
1469
ImportModule(const ir::AstNode * node,const util::StringView & name)1470 void PandaGen::ImportModule(const ir::AstNode *node, const util::StringView &name)
1471 {
1472 Sa().Emit<EcmaImportmodule>(node, name);
1473 }
1474
SetClassComputedFields(const ir::AstNode * node,VReg classReg,VReg computedInstanceFieldArray)1475 void PandaGen::SetClassComputedFields(const ir::AstNode *node, VReg classReg, VReg computedInstanceFieldArray)
1476 {
1477 Ra().Emit<EcmaSetclasscomputedfields>(node, classReg, computedInstanceFieldArray);
1478 }
1479
DefineClassWithBuffer(const ir::AstNode * node,const util::StringView & ctorId,int32_t litIdx,VReg lexenv,VReg base)1480 void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx,
1481 VReg lexenv, VReg base)
1482 {
1483 Ra().Emit<EcmaDefineclasswithbuffer>(node, ctorId, litIdx, lexenv, base);
1484 }
1485
LoadClassComputedInstanceFields(const ir::AstNode * node,VReg ctor)1486 void PandaGen::LoadClassComputedInstanceFields(const ir::AstNode *node, VReg ctor)
1487 {
1488 Sa().Emit<EcmaLoadclasscomputedinstancefields>(node, ctor);
1489 }
1490
DefineClassPrivateFields(const ir::AstNode * node,int32_t privateBufIdx)1491 void PandaGen::DefineClassPrivateFields(const ir::AstNode *node, int32_t privateBufIdx)
1492 {
1493 Sa().Emit<EcmaDefineclassprivatefields>(node, util::Helpers::ToStringView(Allocator(), privateBufIdx), LexEnv());
1494 }
1495
ClassFieldAdd(const ir::AstNode * node,VReg obj,VReg prop)1496 void PandaGen::ClassFieldAdd(const ir::AstNode *node, VReg obj, VReg prop)
1497 {
1498 Ra().Emit<EcmaClassfieldadd>(node, obj, prop);
1499 }
1500
ClassPrivateFieldAdd(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1501 void PandaGen::ClassPrivateFieldAdd(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1502 {
1503 Ra().Emit<EcmaClassprivatefieldadd>(node, prop, ctor, obj);
1504 }
1505
ClassPrivateMethodOrAccessorAdd(const ir::AstNode * node,VReg ctor,VReg obj)1506 void PandaGen::ClassPrivateMethodOrAccessorAdd(const ir::AstNode *node, VReg ctor, VReg obj)
1507 {
1508 Ra().Emit<EcmaClassprivatemethodoraccessoradd>(node, ctor, obj);
1509 }
1510
ClassPrivateFieldGet(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1511 void PandaGen::ClassPrivateFieldGet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1512 {
1513 Ra().Emit<EcmaClassprivatefieldget>(node, prop, ctor, obj);
1514 }
1515
ClassPrivateFieldSet(const ir::AstNode * node,VReg ctor,VReg obj,const util::StringView & prop)1516 void PandaGen::ClassPrivateFieldSet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop)
1517 {
1518 Ra().Emit<EcmaClassprivatefieldset>(node, prop, ctor, obj);
1519 }
1520
ClassPrivateFieldIn(const ir::AstNode * node,VReg ctor,const util::StringView & prop)1521 void PandaGen::ClassPrivateFieldIn(const ir::AstNode *node, VReg ctor, const util::StringView &prop)
1522 {
1523 Ra().Emit<EcmaClassprivatefieldin>(node, prop, ctor);
1524 }
1525
LoadModuleVariable(const ir::AstNode * node,VReg module,const util::StringView & name)1526 void PandaGen::LoadModuleVariable(const ir::AstNode *node, VReg module, const util::StringView &name)
1527 {
1528 Ra().Emit<EcmaLdmodvarbyname>(node, name, module);
1529 }
1530
StoreModuleVar(const ir::AstNode * node,const util::StringView & name)1531 void PandaGen::StoreModuleVar(const ir::AstNode *node, const util::StringView &name)
1532 {
1533 Sa().Emit<EcmaStmodulevar>(node, name);
1534 }
1535
CopyModule(const ir::AstNode * node,VReg module)1536 void PandaGen::CopyModule(const ir::AstNode *node, VReg module)
1537 {
1538 Ra().Emit<EcmaCopymodule>(node, module);
1539 }
1540
StSuperByName(const ir::AstNode * node,VReg obj,const util::StringView & key)1541 void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key)
1542 {
1543 Ra().Emit<EcmaStsuperbyname>(node, key, obj);
1544 }
1545
LdSuperByName(const ir::AstNode * node,const util::StringView & key)1546 void PandaGen::LdSuperByName(const ir::AstNode *node, const util::StringView &key)
1547 {
1548 Ra().Emit<EcmaLdsuperbyname>(node, key);
1549 }
1550
StSuperByValue(const ir::AstNode * node,VReg obj,VReg prop)1551 void PandaGen::StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop)
1552 {
1553 Ra().Emit<EcmaStsuperbyvalue>(node, obj, prop);
1554 }
1555
LdSuperByValue(const ir::AstNode * node,VReg obj)1556 void PandaGen::LdSuperByValue(const ir::AstNode *node, VReg obj)
1557 {
1558 Ra().Emit<EcmaLdsuperbyvalue>(node, obj);
1559 }
1560
StoreSuperProperty(const ir::AstNode * node,VReg obj,const Operand & prop)1561 void PandaGen::StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
1562 {
1563 if (std::holds_alternative<util::StringView>(prop)) {
1564 StSuperByName(node, obj, std::get<util::StringView>(prop));
1565 return;
1566 }
1567
1568 ASSERT(std::holds_alternative<VReg>(prop));
1569 StSuperByValue(node, obj, std::get<VReg>(prop));
1570 }
1571
LoadSuperProperty(const ir::AstNode * node,const Operand & prop)1572 void PandaGen::LoadSuperProperty(const ir::AstNode *node, const Operand &prop)
1573 {
1574 if (std::holds_alternative<util::StringView>(prop)) {
1575 LdSuperByName(node, std::get<util::StringView>(prop));
1576 return;
1577 }
1578
1579 ASSERT(std::holds_alternative<VReg>(prop));
1580 LdSuperByValue(node, std::get<VReg>(prop));
1581 }
1582
LoadLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1583 void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1584 {
1585 Sa().Emit<EcmaLdlexvardyn>(node, level, slot);
1586 }
1587
LoadLexical(const ir::AstNode * node,const util::StringView & name,uint32_t level,uint32_t slot)1588 void PandaGen::LoadLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot)
1589 {
1590 Sa().Emit<EcmaLdlexdyn>(node, name, level, slot);
1591 }
1592
StoreLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1593 void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1594 {
1595 Ra().Emit<EcmaStlexvardyn>(node, level, slot);
1596 }
1597
StoreLexical(const ir::AstNode * node,const util::StringView & name,uint32_t level,uint32_t slot)1598 void PandaGen::StoreLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot)
1599 {
1600 Ra().Emit<EcmaStlexdyn>(node, name, level, slot);
1601 }
1602
ThrowIfSuperNotCorrectCall(const ir::AstNode * node,int64_t num)1603 void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num)
1604 {
1605 Sa().Emit<EcmaThrowifsupernotcorrectcall>(node, num);
1606 }
1607
ThrowTdz(const ir::AstNode * node,const util::StringView & name)1608 void PandaGen::ThrowTdz(const ir::AstNode *node, const util::StringView &name)
1609 {
1610 Sa().Emit<EcmaThrowtdz>(node, name);
1611 }
1612
ThrowConstAssignment(const ir::AstNode * node,const util::StringView & name)1613 void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name)
1614 {
1615 Ra().Emit<EcmaThrowconstassignment>(node, name);
1616 }
1617
PopLexEnv(const ir::AstNode * node)1618 void PandaGen::PopLexEnv(const ir::AstNode *node)
1619 {
1620 Sa().Emit<EcmaPoplexenvdyn>(node);
1621 }
1622
CopyLexEnv(const ir::AstNode * node)1623 void PandaGen::CopyLexEnv(const ir::AstNode *node)
1624 {
1625 Sa().Emit<EcmaCopylexenvdyn>(node);
1626 }
1627
NewLexEnv(const ir::AstNode * node,uint32_t num)1628 void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num)
1629 {
1630 Sa().Emit<EcmaNewlexenvdyn>(node, num);
1631 }
1632
LdLexEnv(const ir::AstNode * node)1633 void PandaGen::LdLexEnv(const ir::AstNode *node)
1634 {
1635 Sa().Emit<EcmaLdlexenvdyn>(node);
1636 }
1637
ToNamedPropertyKey(const ir::Expression * prop,bool isComputed)1638 Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed)
1639 {
1640 VReg res {VReg::REG_START};
1641
1642 if (!isComputed) {
1643 if (prop->IsIdentifier()) {
1644 return prop->AsIdentifier()->Name();
1645 }
1646 return res;
1647 }
1648
1649 if (prop->IsStringLiteral()) {
1650 const util::StringView &str = prop->AsStringLiteral()->Str();
1651
1652 /* NOTE: dbatyai. remove this when runtime handles __proto__ as property name correctly */
1653 if (str.Is("__proto__")) {
1654 return res;
1655 }
1656
1657 int64_t index = util::Helpers::GetIndex(str);
1658 if (index != util::Helpers::INVALID_INDEX) {
1659 return index;
1660 }
1661
1662 return str;
1663 }
1664
1665 if (prop->IsNumberLiteral()) {
1666 auto num = prop->AsNumberLiteral()->Number().GetDouble();
1667 if (util::Helpers::IsIndex(num)) {
1668 return static_cast<int64_t>(num);
1669 }
1670
1671 return prop->AsNumberLiteral()->Str();
1672 }
1673
1674 return res;
1675 }
1676
ToPropertyKey(const ir::Expression * prop,bool isComputed,bool isSuperExpression)1677 Operand PandaGen::ToPropertyKey(const ir::Expression *prop, bool isComputed, bool isSuperExpression)
1678 {
1679 Operand op = ToNamedPropertyKey(prop, isComputed);
1680 if (std::holds_alternative<util::StringView>(op)) {
1681 return op;
1682 }
1683
1684 if (std::holds_alternative<int64_t>(op) && !isSuperExpression) {
1685 return op;
1686 }
1687
1688 VReg objReg = AllocReg();
1689 StoreAccumulator(prop, objReg);
1690 prop->Compile(this);
1691
1692 return objReg;
1693 }
1694
ToOwnPropertyKey(const ir::Expression * prop,bool isComputed)1695 Operand PandaGen::ToOwnPropertyKey(const ir::Expression *prop, bool isComputed)
1696 {
1697 Operand op = ToNamedPropertyKey(prop, isComputed);
1698 if (std::holds_alternative<util::StringView>(op)) {
1699 ASSERT(std::holds_alternative<util::StringView>(op) || std::holds_alternative<int64_t>(op));
1700 return op;
1701 }
1702
1703 if (std::holds_alternative<int64_t>(op)) {
1704 return op;
1705 }
1706
1707 VReg propReg = AllocReg();
1708 prop->Compile(this);
1709 StoreAccumulator(prop, propReg);
1710
1711 return propReg;
1712 }
1713
LoadPropertyKeyAcc(const ir::Expression * prop,bool isComputed)1714 void PandaGen::LoadPropertyKeyAcc(const ir::Expression *prop, bool isComputed)
1715 {
1716 Operand op = ToNamedPropertyKey(prop, isComputed);
1717 if (std::holds_alternative<util::StringView>(op)) {
1718 LoadAccumulatorString(prop, std::get<util::StringView>(op));
1719 } else if (std::holds_alternative<int64_t>(op)) {
1720 LoadAccumulatorInt(prop, static_cast<size_t>(std::get<int64_t>(op)));
1721 } else {
1722 prop->Compile(this);
1723 }
1724 }
1725
LoadPropertyKey(const ir::Expression * prop,bool isComputed)1726 VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed)
1727 {
1728 LoadPropertyKeyAcc(prop, isComputed);
1729
1730 VReg propReg = AllocReg();
1731 StoreAccumulator(prop, propReg);
1732
1733 return propReg;
1734 }
1735
LoadEvalVariable(const ir::AstNode * node,const util::StringView & name)1736 void PandaGen::LoadEvalVariable(const ir::AstNode *node, const util::StringView &name)
1737 {
1738 RegScope rs(this);
1739 LoadLexicalContext(node);
1740 Ra().Emit<EcmaLdevalvar>(node, name);
1741 }
1742
StoreEvalVariable(const ir::AstNode * node,const util::StringView & name)1743 void PandaGen::StoreEvalVariable(const ir::AstNode *node, const util::StringView &name)
1744 {
1745 RegScope rs(this);
1746 VReg value = AllocReg();
1747 StoreAccumulator(node, value);
1748 LoadLexicalContext(node);
1749 Ra().Emit<EcmaStevalvar>(node, name, value);
1750 }
1751
DirectEval(const ir::AstNode * node,uint32_t parserStatus)1752 void PandaGen::DirectEval(const ir::AstNode *node, uint32_t parserStatus)
1753 {
1754 RegScope rs(this);
1755
1756 uint32_t index = 0;
1757 uint32_t evalBindingsIndex = 0;
1758 VReg arg0 = AllocReg();
1759 StoreAccumulator(node, arg0);
1760 VReg bindings = AllocReg();
1761 CreateEmptyArray(node);
1762 StoreAccumulator(node, bindings);
1763
1764 GetFunctionObject(node);
1765 StOwnByIndex(node, bindings, index++);
1766 GetNewTarget(node);
1767 StOwnByIndex(node, bindings, index++);
1768 GetThis(node);
1769 StOwnByIndex(node, bindings, index++);
1770
1771 VReg evalBindings = AllocReg();
1772 CreateEmptyArray(node);
1773 StoreAccumulator(node, evalBindings);
1774
1775 LoadAccumulator(node, LexEnv());
1776 StOwnByIndex(node, evalBindings, evalBindingsIndex++);
1777
1778 const auto *iter = Scope()->EnclosingVariableScope();
1779
1780 while (true) {
1781 uint32_t scopeBindingsBuf = iter->EvalBindings();
1782 if (scopeBindingsBuf != INVALID_LITERAL_BUFFER_ID) {
1783 Sa().Emit<EcmaLdevalbindings>(node, util::Helpers::ToStringView(Allocator(), scopeBindingsBuf));
1784 StOwnByIndex(node, evalBindings, evalBindingsIndex++);
1785 }
1786
1787 if (iter->Parent() == nullptr) {
1788 break;
1789 }
1790
1791 iter = iter->Parent()->EnclosingVariableScope();
1792 }
1793
1794 LoadAccumulator(node, evalBindings);
1795 StOwnByIndex(node, bindings, index++);
1796
1797 Sa().Emit<EcmaDirecteval>(node, static_cast<int64_t>(parserStatus), arg0, bindings);
1798 }
1799
LoadLexicalContext(const ir::AstNode * node)1800 void PandaGen::LoadLexicalContext(const ir::AstNode *node)
1801 {
1802 auto result = Scope()->Find(varbinder::VarBinder::LEXICAL_CONTEXT_PARAM);
1803 LoadLexicalVar(node, result.lexLevel, result.variable->AsLocalVariable()->LexIdx());
1804 }
1805
IsDirectEval() const1806 bool PandaGen::IsDirectEval() const
1807 {
1808 return Context()->IsDirectEval();
1809 }
1810
IsEval() const1811 bool PandaGen::IsEval() const
1812 {
1813 return Context()->IsEval();
1814 }
1815
GetVRegType(VReg vreg) const1816 const checker::Type *PandaGen::GetVRegType(VReg vreg) const
1817 {
1818 // We assume that all used regs have any type
1819 if (vreg.GetIndex() > NextReg().GetIndex()) {
1820 return Context()->Checker()->GetGlobalTypesHolder()->GlobalAnyType();
1821 }
1822
1823 return nullptr;
1824 }
1825
1826 } // namespace panda::es2panda::compiler
1827