From e4d18de5d15c6c1d4d279788b35d0cd1ab237e82 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 12 Jan 2012 20:22:08 +0000 Subject: [PATCH] Support segmented stacks on win32. Uses the pvArbitrary slot of the TIB, which is reserved for applications. We only support frames with a static size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148040 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FrameLowering.cpp | 24 ++++++++++++----- test/CodeGen/X86/segmented-stacks.ll | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index c2f2c1ffef4..639f5c20559 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -1357,8 +1357,8 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { if (MF.getFunction()->isVarArg()) report_fatal_error("Segmented stacks do not support vararg functions."); - if (!ST->isTargetLinux() && !ST->isTargetDarwin()) - report_fatal_error("Segmented stacks supported only on linux and darwin."); + if (!ST->isTargetLinux() && !ST->isTargetDarwin() && !ST->isTargetWin32()) + report_fatal_error("Segmented stacks supported only on linux, darwin and win32."); MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock(); MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock(); @@ -1401,6 +1401,8 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { } else if (ST->isTargetDarwin()) { TlsReg = X86::GS; TlsOffset = 0x60 + 90*8; // See pthread_machdep.h. Steal TLS slot 90. + } else { + report_fatal_error("Segmented stacks not supported on this platform."); } if (CompareStackPointer) @@ -1412,7 +1414,18 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { BuildMI(checkMBB, DL, TII.get(X86::CMP64rm)).addReg(ScratchReg) .addReg(0).addImm(1).addReg(0).addImm(TlsOffset).addReg(TlsReg); } else { - TlsReg = X86::GS; + if (ST->isTargetLinux()) { + TlsReg = X86::GS; + TlsOffset = 0x30; + } else if (ST->isTargetDarwin()) { + TlsReg = X86::GS; + TlsOffset = 0x48 + 90*4; + } else if (ST->isTargetWin32()) { + TlsReg = X86::FS; + TlsOffset = 0x14; // pvArbitrary, reserved for application use + } else { + report_fatal_error("Segmented stacks not supported on this platform."); + } if (CompareStackPointer) ScratchReg = X86::ESP; @@ -1420,13 +1433,10 @@ 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 (ST->isTargetLinux()) { - TlsOffset = 0x30; - + if (ST->isTargetLinux() || ST->isTargetWin32()) { BuildMI(checkMBB, DL, TII.get(X86::CMP32rm)).addReg(ScratchReg) .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg); } else if (ST->isTargetDarwin()) { - TlsOffset = 0x48 + 90*4; // TlsOffset doesn't fit into a mod r/m byte so we need an extra register unsigned ScratchReg2; diff --git a/test/CodeGen/X86/segmented-stacks.ll b/test/CodeGen/X86/segmented-stacks.ll index 6e91d00ac6d..4c4c542785e 100644 --- a/test/CodeGen/X86/segmented-stacks.ll +++ b/test/CodeGen/X86/segmented-stacks.ll @@ -2,12 +2,14 @@ ; RUN: llc < %s -mtriple=x86_64-linux -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-Linux ; RUN: llc < %s -mtriple=i686-darwin -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-Darwin ; RUN: llc < %s -mtriple=x86_64-darwin -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin +; RUN: llc < %s -mtriple=i686-mingw32 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-MinGW ; We used to crash with filetype=obj ; RUN: llc < %s -mtriple=i686-linux -segmented-stacks -filetype=obj ; RUN: llc < %s -mtriple=x86_64-linux -segmented-stacks -filetype=obj ; RUN: llc < %s -mtriple=i686-darwin -segmented-stacks -filetype=obj ; RUN: llc < %s -mtriple=x86_64-darwin -segmented-stacks -filetype=obj +; RUN: llc < %s -mtriple=i686-mingw32 -segmented-stacks -filetype=obj ; Just to prevent the alloca from being optimized away declare void @dummy_use(i32*, i32) @@ -58,6 +60,16 @@ define void @test_basic() { ; X64-Darwin-NEXT: callq ___morestack ; X64-Darwin-NEXT: ret +; X32-MinGW: test_basic: + +; X32-MinGW: cmpl %fs:20, %esp +; X32-MinGW-NEXT: ja LBB0_2 + +; X32-MinGW: pushl $0 +; X32-MinGW-NEXT: pushl $48 +; X32-MinGW-NEXT: calll ___morestack +; X32-MinGW-NEXT: ret + } define i32 @test_nested(i32 * nest %closure, i32 %other) { @@ -102,6 +114,14 @@ define i32 @test_nested(i32 * nest %closure, i32 %other) { ; X64-Darwin-NEXT: ret ; X64-Darwin-NEXT: movq %rax, %r10 +; X32-MinGW: cmpl %fs:20, %esp +; X32-MinGW-NEXT: ja LBB1_2 + +; X32-MinGW: pushl $4 +; X32-MinGW-NEXT: pushl $0 +; X32-MinGW-NEXT: calll ___morestack +; X32-MinGW-NEXT: ret + } define void @test_large() { @@ -146,6 +166,15 @@ define void @test_large() { ; X64-Darwin-NEXT: callq ___morestack ; X64-Darwin-NEXT: ret +; X32-MinGW: leal -40008(%esp), %ecx +; X32-MinGW-NEXT: cmpl %fs:20, %ecx +; X32-MinGW-NEXT: ja LBB2_2 + +; X32-MinGW: pushl $0 +; X32-MinGW-NEXT: pushl $40008 +; X32-MinGW-NEXT: calll ___morestack +; X32-MinGW-NEXT: ret + } define fastcc void @test_fastcc() { @@ -194,6 +223,16 @@ define fastcc void @test_fastcc() { ; X64-Darwin-NEXT: callq ___morestack ; X64-Darwin-NEXT: ret +; X32-MinGW: test_fastcc: + +; X32-MinGW: cmpl %fs:20, %esp +; X32-MinGW-NEXT: ja LBB3_2 + +; X32-MinGW: pushl $0 +; X32-MinGW-NEXT: pushl $48 +; X32-MinGW-NEXT: calll ___morestack +; X32-MinGW-NEXT: ret + } define fastcc void @test_fastcc_large() { @@ -246,6 +285,17 @@ define fastcc void @test_fastcc_large() { ; X64-Darwin-NEXT: callq ___morestack ; X64-Darwin-NEXT: ret +; X32-MinGW: test_fastcc_large: + +; X32-MinGW: leal -40008(%esp), %eax +; X32-MinGW-NEXT: cmpl %fs:20, %eax +; X32-MinGW-NEXT: ja LBB4_2 + +; X32-MinGW: pushl $0 +; X32-MinGW-NEXT: pushl $40008 +; X32-MinGW-NEXT: calll ___morestack +; X32-MinGW-NEXT: ret + } define fastcc void @test_fastcc_large_with_ecx_arg(i32 %a) { -- 2.11.0