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 kOpcodePropIsAssertUpperBoundary, // The operation check upper boundary 38 kOpcodePropIsAssertLowerBoundary, // The operation check lower boundary 39 }; 40 41 constexpr unsigned long OPCODEISSTMT = 1ULL << kOpcodePropIsStmt; 42 constexpr unsigned long OPCODEISVARSIZE = 1ULL << kOpcodePropIsVarSize; 43 constexpr unsigned long OPCODENOTMMPL = 1ULL << kOpcodePropNotMMPL; 44 constexpr unsigned long OPCODEISCOMPARE = 1ULL << kOpcodePropIsCompare; 45 constexpr unsigned long OPCODEISTYPECVT = 1ULL << kOpcodePropIsTypeCvt; 46 constexpr unsigned long OPCODEHASSSAUSE = 1ULL << kOpcodePropHasSSAUse; 47 constexpr unsigned long OPCODEHASSSADEF = 1ULL << kOpcodePropHasSSADef; 48 constexpr unsigned long OPCODEISCALL = 1ULL << kOpcodePropIsCall; 49 constexpr unsigned long OPCODEISCALLASSIGNED = 1ULL << kOpcodePropIsCallAssigned; 50 constexpr unsigned long OPCODENOTPURE = 1ULL << kOpcodePropNotPure; 51 constexpr unsigned long OPCODEMAYTHROWEXCEPTION = 1ULL << kOpcodePropMayThrowException; 52 constexpr unsigned long OPCODEASSERTUPPERBOUNDARY = 1ULL << kOpcodePropIsAssertUpperBoundary; 53 constexpr unsigned long OPCODEASSERTLOWERBOUNDARY = 1ULL << kOpcodePropIsAssertLowerBoundary; 54 55 struct OpcodeDesc { 56 uint8 instrucSize; // size of instruction in bytes 57 uint16 flag; // stores the opcode property flags 58 std::string name; 59 }; 60 61 class OpcodeTable { 62 public: 63 OpcodeTable(); 64 ~OpcodeTable() = default; 65 GetTableItemAt(Opcode o)66 OpcodeDesc GetTableItemAt(Opcode o) const 67 { 68 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 69 return table[o]; 70 } 71 IsStmt(Opcode o)72 bool IsStmt(Opcode o) const 73 { 74 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 75 return table[o].flag & OPCODEISSTMT; 76 } 77 IsVarSize(Opcode o)78 bool IsVarSize(Opcode o) const 79 { 80 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 81 return table[o].flag & OPCODEISVARSIZE; 82 } 83 NotMMPL(Opcode o)84 bool NotMMPL(Opcode o) const 85 { 86 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 87 return table[o].flag & OPCODENOTMMPL; 88 } 89 IsCompare(Opcode o)90 bool IsCompare(Opcode o) const 91 { 92 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 93 return table[o].flag & OPCODEISCOMPARE; 94 } 95 IsTypeCvt(Opcode o)96 bool IsTypeCvt(Opcode o) const 97 { 98 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 99 return table[o].flag & OPCODEISTYPECVT; 100 } 101 HasSSAUse(Opcode o)102 bool HasSSAUse(Opcode o) const 103 { 104 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 105 return table[o].flag & OPCODEHASSSAUSE; 106 } 107 HasSSADef(Opcode o)108 bool HasSSADef(Opcode o) const 109 { 110 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 111 return table[o].flag & OPCODEHASSSADEF; 112 } 113 IsCall(Opcode o)114 bool IsCall(Opcode o) const 115 { 116 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 117 return table[o].flag & OPCODEISCALL; 118 } 119 IsCallAssigned(Opcode o)120 bool IsCallAssigned(Opcode o) const 121 { 122 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 123 return table[o].flag & OPCODEISCALLASSIGNED; 124 } 125 IsICall(Opcode o)126 bool IsICall(Opcode o) const 127 { 128 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 129 return o == OP_icall || o == OP_icallassigned || o == OP_icallproto || o == OP_icallprotoassigned; 130 } 131 NotPure(Opcode o)132 bool NotPure(Opcode o) const 133 { 134 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 135 return table[o].flag & OPCODENOTPURE; 136 } 137 MayThrowException(Opcode o)138 bool MayThrowException(Opcode o) const 139 { 140 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 141 return table[o].flag & OPCODEMAYTHROWEXCEPTION; 142 } 143 HasSideEffect(Opcode o)144 bool HasSideEffect(Opcode o) const 145 { 146 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 147 return MayThrowException(o); 148 } 149 GetName(Opcode o)150 const std::string &GetName(Opcode o) const 151 { 152 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 153 return table[o].name; 154 } 155 IsCondBr(Opcode o)156 bool IsCondBr(Opcode o) const 157 { 158 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 159 return o == OP_brtrue || o == OP_brfalse; 160 } 161 AssignActualVar(Opcode o)162 bool AssignActualVar(Opcode o) const 163 { 164 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 165 return o == OP_dassign || o == OP_regassign; 166 } 167 IsAssertBoundary(Opcode o)168 bool IsAssertBoundary(Opcode o) const 169 { 170 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 171 return table[o].flag & (OPCODEASSERTUPPERBOUNDARY | OPCODEASSERTLOWERBOUNDARY); 172 } 173 IsAssertUpperBoundary(Opcode o)174 bool IsAssertUpperBoundary(Opcode o) const 175 { 176 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 177 return table[o].flag & OPCODEASSERTUPPERBOUNDARY; 178 } 179 IsAssertLowerBoundary(Opcode o)180 bool IsAssertLowerBoundary(Opcode o) const 181 { 182 DEBUG_ASSERT(o < OP_last, "invalid opcode"); 183 return table[o].flag & OPCODEASSERTLOWERBOUNDARY; 184 } 185 186 private: 187 OpcodeDesc table[OP_last]; 188 }; 189 extern const OpcodeTable kOpcodeInfo; 190 } // namespace maple 191 #endif // MAPLE_IR_INCLUDE_OPCODE_INFO_H 192