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