xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
10b57cec5SDimitry Andric //===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
9480093f4SDimitry Andric // This file declares the unwind opcode assembler for ARM exception handling
100b57cec5SDimitry Andric // table.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMUNWINDOPASM_H
150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMUNWINDOPASM_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include <cstddef>
190b57cec5SDimitry Andric #include <cstdint>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace llvm {
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric class MCSymbol;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric class UnwindOpcodeAssembler {
260b57cec5SDimitry Andric private:
270b57cec5SDimitry Andric   SmallVector<uint8_t, 32> Ops;
280b57cec5SDimitry Andric   SmallVector<unsigned, 8> OpBegins;
290b57cec5SDimitry Andric   bool HasPersonality = false;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric public:
UnwindOpcodeAssembler()320b57cec5SDimitry Andric   UnwindOpcodeAssembler() {
330b57cec5SDimitry Andric     OpBegins.push_back(0);
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   /// Reset the unwind opcode assembler.
Reset()370b57cec5SDimitry Andric   void Reset() {
380b57cec5SDimitry Andric     Ops.clear();
390b57cec5SDimitry Andric     OpBegins.clear();
400b57cec5SDimitry Andric     OpBegins.push_back(0);
410b57cec5SDimitry Andric     HasPersonality = false;
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   /// Set the personality
setPersonality(const MCSymbol * Per)450b57cec5SDimitry Andric   void setPersonality(const MCSymbol *Per) {
460b57cec5SDimitry Andric     HasPersonality = true;
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   /// Emit unwind opcodes for .save directives
500b57cec5SDimitry Andric   void EmitRegSave(uint32_t RegSave);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   /// Emit unwind opcodes for .vsave directives
530b57cec5SDimitry Andric   void EmitVFPRegSave(uint32_t VFPRegSave);
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   /// Emit unwind opcodes to copy address from source register to $sp.
560b57cec5SDimitry Andric   void EmitSetSP(uint16_t Reg);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   /// Emit unwind opcodes to add $sp with an offset.
590b57cec5SDimitry Andric   void EmitSPOffset(int64_t Offset);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   /// Emit unwind raw opcodes
EmitRaw(const SmallVectorImpl<uint8_t> & Opcodes)620b57cec5SDimitry Andric   void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) {
630b57cec5SDimitry Andric     Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end());
640b57cec5SDimitry Andric     OpBegins.push_back(OpBegins.back() + Opcodes.size());
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric 
67*5ffd83dbSDimitry Andric   /// Finalize the unwind opcode sequence for emitBytes()
680b57cec5SDimitry Andric   void Finalize(unsigned &PersonalityIndex,
690b57cec5SDimitry Andric                 SmallVectorImpl<uint8_t> &Result);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric private:
EmitInt8(unsigned Opcode)720b57cec5SDimitry Andric   void EmitInt8(unsigned Opcode) {
730b57cec5SDimitry Andric     Ops.push_back(Opcode & 0xff);
740b57cec5SDimitry Andric     OpBegins.push_back(OpBegins.back() + 1);
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric 
EmitInt16(unsigned Opcode)770b57cec5SDimitry Andric   void EmitInt16(unsigned Opcode) {
780b57cec5SDimitry Andric     Ops.push_back((Opcode >> 8) & 0xff);
790b57cec5SDimitry Andric     Ops.push_back(Opcode & 0xff);
800b57cec5SDimitry Andric     OpBegins.push_back(OpBegins.back() + 2);
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
emitBytes(const uint8_t * Opcode,size_t Size)83*5ffd83dbSDimitry Andric   void emitBytes(const uint8_t *Opcode, size_t Size) {
840b57cec5SDimitry Andric     Ops.insert(Ops.end(), Opcode, Opcode + Size);
850b57cec5SDimitry Andric     OpBegins.push_back(OpBegins.back() + Size);
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric };
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric } // end namespace llvm
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_MCTARGETDESC_ARMUNWINDOPASM_H
92