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 
270b57cec5SDimitry 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;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   bool HandlesUnwind = false;
510b57cec5SDimitry Andric   bool HandlesExceptions = false;
52e8d8bef9SDimitry Andric   bool EmitAttempted = false;
5381ad6265SDimitry Andric   bool Fragment = false;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   int LastFrameInst = -1;
560b57cec5SDimitry Andric   const FrameInfo *ChainedParent = nullptr;
570b57cec5SDimitry Andric   std::vector<Instruction> Instructions;
5881ad6265SDimitry Andric   struct Epilog {
5981ad6265SDimitry Andric     std::vector<Instruction> Instructions;
6081ad6265SDimitry Andric     unsigned Condition;
6181ad6265SDimitry Andric     MCSymbol *End;
6281ad6265SDimitry Andric   };
6381ad6265SDimitry Andric   MapVector<MCSymbol *, Epilog> EpilogMap;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   FrameInfo() = default;
660b57cec5SDimitry Andric   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
670b57cec5SDimitry Andric       : Begin(BeginFuncEHLabel), Function(Function) {}
680b57cec5SDimitry Andric   FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
690b57cec5SDimitry Andric             const FrameInfo *ChainedParent)
700b57cec5SDimitry Andric       : Begin(BeginFuncEHLabel), Function(Function),
710b57cec5SDimitry Andric         ChainedParent(ChainedParent) {}
72e8d8bef9SDimitry Andric 
73e8d8bef9SDimitry Andric   bool empty() const {
74e8d8bef9SDimitry Andric     if (!Instructions.empty())
75e8d8bef9SDimitry Andric       return false;
76e8d8bef9SDimitry Andric     for (const auto &E : EpilogMap)
7781ad6265SDimitry Andric       if (!E.second.Instructions.empty())
78e8d8bef9SDimitry Andric         return false;
79e8d8bef9SDimitry Andric     return true;
80e8d8bef9SDimitry Andric   }
810b57cec5SDimitry Andric };
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric class UnwindEmitter {
840b57cec5SDimitry Andric public:
850b57cec5SDimitry Andric   virtual ~UnwindEmitter();
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   /// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
880b57cec5SDimitry Andric   virtual void Emit(MCStreamer &Streamer) const = 0;
89e8d8bef9SDimitry Andric   virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI,
90e8d8bef9SDimitry Andric                               bool HandlerData) const = 0;
910b57cec5SDimitry Andric };
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric #endif
96