Index: lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- lib/Target/ARM/ARMFrameLowering.cpp +++ lib/Target/ARM/ARMFrameLowering.cpp @@ -2157,9 +2157,15 @@ // Do not generate a prologue for leaf functions with a stack of size zero. // For non-leaf functions we have to allow for the possibility that the - // call is to a non-split function, as in PR37807. - if (StackSize == 0 && !MFI.hasTailCall()) + // callis to a non-split function, as in PR37807. This function could also + // take the address of a non-split function. When the linker tries to adjust + // its non-existent prologue, it would fail with an error. Mark the object + // file so that such failures are not errors. See this Go language bug-report + // https://go-review.googlesource.com/c/go/+/148819/ + if (StackSize == 0 && !MFI.hasTailCall()) { + MF.getMMI().setHasNosplitStack(true); return; + } // Use R4 and R5 as scratch registers. // We save R4 and R5 before use and restore them before leaving the function. Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -2270,9 +2270,15 @@ // Do not generate a prologue for leaf functions with a stack of size zero. // For non-leaf functions we have to allow for the possibility that the - // call is to a non-split function, as in PR37807. - if (StackSize == 0 && !MFI.hasTailCall()) + // callis to a non-split function, as in PR37807. This function could also + // take the address of a non-split function. When the linker tries to adjust + // its non-existent prologue, it would fail with an error. Mark the object + // file so that such failures are not errors. See this Go language bug-report + // https://go-review.googlesource.com/c/go/+/148819/ + if (StackSize == 0 && !MFI.hasTailCall()) { + MF.getMMI().setHasNosplitStack(true); return; + } MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock(); MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock(); Index: test/CodeGen/X86/segmented-stacks-standalone.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/segmented-stacks-standalone.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -verify-machineinstrs | FileCheck %s -check-prefix=X32-Linux +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s -check-prefix=X64-Linux + +; This test is standalone because segmented-stacks.ll generates +; object-files with both .note.GNU-split-stack (for the split-stack +; functions) and .note.GNU-no-split-stack sections (for the +; non-split-stack functions). But a split-stack function without a +; stack frame should have a .note.GNU-split-stack section regardless +; of any other contents of the compilation unit. + +define void @test_nostack() #0 { + ret void +} + +attributes #0 = { "split-stack" } + +; X32-Linux: .section ".note.GNU-split-stack","",@progbits +; X32-Linux: .section ".note.GNU-no-split-stack","",@progbits + +; X64-Linux: .section ".note.GNU-split-stack","",@progbits +; X64-Linux: .section ".note.GNU-no-split-stack","",@progbits + +; X64-FreeBSD: .section ".note.GNU-split-stack","",@progbits +; X64-FreeBSD: .section ".note.GNU-no-split-stack","",@progbits + +; X32-DFlyBSD: .section ".note.GNU-split-stack","",@progbits +; X32-DFlyBSD: .section ".note.GNU-no-split-stack","",@progbits + +; X64-DFlyBSD: .section ".note.GNU-split-stack","",@progbits +; X64-DFlyBSD: .section ".note.GNU-no-split-stack","",@progbits