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_CODEGEN_H
17#define ES2PANDA_COMPILER_CORE_CODEGEN_H
18
19#include "compiler/base/literals.h"
20#include "compiler/core/ASTCompiler.h"
21#include "compiler/core/regAllocator.h"
22#include "compiler/core/regScope.h"
23namespace ark::es2panda::compiler {
24class CatchTable;
25class DynamicContext;
26
27enum class Constant {
28    JS_NAN,
29    JS_HOLE,
30    JS_INFINITY,
31    JS_UNDEFINED,
32    JS_NULL,
33    JS_TRUE,
34    JS_FALSE,
35    JS_SYMBOL,
36    JS_GLOBAL,
37};
38
39class DebugInfo {
40public:
41    explicit DebugInfo(ArenaAllocator *allocator) : variableDebugInfo_(allocator->Adapter()) {};
42    DEFAULT_COPY_SEMANTIC(DebugInfo);
43    DEFAULT_MOVE_SEMANTIC(DebugInfo);
44    ~DebugInfo() = default;
45
46    ArenaVector<const varbinder::Scope *> &VariableDebugInfo()
47    {
48        return variableDebugInfo_;
49    }
50
51    const ArenaVector<const varbinder::Scope *> &VariableDebugInfo() const
52    {
53        return variableDebugInfo_;
54    }
55
56    const ir::Statement *FirstStatement() const
57    {
58        return firstStmt_;
59    }
60
61private:
62    friend class CodeGen;
63
64    ArenaVector<const varbinder::Scope *> variableDebugInfo_;
65    const ir::Statement *firstStmt_ {};
66};
67
68class CodeGen {
69public:
70    using TypeMap = ArenaUnorderedMap<VReg, const checker::Type *>;
71
72    explicit CodeGen(ArenaAllocator *allocator, RegSpiller *spiller, public_lib::Context *context,
73                     std::tuple<varbinder::FunctionScope *, ProgramElement *, AstCompiler *> toCompile) noexcept
74        : astCompiler_(std::get<AstCompiler *>(toCompile)),
75          allocator_(allocator),
76          context_(context),
77          debugInfo_(allocator_),
78          topScope_(std::get<varbinder::FunctionScope *>(toCompile)),
79          scope_(topScope_),
80          rootNode_(scope_->Node()),
81          insns_(allocator_->Adapter()),
82          catchList_(allocator_->Adapter()),
83          typeMap_(allocator_->Adapter()),
84          programElement_(std::get<ProgramElement *>(toCompile)),
85          sa_(this),
86          ra_(this, spiller),
87          rra_(this, spiller)
88    {
89        astCompiler_->SetCodeGen(this);
90    }
91    virtual ~CodeGen() = default;
92    NO_COPY_SEMANTIC(CodeGen);
93    NO_MOVE_SEMANTIC(CodeGen);
94
95    [[nodiscard]] virtual IRNode *AllocMov(const ir::AstNode *node, VReg vd, VReg vs) = 0;
96    [[nodiscard]] virtual IRNode *AllocMov(const ir::AstNode *node, OutVReg vd, VReg vs) = 0;
97
98    [[nodiscard]] ArenaAllocator *Allocator() const noexcept;
99    [[nodiscard]] const ArenaVector<CatchTable *> &CatchList() const noexcept;
100    [[nodiscard]] const varbinder::FunctionScope *TopScope() const noexcept;
101    [[nodiscard]] const varbinder::Scope *Scope() const noexcept;
102    [[nodiscard]] const ir::AstNode *RootNode() const noexcept;
103
104    [[nodiscard]] ArenaVector<IRNode *> &Insns() noexcept;
105    [[nodiscard]] const ArenaVector<IRNode *> &Insns() const noexcept;
106
107    [[nodiscard]] VReg AllocReg();
108    [[nodiscard]] VReg AllocRegWithType(const checker::Type *type);
109    [[nodiscard]] VReg NextReg() const noexcept;
110
111    [[nodiscard]] std::uint32_t TotalRegsNum() const noexcept;
112    [[nodiscard]] std::size_t LabelCount() const noexcept;
113    [[nodiscard]] const DebugInfo &Debuginfo() const noexcept;
114    [[nodiscard]] constexpr std::uint32_t IcSize() const noexcept
115    {
116        return 0U;
117    }
118
119    [[nodiscard]] bool IsDebug() const noexcept;
120    [[nodiscard]] std::uint32_t ParamCount() const noexcept;
121    [[nodiscard]] std::uint32_t FormalParametersCount() const noexcept;
122    [[nodiscard]] std::uint32_t InternalParamCount() const noexcept;
123    [[nodiscard]] const util::StringView &InternalName() const noexcept;
124    [[nodiscard]] const util::StringView &FunctionName() const noexcept;
125    [[nodiscard]] varbinder::VarBinder *VarBinder() const noexcept;
126
127    [[nodiscard]] Label *AllocLabel();
128    [[nodiscard]] std::uint32_t AddLiteralBuffer(LiteralBuffer &&buf);
129
130    void LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str);
131
132    void SetLabel(const ir::AstNode *node, Label *label);
133    void Branch(const ir::AstNode *node, class Label *label);
134    [[nodiscard]] bool CheckControlFlowChange() const;
135    Label *ControlFlowChangeBreak(const ir::Identifier *label = nullptr);
136    [[nodiscard]] Label *ControlFlowChangeContinue(const ir::Identifier *label);
137
138    uint32_t TryDepth() const;
139    [[nodiscard]] CatchTable *CreateCatchTable(util::StringView exceptionType = "");
140    [[nodiscard]] CatchTable *CreateCatchTable(LabelPair tryLabelPair, util::StringView exceptionType = "");
141    void SortCatchTables();
142
143    void SetFirstStmt(const ir::Statement *stmt) noexcept;
144
145    [[noreturn]] static void Unimplemented();
146
147    void SetVRegType(VReg vreg, const checker::Type *type);
148
149    [[nodiscard]] virtual const checker::Type *GetVRegType(VReg vreg) const;
150
151    [[nodiscard]] public_lib::Context *Context() const noexcept;
152
153    [[nodiscard]] virtual checker::Type const *TypeForVar(varbinder::Variable const *var) const noexcept;
154
155    compiler::AstCompiler *GetAstCompiler() const;
156
157protected:
158    [[nodiscard]] SimpleAllocator &Sa() noexcept;
159    [[nodiscard]] const SimpleAllocator &Sa() const noexcept;
160    [[nodiscard]] RegAllocator &Ra() noexcept;
161    [[nodiscard]] const RegAllocator &Ra() const noexcept;
162    [[nodiscard]] RangeRegAllocator &Rra() noexcept;
163    [[nodiscard]] const RangeRegAllocator &Rra() const noexcept;
164    [[nodiscard]] ProgramElement *ProgElement() const noexcept;
165    [[nodiscard]] TypeMap &GetTypeMap() noexcept;
166    [[nodiscard]] const TypeMap &GetTypeMap() const noexcept;
167
168private:
169    AstCompiler *astCompiler_;
170    ArenaAllocator *allocator_ {};
171    public_lib::Context *context_ {};
172    DebugInfo debugInfo_;
173    varbinder::FunctionScope *topScope_ {};
174    varbinder::Scope *scope_ {};
175    const ir::AstNode *rootNode_ {};
176    ArenaVector<IRNode *> insns_;
177    ArenaVector<CatchTable *> catchList_;
178    TypeMap typeMap_;
179    ProgramElement *programElement_ {};
180    DynamicContext *dynamicContext_ {};
181
182    SimpleAllocator sa_;
183    RegAllocator ra_;
184    RangeRegAllocator rra_;
185    std::size_t labelId_ {0};
186    std::uint32_t literalBufferIdx_ {0};
187
188    std::uint32_t usedRegs_ {VReg::REG_START};
189    std::uint32_t totalRegs_ {VReg::REG_START};
190    friend class ScopeContext;
191    friend class RegScope;
192    friend class LocalRegScope;
193    friend class LoopRegScope;
194    friend class ParamRegScope;
195    friend class FunctionRegScope;
196    friend class DynamicContext;
197};
198}  // namespace ark::es2panda::compiler
199
200#endif
201