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