Support segmented stacks on Win64
authorReid Kleckner <reid@kleckner.net>
Tue, 1 Apr 2014 18:34:21 +0000 (18:34 +0000)
committerReid Kleckner <reid@kleckner.net>
Tue, 1 Apr 2014 18:34:21 +0000 (18:34 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205342 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FrameLowering.cpp
test/CodeGen/X86/segmented-stacks.ll

index 5054d293cf093566143bd293bfdd35fcc869e2c0..f0ad4d12d00d5e6b7fd67ac39e3aff79f3e25ad8 100644 (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()) {
index 08a98ef51ec4ffca57cf641d71e0f5cb7715c59c..c02152bb6383682015f380a61c0e62efc7082663 100644 (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
 ; 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