1 //===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_MC_MCWINEH_H
10 #define LLVM_MC_MCWINEH_H
11 
12 #include "llvm/ADT/MapVector.h"
13 #include <vector>
14 
15 namespace llvm {
16 class MCSection;
17 class MCStreamer;
18 class MCSymbol;
19 
20 namespace WinEH {
21 struct Instruction {
22   const MCSymbol *Label;
23   unsigned Offset;
24   unsigned Register;
25   unsigned Operation;
26 
27   Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off)
28     : Label(L), Offset(Off), Register(Reg), Operation(Op) {}
29 
30   bool operator==(const Instruction &I) const {
31     // Check whether two instructions refer to the same operation
32     // applied at a different spot (i.e. pointing at a different label).
33     return Offset == I.Offset && Register == I.Register &&
34            Operation == I.Operation;
35   }
36   bool operator!=(const Instruction &I) const { return !(*this == I); }
37 };
38 
39 struct FrameInfo {
40   const MCSymbol *Begin = nullptr;
41   const MCSymbol *End = nullptr;
42   const MCSymbol *FuncletOrFuncEnd = nullptr;
43   const MCSymbol *ExceptionHandler = nullptr;
44   const MCSymbol *Function = nullptr;
45   const MCSymbol *PrologEnd = nullptr;
46   const MCSymbol *Symbol = nullptr;
47   MCSection *TextSection = nullptr;
48   uint32_t PackedInfo = 0;
49 
50   bool HandlesUnwind = false;
51   bool HandlesExceptions = false;
52   bool EmitAttempted = false;
53   bool Fragment = false;
54 
55   int LastFrameInst = -1;
56   const FrameInfo *ChainedParent = nullptr;
57   std::vector<Instruction> Instructions;
58   struct Epilog {
59     std::vector<Instruction> Instructions;
60     unsigned Condition;
61     MCSymbol *End;
62   };
63   MapVector<MCSymbol *, Epilog> EpilogMap;
64 
65   FrameInfo() = default;
66   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
67       : Begin(BeginFuncEHLabel), Function(Function) {}
68   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
69             const FrameInfo *ChainedParent)
70       : Begin(BeginFuncEHLabel), Function(Function),
71         ChainedParent(ChainedParent) {}
72 
73   bool empty() const {
74     if (!Instructions.empty())
75       return false;
76     for (const auto &E : EpilogMap)
77       if (!E.second.Instructions.empty())
78         return false;
79     return true;
80   }
81 };
82 
83 class UnwindEmitter {
84 public:
85   virtual ~UnwindEmitter();
86 
87   /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
88   virtual void Emit(MCStreamer &Streamer) const = 0;
89   virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI,
90                               bool HandlerData) const = 0;
91 };
92 }
93 }
94 
95 #endif
96