1 //===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file declares the unwind opcode assmebler for ARM exception handling 11 // table. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef ARM_UNWIND_OP_ASM_H 16 #define ARM_UNWIND_OP_ASM_H 17 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Support/ARMEHABI.h" 20 #include "llvm/Support/DataTypes.h" 21 22 namespace llvm { 23 24 class MCSymbol; 25 26 class UnwindOpcodeAssembler { 27 private: 28 llvm::SmallVector<uint8_t, 32> Ops; 29 llvm::SmallVector<unsigned, 8> OpBegins; 30 bool HasPersonality; 31 32 public: 33 UnwindOpcodeAssembler() 34 : HasPersonality(0) { 35 OpBegins.push_back(0); 36 } 37 38 /// Reset the unwind opcode assembler. 39 void Reset() { 40 Ops.clear(); 41 OpBegins.clear(); 42 OpBegins.push_back(0); 43 HasPersonality = 0; 44 } 45 46 /// Set the personality 47 void setPersonality(const MCSymbol *Per) { 48 HasPersonality = 1; 49 } 50 51 /// Emit unwind opcodes for .save directives 52 void EmitRegSave(uint32_t RegSave); 53 54 /// Emit unwind opcodes for .vsave directives 55 void EmitVFPRegSave(uint32_t VFPRegSave); 56 57 /// Emit unwind opcodes to copy address from source register to $sp. 58 void EmitSetSP(uint16_t Reg); 59 60 /// Emit unwind opcodes to add $sp with an offset. 61 void EmitSPOffset(int64_t Offset); 62 63 /// Emit unwind raw opcodes 64 void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) { 65 Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end()); 66 OpBegins.push_back(OpBegins.back() + Opcodes.size()); 67 } 68 69 /// Finalize the unwind opcode sequence for EmitBytes() 70 void Finalize(unsigned &PersonalityIndex, 71 SmallVectorImpl<uint8_t> &Result); 72 73 private: 74 void EmitInt8(unsigned Opcode) { 75 Ops.push_back(Opcode & 0xff); 76 OpBegins.push_back(OpBegins.back() + 1); 77 } 78 79 void EmitInt16(unsigned Opcode) { 80 Ops.push_back((Opcode >> 8) & 0xff); 81 Ops.push_back(Opcode & 0xff); 82 OpBegins.push_back(OpBegins.back() + 2); 83 } 84 85 void EmitBytes(const uint8_t *Opcode, size_t Size) { 86 Ops.insert(Ops.end(), Opcode, Opcode + Size); 87 OpBegins.push_back(OpBegins.back() + Size); 88 } 89 }; 90 91 } // namespace llvm 92 93 #endif // ARM_UNWIND_OP_ASM_H 94