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 MAPLEBE_INCLUDE_CG_CFI_H 17 #define MAPLEBE_INCLUDE_CG_CFI_H 18 19 #include "insn.h" 20 #include "mempool_allocator.h" 21 #include "mir_symbol.h" 22 #include "operand.h" 23 #include "common_utils.h" 24 25 /* 26 * Reference: 27 * GNU Binutils. AS documentation 28 * https://sourceware.org/binutils/docs-2.28/as/index.html 29 * 30 * CFI blog 31 * https://www.imperialviolet.org/2017/01/18/cfi.html 32 * 33 * System V Application Binary Interface 34 * AMD64 Architecture Processor Supplement. Draft Version 0.99.7 35 * https://www.uclibc.org/docs/psABI-x86_64.pdf $ 3.7 Figure 3.36 36 * (RBP->6, RSP->7) 37 * 38 * System V Application Binary Interface 39 * Inte386 Architecture Processor Supplement. Version 1.0 40 * https://www.uclibc.org/docs/psABI-i386.pdf $ 2.5 Table 2.14 41 * (EBP->5, ESP->4) 42 * 43 * DWARF for ARM Architecture (ARM IHI 0040B) 44 * infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf 45 * $ 3.1 Table 1 46 * (0-15 -> R0-R15) 47 */ 48 namespace cfi { 49 using namespace maple; 50 51 enum CfiOpcode : uint8 { 52 #define CFI_DEFINE(k, sub, n, o0, o1, o2) OP_CFI_##k##sub, 53 #define ARM_DIRECTIVES_DEFINE(k, sub, n, o0, o1, o2) OP_ARM_DIRECTIVES_##k##sub, 54 #include "cfi.def" 55 #undef CFI_DEFINE 56 #undef ARM_DIRECTIVES_DEFINE 57 kOpCfiLast 58 }; 59 60 class CfiInsn : public maplebe::Insn { 61 public: CfiInsn(MemPool & memPool,maplebe::MOperator op)62 CfiInsn(MemPool &memPool, maplebe::MOperator op) : Insn(memPool, op) {} 63 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0)64 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0) : Insn(memPool, op, opnd0) {} 65 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1)66 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1) 67 : Insn(memPool, op, opnd0, opnd1) 68 { 69 } 70 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1,maplebe::Operand & opnd2)71 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1, 72 maplebe::Operand &opnd2) 73 : Insn(memPool, op, opnd0, opnd1, opnd2) 74 { 75 } 76 77 ~CfiInsn() = default; 78 IsMachineInstruction()79 bool IsMachineInstruction() const override 80 { 81 return false; 82 } 83 84 void Dump() const override; 85 86 #if DEBUG 87 void Check() const override; 88 #endif 89 IsCfiInsn()90 bool IsCfiInsn() const override 91 { 92 return true; 93 } 94 IsTargetInsn()95 bool IsTargetInsn() const override 96 { 97 return false; 98 } 99 IsRegDefined(maplebe::regno_t regNO)100 bool IsRegDefined(maplebe::regno_t regNO) const override 101 { 102 CHECK_FATAL(false, "cfi do not def regs"); 103 return false; 104 } 105 GetDefRegs()106 std::set<uint32> GetDefRegs() const override 107 { 108 CHECK_FATAL(false, "cfi do not def regs"); 109 return std::set<uint32>(); 110 } 111 GetBothDefUseOpnd()112 uint32 GetBothDefUseOpnd() const override 113 { 114 return maplebe::kInsnMaxOpnd; 115 } 116 117 private: 118 CfiInsn &operator=(const CfiInsn &); 119 }; 120 121 class RegOperand : public maplebe::OperandVisitable<RegOperand> { 122 public: RegOperand(uint32 no,uint32 size)123 RegOperand(uint32 no, uint32 size) : OperandVisitable(kOpdRegister, size), regNO(no) {} 124 125 ~RegOperand() = default; 126 using OperandVisitable<RegOperand>::OperandVisitable; 127 GetRegisterNO()128 uint32 GetRegisterNO() const 129 { 130 return regNO; 131 } Clone(MemPool & memPool)132 Operand *Clone(MemPool &memPool) const override 133 { 134 Operand *opnd = memPool.Clone<RegOperand>(*this); 135 return opnd; 136 } 137 138 void Dump() const override; 139 Less(const Operand & right)140 bool Less(const Operand &right) const override 141 { 142 (void)right; 143 return false; 144 } 145 146 private: 147 uint32 regNO; 148 }; 149 150 class ImmOperand : public maplebe::OperandVisitable<ImmOperand> { 151 public: ImmOperand(int64 val,uint32 size)152 ImmOperand(int64 val, uint32 size) : OperandVisitable(kOpdImmediate, size), val(val) {} 153 154 ~ImmOperand() = default; 155 using OperandVisitable<ImmOperand>::OperandVisitable; 156 Clone(MemPool & memPool)157 Operand *Clone(MemPool &memPool) const override 158 { 159 Operand *opnd = memPool.Clone<ImmOperand>(*this); 160 return opnd; 161 } GetValue()162 int64 GetValue() const 163 { 164 return val; 165 } 166 167 void Dump() const override; 168 Less(const Operand & right)169 bool Less(const Operand &right) const override 170 { 171 (void)right; 172 return false; 173 } 174 175 private: 176 int64 val; 177 }; 178 179 class SymbolOperand : public maplebe::OperandVisitable<SymbolOperand> { 180 public: SymbolOperand(maple::MIRSymbol & mirSymbol,uint8 size)181 SymbolOperand(maple::MIRSymbol &mirSymbol, uint8 size) : OperandVisitable(kOpdStImmediate, size), symbol(&mirSymbol) 182 { 183 } 184 ~SymbolOperand() = default; 185 using OperandVisitable<SymbolOperand>::OperandVisitable; 186 Clone(MemPool & memPool)187 Operand *Clone(MemPool &memPool) const override 188 { 189 Operand *opnd = memPool.Clone<SymbolOperand>(*this); 190 return opnd; 191 } 192 Less(const Operand & right)193 bool Less(const Operand &right) const override 194 { 195 (void)right; 196 return false; 197 } 198 Dump()199 void Dump() const override 200 { 201 LogInfo::MapleLogger() << "symbol is : " << symbol->GetName(); 202 } 203 204 private: 205 maple::MIRSymbol *symbol; 206 }; 207 208 class StrOperand : public maplebe::OperandVisitable<StrOperand> { 209 public: StrOperand(const std::string & str,MemPool & memPool)210 StrOperand(const std::string &str, MemPool &memPool) : OperandVisitable(kOpdString, 0), str(str, &memPool) {} 211 212 ~StrOperand() = default; 213 using OperandVisitable<StrOperand>::OperandVisitable; 214 Clone(MemPool & memPool)215 Operand *Clone(MemPool &memPool) const override 216 { 217 Operand *opnd = memPool.Clone<StrOperand>(*this); 218 return opnd; 219 } 220 Less(const Operand & right)221 bool Less(const Operand &right) const override 222 { 223 (void)right; 224 return false; 225 } 226 GetStr()227 const MapleString &GetStr() const 228 { 229 return str; 230 } 231 232 void Dump() const override; 233 234 private: 235 const MapleString str; 236 }; 237 238 class LabelOperand : public maplebe::OperandVisitable<LabelOperand> { 239 public: LabelOperand(const std::string & parent,LabelIdx labIdx,MemPool & memPool)240 LabelOperand(const std::string &parent, LabelIdx labIdx, MemPool &memPool) 241 : OperandVisitable(kOpdBBAddress, 0), parentFunc(parent, &memPool), labelIndex(labIdx) 242 { 243 } 244 245 ~LabelOperand() = default; 246 using OperandVisitable<LabelOperand>::OperandVisitable; 247 Clone(MemPool & memPool)248 Operand *Clone(MemPool &memPool) const override 249 { 250 Operand *opnd = memPool.Clone<LabelOperand>(*this); 251 return opnd; 252 } 253 Less(const Operand & right)254 bool Less(const Operand &right) const override 255 { 256 (void)right; 257 return false; 258 } 259 260 void Dump() const override; 261 GetParentFunc()262 const MapleString &GetParentFunc() const 263 { 264 return parentFunc; 265 } GetIabelIdx()266 LabelIdx GetIabelIdx() const 267 { 268 return labelIndex; 269 }; 270 271 private: 272 const MapleString parentFunc; 273 LabelIdx labelIndex; 274 }; 275 276 class CFIOpndEmitVisitor 277 : public maplebe::OperandVisitorBase, 278 public maplebe::OperandVisitors<RegOperand, ImmOperand, SymbolOperand, StrOperand, LabelOperand> { 279 public: CFIOpndEmitVisitor(maplebe::Emitter & asmEmitter)280 explicit CFIOpndEmitVisitor(maplebe::Emitter &asmEmitter) : emitter(asmEmitter) {} 281 virtual ~CFIOpndEmitVisitor() = default; 282 283 protected: 284 maplebe::Emitter &emitter; 285 286 private: 287 void Visit(RegOperand *v) final; 288 void Visit(ImmOperand *v) final; 289 void Visit(SymbolOperand *v) final; 290 void Visit(StrOperand *v) final; 291 void Visit(LabelOperand *v) final; 292 }; 293 } /* namespace cfi */ 294 295 #endif /* MAPLEBE_INCLUDE_CG_CFI_H */ 296