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