mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
x86_64: Fix calls to __morestack under the large code model.
Under the large code model, we cannot assume that __morestack lives within 2^31 bytes of the call site, so we cannot use pc-relative addressing. We cannot perform the call via a temporary register, as the rax register may be used to store the static chain, and all other suitable registers may be either callee-save or used for parameter passing. We cannot use the stack at this point either because __morestack manipulates the stack directly. To avoid these issues, perform an indirect call via a read-only memory location containing the address. This solution is not perfect, as it assumes that the .rodata section is laid out within 2^31 bytes of each function body, but this seems to be sufficient for JIT. Differential Revision: http://reviews.llvm.org/D6787 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225003 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dd890d5c5e
commit
d8ae3e1fee
@ -161,6 +161,13 @@ class MachineModuleInfo : public ImmutablePass {
|
|||||||
/// to _fltused on Windows targets.
|
/// to _fltused on Windows targets.
|
||||||
bool UsesVAFloatArgument;
|
bool UsesVAFloatArgument;
|
||||||
|
|
||||||
|
/// UsesMorestackAddr - True if the module calls the __morestack function
|
||||||
|
/// indirectly, as is required under the large code model on x86. This is used
|
||||||
|
/// to emit a definition of a symbol, __morestack_addr, containing the
|
||||||
|
/// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more
|
||||||
|
/// details.
|
||||||
|
bool UsesMorestackAddr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
@ -234,6 +241,14 @@ public:
|
|||||||
UsesVAFloatArgument = b;
|
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
|
/// \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
|
/// function's prologue. Used to construct frame maps for debug and exception
|
||||||
/// handling comsumers.
|
/// handling comsumers.
|
||||||
|
@ -1011,6 +1011,23 @@ bool AsmPrinter::doFinalization(Module &M) {
|
|||||||
// Emit llvm.ident metadata in an '.ident' directive.
|
// Emit llvm.ident metadata in an '.ident' directive.
|
||||||
EmitModuleIdents(M);
|
EmitModuleIdents(M);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
// If we don't have any trampolines, then we don't require stack memory
|
// If we don't have any trampolines, then we don't require stack memory
|
||||||
// to be executable. Some targets have a directive to declare this.
|
// to be executable. Some targets have a directive to declare this.
|
||||||
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
|
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
|
||||||
|
@ -273,7 +273,7 @@ bool MachineModuleInfo::doInitialization(Module &M) {
|
|||||||
CurCallSite = 0;
|
CurCallSite = 0;
|
||||||
CallsEHReturn = 0;
|
CallsEHReturn = 0;
|
||||||
CallsUnwindInit = 0;
|
CallsUnwindInit = 0;
|
||||||
DbgInfoAvailable = UsesVAFloatArgument = false;
|
DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false;
|
||||||
// Always emit some info, by default "no personality" info.
|
// Always emit some info, by default "no personality" info.
|
||||||
Personalities.push_back(nullptr);
|
Personalities.push_back(nullptr);
|
||||||
AddrLabelSymbols = nullptr;
|
AddrLabelSymbols = nullptr;
|
||||||
|
@ -1648,12 +1648,36 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// __morestack is in libgcc
|
// __morestack is in libgcc
|
||||||
if (Is64Bit)
|
if (Is64Bit && MF.getTarget().getCodeModel() == CodeModel::Large) {
|
||||||
BuildMI(allocMBB, DL, TII.get(X86::CALL64pcrel32))
|
// Under the large code model, we cannot assume that __morestack lives
|
||||||
.addExternalSymbol("__morestack");
|
// within 2^31 bytes of the call site, so we cannot use pc-relative
|
||||||
else
|
// addressing. We cannot perform the call via a temporary register,
|
||||||
BuildMI(allocMBB, DL, TII.get(X86::CALLpcrel32))
|
// as the rax register may be used to store the static chain, and all
|
||||||
.addExternalSymbol("__morestack");
|
// other suitable registers may be either callee-save or used for
|
||||||
|
// parameter passing. We cannot use the stack at this point either
|
||||||
|
// because __morestack manipulates the stack directly.
|
||||||
|
//
|
||||||
|
// To avoid these issues, perform an indirect call via a read-only memory
|
||||||
|
// location containing the address.
|
||||||
|
//
|
||||||
|
// This solution is not perfect, as it assumes that the .rodata section
|
||||||
|
// is laid out within 2^31 bytes of each function body, but this seems
|
||||||
|
// to be sufficient for JIT.
|
||||||
|
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)
|
if (IsNested)
|
||||||
BuildMI(allocMBB, DL, TII.get(X86::MORESTACK_RET_RESTORE_R10));
|
BuildMI(allocMBB, DL, TII.get(X86::MORESTACK_RET_RESTORE_R10));
|
||||||
|
@ -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=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 -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=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=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
|
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin
|
||||||
@ -57,6 +58,16 @@ define void @test_basic() #0 {
|
|||||||
; X64-Linux-NEXT: callq __morestack
|
; X64-Linux-NEXT: callq __morestack
|
||||||
; X64-Linux-NEXT: ret
|
; 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-LABEL: test_basic:
|
||||||
|
|
||||||
; X32ABI: cmpl %fs:64, %esp
|
; X32ABI: cmpl %fs:64, %esp
|
||||||
@ -626,3 +637,7 @@ define void @test_nostack() #0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attributes #0 = { "split-stack" }
|
attributes #0 = { "split-stack" }
|
||||||
|
|
||||||
|
; X64-Linux-Large: .rodata
|
||||||
|
; X64-Linux-Large-NEXT: __morestack_addr:
|
||||||
|
; X64-Linux-Large-NEXT: .quad __morestack
|
||||||
|
Loading…
Reference in New Issue
Block a user