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