1532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//===-- ARMUnwindOpAsm.h - ARM Unwind Opcodes Assembler ---------*- C++ -*-===//
2532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//
3532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//                     The LLVM Compiler Infrastructure
4532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//
5532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien// This file is distributed under the University of Illinois Open Source
6532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien// License. See LICENSE.TXT for details.
7532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//
8532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//===----------------------------------------------------------------------===//
9532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//
10532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien// This file declares the unwind opcode assmebler for ARM exception handling
11532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien// table.
12532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//
13532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien//===----------------------------------------------------------------------===//
14532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
15532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien#ifndef ARM_UNWIND_OP_ASM_H
16532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien#define ARM_UNWIND_OP_ASM_H
17532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
18532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien#include "llvm/ADT/SmallVector.h"
1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/ARMEHABI.h"
20532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien#include "llvm/Support/DataTypes.h"
21532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
22532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chiennamespace llvm {
23532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
24532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chienclass MCSymbol;
25532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
26532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chienclass UnwindOpcodeAssembler {
27532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chienprivate:
2818cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  llvm::SmallVector<uint8_t, 32> Ops;
2918cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  llvm::SmallVector<unsigned, 8> OpBegins;
30532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  bool HasPersonality;
31532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
32532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chienpublic:
33532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  UnwindOpcodeAssembler()
3418cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien      : HasPersonality(0) {
3518cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.push_back(0);
36532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  }
37532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
38532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  /// Reset the unwind opcode assembler.
39532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  void Reset() {
4018cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    Ops.clear();
4118cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.clear();
4218cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.push_back(0);
43532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien    HasPersonality = 0;
44532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  }
45532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// Set the personality
47532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  void setPersonality(const MCSymbol *Per) {
48532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien    HasPersonality = 1;
49532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  }
50532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
51532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  /// Emit unwind opcodes for .save directives
52532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  void EmitRegSave(uint32_t RegSave);
53532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
54532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  /// Emit unwind opcodes for .vsave directives
55532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  void EmitVFPRegSave(uint32_t VFPRegSave);
56532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
5718cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  /// Emit unwind opcodes to copy address from source register to $sp.
5818cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  void EmitSetSP(uint16_t Reg);
59532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
6018cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  /// Emit unwind opcodes to add $sp with an offset.
61532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  void EmitSPOffset(int64_t Offset);
62532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  /// Emit unwind raw opcodes
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void EmitRaw(const SmallVectorImpl<uint8_t> &Opcodes) {
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Ops.insert(Ops.end(), Opcodes.begin(), Opcodes.end());
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    OpBegins.push_back(OpBegins.back() + Opcodes.size());
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
69532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  /// Finalize the unwind opcode sequence for EmitBytes()
7018cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  void Finalize(unsigned &PersonalityIndex,
7118cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien                SmallVectorImpl<uint8_t> &Result);
72532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
73532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chienprivate:
7418cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  void EmitInt8(unsigned Opcode) {
7518cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    Ops.push_back(Opcode & 0xff);
7618cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.push_back(OpBegins.back() + 1);
77532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien  }
78532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
7918cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  void EmitInt16(unsigned Opcode) {
8018cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    Ops.push_back((Opcode >> 8) & 0xff);
8118cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    Ops.push_back(Opcode & 0xff);
8218cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.push_back(OpBegins.back() + 2);
8318cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  }
84532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
8518cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  void EmitBytes(const uint8_t *Opcode, size_t Size) {
8618cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    Ops.insert(Ops.end(), Opcode, Opcode + Size);
8718cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien    OpBegins.push_back(OpBegins.back() + Size);
8818cba562c8016f8095643b5dd8c4b34b294b62ddLogan Chien  }
89532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien};
90532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
91532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien} // namespace llvm
92532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien
93532854d7ab47d4ec20fd8cec703aa8c89d4eefb2Logan Chien#endif // ARM_UNWIND_OP_ASM_H
94