1251607Sdim//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//
2251607Sdim//
3251607Sdim//                     The LLVM Compiler Infrastructure
4251607Sdim//
5251607Sdim// This file is distributed under the University of Illinois Open Source
6251607Sdim// License. See LICENSE.TXT for details.
7251607Sdim//
8251607Sdim//===----------------------------------------------------------------------===//
9251607Sdim//
10251607Sdim// This file declares the unwind opcode assmebler for ARM exception handling
11251607Sdim// table.
12251607Sdim//
13251607Sdim//===----------------------------------------------------------------------===//
14251607Sdim
15251607Sdim#ifndef ARM_UNWIND_OP_ASM_H
16251607Sdim#define ARM_UNWIND_OP_ASM_H
17251607Sdim
18251607Sdim#include "ARMUnwindOp.h"
19251607Sdim
20251607Sdim#include "llvm/ADT/SmallVector.h"
21251607Sdim#include "llvm/ADT/StringRef.h"
22251607Sdim#include "llvm/Support/DataTypes.h"
23251607Sdim
24251607Sdimnamespace llvm {
25251607Sdim
26251607Sdimclass MCSymbol;
27251607Sdim
28251607Sdimclass UnwindOpcodeAssembler {
29251607Sdimprivate:
30263508Sdim  llvm::SmallVector<uint8_t, 32> Ops;
31263508Sdim  llvm::SmallVector<unsigned, 8> OpBegins;
32251607Sdim  bool HasPersonality;
33251607Sdim
34251607Sdimpublic:
35251607Sdim  UnwindOpcodeAssembler()
36263508Sdim      : HasPersonality(0) {
37263508Sdim    OpBegins.push_back(0);
38251607Sdim  }
39251607Sdim
40251607Sdim  /// Reset the unwind opcode assembler.
41251607Sdim  void Reset() {
42263508Sdim    Ops.clear();
43263508Sdim    OpBegins.clear();
44263508Sdim    OpBegins.push_back(0);
45251607Sdim    HasPersonality = 0;
46251607Sdim  }
47251607Sdim
48251607Sdim  /// Set the personality index
49251607Sdim  void setPersonality(const MCSymbol *Per) {
50251607Sdim    HasPersonality = 1;
51251607Sdim  }
52251607Sdim
53251607Sdim  /// Emit unwind opcodes for .save directives
54251607Sdim  void EmitRegSave(uint32_t RegSave);
55251607Sdim
56251607Sdim  /// Emit unwind opcodes for .vsave directives
57251607Sdim  void EmitVFPRegSave(uint32_t VFPRegSave);
58251607Sdim
59263508Sdim  /// Emit unwind opcodes to copy address from source register to $sp.
60263508Sdim  void EmitSetSP(uint16_t Reg);
61251607Sdim
62263508Sdim  /// Emit unwind opcodes to add $sp with an offset.
63251607Sdim  void EmitSPOffset(int64_t Offset);
64251607Sdim
65251607Sdim  /// Finalize the unwind opcode sequence for EmitBytes()
66263508Sdim  void Finalize(unsigned &PersonalityIndex,
67263508Sdim                SmallVectorImpl<uint8_t> &Result);
68251607Sdim
69251607Sdimprivate:
70263508Sdim  void EmitInt8(unsigned Opcode) {
71263508Sdim    Ops.push_back(Opcode & 0xff);
72263508Sdim    OpBegins.push_back(OpBegins.back() + 1);
73251607Sdim  }
74251607Sdim
75263508Sdim  void EmitInt16(unsigned Opcode) {
76263508Sdim    Ops.push_back((Opcode >> 8) & 0xff);
77263508Sdim    Ops.push_back(Opcode & 0xff);
78263508Sdim    OpBegins.push_back(OpBegins.back() + 2);
79263508Sdim  }
80251607Sdim
81263508Sdim  void EmitBytes(const uint8_t *Opcode, size_t Size) {
82263508Sdim    Ops.insert(Ops.end(), Opcode, Opcode + Size);
83263508Sdim    OpBegins.push_back(OpBegins.back() + Size);
84263508Sdim  }
85251607Sdim};
86251607Sdim
87251607Sdim} // namespace llvm
88251607Sdim
89251607Sdim#endif // ARM_UNWIND_OP_ASM_H
90