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(const CfiInsn & other)64 CfiInsn(const CfiInsn &other) : maplebe::Insn(other) {} 65 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0)66 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0) : Insn(memPool, op, opnd0) {} 67 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1)68 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1) 69 : Insn(memPool, op, opnd0, opnd1) 70 { 71 } 72 CfiInsn(MemPool & memPool,maplebe::MOperator op,maplebe::Operand & opnd0,maplebe::Operand & opnd1,maplebe::Operand & opnd2)73 CfiInsn(MemPool &memPool, maplebe::MOperator op, maplebe::Operand &opnd0, maplebe::Operand &opnd1, 74 maplebe::Operand &opnd2) 75 : Insn(memPool, op, opnd0, opnd1, opnd2) 76 { 77 } 78 79 ~CfiInsn() = default; 80 CloneTree(MapleAllocator & allocator)81 CfiInsn *CloneTree(MapleAllocator &allocator) const override 82 { 83 auto *insn = allocator.GetMemPool()->New<CfiInsn>(*this); 84 insn->DeepClone(*this, allocator); 85 return insn; 86 } 87 IsMachineInstruction()88 bool IsMachineInstruction() const override 89 { 90 return false; 91 } 92 93 void Dump() const override; 94 95 bool CheckMD() const override; 96 IsCfiInsn()97 bool IsCfiInsn() const override 98 { 99 return true; 100 } 101 IsTargetInsn()102 bool IsTargetInsn() const override 103 { 104 return false; 105 } 106 IsRegDefined(maplebe::regno_t regNO)107 bool IsRegDefined(maplebe::regno_t regNO) const override 108 { 109 CHECK_FATAL(false, "cfi do not def regs"); 110 return false; 111 } 112 GetDefRegs()113 std::set<uint32> GetDefRegs() const override 114 { 115 CHECK_FATAL(false, "cfi do not def regs"); 116 return std::set<uint32>(); 117 } 118 119 private: 120 CfiInsn &operator=(const CfiInsn &); 121 }; 122 123 class RegOperand : public maplebe::OperandVisitable<RegOperand> { 124 public: RegOperand(uint32 no,uint32 size)125 RegOperand(uint32 no, uint32 size) : OperandVisitable(kOpdRegister, size), regNO(no) {} 126 127 ~RegOperand() = default; 128 using OperandVisitable<RegOperand>::OperandVisitable; 129 GetRegisterNO()130 uint32 GetRegisterNO() const 131 { 132 return regNO; 133 } 134 CloneTree(MapleAllocator & allocator)135 RegOperand *CloneTree(MapleAllocator &allocator) const override 136 { 137 return allocator.GetMemPool()->New<RegOperand>(*this); 138 } 139 Clone(MemPool & memPool)140 Operand *Clone(MemPool &memPool) const override 141 { 142 Operand *opnd = memPool.Clone<RegOperand>(*this); 143 return opnd; 144 } 145 146 void Dump() const override; 147 Less(const Operand & right)148 bool Less(const Operand &right) const override 149 { 150 (void)right; 151 return false; 152 } 153 154 private: 155 uint32 regNO; 156 }; 157 158 class ImmOperand : public maplebe::OperandVisitable<ImmOperand> { 159 public: ImmOperand(int64 val,uint32 size)160 ImmOperand(int64 val, uint32 size) : OperandVisitable(kOpdImmediate, size), val(val) {} 161 162 ~ImmOperand() = default; 163 using OperandVisitable<ImmOperand>::OperandVisitable; 164 CloneTree(MapleAllocator & allocator)165 ImmOperand *CloneTree(MapleAllocator &allocator) const override 166 { 167 // const MIRSymbol is not changed in cg, so we can do shallow copy 168 return allocator.GetMemPool()->New<ImmOperand>(*this); 169 } 170 Clone(MemPool & memPool)171 Operand *Clone(MemPool &memPool) const override 172 { 173 Operand *opnd = memPool.Clone<ImmOperand>(*this); 174 return opnd; 175 } GetValue()176 int64 GetValue() const 177 { 178 return val; 179 } 180 181 void Dump() const override; 182 Less(const Operand & right)183 bool Less(const Operand &right) const override 184 { 185 (void)right; 186 return false; 187 } 188 189 private: 190 int64 val; 191 }; 192 193 class SymbolOperand : public maplebe::OperandVisitable<SymbolOperand> { 194 public: SymbolOperand(maple::MIRSymbol & mirSymbol,uint8 size)195 SymbolOperand(maple::MIRSymbol &mirSymbol, uint8 size) : OperandVisitable(kOpdStImmediate, size), symbol(&mirSymbol) 196 { 197 } 198 ~SymbolOperand() = default; 199 using OperandVisitable<SymbolOperand>::OperandVisitable; 200 CloneTree(MapleAllocator & allocator)201 SymbolOperand *CloneTree(MapleAllocator &allocator) const override 202 { 203 // const MIRSymbol is not changed in cg, so we can do shallow copy 204 return allocator.GetMemPool()->New<SymbolOperand>(*this); 205 } 206 Clone(MemPool & memPool)207 Operand *Clone(MemPool &memPool) const override 208 { 209 Operand *opnd = memPool.Clone<SymbolOperand>(*this); 210 return opnd; 211 } 212 Less(const Operand & right)213 bool Less(const Operand &right) const override 214 { 215 (void)right; 216 return false; 217 } 218 Dump()219 void Dump() const override 220 { 221 LogInfo::MapleLogger() << "symbol is : " << symbol->GetName(); 222 } 223 224 private: 225 maple::MIRSymbol *symbol; 226 }; 227 228 class StrOperand : public maplebe::OperandVisitable<StrOperand> { 229 public: StrOperand(const std::string & str,MemPool & memPool)230 StrOperand(const std::string &str, MemPool &memPool) : OperandVisitable(kOpdString, 0), str(str, &memPool) {} 231 232 ~StrOperand() = default; 233 using OperandVisitable<StrOperand>::OperandVisitable; 234 CloneTree(MapleAllocator & allocator)235 StrOperand *CloneTree(MapleAllocator &allocator) const override 236 { 237 return allocator.GetMemPool()->New<StrOperand>(*this); 238 } 239 Clone(MemPool & memPool)240 Operand *Clone(MemPool &memPool) const override 241 { 242 Operand *opnd = memPool.Clone<StrOperand>(*this); 243 return opnd; 244 } 245 Less(const Operand & right)246 bool Less(const Operand &right) const override 247 { 248 (void)right; 249 return false; 250 } 251 GetStr()252 const MapleString &GetStr() const 253 { 254 return str; 255 } 256 257 void Dump() const override; 258 259 private: 260 const MapleString str; 261 }; 262 263 class LabelOperand : public maplebe::OperandVisitable<LabelOperand> { 264 public: LabelOperand(const std::string & parent,LabelIdx labIdx,MemPool & memPool)265 LabelOperand(const std::string &parent, LabelIdx labIdx, MemPool &memPool) 266 : OperandVisitable(kOpdBBAddress, 0), parentFunc(parent, &memPool), labelIndex(labIdx) 267 { 268 } 269 270 ~LabelOperand() = default; 271 using OperandVisitable<LabelOperand>::OperandVisitable; 272 CloneTree(MapleAllocator & allocator)273 LabelOperand *CloneTree(MapleAllocator &allocator) const override 274 { 275 return allocator.GetMemPool()->New<LabelOperand>(*this); 276 } 277 Clone(MemPool & memPool)278 Operand *Clone(MemPool &memPool) const override 279 { 280 Operand *opnd = memPool.Clone<LabelOperand>(*this); 281 return opnd; 282 } 283 Less(const Operand & right)284 bool Less(const Operand &right) const override 285 { 286 (void)right; 287 return false; 288 } 289 290 void Dump() const override; 291 GetParentFunc()292 const MapleString &GetParentFunc() const 293 { 294 return parentFunc; 295 } GetIabelIdx()296 LabelIdx GetIabelIdx() const 297 { 298 return labelIndex; 299 }; 300 301 private: 302 const MapleString parentFunc; 303 LabelIdx labelIndex; 304 }; 305 306 class CFIOpndEmitVisitor 307 : public maplebe::OperandVisitorBase, 308 public maplebe::OperandVisitors<RegOperand, ImmOperand, SymbolOperand, StrOperand, LabelOperand> { 309 public: CFIOpndEmitVisitor(maplebe::Emitter & asmEmitter)310 explicit CFIOpndEmitVisitor(maplebe::Emitter &asmEmitter) : emitter(asmEmitter) {} 311 virtual ~CFIOpndEmitVisitor() = default; 312 313 protected: 314 maplebe::Emitter &emitter; 315 316 private: 317 void Visit(RegOperand *v) final; 318 void Visit(ImmOperand *v) final; 319 void Visit(SymbolOperand *v) final; 320 void Visit(StrOperand *v) final; 321 void Visit(LabelOperand *v) final; 322 }; 323 } /* namespace cfi */ 324 325 #endif /* MAPLEBE_INCLUDE_CG_CFI_H */ 326