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 "llvm/Support/Compiler.h" 14 #include "llvm/Support/SMLoc.h" 15 #include <vector> 16 17 namespace llvm { 18 class MCSection; 19 class MCStreamer; 20 class MCSymbol; 21 22 namespace WinEH { 23 struct Instruction { 24 const MCSymbol *Label; 25 unsigned Offset; 26 unsigned Register; 27 unsigned Operation; 28 InstructionInstruction29 Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off) 30 : Label(L), Offset(Off), Register(Reg), Operation(Op) {} 31 32 bool operator==(const Instruction &I) const { 33 // Check whether two instructions refer to the same operation 34 // applied at a different spot (i.e. pointing at a different label). 35 return Offset == I.Offset && Register == I.Register && 36 Operation == I.Operation; 37 } 38 bool operator!=(const Instruction &I) const { return !(*this == I); } 39 }; 40 41 struct FrameInfo { 42 const MCSymbol *Begin = nullptr; 43 const MCSymbol *End = nullptr; 44 const MCSymbol *FuncletOrFuncEnd = nullptr; 45 const MCSymbol *ExceptionHandler = nullptr; 46 const MCSymbol *Function = nullptr; 47 SMLoc FunctionLoc; 48 const MCSymbol *PrologEnd = nullptr; 49 const MCSymbol *Symbol = nullptr; 50 MCSection *TextSection = nullptr; 51 uint32_t PackedInfo = 0; 52 uint32_t PrologCodeBytes = 0; 53 54 bool HandlesUnwind = false; 55 bool HandlesExceptions = false; 56 bool EmitAttempted = false; 57 bool Fragment = false; 58 constexpr static uint8_t DefaultVersion = 1; 59 uint8_t Version = DefaultVersion; 60 61 int LastFrameInst = -1; 62 const FrameInfo *ChainedParent = nullptr; 63 std::vector<Instruction> Instructions; 64 struct Epilog { 65 std::vector<Instruction> Instructions; 66 unsigned Condition; 67 const MCSymbol *Start = nullptr; 68 const MCSymbol *End = nullptr; 69 const MCSymbol *UnwindV2Start = nullptr; 70 SMLoc Loc; 71 }; 72 MapVector<MCSymbol *, Epilog> EpilogMap; 73 74 // For splitting unwind info of large functions 75 struct Segment { 76 int64_t Offset; 77 int64_t Length; 78 bool HasProlog; 79 MCSymbol *Symbol = nullptr; 80 // Map an Epilog's symbol to its offset within the function. 81 MapVector<MCSymbol *, int64_t> Epilogs; 82 83 Segment(int64_t Offset, int64_t Length, bool HasProlog = false) OffsetFrameInfo::Segment84 : Offset(Offset), Length(Length), HasProlog(HasProlog) {} 85 }; 86 87 std::vector<Segment> Segments; 88 89 FrameInfo() = default; FrameInfoFrameInfo90 FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) 91 : Begin(BeginFuncEHLabel), Function(Function) {} FrameInfoFrameInfo92 FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, 93 const FrameInfo *ChainedParent) 94 : Begin(BeginFuncEHLabel), Function(Function), 95 ChainedParent(ChainedParent) {} 96 emptyFrameInfo97 bool empty() const { 98 if (!Instructions.empty()) 99 return false; 100 for (const auto &E : EpilogMap) 101 if (!E.second.Instructions.empty()) 102 return false; 103 return true; 104 } 105 }; 106 107 class LLVM_ABI UnwindEmitter { 108 public: 109 virtual ~UnwindEmitter(); 110 111 /// This emits the unwind info sections (.pdata and .xdata in PE/COFF). 112 virtual void Emit(MCStreamer &Streamer) const = 0; 113 virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI, 114 bool HandlerData) const = 0; 115 }; 116 } 117 } 118 119 #endif 120