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#ifndef ES2PANDA_COMPILER_CORE_PANDAGEN_H
17#define ES2PANDA_COMPILER_CORE_PANDAGEN_H
18
19#include <compiler/base/optionalChain.h>
20#include <compiler/core/envScope.h>
21#include <compiler/core/inlineCache.h>
22#include <compiler/core/regAllocator.h>
23#include <compiler/core/regScope.h>
24#include <ir/irnode.h>
25#include <lexer/token/tokenType.h>
26#include <libpandafile/file_items.h>
27#include <macros.h>
28#include <util/enumbitops.h>
29
30#include <regex>
31
32namespace panda::es2panda::binder {
33class FunctionScope;
34class ModuleVaribale;
35class ScopeFindResult;
36class Scope;
37}  // namespace panda::es2panda::binder
38
39namespace panda::es2panda::ir {
40class AstNode;
41class ScriptFunction;
42class Statement;
43class Expression;
44class Identifier;
45}  // namespace panda::es2panda::ir
46
47DEFINE_BITOPS(panda::panda_file::FunctionKind);
48
49namespace panda::es2panda::compiler {
50class FunctionBuilder;
51class CompilerContext;
52class LiteralBuffer;
53class DynamicContext;
54class CatchTable;
55
56enum class Constant {
57    JS_NAN,
58    JS_HOLE,
59    JS_INFINITY,
60    JS_UNDEFINED,
61    JS_NULL,
62    JS_TRUE,
63    JS_FALSE,
64    JS_SYMBOL,
65    JS_GLOBAL,
66};
67
68class DebugInfo {
69public:
70    explicit DebugInfo(ArenaAllocator *allocator) : variableDebugInfo(allocator->Adapter()) {};
71    DEFAULT_COPY_SEMANTIC(DebugInfo);
72    DEFAULT_MOVE_SEMANTIC(DebugInfo);
73    ~DebugInfo() = default;
74
75    ArenaVector<const binder::Scope *> variableDebugInfo;
76    const ir::Statement *firstStmt {};
77};
78
79class PandaGen {
80public:
81    explicit PandaGen(ArenaAllocator *allocator, CompilerContext *context, binder::FunctionScope *scope)
82        : allocator_(allocator),
83          context_(context),
84          builder_(nullptr),
85          debugInfo_(allocator_),
86          topScope_(scope),
87          scope_(topScope_),
88          rootNode_(scope->Node()),
89          insns_(allocator_->Adapter()),
90          catchList_(allocator_->Adapter()),
91          strings_(allocator_->Adapter()),
92          buffStorage_(allocator_->Adapter()),
93          ra_(this)
94    {
95    }
96    ~PandaGen() = default;
97    NO_COPY_SEMANTIC(PandaGen);
98    NO_MOVE_SEMANTIC(PandaGen);
99
100    inline ArenaAllocator *Allocator() const
101    {
102        return allocator_;
103    }
104
105    inline CompilerContext *Context() const
106    {
107        return context_;
108    }
109
110    const ArenaSet<util::StringView> &Strings() const
111    {
112        return strings_;
113    }
114
115    const ArenaVector<CatchTable *> &CatchList() const
116    {
117        return catchList_;
118    }
119
120    binder::FunctionScope *TopScope() const
121    {
122        return topScope_;
123    }
124
125    binder::Scope *Scope() const
126    {
127        return scope_;
128    }
129
130    const ir::AstNode *RootNode() const
131    {
132        return rootNode_;
133    }
134
135    ArenaList<IRNode *> &Insns()
136    {
137        return insns_;
138    }
139
140    const ArenaList<IRNode *> &Insns() const
141    {
142        return insns_;
143    }
144
145    void SetInsns(ArenaList<IRNode *> &newInsns)
146    {
147        insns_.assign(newInsns.begin(), newInsns.end());
148    }
149
150    VReg AllocReg()
151    {
152        if (usedRegs_ > UINT16_MAX) {
153            throw Error(ErrorType::GENERIC, "Can't alloc new reg because all regs ran out");
154        }
155        return usedRegs_++;
156    }
157
158    VReg NextReg() const
159    {
160        return usedRegs_;
161    }
162
163    uint32_t TotalRegsNum() const
164    {
165        return totalRegs_;
166    }
167
168    size_t LabelCount() const
169    {
170        return labelId_;
171    }
172
173    const DebugInfo &Debuginfo() const
174    {
175        return debugInfo_;
176    }
177
178    FunctionBuilder *FuncBuilder() const
179    {
180        return builder_;
181    }
182
183    EnvScope *GetEnvScope() const
184    {
185        return envScope_;
186    }
187
188    const ArenaVector<compiler::LiteralBuffer *> &BuffStorage() const
189    {
190        return buffStorage_;
191    }
192
193    OptionalChain *GetOptionalChain() const
194    {
195        return optionalChain_;
196    }
197
198    uint32_t IcSize() const
199    {
200        return ic_.Size();
201    }
202
203    void SetSourceLocationFlag(lexer::SourceLocationFlag flag)
204    {
205        ra_.SetSourceLocationFlag(flag);
206    }
207
208    void AdjustSpillInsns()
209    {
210        ra_.AdjustInsRegWhenHasSpill();
211        totalRegs_ += ra_.GetSpillRegsCount();
212    }
213
214    uint16_t GetSpillRegsCount() const
215    {
216        if (ra_.HasSpill()) {
217            return ra_.GetSpillRegsCount();
218        }
219        return 0;
220    }
221
222    panda::panda_file::FunctionKind GetFunctionKind() const
223    {
224        return funcKind_;
225    }
226
227    bool IsConcurrent() const
228    {
229        return funcKind_ == panda::panda_file::FunctionKind::CONCURRENT_FUNCTION;
230    }
231
232    bool IsSendable() const
233    {
234        return (funcKind_ & panda::panda_file::FunctionKind::SENDABLE_FUNCTION) != 0;
235    }
236
237    void SetFunctionKind();
238    void SetInSendable();
239
240    bool IsDebug() const;
241    bool isDebuggerEvaluateExpressionMode() const;
242    std::string SourceFile() const;
243    uint32_t ParamCount() const;
244    uint32_t FormalParametersCount() const;
245    uint32_t InternalParamCount() const;
246    const util::StringView &InternalName() const;
247    const util::StringView &FunctionName() const;
248    binder::Binder *Binder() const;
249
250    Label *AllocLabel();
251
252    bool FunctionHasFinalizer() const;
253    bool IsAsyncFunction() const;
254    void FunctionInit(CatchTable* catchTable);
255    void FunctionEnter();
256    void FunctionExit();
257
258    LiteralBuffer *NewLiteralBuffer();
259    int32_t AddLiteralBuffer(LiteralBuffer *buf);
260    int32_t AddLexicalVarNamesForDebugInfo(ArenaMap<uint32_t, std::pair<util::StringView, int>> &lexicalVars);
261
262    void InitializeLexEnv(const ir::AstNode *node);
263    void CopyFunctionArguments(const ir::AstNode *node);
264    void GetFunctionObject(const ir::AstNode *node);
265    void GetNewTarget(const ir::AstNode *node);
266    void GetThis(const ir::AstNode *node);
267    void SetThis(const ir::AstNode *node);
268    void LoadVar(const ir::Identifier *node, const binder::ScopeFindResult &result);
269    void StoreVar(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration);
270
271    void StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name);
272    void StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name);
273
274    void StoreAccumulator(const ir::AstNode *node, VReg vreg);
275    void LoadAccFromArgs(const ir::AstNode *node);
276    void LoadObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
277
278    void LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop);
279
280    void StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
281    void DefineOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
282    void DefineClassPrivateField(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj);
283    void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting = false);
284    void DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
285    void LoadAccumulator(const ir::AstNode *node, VReg reg);
286    void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name);
287    void StoreGlobalVar(const ir::AstNode *node, const util::StringView &name);
288
289    void LoadObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name, bool throwUndefinedIfHole);
290    void TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name);
291    void StoreObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name);
292    void TryStoreGlobalByName(const ir::AstNode *node, const util::StringView &name);
293
294    void LoadAccFromLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result);
295    void StoreAccToLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration);
296
297    void LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str);
298    void LoadAccumulatorFloat(const ir::AstNode *node, double num);
299    void LoadAccumulatorInt(const ir::AstNode *node, int32_t num);
300    void LoadAccumulatorInt(const ir::AstNode *node, size_t num);
301    void LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num);
302
303    void LoadConst(const ir::AstNode *node, Constant id);
304    void StoreConst(const ir::AstNode *node, VReg reg, Constant id);
305    void MoveVreg(const ir::AstNode *node, VReg vd, VReg vs);
306
307    void SetLabel(const ir::AstNode *node, Label *label);
308    void Branch(const ir::AstNode *node, class Label *label);
309    bool CheckControlFlowChange() const;
310    Label *ControlFlowChangeBreak(const ir::Identifier *label = nullptr);
311    Label *ControlFlowChangeContinue(const ir::Identifier *label);
312    void ControlFlowChangeReturn();
313
314    void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, class Label *ifFalse);
315    void Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand);
316    void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs);
317    void Equal(const ir::AstNode *node, VReg lhs);
318    void NotEqual(const ir::AstNode *node, VReg lhs);
319    void StrictEqual(const ir::AstNode *node, VReg lhs);
320    void StrictNotEqual(const ir::AstNode *node, VReg lhs);
321    void LessThan(const ir::AstNode *node, VReg lhs);
322    void LessEqual(const ir::AstNode *node, VReg lhs);
323    void GreaterThan(const ir::AstNode *node, VReg lhs);
324    void GreaterEqual(const ir::AstNode *node, VReg lhs);
325    void IsTrue(const ir::AstNode *node);
326
327    void BranchIfUndefined(const ir::AstNode *node, class Label *target);
328    void BranchIfStrictUndefined(const ir::AstNode *node, class Label *target);
329    void BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target);
330    void BranchIfNotUndefined(const ir::AstNode *node, class Label *target);
331    void BranchIfHole(const ir::AstNode *node, class Label *target);
332    void BranchIfTrue(const ir::AstNode *node, class Label *target);
333    void BranchIfNotTrue(const ir::AstNode *node, class Label *target);
334    void BranchIfFalse(const ir::AstNode *node, class Label *target);
335    void BranchIfNotFalse(const ir::AstNode *node, class Label *target);
336    void BranchIfStrictNull(const ir::AstNode *node, class Label *target);
337
338    void EmitThrow(const ir::AstNode *node);
339    void EmitRethrow(const ir::AstNode *node);
340    void EmitReturn(const ir::AstNode *node);
341    void EmitReturnUndefined(const ir::AstNode *node);
342    void ValidateClassDirectReturn(const ir::AstNode *node);
343    void DirectReturn(const ir::AstNode *node);
344    void ExplicitReturn(const ir::AstNode *node);
345    void ImplicitReturn(const ir::AstNode *node);
346    void EmitAwait(const ir::AstNode *node);
347
348    void CallThis(const ir::AstNode *node, VReg startReg, size_t argCount);
349    void Call(const ir::AstNode *node, VReg startReg, size_t argCount);
350    void CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args);
351    void SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount);
352    void SuperCallSpread(const ir::AstNode *node, VReg vs);
353    void SuperCallForwardAllArgs(const ir::AstNode *node, VReg funcObj);
354    void NotifyConcurrentResult(const ir::AstNode *node);
355    void CallInit(const ir::AstNode *node, VReg thisReg);
356
357    void NewObject(const ir::AstNode *node, VReg startReg, size_t argCount);
358    void DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name);
359
360    void TypeOf(const ir::AstNode *node);
361    void NewObjSpread(const ir::AstNode *node, VReg obj);
362    void GetUnmappedArgs(const ir::AstNode *node);
363
364    void Negate(const ir::AstNode *node);
365    void ToNumber(const ir::AstNode *node, VReg arg);
366    void ToNumeric(const ir::AstNode *node, VReg arg);
367
368    void CreateGeneratorObj(const ir::AstNode *node, VReg funcObj);
369    void ResumeGenerator(const ir::AstNode *node, VReg genObj);
370    void GetResumeMode(const ir::AstNode *node, VReg genObj);
371
372    void AsyncFunctionEnter(const ir::AstNode *node);
373    void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj);
374    void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj);
375    void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj);
376
377    void GeneratorYield(const ir::AstNode *node, VReg genObj);
378    void GeneratorComplete(const ir::AstNode *node, VReg genObj);
379    void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj);
380    void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done);
381    void SuspendGenerator(const ir::AstNode *node, VReg genObj);
382
383    void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj, VReg value, VReg canSuspend);
384    void AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj);
385
386    void GetTemplateObject(const ir::AstNode *node, VReg value);
387    void CopyRestArgs(const ir::AstNode *node, uint32_t index);
388
389    void GetPropIterator(const ir::AstNode *node);
390    void GetNextPropName(const ir::AstNode *node, VReg iter);
391    void CreateEmptyObject(const ir::AstNode *node);
392    void CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx);
393    void SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj);
394    void CopyDataProperties(const ir::AstNode *node, VReg dst);
395    void DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter,
396                                   bool setName);
397    void CreateEmptyArray(const ir::AstNode *node);
398    void CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj);
399    void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx);
400    void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index);
401
402    void ThrowIfNotObject(const ir::AstNode *node, VReg obj);
403    void ThrowThrowNotExist(const ir::AstNode *node);
404    void GetIterator(const ir::AstNode *node);
405    void GetAsyncIterator(const ir::AstNode *node);
406
407    void CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount);
408    void ThrowObjectNonCoercible(const ir::AstNode *node);
409    void CloseIterator(const ir::AstNode *node, VReg iter);
410    void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base);
411    void DefineSendableClass(const ir::AstNode *node, const util::StringView &ctorId,
412                             int32_t litIdx, VReg base);
413    void LoadSendableClass(const ir::AstNode *node, int32_t level);
414
415    void LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable);
416    void LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable);
417    void StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable);
418    void GetModuleNamespace(const ir::AstNode *node, uint32_t index);
419    void DynamicImportCall(const ir::AstNode *node);
420
421    void StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key);
422    void LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key);
423    void StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop);
424    void LdSuperByValue(const ir::AstNode *node, VReg obj);
425    void StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
426    void LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
427
428    void PopLexEnv(const ir::AstNode *node);
429    void GenDebugger(const ir::AstNode *node);
430    void NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::VariableScope *scope);
431    void NewLexEnv(const ir::AstNode *node, uint32_t num);
432    void NewSendableEnv(const ir::AstNode *node, uint32_t num);
433    void NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx);
434    void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
435    void LoadSendableVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
436    void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name);
437    void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
438    void StoreSendableVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
439    void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const binder::LocalVariable *local);
440    void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value);
441
442    void ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num);
443    void ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name);
444    void ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name);
445
446    uint32_t TryDepth() const;
447    CatchTable *CreateCatchTable();
448    void SortCatchTables();
449
450    void LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index);
451    void LoadObjByValue(const ir::AstNode *node, VReg obj);
452
453    void StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop);
454    void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index);
455    void StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop);
456
457    void DefineFieldByName(const ir::AstNode *node, VReg obj, const util::StringView &prop);
458    void DefineFieldByIndex(const ir::AstNode *node, VReg obj, int64_t index);
459    void DefineFieldByValue(const ir::AstNode *node, VReg obj, VReg prop);
460
461    void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting = false);
462    void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting = false);
463    void StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index);
464
465    Operand ToNamedPropertyKey(const ir::Expression *prop, bool isComputed);
466    Operand ToPropertyKey(const ir::Expression *prop, bool isComputed);
467    VReg LoadPropertyKey(const ir::Expression *prop, bool isComputed);
468    void ToComputedPropertyKey(const ir::AstNode *node);
469
470    void ReArrangeIc();
471
472    void CreatePrivateProperty(const ir::AstNode *node, uint32_t num, int32_t bufIdx);
473    void TestIn(const ir::AstNode *node, uint32_t level, uint32_t slot);
474    void LoadPrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot);
475    void StorePrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj);
476    void ThrowTypeErrorIfFalse(const ir::AstNode *node, util::StringView str);
477    void ThrowTypeError(const ir::AstNode *node, util::StringView str);
478
479    /*
480     * Since the [Function] is not implemented yet, We compile the test262's framework code
481     * which obtains the [global] Object as following into [LoadConst.Global] directly.
482     * ```
483     *    var __globalObject = Function("return this;")();
484     *    var __globalObject = new Function("return this;")();
485     * ```
486     */
487    bool TryCompileFunctionCallOrNewExpression(const ir::Expression *expr);
488
489    void SetFirstStmt(const ir::Statement *stmt)
490    {
491        debugInfo_.firstStmt = stmt;
492    }
493
494    [[noreturn]] static void Unimplemented()
495    {
496        throw Error(ErrorType::GENERIC, "Unimplemented code path");
497    }
498
499    IcSizeType GetCurrentSlot() const
500    {
501        return currentSlot_;
502    }
503
504    void IncreaseCurrentSlot(ICSlot inc)
505    {
506        currentSlot_ += inc;
507    }
508
509    void ResetCurrentSlot(IcSizeType slotSize)
510    {
511        currentSlot_ = slotSize;
512    }
513
514    void SetIcOverFlow()
515    {
516        icOverFlow_ = true;
517    }
518
519    bool IsIcOverFlow() const
520    {
521        return icOverFlow_;
522    }
523
524private:
525    ArenaAllocator *allocator_;
526    CompilerContext *context_;
527    FunctionBuilder *builder_;
528    DebugInfo debugInfo_;
529    binder::FunctionScope *topScope_;
530    binder::Scope *scope_;
531    const ir::AstNode *rootNode_;
532    ArenaList<IRNode *> insns_;
533    ArenaVector<CatchTable *> catchList_;
534    ArenaSet<util::StringView> strings_;
535    ArenaVector<LiteralBuffer *> buffStorage_;
536    EnvScope *envScope_ {};
537    DynamicContext *dynamicContext_ {};
538    OptionalChain *optionalChain_ {};
539    InlineCache ic_;
540    RegAllocator ra_;
541    IcSizeType currentSlot_ {0};
542
543    uint32_t usedRegs_ {0};
544    uint32_t totalRegs_ {0};
545    friend class ScopeContext;
546    friend class RegScope;
547    friend class LocalRegScope;
548    friend class LoopRegScope;
549    friend class ParamRegScope;
550    friend class FunctionRegScope;
551    friend class EnvScope;
552    friend class LoopEnvScope;
553    friend class DynamicContext;
554    friend class OptionalChain;
555    size_t labelId_ {0};
556    panda::panda_file::FunctionKind funcKind_ {panda::panda_file::FunctionKind::NONE};
557    bool icOverFlow_ {false};
558    bool inSendable_ {false};
559};
560}  // namespace panda::es2panda::compiler
561
562#endif
563