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/core/codeGen.h"
20#include "compiler/base/optionalChain.h"
21#include "compiler/core/envScope.h"
22#include "compiler/core/function.h"
23
24#include "compiler/core/regAllocator.h"
25#include "compiler/core/regScope.h"
26#include "ir/irnode.h"
27#include "lexer/token/tokenType.h"
28#include "macros.h"
29
30#include <unordered_map>
31
32namespace ark::es2panda::varbinder {
33class FunctionScope;
34class Scope;
35}  // namespace ark::es2panda::varbinder
36
37namespace ark::es2panda::ir {
38class AstNode;
39class ScriptFunction;
40class Statement;
41class Expression;
42class Identifier;
43}  // namespace ark::es2panda::ir
44
45namespace ark::es2panda::compiler {
46class FunctionBuilder;
47class DynamicContext;
48
49class PandaGen final : public CodeGen {
50public:
51    explicit PandaGen(ArenaAllocator *allocator, RegSpiller *spiller, public_lib::Context *context,
52                      std::tuple<varbinder::FunctionScope *, ProgramElement *, AstCompiler *> toCompile);
53
54    ~PandaGen() override = default;
55    NO_COPY_SEMANTIC(PandaGen);
56    NO_MOVE_SEMANTIC(PandaGen);
57
58    [[nodiscard]] FunctionBuilder *FuncBuilder() const noexcept;
59    [[nodiscard]] EnvScope *GetEnvScope() const noexcept;
60
61    void OptionalChainCheck(bool optional, VReg obj) const;
62
63    [[nodiscard]] VReg LexEnv() const noexcept;
64
65    bool FunctionHasFinalizer() const;
66    void FunctionInit(CatchTable *catchTable);
67    void FunctionEnter();
68    void FunctionExit();
69
70    void StoreAccumulator(const ir::AstNode *node, VReg vreg);
71    void LoadAccumulator(const ir::AstNode *node, VReg reg);
72
73    [[nodiscard]] IRNode *AllocMov(const ir::AstNode *node, VReg vd, VReg vs) override;
74    [[nodiscard]] IRNode *AllocMov(const ir::AstNode *node, OutVReg vd, VReg vs) override;
75    void MoveVreg(const ir::AstNode *node, VReg vd, VReg vs);
76
77    void LoadAccumulatorDouble(const ir::AstNode *node, double num);
78    void LoadAccumulatorInt(const ir::AstNode *node, size_t num);
79
80    void LoadConst(const ir::AstNode *node, Constant id);
81    void StoreConst(const ir::AstNode *node, VReg reg, Constant id);
82
83    void GetFunctionObject(const ir::AstNode *node);
84    void GetNewTarget(const ir::AstNode *node);
85    void GetThis(const ir::AstNode *node);
86    void SetThis(const ir::AstNode *node);
87    void LoadVar(const ir::Identifier *node, const varbinder::ConstScopeFindResult &result);
88    void StoreVar(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, bool isDeclaration);
89
90    void LoadAccFromArgs(const ir::AstNode *node);
91    void LoadObjProperty(const ir::AstNode *node, const Operand &prop);
92
93    void LoadObjByName(const ir::AstNode *node, const util::StringView &prop);
94
95    void StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
96    void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
97    void DeleteObjProperty(const ir::AstNode *node, VReg obj, VReg prop);
98    void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name);
99    void StoreGlobalVar(const ir::AstNode *node, const util::StringView &name);
100    void StoreGlobalLet(const ir::AstNode *node, const util::StringView &name);
101
102    void TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name);
103    void TryStoreGlobalByName(const ir::AstNode *node, const util::StringView &name);
104
105    void LoadAccFromLexEnv(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result);
106    void StoreAccToLexEnv(const ir::AstNode *node, const varbinder::ConstScopeFindResult &result, bool isDeclaration);
107
108    void LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &bigInt);
109
110    void Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, class Label *ifFalse);
111    void Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand);
112    void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs);
113
114    void BranchIfUndefined(const ir::AstNode *node, class Label *target);
115    void BranchIfNotUndefined(const ir::AstNode *node, class Label *target);
116    void BranchIfHole(const ir::AstNode *node, class Label *target);
117
118    void BranchIfTrue(const ir::AstNode *node, class Label *target);
119    void BranchIfNotTrue(const ir::AstNode *node, class Label *target);
120    void BranchIfFalse(const ir::AstNode *node, class Label *target);
121    void BranchIfCoercible(const ir::AstNode *node, class Label *target);
122
123    void EmitThrow(const ir::AstNode *node);
124    void EmitRethrow(const ir::AstNode *node);
125    void EmitReturn(const ir::AstNode *node);
126    void EmitReturnUndefined(const ir::AstNode *node);
127    void ValidateClassDirectReturn(const ir::AstNode *node);
128    void DirectReturn(const ir::AstNode *node);
129    void ImplicitReturn(const ir::AstNode *node);
130    void EmitAwait(const ir::AstNode *node);
131
132    static constexpr auto MAX_RANGE_CALL_ARG = 128;
133    void CallTagged(const ir::AstNode *node, VReg callee, VReg thisReg, const ArenaVector<ir::Expression *> &arguments);
134    void Call(const ir::AstNode *node, VReg callee, VReg thisReg, const ArenaVector<ir::Expression *> &arguments);
135    void Call0This(const ir::AstNode *node, VReg callee, VReg thisReg);
136    void Call1This(const ir::AstNode *node, VReg callee, VReg thisReg, VReg arg0);
137
138    void CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args);
139    void SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount);
140    void SuperCallSpread(const ir::AstNode *node, VReg vs);
141
142    void LoadHomeObject(const ir::AstNode *node);
143    void NewObject(const ir::AstNode *node, VReg startReg, size_t argCount);
144    void DefineMethod(const ir::AstNode *node, const util::StringView &name);
145    void DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name);
146
147    void TypeOf(const ir::AstNode *node);
148    void NewObjSpread(const ir::AstNode *node, VReg obj, VReg target);
149    void GetUnmappedArgs(const ir::AstNode *node);
150
151    void Negate(const ir::AstNode *node);
152    void ToBoolean(const ir::AstNode *node);
153    void ToNumber(const ir::AstNode *node, VReg arg);
154
155    void CreateGeneratorObj(const ir::AstNode *node, VReg funcObj);
156    void ResumeGenerator(const ir::AstNode *node, VReg genObj);
157    void GetResumeMode(const ir::AstNode *node, VReg genObj);
158
159    void AsyncFunctionEnter(const ir::AstNode *node);
160    void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj);
161    void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj);
162    void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj);
163
164    void GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name);
165    void GeneratorYield(const ir::AstNode *node, VReg genObj);
166    void GeneratorComplete(const ir::AstNode *node, VReg genObj);
167    void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj);
168    void CreateIterResultObject(const ir::AstNode *node, bool done);
169    void SuspendGenerator(const ir::AstNode *node, VReg genObj);
170    void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj);
171
172    void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj);
173    void AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj);
174
175    void GetTemplateObject(const ir::AstNode *node, VReg value);
176    void CopyRestArgs(const ir::AstNode *node, uint32_t index);
177
178    void GetPropIterator(const ir::AstNode *node);
179    void GetNextPropName(const ir::AstNode *node, VReg iter);
180    void CreateEmptyObject(const ir::AstNode *node);
181    void CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx);
182    void CreateObjectHavingMethod(const ir::AstNode *node, uint32_t idx);
183    void SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj);
184    void CopyDataProperties(const ir::AstNode *node, VReg dst, VReg src);
185    void DefineGetterSetterByValue(const ir::AstNode *node, std::tuple<VReg, VReg, VReg, VReg> registers, bool setName);
186    void CreateEmptyArray(const ir::AstNode *node);
187    size_t HandleArrayLiterals(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements);
188    void HandleArraySpread(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj);
189    void CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj);
190    void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx);
191    void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index);
192
193    void CreateRegExpWithLiteral(const ir::AstNode *node, const util::StringView &pattern, uint8_t flags);
194
195    void ThrowIfNotObject(const ir::AstNode *node);
196    void ThrowThrowNotExist(const ir::AstNode *node);
197    void GetIterator(const ir::AstNode *node);
198    void GetAsyncIterator(const ir::AstNode *node);
199
200    void CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount);
201    void ThrowObjectNonCoercible(const ir::AstNode *node);
202    void CloseIterator(const ir::AstNode *node, VReg iter);
203    void SetClassComputedFields(const ir::AstNode *node, VReg classReg, VReg computedInstanceFieldArray);
204    void DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, uint32_t litIdx, VReg lexenv,
205                               VReg base);
206    void LoadClassComputedInstanceFields(const ir::AstNode *node, VReg ctor);
207    void DefineClassPrivateFields(const ir::AstNode *node, uint32_t privateBufIdx);
208    void ClassFieldAdd(const ir::AstNode *node, VReg obj, VReg prop);
209    void ClassPrivateFieldAdd(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop);
210    void ClassPrivateMethodOrAccessorAdd(const ir::AstNode *node, VReg ctor, VReg obj);
211    void ClassPrivateFieldGet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop);
212    void ClassPrivateFieldSet(const ir::AstNode *node, VReg ctor, VReg obj, const util::StringView &prop);
213    void ClassPrivateFieldIn(const ir::AstNode *node, VReg ctor, const util::StringView &prop);
214
215    void ImportModule(const ir::AstNode *node, const util::StringView &name);
216    void LoadModuleVariable(const ir::AstNode *node, VReg module, const util::StringView &name);
217    void StoreModuleVar(const ir::AstNode *node, const util::StringView &name);
218    void CopyModule(const ir::AstNode *node, VReg module);
219
220    void StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key);
221    void LdSuperByName(const ir::AstNode *node, const util::StringView &key);
222    void StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop);
223    void LdSuperByValue(const ir::AstNode *node, VReg obj);
224    void StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop);
225    void LoadSuperProperty(const ir::AstNode *node, const Operand &prop);
226
227    void LdLexEnv(const ir::AstNode *node);
228    void PopLexEnv(const ir::AstNode *node);
229    void CopyLexEnv(const ir::AstNode *node);
230    void NewLexEnv(const ir::AstNode *node, uint32_t num);
231    void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
232    void LoadLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot);
233    void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot);
234    void StoreLexical(const ir::AstNode *node, const util::StringView &name, uint32_t level, uint32_t slot);
235
236    void ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num);
237    void ThrowTdz(const ir::AstNode *node, const util::StringView &name);
238    void ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name);
239
240    void LoadObjByIndex(const ir::AstNode *node, int64_t index);
241    void LoadObjByValue(const ir::AstNode *node, VReg obj);
242
243    void StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop);
244    void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index);
245    void StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop);
246
247    void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop);
248    void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop);
249    void StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index);
250
251    static Operand ToNamedPropertyKey(const ir::Expression *prop, bool isComputed);
252    void LoadPropertyKeyAcc(const ir::Expression *prop, bool isComputed);
253    Operand ToPropertyKey(const ir::Expression *prop, bool isComputed, bool isSuperExpression = false);
254    Operand ToOwnPropertyKey(const ir::Expression *prop, bool isComputed);
255    VReg LoadPropertyKey(const ir::Expression *prop, bool isComputed);
256
257    void LoadEvalVariable(const ir::AstNode *node, const util::StringView &name);
258    void StoreEvalVariable(const ir::AstNode *node, const util::StringView &name);
259    void DirectEval(const ir::AstNode *node, uint32_t parserStatus);
260    void LoadLexicalContext(const ir::AstNode *node);
261    bool IsDirectEval() const;
262    bool IsEval() const;
263
264    const checker::Type *GetVRegType(VReg vreg) const override;
265
266private:
267    void LoadEvalBindings(const ir::AstNode *node);
268    void Call0Args(const ir::AstNode *n, VReg c, VReg thisR, bool hasThis);
269    void Call1Arg(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args, bool hasThis);
270    void Call2Args(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args, bool hasThis);
271    void Call3Args(const ir::AstNode *n, VReg c, VReg thisR, const ArenaVector<ir::Expression *> &args, bool hasThis);
272    bool CallArgsTagged(const ir::AstNode *node, VReg callee, VReg thisReg,
273                        const ArenaVector<ir::Expression *> &arguments, bool hasThis);
274    FunctionBuilder *builder_ {};
275    EnvScope *envScope_ {};
276    OptionalChain *optionalChain_ {};
277
278    friend class EnvScope;
279    friend class LoopEnvScope;
280    friend class DynamicContext;
281    friend class OptionalChain;
282};
283}  // namespace ark::es2panda::compiler
284
285#endif
286