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   uint32_t PrologCodeBytes = 0;
50 
51   bool HandlesUnwind = false;
52   bool HandlesExceptions = false;
53   bool EmitAttempted = false;
54   bool Fragment = false;
55 
56   int LastFrameInst = -1;
57   const FrameInfo *ChainedParent = nullptr;
58   std::vector<Instruction> Instructions;
59   struct Epilog {
60     std::vector<Instruction> Instructions;
61     unsigned Condition;
62     MCSymbol *End;
63   };
64   MapVector<MCSymbol *, Epilog> EpilogMap;
65 
66   // For splitting unwind info of large functions
67   struct Segment {
68     int64_t Offset;
69     int64_t Length;
70     bool HasProlog;
71     MCSymbol *Symbol;
72     // Map an Epilog's symbol to its offset within the function.
73     MapVector<MCSymbol *, int64_t> Epilogs;
74 
75     Segment(int64_t Offset, int64_t Length, bool HasProlog = false)
76         : Offset(Offset), Length(Length), HasProlog(HasProlog) {}
77   };
78 
79   std::vector<Segment> Segments;
80 
81   FrameInfo() = default;
82   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
83       : Begin(BeginFuncEHLabel), Function(Function) {}
84   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
85             const FrameInfo *ChainedParent)
86       : Begin(BeginFuncEHLabel), Function(Function),
87         ChainedParent(ChainedParent) {}
88 
89   bool empty() const {
90     if (!Instructions.empty())
91       return false;
92     for (const auto &E : EpilogMap)
93       if (!E.second.Instructions.empty())
94         return false;
95     return true;
96   }
97 };
98 
99 class UnwindEmitter {
100 public:
101   virtual ~UnwindEmitter();
102 
103   /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
104   virtual void Emit(MCStreamer &Streamer) const = 0;
105   virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI,
106                               bool HandlerData) const = 0;
107 };
108 }
109 }
110 
111 #endif
112