Index: llvm/include/llvm/MC/MCWinEH.h =================================================================== --- llvm/include/llvm/MC/MCWinEH.h +++ llvm/include/llvm/MC/MCWinEH.h @@ -36,7 +36,7 @@ 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; Index: llvm/lib/MC/MCStreamer.cpp =================================================================== --- llvm/lib/MC/MCStreamer.cpp +++ llvm/lib/MC/MCStreamer.cpp @@ -692,6 +692,8 @@ MCSymbol *Label = emitCFILabel(); CurFrame->End = Label; + if (!CurFrame->FuncletOrFuncEnd) + CurFrame->FuncletOrFuncEnd = CurFrame->End; } void MCStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) { Index: llvm/lib/MC/MCWin64EH.cpp =================================================================== --- llvm/lib/MC/MCWin64EH.cpp +++ llvm/lib/MC/MCWin64EH.cpp @@ -505,7 +505,9 @@ 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. + // of code. + // This can happen if unwind info is forced to be generated (with a + // .seh_handlerdata directive) directly after the start of the function. RawFuncLength = 0; } else { // FIXME: GetAbsDifference tries to compute the length of the function @@ -687,6 +689,16 @@ 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); Index: llvm/test/MC/AArch64/seh.s =================================================================== --- llvm/test/MC/AArch64/seh.s +++ llvm/test/MC/AArch64/seh.s @@ -49,6 +49,17 @@ // 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 +// CHECK: RuntimeFunction { +// CHECK-NEXT: Function: handlerFunc +// CHECK-NEXT: ExceptionRecord: .xdata +// CHECK-NEXT: ExceptionData { +// CHECK-NEXT: FunctionLength: 4 .text .globl func