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 GetBothDefUseOpnd()119 uint32 GetBothDefUseOpnd() const override 120 { 121 return maplebe::kInsnMaxOpnd; 122 } 123 124 private: 125 CfiInsn &operator=(const CfiInsn &); 126 }; 127 128 class RegOperand : public maplebe::OperandVisitable<RegOperand> { 129 public: RegOperand(uint32 no,uint32 size)130 RegOperand(uint32 no, uint32 size) : OperandVisitable(kOpdRegister, size), regNO(no) {} 131 132 ~RegOperand() = default; 133 using OperandVisitable<RegOperand>::OperandVisitable; 134 GetRegisterNO()135 uint32 GetRegisterNO() const 136 { 137 return regNO; 138 } 139 CloneTree(MapleAllocator & allocator)140 RegOperand *CloneTree(MapleAllocator &allocator) const override 141 { 142 return allocator.GetMemPool()->New<RegOperand>(*this); 143 } 144 Clone(MemPool & memPool)145 Operand *Clone(MemPool &memPool) const override 146 { 147 Operand *opnd = memPool.Clone<RegOperand>(*this); 148 return opnd; 149 } 150 151 void Dump() const override; 152 Less(const Operand & right)153 bool Less(const Operand &right) const override 154 { 155 (void)right; 156 return false; 157 } 158 159 private: 160 uint32 regNO; 161 }; 162 163 class ImmOperand : public maplebe::OperandVisitable<ImmOperand> { 164 public: ImmOperand(int64 val,uint32 size)165 ImmOperand(int64 val, uint32 size) : OperandVisitable(kOpdImmediate, size), val(val) {} 166 167 ~ImmOperand() = default; 168 using OperandVisitable<ImmOperand>::OperandVisitable; 169 CloneTree(MapleAllocator & allocator)170 ImmOperand *CloneTree(MapleAllocator &allocator) const override 171 { 172 // const MIRSymbol is not changed in cg, so we can do shallow copy 173 return allocator.GetMemPool()->New<ImmOperand>(*this); 174 } 175 Clone(MemPool & memPool)176 Operand *Clone(MemPool &memPool) const override 177 { 178 Operand *opnd = memPool.Clone<ImmOperand>(*this); 179 return opnd; 180 } GetValue()181 int64 GetValue() const 182 { 183 return val; 184 } 185 186 void Dump() const override; 187 Less(const Operand & right)188 bool Less(const Operand &right) const override 189 { 190 (void)right; 191 return false; 192 } 193 194 private: 195 int64 val; 196 }; 197 198 class SymbolOperand : public maplebe::OperandVisitable<SymbolOperand> { 199 public: SymbolOperand(maple::MIRSymbol & mirSymbol,uint8 size)200 SymbolOperand(maple::MIRSymbol &mirSymbol, uint8 size) : OperandVisitable(kOpdStImmediate, size), symbol(&mirSymbol) 201 { 202 } 203 ~SymbolOperand() = default; 204 using OperandVisitable<SymbolOperand>::OperandVisitable; 205 CloneTree(MapleAllocator & allocator)206 SymbolOperand *CloneTree(MapleAllocator &allocator) const override 207 { 208 // const MIRSymbol is not changed in cg, so we can do shallow copy 209 return allocator.GetMemPool()->New<SymbolOperand>(*this); 210 } 211 Clone(MemPool & memPool)212 Operand *Clone(MemPool &memPool) const override 213 { 214 Operand *opnd = memPool.Clone<SymbolOperand>(*this); 215 return opnd; 216 } 217 Less(const Operand & right)218 bool Less(const Operand &right) const override 219 { 220 (void)right; 221 return false; 222 } 223 Dump()224 void Dump() const override 225 { 226 LogInfo::MapleLogger() << "symbol is : " << symbol->GetName(); 227 } 228 229 private: 230 maple::MIRSymbol *symbol; 231 }; 232 233 class StrOperand : public maplebe::OperandVisitable<StrOperand> { 234 public: StrOperand(const std::string & str,MemPool & memPool)235 StrOperand(const std::string &str, MemPool &memPool) : OperandVisitable(kOpdString, 0), str(str, &memPool) {} 236 237 ~StrOperand() = default; 238 using OperandVisitable<StrOperand>::OperandVisitable; 239 CloneTree(MapleAllocator & allocator)240 StrOperand *CloneTree(MapleAllocator &allocator) const override 241 { 242 return allocator.GetMemPool()->New<StrOperand>(*this); 243 } 244 Clone(MemPool & memPool)245 Operand *Clone(MemPool &memPool) const override 246 { 247 Operand *opnd = memPool.Clone<StrOperand>(*this); 248 return opnd; 249 } 250 Less(const Operand & right)251 bool Less(const Operand &right) const override 252 { 253 (void)right; 254 return false; 255 } 256 GetStr()257 const MapleString &GetStr() const 258 { 259 return str; 260 } 261 262 void Dump() const override; 263 264 private: 265 const MapleString str; 266 }; 267 268 class LabelOperand : public maplebe::OperandVisitable<LabelOperand> { 269 public: LabelOperand(const std::string & parent,LabelIdx labIdx,MemPool & memPool)270 LabelOperand(const std::string &parent, LabelIdx labIdx, MemPool &memPool) 271 : OperandVisitable(kOpdBBAddress, 0), parentFunc(parent, &memPool), labelIndex(labIdx) 272 { 273 } 274 275 ~LabelOperand() = default; 276 using OperandVisitable<LabelOperand>::OperandVisitable; 277 CloneTree(MapleAllocator & allocator)278 LabelOperand *CloneTree(MapleAllocator &allocator) const override 279 { 280 return allocator.GetMemPool()->New<LabelOperand>(*this); 281 } 282 Clone(MemPool & memPool)283 Operand *Clone(MemPool &memPool) const override 284 { 285 Operand *opnd = memPool.Clone<LabelOperand>(*this); 286 return opnd; 287 } 288 Less(const Operand & right)289 bool Less(const Operand &right) const override 290 { 291 (void)right; 292 return false; 293 } 294 295 void Dump() const override; 296 GetParentFunc()297 const MapleString &GetParentFunc() const 298 { 299 return parentFunc; 300 } GetIabelIdx()301 LabelIdx GetIabelIdx() const 302 { 303 return labelIndex; 304 }; 305 306 private: 307 const MapleString parentFunc; 308 LabelIdx labelIndex; 309 }; 310 311 class CFIOpndEmitVisitor 312 : public maplebe::OperandVisitorBase, 313 public maplebe::OperandVisitors<RegOperand, ImmOperand, SymbolOperand, StrOperand, LabelOperand> { 314 public: CFIOpndEmitVisitor(maplebe::Emitter & asmEmitter)315 explicit CFIOpndEmitVisitor(maplebe::Emitter &asmEmitter) : emitter(asmEmitter) {} 316 virtual ~CFIOpndEmitVisitor() = default; 317 318 protected: 319 maplebe::Emitter &emitter; 320 321 private: 322 void Visit(RegOperand *v) final; 323 void Visit(ImmOperand *v) final; 324 void Visit(SymbolOperand *v) final; 325 void Visit(StrOperand *v) final; 326 void Visit(LabelOperand *v) final; 327 }; 328 } /* namespace cfi */ 329 330 #endif /* MAPLEBE_INCLUDE_CG_CFI_H */ 331