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.
|
||||
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:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
@ -234,6 +241,14 @@ public:
|
||||
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.
|
||||
|
@ -1011,6 +1011,23 @@ bool AsmPrinter::doFinalization(Module &M) {
|
||||
// Emit llvm.ident metadata in an '.ident' directive.
|
||||
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
|
||||
// to be executable. Some targets have a directive to declare this.
|
||||
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
|
||||
|
@ -273,7 +273,7 @@ bool MachineModuleInfo::doInitialization(Module &M) {
|
||||
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;
|
||||
|
@ -1648,12 +1648,36 @@ X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
|
||||
}
|
||||
|
||||
// __morestack is in libgcc
|
||||
if (Is64Bit && MF.getTarget().getCodeModel() == CodeModel::Large) {
|
||||
// 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.
|
||||
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));
|
||||
|
@ -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
|
||||
@ -57,6 +58,16 @@ define void @test_basic() #0 {
|
||||
; 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
|
||||
@ -626,3 +637,7 @@ define void @test_nostack() #0 {
|
||||
}
|
||||
|
||||
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