Support segmented stacks on Win64

Identical to Win32 method except the GS segment register is used for TLS
instead of FS and pvArbitrary is at TEB offset 0x28 instead of 0x14.

llvm-svn: 205342
This commit is contained in:
Reid Kleckner 2014-04-01 18:34:21 +00:00
parent 553751b9bc
commit 101102711d
2 changed files with 59 additions and 5 deletions

View File

@ -1167,7 +1167,7 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
if (MF.getFunction()->isVarArg())
report_fatal_error("Segmented stacks do not support vararg functions.");
if (!STI.isTargetLinux() && !STI.isTargetDarwin() &&
!STI.isTargetWin32() && !STI.isTargetFreeBSD())
!STI.isTargetWin32() && !STI.isTargetWin64() && !STI.isTargetFreeBSD())
report_fatal_error("Segmented stacks not supported on this platform.");
MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock();
@ -1211,6 +1211,9 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
} else if (STI.isTargetDarwin()) {
TlsReg = X86::GS;
TlsOffset = 0x60 + 90*8; // See pthread_machdep.h. Steal TLS slot 90.
} else if (STI.isTargetWin64()) {
TlsReg = X86::GS;
TlsOffset = 0x28; // pvArbitrary, reserved for application use
} else if (STI.isTargetFreeBSD()) {
TlsReg = X86::FS;
TlsOffset = 0x18;
@ -1248,7 +1251,7 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
BuildMI(checkMBB, DL, TII.get(X86::LEA32r), ScratchReg).addReg(X86::ESP)
.addImm(1).addReg(0).addImm(-StackSize).addReg(0);
if (STI.isTargetLinux() || STI.isTargetWin32()) {
if (STI.isTargetLinux() || STI.isTargetWin32() || STI.isTargetWin64()) {
BuildMI(checkMBB, DL, TII.get(X86::CMP32rm)).addReg(ScratchReg)
.addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg);
} else if (STI.isTargetDarwin()) {

View File

@ -4,6 +4,7 @@
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin
; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-MinGW
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-FreeBSD
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-MinGW
; We used to crash with filetype=obj
; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -segmented-stacks -filetype=obj
@ -12,16 +13,14 @@
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -segmented-stacks -filetype=obj
; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -segmented-stacks -filetype=obj
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -segmented-stacks -filetype=obj
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -segmented-stacks -filetype=obj
; RUN: not llc < %s -mcpu=generic -mtriple=x86_64-solaris -segmented-stacks 2> %t.log
; RUN: FileCheck %s -input-file=%t.log -check-prefix=X64-Solaris
; RUN: not llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -segmented-stacks 2> %t.log
; RUN: FileCheck %s -input-file=%t.log -check-prefix=X64-MinGW
; RUN: not llc < %s -mcpu=generic -mtriple=i686-freebsd -segmented-stacks 2> %t.log
; RUN: FileCheck %s -input-file=%t.log -check-prefix=X32-FreeBSD
; X64-Solaris: Segmented stacks not supported on this platform
; X64-MinGW: Segmented stacks not supported on this platform
; X32-FreeBSD: Segmented stacks not supported on FreeBSD i386
; Just to prevent the alloca from being optimized away
@ -83,6 +82,16 @@ define void @test_basic() {
; X32-MinGW-NEXT: calll ___morestack
; X32-MinGW-NEXT: ret
; X64-MinGW-LABEL: test_basic:
; X64-MinGW: cmpq %gs:40, %rsp
; X64-MinGW-NEXT: ja .LBB0_2
; X64-MinGW: movabsq $72, %r10
; X64-MinGW-NEXT: movabsq $32, %r11
; X64-MinGW-NEXT: callq __morestack
; X64-MinGW-NEXT: retq
; X64-FreeBSD-LABEL: test_basic:
; X64-FreeBSD: cmpq %fs:24, %rsp
@ -145,6 +154,17 @@ define i32 @test_nested(i32 * nest %closure, i32 %other) {
; X32-MinGW-NEXT: calll ___morestack
; X32-MinGW-NEXT: ret
; X64-MinGW-LABEL: test_nested:
; X64-MinGW: cmpq %gs:40, %rsp
; X64-MinGW-NEXT: ja .LBB1_2
; X64-MinGW: movq %r10, %rax
; X64-MinGW-NEXT: movabsq $0, %r10
; X64-MinGW-NEXT: movabsq $32, %r11
; X64-MinGW-NEXT: callq __morestack
; X64-MinGW-NEXT: retq
; X64-MinGW-NEXT: movq %rax, %r10
; X64-FreeBSD: cmpq %fs:24, %rsp
; X64-FreeBSD-NEXT: ja .LBB1_2
@ -208,6 +228,16 @@ define void @test_large() {
; X32-MinGW-NEXT: calll ___morestack
; X32-MinGW-NEXT: ret
; X64-MinGW-LABEL: test_large:
; X64-MinGW: leaq -40040(%rsp), %r11
; X64-MinGW-NEXT: cmpq %gs:40, %r11
; X64-MinGW-NEXT: ja .LBB2_2
; X64-MinGW: movabsq $40040, %r10
; X64-MinGW-NEXT: movabsq $32, %r11
; X64-MinGW-NEXT: callq __morestack
; X64-MinGW-NEXT: retq
; X64-FreeBSD: leaq -40008(%rsp), %r11
; X64-FreeBSD-NEXT: cmpq %fs:24, %r11
; X64-FreeBSD-NEXT: ja .LBB2_2
@ -275,6 +305,16 @@ define fastcc void @test_fastcc() {
; X32-MinGW-NEXT: calll ___morestack
; X32-MinGW-NEXT: ret
; X64-MinGW-LABEL: test_fastcc:
; X64-MinGW: cmpq %gs:40, %rsp
; X64-MinGW-NEXT: ja .LBB3_2
; X64-MinGW: movabsq $72, %r10
; X64-MinGW-NEXT: movabsq $32, %r11
; X64-MinGW-NEXT: callq __morestack
; X64-MinGW-NEXT: retq
; X64-FreeBSD-LABEL: test_fastcc:
; X64-FreeBSD: cmpq %fs:24, %rsp
@ -348,6 +388,17 @@ define fastcc void @test_fastcc_large() {
; X32-MinGW-NEXT: calll ___morestack
; X32-MinGW-NEXT: ret
; X64-MinGW-LABEL: test_fastcc_large:
; X64-MinGW: leaq -40040(%rsp), %r11
; X64-MinGW-NEXT: cmpq %gs:40, %r11
; X64-MinGW-NEXT: ja .LBB4_2
; X64-MinGW: movabsq $40040, %r10
; X64-MinGW-NEXT: movabsq $32, %r11
; X64-MinGW-NEXT: callq __morestack
; X64-MinGW-NEXT: retq
; X64-FreeBSD-LABEL: test_fastcc_large:
; X64-FreeBSD: leaq -40008(%rsp), %r11