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