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_IR_IRNODE_H
17 #define ES2PANDA_COMPILER_IR_IRNODE_H
18 
19 #include "compiler/base/literals.h"
20 #include "compiler/core/vReg.h"
21 #include "compiler/core/programElement.h"
22 #include "lexer/token/sourceLocation.h"
23 #include "macros.h"
24 #include "util/ustring.h"
25 #include "utils/span.h"
26 
27 #include <cstdint>
28 #include <list>
29 #include <limits>
30 #include <sstream>
31 #include <utility>
32 #include <variant>
33 #include <vector>
34 
35 namespace ark::es2panda::ir {
36 class AstNode;
37 }  // namespace ark::es2panda::ir
38 
39 namespace ark::es2panda::compiler {
40 enum class OperandKind {
41     // the least significant bit indicates vreg
42     // the second bit indicates src or dst
43     SRC_VREG,
44     DST_VREG,
45     SRC_DST_VREG,
46     IMM,
47     ID,
48     STRING_ID,
49     LABEL
50 };
51 
52 enum class OperandType {
53     REF,  // ref
54     B32,  // u1 u2 i8 u8 i16 u16 i32 u32 b32 f32
55     B64,  // i64, f64, b64
56     ANY,  // any
57     NONE
58 };
59 
60 struct OutVReg {
61     const VReg *reg;
62     OperandType type;
63 };
64 
65 class FormatItem {
66 public:
FormatItem(OperandKind kind, uint32_t bitWidth)67     constexpr FormatItem(OperandKind kind, uint32_t bitWidth) : kind_(kind), bitWidth_(bitWidth) {}
68 
Kind() const69     OperandKind Kind() const
70     {
71         return kind_;
72     };
73 
IsVReg() const74     bool constexpr IsVReg() const
75     {
76         return kind_ == OperandKind::SRC_VREG || kind_ == OperandKind::DST_VREG || kind_ == OperandKind::SRC_DST_VREG;
77     }
78 
BitWidth() const79     uint32_t BitWidth() const
80     {
81         return bitWidth_;
82     };
83 
84 private:
85     OperandKind kind_;
86     uint32_t bitWidth_;
87 };
88 
89 class Format {
90 public:
Format(const FormatItem *item, size_t size)91     constexpr Format(const FormatItem *item, size_t size) : item_(item), size_(size) {}
92 
GetFormatItem() const93     ark::Span<const FormatItem> GetFormatItem() const
94     {
95         return ark::Span<const FormatItem>(item_, size_);
96     }
97 
98 private:
99     const FormatItem *item_;
100     size_t size_;
101 };
102 
103 using Formats = ark::Span<const Format>;
104 
105 class Label;
106 class IRNode;
107 
108 using Operand = std::variant<compiler::VReg, double, int64_t, util::StringView, Label *>;
109 
110 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
111 #define FIRST_NODE_OF_FUNCTION (reinterpret_cast<ir::AstNode *>(0x1))
112 
113 class IRNode {
114 public:
IRNode(const ir::AstNode *node)115     explicit IRNode(const ir::AstNode *node) : node_(node) {};
116     virtual ~IRNode() = default;
117 
118     NO_COPY_SEMANTIC(IRNode);
119     NO_MOVE_SEMANTIC(IRNode);
120 
Node() const121     const ir::AstNode *Node() const
122     {
123         return node_;
124     }
125 
MapRegister(uint32_t reg, uint32_t totalRegs)126     static uint16_t MapRegister(uint32_t reg, uint32_t totalRegs)
127     {
128         ASSERT(reg != VReg::Invalid().GetIndex());
129 
130         uint32_t regCount = VReg::REG_START - totalRegs;
131         uint16_t newReg = 0;
132 
133         if (reg >= VReg::PARAM_START) {
134             newReg = reg - VReg::PARAM_START + regCount;
135             // NOTE: dbatiz. Remove this else if, and fix the regIndexes
136         } else if (reg <= regCount + VReg::MANDATORY_PARAM_NUM) {
137             newReg = VReg::REG_START - totalRegs + VReg::MANDATORY_PARAM_NUM + reg;
138         } else {
139             uint32_t regOffset = reg - totalRegs;
140             newReg = std::abs(static_cast<int32_t>(regOffset - regCount));
141         }
142 
143         return newReg;
144     }
145 
146     static constexpr auto MAX_REG_OPERAND = 5;
147 
148     virtual Formats GetFormats() const = 0;
149     virtual size_t Registers([[maybe_unused]] std::array<VReg *, MAX_REG_OPERAND> *regs) = 0;
150     virtual size_t Registers([[maybe_unused]] std::array<const VReg *, MAX_REG_OPERAND> *regs) const = 0;
151     virtual size_t OutRegisters([[maybe_unused]] std::array<OutVReg, MAX_REG_OPERAND> *regs) const = 0;
152     virtual void Transform(ark::pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement,
153                            [[maybe_unused]] uint32_t totalRegs) const = 0;
154 
155 private:
156     const ir::AstNode *node_;
157 };
158 }  // namespace ark::es2panda::compiler
159 
160 #endif
161