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 InstructionInstruction27 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 = nullptr; 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) OffsetFrameInfo::Segment76 : Offset(Offset), Length(Length), HasProlog(HasProlog) {} 77 }; 78 79 std::vector<Segment> Segments; 80 81 FrameInfo() = default; FrameInfoFrameInfo82 FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) 83 : Begin(BeginFuncEHLabel), Function(Function) {} FrameInfoFrameInfo84 FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, 85 const FrameInfo *ChainedParent) 86 : Begin(BeginFuncEHLabel), Function(Function), 87 ChainedParent(ChainedParent) {} 88 emptyFrameInfo89 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