diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 639f5c20559..e5f67526143 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -1357,8 +1357,9 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { if (MF.getFunction()->isVarArg()) report_fatal_error("Segmented stacks do not support vararg functions."); - if (!ST->isTargetLinux() && !ST->isTargetDarwin() && !ST->isTargetWin32()) - report_fatal_error("Segmented stacks supported only on linux, darwin and win32."); + if (!ST->isTargetLinux() && !ST->isTargetDarwin() && + !ST->isTargetWin32() && !ST->isTargetFreeBSD()) + report_fatal_error("Segmented stacks not supported on this platform."); MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock(); MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock(); @@ -1401,6 +1402,9 @@ 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 if (ST->isTargetFreeBSD()) { + TlsReg = X86::FS; + TlsOffset = 0x18; } else { report_fatal_error("Segmented stacks not supported on this platform."); } @@ -1423,6 +1427,8 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const { } else if (ST->isTargetWin32()) { TlsReg = X86::FS; TlsOffset = 0x14; // pvArbitrary, reserved for application use + } else if (ST->isTargetFreeBSD()) { + report_fatal_error("Segmented stacks not supported on FreeBSD i386."); } else { report_fatal_error("Segmented stacks not supported on this platform."); } diff --git a/test/CodeGen/X86/segmented-stacks.ll b/test/CodeGen/X86/segmented-stacks.ll index 4c4c542785e..3650304a088 100644 --- a/test/CodeGen/X86/segmented-stacks.ll +++ b/test/CodeGen/X86/segmented-stacks.ll @@ -3,6 +3,7 @@ ; 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 +; RUN: llc < %s -mtriple=x86_64-freebsd -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-FreeBSD ; We used to crash with filetype=obj ; RUN: llc < %s -mtriple=i686-linux -segmented-stacks -filetype=obj @@ -10,6 +11,7 @@ ; 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 +; RUN: llc < %s -mtriple=x86_64-freebsd -segmented-stacks -filetype=obj ; Just to prevent the alloca from being optimized away declare void @dummy_use(i32*, i32) @@ -70,6 +72,16 @@ define void @test_basic() { ; X32-MinGW-NEXT: calll ___morestack ; X32-MinGW-NEXT: ret +; X64-FreeBSD: test_basic: + +; X64-FreeBSD: cmpq %fs:24, %rsp +; X64-FreeBSD-NEXT: ja .LBB0_2 + +; X64-FreeBSD: movabsq $40, %r10 +; X64-FreeBSD-NEXT: movabsq $0, %r11 +; X64-FreeBSD-NEXT: callq __morestack +; X64-FreeBSD-NEXT: ret + } define i32 @test_nested(i32 * nest %closure, i32 %other) { @@ -122,6 +134,16 @@ define i32 @test_nested(i32 * nest %closure, i32 %other) { ; X32-MinGW-NEXT: calll ___morestack ; X32-MinGW-NEXT: ret +; X64-FreeBSD: cmpq %fs:24, %rsp +; X64-FreeBSD-NEXT: ja .LBB1_2 + +; X64-FreeBSD: movq %r10, %rax +; X64-FreeBSD-NEXT: movabsq $0, %r10 +; X64-FreeBSD-NEXT: movabsq $0, %r11 +; X64-FreeBSD-NEXT: callq __morestack +; X64-FreeBSD-NEXT: ret +; X64-FreeBSD-NEXT: movq %rax, %r10 + } define void @test_large() { @@ -175,6 +197,15 @@ define void @test_large() { ; X32-MinGW-NEXT: calll ___morestack ; X32-MinGW-NEXT: ret +; X64-FreeBSD: leaq -40008(%rsp), %r11 +; X64-FreeBSD-NEXT: cmpq %fs:24, %r11 +; X64-FreeBSD-NEXT: ja .LBB2_2 + +; X64-FreeBSD: movabsq $40008, %r10 +; X64-FreeBSD-NEXT: movabsq $0, %r11 +; X64-FreeBSD-NEXT: callq __morestack +; X64-FreeBSD-NEXT: ret + } define fastcc void @test_fastcc() { @@ -233,6 +264,16 @@ define fastcc void @test_fastcc() { ; X32-MinGW-NEXT: calll ___morestack ; X32-MinGW-NEXT: ret +; X64-FreeBSD: test_fastcc: + +; X64-FreeBSD: cmpq %fs:24, %rsp +; X64-FreeBSD-NEXT: ja .LBB3_2 + +; X64-FreeBSD: movabsq $40, %r10 +; X64-FreeBSD-NEXT: movabsq $0, %r11 +; X64-FreeBSD-NEXT: callq __morestack +; X64-FreeBSD-NEXT: ret + } define fastcc void @test_fastcc_large() { @@ -296,6 +337,17 @@ define fastcc void @test_fastcc_large() { ; X32-MinGW-NEXT: calll ___morestack ; X32-MinGW-NEXT: ret +; X64-FreeBSD: test_fastcc_large: + +; X64-FreeBSD: leaq -40008(%rsp), %r11 +; X64-FreeBSD-NEXT: cmpq %fs:24, %r11 +; X64-FreeBSD-NEXT: ja .LBB4_2 + +; X64-FreeBSD: movabsq $40008, %r10 +; X64-FreeBSD-NEXT: movabsq $0, %r11 +; X64-FreeBSD-NEXT: callq __morestack +; X64-FreeBSD-NEXT: ret + } define fastcc void @test_fastcc_large_with_ecx_arg(i32 %a) {