Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix failure to invoke exception handler on Win64
When the last instruction prior to a function epilogue is a call, we need to emit a nop so that the return address is not in the epilogue IP range. This is consistent with MSVC's behavior, and may be a workaround for a bug in the Win64 unwinder. Differential Revision: http://reviews.llvm.org/D4751 Patch by Vadim Chugunov! llvm-svn: 214775
- Loading branch information
Showing
4 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
; RUN: llc < %s -mtriple=x86_64-pc-mingw32 | FileCheck %s -check-prefix=WIN64 | ||
|
||
declare void @bar() | ||
declare void @baz() | ||
declare i32 @personality(...) | ||
|
||
; Check for 'nop' between the last call and the epilogue. | ||
define void @foo1() { | ||
|
||
invoke void @bar() | ||
to label %normal | ||
unwind label %catch | ||
|
||
normal: | ||
ret void | ||
|
||
catch: | ||
%1 = landingpad { i8*, i32 } personality i32 (...)* @personality cleanup | ||
resume { i8*, i32 } %1 | ||
} | ||
; WIN64-LABEL: foo1: | ||
; WIN64: .seh_proc foo1 | ||
; WIN64: callq bar | ||
; WIN64: nop | ||
; WIN64: addq ${{[0-9]+}}, %rsp | ||
; WIN64: retq | ||
; Check for 'ud2' after noreturn call | ||
; WIN64: callq _Unwind_Resume | ||
; WIN64-NEXT: ud2 | ||
; WIN64: .seh_endproc | ||
|
||
|
||
; Check it still works when blocks are reordered. | ||
@something = global i32 0 | ||
define void @foo2(i1 zeroext %cond ) { | ||
br i1 %cond, label %a, label %b, !prof !0 | ||
a: | ||
call void @bar() | ||
br label %done | ||
b: | ||
call void @baz() | ||
store i32 0, i32* @something | ||
br label %done | ||
done: | ||
ret void | ||
} | ||
!0 = metadata !{metadata !"branch_weights", i32 100, i32 0} | ||
; WIN64-LABEL: foo2: | ||
; WIN64: callq bar | ||
; WIN64: nop | ||
; WIN64: addq ${{[0-9]+}}, %rsp | ||
; WIN64: retq | ||
|
||
|
||
; Check nop is not emitted when call is not adjacent to epilogue. | ||
define i32 @foo3() { | ||
call void @bar() | ||
ret i32 0 | ||
} | ||
; WIN64-LABEL: foo3: | ||
; WIN64: callq bar | ||
; WIN64: xorl | ||
; WIN64-NOT: nop | ||
; WIN64: addq ${{[0-9]+}}, %rsp | ||
; WIN64: retq |