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