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 "ARMUnwindOp.h" 19 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/DataTypes.h" 23 24 namespace llvm { 25 26 class MCSymbol; 27 28 class UnwindOpcodeAssembler { 29 private: 30 llvm::SmallVector<uint8_t, 32> Ops; 31 llvm::SmallVector<unsigned, 8> OpBegins; 32 bool HasPersonality; 33 34 public: 35 UnwindOpcodeAssembler() 36 : HasPersonality(0) { 37 OpBegins.push_back(0); 38 } 39 40 /// Reset the unwind opcode assembler. 41 void Reset() { 42 Ops.clear(); 43 OpBegins.clear(); 44 OpBegins.push_back(0); 45 HasPersonality = 0; 46 } 47 48 /// Set the personality index 49 void setPersonality(const MCSymbol *Per) { 50 HasPersonality = 1; 51 } 52 53 /// Emit unwind opcodes for .save directives 54 void EmitRegSave(uint32_t RegSave); 55 56 /// Emit unwind opcodes for .vsave directives 57 void EmitVFPRegSave(uint32_t VFPRegSave); 58 59 /// Emit unwind opcodes to copy address from source register to $sp. 60 void EmitSetSP(uint16_t Reg); 61 62 /// Emit unwind opcodes to add $sp with an offset. 63 void EmitSPOffset(int64_t Offset); 64 65 /// Finalize the unwind opcode sequence for EmitBytes() 66 void Finalize(unsigned &PersonalityIndex, 67 SmallVectorImpl<uint8_t> &Result); 68 69 private: 70 void EmitInt8(unsigned Opcode) { 71 Ops.push_back(Opcode & 0xff); 72 OpBegins.push_back(OpBegins.back() + 1); 73 } 74 75 void EmitInt16(unsigned Opcode) { 76 Ops.push_back((Opcode >> 8) & 0xff); 77 Ops.push_back(Opcode & 0xff); 78 OpBegins.push_back(OpBegins.back() + 2); 79 } 80 81 void EmitBytes(const uint8_t *Opcode, size_t Size) { 82 Ops.insert(Ops.end(), Opcode, Opcode + Size); 83 OpBegins.push_back(OpBegins.back() + Size); 84 } 85 }; 86 87 } // namespace llvm 88 89 #endif // ARM_UNWIND_OP_ASM_H 90