Index: lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetMachine.cpp +++ lib/Target/AArch64/AArch64TargetMachine.cpp @@ -263,6 +263,15 @@ this->Options.NoTrapAfterNoreturn = true; } + if (TT.isOSWindows()) { + // Unwinding can get confused if the last instruction in a function or + // funclet is a call. + // + // FIXME: This isn't very efficient; it's only really necessary if the + // call would be the last instruction in a function/funclet. + this->Options.TrapUnreachable = true; + } + // Enable GlobalISel at or below EnableGlobalISelAt0. if (getOptLevel() <= EnableGlobalISelAtO) setGlobalISel(true); Index: test/CodeGen/AArch64/windows-trap.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/windows-trap.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=aarch64-win32 %s -o - | FileCheck %s + +declare void @callee() noreturn + +; Make sure the call isn't the last instruction in the function; if it is, +; unwinding may break. +; +; (The instruction after the call doesn't have to be anything in particular, +; but trapping has the nice side-effect of catching bugs.) + +define void @test_unreachable() { +; CHECK-LABEL: test_unreachable: +; CHECK: bl callee +; CHECK-NEXT: brk #0x1 + call void @callee() noreturn + unreachable +}