mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
0f20d48a09
This reapplies 36c64af9d7f97414d48681b74352c9684077259b in updated form. Emit the xdata for each function at .seh_endproc. This keeps the exact same output header order for most code generated by the LLVM CodeGen layer. (Sections still change order for code built from assembly where functions lack an explicit .seh_handlerdata directive, and functions with chained unwind info.) The practical effect should be that assembly output lacks superfluous ".seh_handlerdata; .text" pairs at the end of functions that don't handle exceptions, which allows such functions to use the AArch64 packed unwind format again. Differential Revision: https://reviews.llvm.org/D87448
90 lines
2.6 KiB
C++
90 lines
2.6 KiB
C++
//===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_MC_MCWINEH_H
|
|
#define LLVM_MC_MCWINEH_H
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
class MCSection;
|
|
class MCStreamer;
|
|
class MCSymbol;
|
|
|
|
namespace WinEH {
|
|
struct Instruction {
|
|
const MCSymbol *Label;
|
|
unsigned Offset;
|
|
unsigned Register;
|
|
unsigned Operation;
|
|
|
|
Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off)
|
|
: Label(L), Offset(Off), Register(Reg), Operation(Op) {}
|
|
|
|
bool operator==(const Instruction &I) const {
|
|
// Check whether two instructions refer to the same operation
|
|
// applied at a different spot (i.e. pointing at a different label).
|
|
return Offset == I.Offset && Register == I.Register &&
|
|
Operation == I.Operation;
|
|
}
|
|
bool operator!=(const Instruction &I) const { return !(*this == I); }
|
|
};
|
|
|
|
struct FrameInfo {
|
|
const MCSymbol *Begin = nullptr;
|
|
const MCSymbol *End = nullptr;
|
|
const MCSymbol *FuncletOrFuncEnd = nullptr;
|
|
const MCSymbol *ExceptionHandler = nullptr;
|
|
const MCSymbol *Function = nullptr;
|
|
const MCSymbol *PrologEnd = nullptr;
|
|
const MCSymbol *Symbol = nullptr;
|
|
MCSection *TextSection = nullptr;
|
|
uint32_t PackedInfo = 0;
|
|
|
|
bool HandlesUnwind = false;
|
|
bool HandlesExceptions = false;
|
|
bool EmitAttempted = false;
|
|
|
|
int LastFrameInst = -1;
|
|
const FrameInfo *ChainedParent = nullptr;
|
|
std::vector<Instruction> Instructions;
|
|
MapVector<MCSymbol*, std::vector<Instruction>> EpilogMap;
|
|
|
|
FrameInfo() = default;
|
|
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel)
|
|
: Begin(BeginFuncEHLabel), Function(Function) {}
|
|
FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel,
|
|
const FrameInfo *ChainedParent)
|
|
: Begin(BeginFuncEHLabel), Function(Function),
|
|
ChainedParent(ChainedParent) {}
|
|
|
|
bool empty() const {
|
|
if (!Instructions.empty())
|
|
return false;
|
|
for (const auto &E : EpilogMap)
|
|
if (!E.second.empty())
|
|
return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class UnwindEmitter {
|
|
public:
|
|
virtual ~UnwindEmitter();
|
|
|
|
/// This emits the unwind info sections (.pdata and .xdata in PE/COFF).
|
|
virtual void Emit(MCStreamer &Streamer) const = 0;
|
|
virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI,
|
|
bool HandlerData) const = 0;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|