10b57cec5SDimitry Andric //===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_MC_MCWINEH_H
100b57cec5SDimitry Andric #define LLVM_MC_MCWINEH_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/MapVector.h"
130b57cec5SDimitry Andric #include <vector>
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric namespace llvm {
160b57cec5SDimitry Andric class MCSection;
170b57cec5SDimitry Andric class MCStreamer;
180b57cec5SDimitry Andric class MCSymbol;
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace WinEH {
210b57cec5SDimitry Andric struct Instruction {
220b57cec5SDimitry Andric   const MCSymbol *Label;
230b57cec5SDimitry Andric   unsigned Offset;
240b57cec5SDimitry Andric   unsigned Register;
250b57cec5SDimitry Andric   unsigned Operation;
260b57cec5SDimitry Andric 
InstructionInstruction270b57cec5SDimitry Andric   Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off)
280b57cec5SDimitry Andric     : Label(L), Offset(Off), Register(Reg), Operation(Op) {}
29e8d8bef9SDimitry Andric 
30e8d8bef9SDimitry Andric   bool operator==(const Instruction &I) const {
31e8d8bef9SDimitry Andric     // Check whether two instructions refer to the same operation
32e8d8bef9SDimitry Andric     // applied at a different spot (i.e. pointing at a different label).
33e8d8bef9SDimitry Andric     return Offset == I.Offset && Register == I.Register &&
34e8d8bef9SDimitry Andric            Operation == I.Operation;
35e8d8bef9SDimitry Andric   }
36e8d8bef9SDimitry Andric   bool operator!=(const Instruction &I) const { return !(*this == I); }
370b57cec5SDimitry Andric };
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric struct FrameInfo {
400b57cec5SDimitry Andric   const MCSymbol *Begin = nullptr;
410b57cec5SDimitry Andric   const MCSymbol *End = nullptr;
420b57cec5SDimitry Andric   const MCSymbol *FuncletOrFuncEnd = nullptr;
430b57cec5SDimitry Andric   const MCSymbol *ExceptionHandler = nullptr;
440b57cec5SDimitry Andric   const MCSymbol *Function = nullptr;
450b57cec5SDimitry Andric   const MCSymbol *PrologEnd = nullptr;
460b57cec5SDimitry Andric   const MCSymbol *Symbol = nullptr;
47e8d8bef9SDimitry Andric   MCSection *TextSection = nullptr;
48e8d8bef9SDimitry Andric   uint32_t PackedInfo = 0;
49bdd1243dSDimitry Andric   uint32_t PrologCodeBytes = 0;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   bool HandlesUnwind = false;
520b57cec5SDimitry Andric   bool HandlesExceptions = false;
53e8d8bef9SDimitry Andric   bool EmitAttempted = false;
5481ad6265SDimitry Andric   bool Fragment = false;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   int LastFrameInst = -1;
570b57cec5SDimitry Andric   const FrameInfo *ChainedParent = nullptr;
580b57cec5SDimitry Andric   std::vector<Instruction> Instructions;
5981ad6265SDimitry Andric   struct Epilog {
6081ad6265SDimitry Andric     std::vector<Instruction> Instructions;
6181ad6265SDimitry Andric     unsigned Condition;
6281ad6265SDimitry Andric     MCSymbol *End;
6381ad6265SDimitry Andric   };
6481ad6265SDimitry Andric   MapVector<MCSymbol *, Epilog> EpilogMap;
650b57cec5SDimitry Andric 
66bdd1243dSDimitry Andric   // For splitting unwind info of large functions
67bdd1243dSDimitry Andric   struct Segment {
68bdd1243dSDimitry Andric     int64_t Offset;
69bdd1243dSDimitry Andric     int64_t Length;
70bdd1243dSDimitry Andric     bool HasProlog;
7106c3fb27SDimitry Andric     MCSymbol *Symbol = nullptr;
72bdd1243dSDimitry Andric     // Map an Epilog's symbol to its offset within the function.
73bdd1243dSDimitry Andric     MapVector<MCSymbol *, int64_t> Epilogs;
74bdd1243dSDimitry Andric 
75bdd1243dSDimitry Andric     Segment(int64_t Offset, int64_t Length, bool HasProlog = false)
OffsetFrameInfo::Segment76bdd1243dSDimitry Andric         : Offset(Offset), Length(Length), HasProlog(HasProlog) {}
77bdd1243dSDimitry Andric   };
78bdd1243dSDimitry Andric 
79bdd1243dSDimitry Andric   std::vector<Segment> Segments;
80bdd1243dSDimitry Andric 
810b57cec5SDimitry Andric   FrameInfo() = default;
FrameInfoFrameInfo820b57cec5SDimitry Andric   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
830b57cec5SDimitry Andric       : Begin(BeginFuncEHLabel), Function(Function) {}
FrameInfoFrameInfo840b57cec5SDimitry Andric   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
850b57cec5SDimitry Andric             const FrameInfo *ChainedParent)
860b57cec5SDimitry Andric       : Begin(BeginFuncEHLabel), Function(Function),
870b57cec5SDimitry Andric         ChainedParent(ChainedParent) {}
88e8d8bef9SDimitry Andric 
emptyFrameInfo89e8d8bef9SDimitry Andric   bool empty() const {
90e8d8bef9SDimitry Andric     if (!Instructions.empty())
91e8d8bef9SDimitry Andric       return false;
92e8d8bef9SDimitry Andric     for (const auto &E : EpilogMap)
9381ad6265SDimitry Andric       if (!E.second.Instructions.empty())
94e8d8bef9SDimitry Andric         return false;
95e8d8bef9SDimitry Andric     return true;
96e8d8bef9SDimitry Andric   }
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric class UnwindEmitter {
1000b57cec5SDimitry Andric public:
1010b57cec5SDimitry Andric   virtual ~UnwindEmitter();
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
1040b57cec5SDimitry Andric   virtual void Emit(MCStreamer &Streamer) const = 0;
105e8d8bef9SDimitry Andric   virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI,
106e8d8bef9SDimitry Andric                               bool HandlerData) const = 0;
1070b57cec5SDimitry Andric };
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric #endif
112