1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[MC] [Win64EH] Fill in FuncletOrFuncEnd if missing

This can happen e.g. for code that declare .seh_proc/.seh_endproc
in assembly, or for code that use .seh_handlerdata (which triggers
the unwind info to be emitted before the end of the function).

The TextSection field must be made non-const to be able to use it
with Streamer.SwitchSection().

Differential Revision: https://reviews.llvm.org/D86528
This commit is contained in:
Martin Storsjö 2020-08-20 11:39:25 +03:00
parent ccee9bafd6
commit 7550015c23
4 changed files with 20 additions and 4 deletions

View File

@ -36,7 +36,7 @@ struct FrameInfo {
const MCSymbol *Function = nullptr;
const MCSymbol *PrologEnd = nullptr;
const MCSymbol *Symbol = nullptr;
const MCSection *TextSection = nullptr;
MCSection *TextSection = nullptr;
bool HandlesUnwind = false;
bool HandlesExceptions = false;

View File

@ -692,6 +692,8 @@ void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) {
MCSymbol *Label = emitCFILabel();
CurFrame->End = Label;
if (!CurFrame->FuncletOrFuncEnd)
CurFrame->FuncletOrFuncEnd = CurFrame->End;
}
void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {

View File

@ -525,9 +525,7 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
int64_t RawFuncLength;
if (!info->FuncletOrFuncEnd) {
// FIXME: This is very wrong; we emit SEH data which covers zero bytes
// of code. But otherwise test/MC/AArch64/seh.s crashes.
RawFuncLength = 0;
report_fatal_error("FuncletOrFuncEnd not set");
} else {
// FIXME: GetAbsDifference tries to compute the length of the function
// immediately, before the whole file is emitted, but in general
@ -702,6 +700,16 @@ void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {
void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(
MCStreamer &Streamer, WinEH::FrameInfo *info) const {
// Called if there's an .seh_handlerdata directive before the end of the
// function. This forces writing the xdata record already here - and
// in this case, the function isn't actually ended already, but the xdata
// record needs to know the function length. In these cases, if the funclet
// end hasn't been marked yet, the xdata function length won't cover the
// whole function, only up to this point.
if (!info->FuncletOrFuncEnd) {
Streamer.SwitchSection(info->TextSection);
info->FuncletOrFuncEnd = Streamer.emitCFILabel();
}
// Switch sections (the static function above is meant to be called from
// here and from Emit().
MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);

View File

@ -46,6 +46,12 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: UnwindInformation [
// CHECK-NEXT: RuntimeFunction {
// CHECK-NEXT: Function: func
// CHECK-NEXT: ExceptionRecord: .xdata
// CHECK-NEXT: ExceptionData {
// CHECK-NEXT: FunctionLength: 8
.text
.globl func