Index: include/llvm/CodeGen/MachineModuleInfo.h =================================================================== --- include/llvm/CodeGen/MachineModuleInfo.h +++ include/llvm/CodeGen/MachineModuleInfo.h @@ -161,6 +161,8 @@ /// to _fltused on Windows targets. bool UsesVAFloatArgument; + bool UsesMorestackAddr; + public: static char ID; // Pass identification, replacement for typeid @@ -234,6 +236,14 @@ UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -995,6 +995,23 @@ if (const MCSection *S = MAI->getNonexecutableStackSection(OutContext)) OutStreamer.SwitchSection(S); + // Emit __morestack address if needed for indirect calls. + if (MMI->usesMorestackAddr()) { + const MCSection *ReadOnlySection = + getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(), + /*C=*/nullptr); + OutStreamer.SwitchSection(ReadOnlySection); + + MCSymbol *AddrSymbol = + OutContext.GetOrCreateSymbol(StringRef("__morestack_addr")); + OutStreamer.EmitLabel(AddrSymbol); + + const DataLayout &DL = *TM.getSubtargetImpl()->getDataLayout(); + unsigned PtrSize = DL.getPointerSize(0); + OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("__morestack"), + PtrSize); + } + // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. EmitEndOfAsmFile(M); Index: lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- lib/CodeGen/MachineModuleInfo.cpp +++ lib/CodeGen/MachineModuleInfo.cpp @@ -273,7 +273,7 @@ CurCallSite = 0; CallsEHReturn = 0; CallsUnwindInit = 0; - DbgInfoAvailable = UsesVAFloatArgument = false; + DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; // Always emit some info, by default "no personality" info. Personalities.push_back(nullptr); AddrLabelSymbols = nullptr; Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -1640,12 +1640,23 @@ } // __morestack is in libgcc - if (Is64Bit) - BuildMI(allocMBB, DL, TII.get(X86::CALL64pcrel32)) - .addExternalSymbol("__morestack"); - else - BuildMI(allocMBB, DL, TII.get(X86::CALLpcrel32)) - .addExternalSymbol("__morestack"); + if (Is64Bit && MF.getTarget().getCodeModel() == CodeModel::Large) { + // Avoid PC-relative call. + BuildMI(allocMBB, DL, TII.get(X86::CALL64m)) + .addReg(X86::RIP) + .addImm(0) + .addReg(0) + .addExternalSymbol("__morestack_addr") + .addReg(0); + MF.getMMI().setUsesMorestackAddr(true); + } else { + if (Is64Bit) + BuildMI(allocMBB, DL, TII.get(X86::CALL64pcrel32)) + .addExternalSymbol("__morestack"); + else + BuildMI(allocMBB, DL, TII.get(X86::CALLpcrel32)) + .addExternalSymbol("__morestack"); + } if (IsNested) BuildMI(allocMBB, DL, TII.get(X86::MORESTACK_RET_RESTORE_R10)); Index: test/CodeGen/X86/segmented-stacks.ll =================================================================== --- test/CodeGen/X86/segmented-stacks.ll +++ test/CodeGen/X86/segmented-stacks.ll @@ -1,5 +1,6 @@ ; 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 +; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -code-model=large -verify-machineinstrs | FileCheck %s -check-prefix=X64-Linux-Large ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnux32 -verify-machineinstrs | FileCheck %s -check-prefix=X32ABI ; RUN: llc < %s -mcpu=generic -mtriple=i686-darwin -verify-machineinstrs | FileCheck %s -check-prefix=X32-Darwin ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin @@ -53,6 +54,16 @@ ; X64-Linux-NEXT: callq __morestack ; X64-Linux-NEXT: ret +; X64-Linux-Large-LABEL: test_basic: + +; X64-Linux-Large: cmpq %fs:112, %rsp +; X64-Linux-Large-NEXT: ja .LBB0_2 + +; X64-Linux-Large: movabsq $40, %r10 +; X64-Linux-Large-NEXT: movabsq $0, %r11 +; X64-Linux-Large-NEXT: callq *__morestack_addr(%rip) +; X64-Linux-Large-NEXT: ret + ; X32ABI-LABEL: test_basic: ; X32ABI: cmpl %fs:64, %esp @@ -518,3 +529,7 @@ } attributes #0 = { "split-stack" } + +; X64-Linux-Large: .rodata +; X64-Linux-Large-NEXT: __morestack_addr: +; X64-Linux-Large-NEXT: .quad __morestack