• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 MAPLE_IR_INCLUDE_OPCODE_INFO_H
17 #define MAPLE_IR_INCLUDE_OPCODE_INFO_H
18 #include "types_def.h"
19 #include "opcodes.h"
20 #include "mpl_logging.h"
21 
22 namespace maple {
23 enum OpcodeProp {
24     kOpcodePropNone,
25     kOpcodePropIsStmt,          // The instruction is a stmt, so has 2 stmt pointers
26     kOpcodePropIsVarSize,       // The instruction size is not fixed
27     kOpcodePropNotMMPL,         // The instruction is not allowed in Machine Maple IR
28     kOpcodePropIsCompare,       // The instruction is one of the 6 comparison ops
29     kOpcodePropIsTypeCvt,       // The instruction is a type conversion op
30     kOpcodePropHasSSAUse,       // The instruction may incur a use in SSA form
31     kOpcodePropHasSSADef,       // The instruction may incur a def in SSA form
32     kOpcodePropIsCall,          // The instruction is among the call instructions
33     kOpcodePropIsCallAssigned,  // The instruction is among the call instructions with implicit assignments of the
34     // returned values
35     kOpcodePropNotPure,  // The operation does not return same result with idential operands
36     kOpcodePropMayThrowException,
37     kOpcodePropIsAssertNonnull,        // The operation check nonnnull
38     kOpcodePropIsAssertUpperBoundary,  // The operation check upper boundary
39     kOpcodePropIsAssertLowerBoundary,  // The operation check lower boundary
40 };
41 
42 constexpr unsigned long OPCODEISSTMT = 1ULL << kOpcodePropIsStmt;
43 constexpr unsigned long OPCODEISVARSIZE = 1ULL << kOpcodePropIsVarSize;
44 constexpr unsigned long OPCODENOTMMPL = 1ULL << kOpcodePropNotMMPL;
45 constexpr unsigned long OPCODEISCOMPARE = 1ULL << kOpcodePropIsCompare;
46 constexpr unsigned long OPCODEISTYPECVT = 1ULL << kOpcodePropIsTypeCvt;
47 constexpr unsigned long OPCODEHASSSAUSE = 1ULL << kOpcodePropHasSSAUse;
48 constexpr unsigned long OPCODEHASSSADEF = 1ULL << kOpcodePropHasSSADef;
49 constexpr unsigned long OPCODEISCALL = 1ULL << kOpcodePropIsCall;
50 constexpr unsigned long OPCODEISCALLASSIGNED = 1ULL << kOpcodePropIsCallAssigned;
51 constexpr unsigned long OPCODENOTPURE = 1ULL << kOpcodePropNotPure;
52 constexpr unsigned long OPCODEMAYTHROWEXCEPTION = 1ULL << kOpcodePropMayThrowException;
53 constexpr unsigned long OPCODEASSERTNONNULL = 1ULL << kOpcodePropIsAssertNonnull;
54 constexpr unsigned long OPCODEASSERTUPPERBOUNDARY = 1ULL << kOpcodePropIsAssertUpperBoundary;
55 constexpr unsigned long OPCODEASSERTLOWERBOUNDARY = 1ULL << kOpcodePropIsAssertLowerBoundary;
56 
57 struct OpcodeDesc {
58     uint8 instrucSize;  // size of instruction in bytes
59     uint16 flag;        // stores the opcode property flags
60     std::string name;
61 };
62 
63 class OpcodeTable {
64 public:
65     OpcodeTable();
66     ~OpcodeTable() = default;
67 
GetTableItemAt(Opcode o)68     OpcodeDesc GetTableItemAt(Opcode o) const
69     {
70         DEBUG_ASSERT(o < OP_last, "invalid opcode");
71         return table[o];
72     }
73 
IsStmt(Opcode o)74     bool IsStmt(Opcode o) const
75     {
76         DEBUG_ASSERT(o < OP_last, "invalid opcode");
77         return table[o].flag & OPCODEISSTMT;
78     }
79 
IsVarSize(Opcode o)80     bool IsVarSize(Opcode o) const
81     {
82         DEBUG_ASSERT(o < OP_last, "invalid opcode");
83         return table[o].flag & OPCODEISVARSIZE;
84     }
85 
NotMMPL(Opcode o)86     bool NotMMPL(Opcode o) const
87     {
88         DEBUG_ASSERT(o < OP_last, "invalid opcode");
89         return table[o].flag & OPCODENOTMMPL;
90     }
91 
IsCompare(Opcode o)92     bool IsCompare(Opcode o) const
93     {
94         DEBUG_ASSERT(o < OP_last, "invalid opcode");
95         return table[o].flag & OPCODEISCOMPARE;
96     }
97 
IsTypeCvt(Opcode o)98     bool IsTypeCvt(Opcode o) const
99     {
100         DEBUG_ASSERT(o < OP_last, "invalid opcode");
101         return table[o].flag & OPCODEISTYPECVT;
102     }
103 
HasSSAUse(Opcode o)104     bool HasSSAUse(Opcode o) const
105     {
106         DEBUG_ASSERT(o < OP_last, "invalid opcode");
107         return table[o].flag & OPCODEHASSSAUSE;
108     }
109 
HasSSADef(Opcode o)110     bool HasSSADef(Opcode o) const
111     {
112         DEBUG_ASSERT(o < OP_last, "invalid opcode");
113         return table[o].flag & OPCODEHASSSADEF;
114     }
115 
IsCall(Opcode o)116     bool IsCall(Opcode o) const
117     {
118         DEBUG_ASSERT(o < OP_last, "invalid opcode");
119         return table[o].flag & OPCODEISCALL;
120     }
121 
IsCallAssigned(Opcode o)122     bool IsCallAssigned(Opcode o) const
123     {
124         DEBUG_ASSERT(o < OP_last, "invalid opcode");
125         return table[o].flag & OPCODEISCALLASSIGNED;
126     }
127 
IsICall(Opcode o)128     bool IsICall(Opcode o) const
129     {
130         DEBUG_ASSERT(o < OP_last, "invalid opcode");
131         return o == OP_icall || o == OP_icallassigned || o == OP_icallproto || o == OP_icallprotoassigned ||
132                o == OP_virtualicall || o == OP_virtualicallassigned || o == OP_interfaceicall ||
133                o == OP_interfaceicallassigned;
134     }
135 
NotPure(Opcode o)136     bool NotPure(Opcode o) const
137     {
138         DEBUG_ASSERT(o < OP_last, "invalid opcode");
139         return table[o].flag & OPCODENOTPURE;
140     }
141 
MayThrowException(Opcode o)142     bool MayThrowException(Opcode o) const
143     {
144         DEBUG_ASSERT(o < OP_last, "invalid opcode");
145         return table[o].flag & OPCODEMAYTHROWEXCEPTION;
146     }
147 
HasSideEffect(Opcode o)148     bool HasSideEffect(Opcode o) const
149     {
150         DEBUG_ASSERT(o < OP_last, "invalid opcode");
151         return MayThrowException(o);
152     }
153 
GetName(Opcode o)154     const std::string &GetName(Opcode o) const
155     {
156         DEBUG_ASSERT(o < OP_last, "invalid opcode");
157         return table[o].name;
158     }
159 
IsCondBr(Opcode o)160     bool IsCondBr(Opcode o) const
161     {
162         DEBUG_ASSERT(o < OP_last, "invalid opcode");
163         return o == OP_brtrue || o == OP_brfalse;
164     }
165 
AssignActualVar(Opcode o)166     bool AssignActualVar(Opcode o) const
167     {
168         DEBUG_ASSERT(o < OP_last, "invalid opcode");
169         return o == OP_dassign || o == OP_regassign;
170     }
171 
IsAssertNonnull(Opcode o)172     bool IsAssertNonnull(Opcode o) const
173     {
174         DEBUG_ASSERT(o < OP_last, "invalid opcode");
175         return table[o].flag & OPCODEASSERTNONNULL;
176     }
177 
IsCallAssertNonnull(Opcode o)178     bool IsCallAssertNonnull(Opcode o) const
179     {
180         DEBUG_ASSERT(o < OP_last, "invalid opcode");
181         return o == OP_callassertnonnull;
182     }
183 
IsAssertBoundary(Opcode o)184     bool IsAssertBoundary(Opcode o) const
185     {
186         DEBUG_ASSERT(o < OP_last, "invalid opcode");
187         return table[o].flag & (OPCODEASSERTUPPERBOUNDARY | OPCODEASSERTLOWERBOUNDARY);
188     }
189 
IsAssertUpperBoundary(Opcode o)190     bool IsAssertUpperBoundary(Opcode o) const
191     {
192         DEBUG_ASSERT(o < OP_last, "invalid opcode");
193         return table[o].flag & OPCODEASSERTUPPERBOUNDARY;
194     }
195 
IsAssertLowerBoundary(Opcode o)196     bool IsAssertLowerBoundary(Opcode o) const
197     {
198         DEBUG_ASSERT(o < OP_last, "invalid opcode");
199         return table[o].flag & OPCODEASSERTLOWERBOUNDARY;
200     }
201 
IsCallAssertBoundary(Opcode o)202     bool IsCallAssertBoundary(Opcode o) const
203     {
204         DEBUG_ASSERT(o < OP_last, "invalid opcode");
205         return o == OP_callassertle;
206     }
207 
IsAssertLeBoundary(Opcode o)208     bool IsAssertLeBoundary(Opcode o) const
209     {
210         DEBUG_ASSERT(o < OP_last, "invalid opcode");
211         return (o == OP_callassertle || o == OP_returnassertle || o == OP_assignassertle);
212     }
213 
IsCalcAssertBoundary(Opcode o)214     bool IsCalcAssertBoundary(Opcode o) const
215     {
216         DEBUG_ASSERT(o < OP_last, "invalid opcode");
217         return (o == OP_calcassertlt || o == OP_calcassertge);
218     }
219 
220 private:
221     OpcodeDesc table[OP_last];
222 };
223 extern const OpcodeTable kOpcodeInfo;
224 }  // namespace maple
225 #endif  // MAPLE_IR_INCLUDE_OPCODE_INFO_H
226