1//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the unwind opcode assmebler for ARM exception handling
11// table.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef ARM_UNWIND_OP_ASM_H
16#define ARM_UNWIND_OP_ASM_H
17
18#include "ARMUnwindOp.h"
19
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/DataTypes.h"
23
24namespace llvm {
25
26class MCSymbol;
27
28class UnwindOpcodeAssembler {
29private:
30  llvm::SmallVector<uint8_t, 8> Ops;
31
32  unsigned Offset;
33  unsigned PersonalityIndex;
34  bool HasPersonality;
35
36  enum {
37    // The number of bytes to be preserved for the size and personality index
38    // prefix of unwind opcodes.
39    NUM_PRESERVED_PREFIX_BUF = 2
40  };
41
42public:
43  UnwindOpcodeAssembler()
44      : Ops(NUM_PRESERVED_PREFIX_BUF), Offset(NUM_PRESERVED_PREFIX_BUF),
45        PersonalityIndex(NUM_PERSONALITY_INDEX), HasPersonality(0) {
46  }
47
48  /// Reset the unwind opcode assembler.
49  void Reset() {
50    Ops.resize(NUM_PRESERVED_PREFIX_BUF);
51    Offset = NUM_PRESERVED_PREFIX_BUF;
52    PersonalityIndex = NUM_PERSONALITY_INDEX;
53    HasPersonality = 0;
54  }
55
56  /// Get the size of the payload (including the size byte)
57  size_t size() const {
58    return Ops.size() - Offset;
59  }
60
61  /// Get the beginning of the payload
62  const uint8_t *begin() const {
63    return Ops.begin() + Offset;
64  }
65
66  /// Get the payload
67  StringRef data() const {
68    return StringRef(reinterpret_cast<const char *>(begin()), size());
69  }
70
71  /// Set the personality index
72  void setPersonality(const MCSymbol *Per) {
73    HasPersonality = 1;
74  }
75
76  /// Get the personality index
77  unsigned getPersonalityIndex() const {
78    return PersonalityIndex;
79  }
80
81  /// Emit unwind opcodes for .save directives
82  void EmitRegSave(uint32_t RegSave);
83
84  /// Emit unwind opcodes for .vsave directives
85  void EmitVFPRegSave(uint32_t VFPRegSave);
86
87  /// Emit unwind opcodes for .setfp directives
88  void EmitSetFP(uint16_t FPReg);
89
90  /// Emit unwind opcodes to update stack pointer
91  void EmitSPOffset(int64_t Offset);
92
93  /// Finalize the unwind opcode sequence for EmitBytes()
94  void Finalize();
95
96private:
97  /// Get the size of the opcodes in bytes.
98  size_t getOpcodeSize() const {
99    return Ops.size() - NUM_PRESERVED_PREFIX_BUF;
100  }
101
102  /// Add the length prefix to the payload
103  void AddOpcodeSizePrefix(size_t Pos);
104
105  /// Add personality index prefix in some compact format
106  void AddPersonalityIndexPrefix(size_t Pos, unsigned PersonalityIndex);
107
108  /// Fill the words with finish opcode if it is not aligned
109  void EmitFinishOpcodes();
110};
111
112} // namespace llvm
113
114#endif // ARM_UNWIND_OP_ASM_H
115