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