llvm-6502/lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h
Saleem Abdulrasool e502a6aad3 ARM IAS: add support for .unwind_raw directive
This implements the unwind_raw directive for the ARM IAS.  The unwind_raw
directive takes the form of a stack offset value followed by one or more bytes
representing the opcodes to be emitted.  The opcode emitted will interpreted as
if it were assembled by the opcode assembler via the standard unwinding
directives.

Thanks to Logan Chien for an extra test!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199707 91177308-0d34-0410-b5e6-96231b3b80d8
2014-01-21 02:33:10 +00:00

95 lines
2.4 KiB
C++

//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the unwind opcode assmebler for ARM exception handling
// table.
//
//===----------------------------------------------------------------------===//
#ifndef ARM_UNWIND_OP_ASM_H
#define ARM_UNWIND_OP_ASM_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ARMEHABI.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
class MCSymbol;
class UnwindOpcodeAssembler {
private:
llvm::SmallVector<uint8_t, 32> Ops;
llvm::SmallVector<unsigned, 8> OpBegins;
bool HasPersonality;
public:
UnwindOpcodeAssembler()
: HasPersonality(0) {
OpBegins.push_back(0);
}
/// Reset the unwind opcode assembler.
void Reset() {
Ops.clear();
OpBegins.clear();
OpBegins.push_back(0);
HasPersonality = 0;
}
/// Set the personality
void setPersonality(const MCSymbol *Per) {
HasPersonality = 1;
}
/// Emit unwind opcodes for .save directives
void EmitRegSave(uint32_t RegSave);
/// Emit unwind opcodes for .vsave directives
void EmitVFPRegSave(uint32_t VFPRegSave);
/// Emit unwind opcodes to copy address from source register to $sp.
void EmitSetSP(uint16_t Reg);
/// Emit unwind opcodes to add $sp with an offset.
void EmitSPOffset(int64_t Offset);
/// Emit unwind raw opcodes
void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) {
Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end());
OpBegins.push_back(OpBegins.back() + Opcodes.size());
}
/// Finalize the unwind opcode sequence for EmitBytes()
void Finalize(unsigned &PersonalityIndex,
SmallVectorImpl<uint8_t> &Result);
private:
void EmitInt8(unsigned Opcode) {
Ops.push_back(Opcode & 0xff);
OpBegins.push_back(OpBegins.back() + 1);
}
void EmitInt16(unsigned Opcode) {
Ops.push_back((Opcode >> 8) & 0xff);
Ops.push_back(Opcode & 0xff);
OpBegins.push_back(OpBegins.back() + 2);
}
void EmitBytes(const uint8_t *Opcode, size_t Size) {
Ops.insert(Ops.end(), Opcode, Opcode + Size);
OpBegins.push_back(OpBegins.back() + Size);
}
};
} // namespace llvm
#endif // ARM_UNWIND_OP_ASM_H