mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-16 11:05:54 +00:00
Make Win32 put the SRet address into EAX, fixes PR15556
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178291 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
af0d148b20
commit
a46f82dbf9
@ -816,14 +816,16 @@ bool X86FastISel::X86SelectRet(const Instruction *I) {
|
||||
// The x86-64 ABI for returning structs by value requires that we copy
|
||||
// the sret argument into %rax for the return. We saved the argument into
|
||||
// a virtual register in the entry block, so now we copy the value out
|
||||
// and into %rax.
|
||||
if (Subtarget->is64Bit() && F.hasStructRetAttr()) {
|
||||
// and into %rax. We also do the same with %eax for Win32.
|
||||
if (F.hasStructRetAttr() &&
|
||||
(Subtarget->is64Bit() || Subtarget->isTargetWindows())) {
|
||||
unsigned Reg = X86MFInfo->getSRetReturnReg();
|
||||
assert(Reg &&
|
||||
"SRetReturnReg should have been set in LowerFormalArguments()!");
|
||||
unsigned RetReg = Subtarget->is64Bit() ? X86::RAX : X86::EAX;
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY),
|
||||
X86::RAX).addReg(Reg);
|
||||
RetRegs.push_back(X86::RAX);
|
||||
RetReg).addReg(Reg);
|
||||
RetRegs.push_back(RetReg);
|
||||
}
|
||||
|
||||
// Now emit the RET.
|
||||
|
@ -1666,10 +1666,11 @@ X86TargetLowering::LowerReturn(SDValue Chain,
|
||||
|
||||
// The x86-64 ABIs require that for returning structs by value we copy
|
||||
// the sret argument into %rax/%eax (depending on ABI) for the return.
|
||||
// Win32 requires us to put the sret argument to %eax as well.
|
||||
// We saved the argument into a virtual register in the entry block,
|
||||
// so now we copy the value out and into %rax/%eax.
|
||||
if (Subtarget->is64Bit() &&
|
||||
DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
|
||||
if (DAG.getMachineFunction().getFunction()->hasStructRetAttr() &&
|
||||
(Subtarget->is64Bit() || Subtarget->isTargetWindows())) {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
|
||||
unsigned Reg = FuncInfo->getSRetReturnReg();
|
||||
@ -1677,12 +1678,14 @@ X86TargetLowering::LowerReturn(SDValue Chain,
|
||||
"SRetReturnReg should have been set in LowerFormalArguments().");
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy());
|
||||
|
||||
unsigned RetValReg = Subtarget->isTarget64BitILP32() ? X86::EAX : X86::RAX;
|
||||
unsigned RetValReg
|
||||
= (Subtarget->is64Bit() && !Subtarget->isTarget64BitILP32()) ?
|
||||
X86::RAX : X86::EAX;
|
||||
Chain = DAG.getCopyToReg(Chain, dl, RetValReg, Val, Flag);
|
||||
Flag = Chain.getValue(1);
|
||||
|
||||
// RAX/EAX now acts like a return value.
|
||||
RetOps.push_back(DAG.getRegister(RetValReg, MVT::i64));
|
||||
RetOps.push_back(DAG.getRegister(RetValReg, getPointerTy()));
|
||||
}
|
||||
|
||||
RetOps[0] = Chain; // Update chain.
|
||||
@ -2036,9 +2039,11 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
|
||||
// The x86-64 ABIs require that for returning structs by value we copy
|
||||
// the sret argument into %rax/%eax (depending on ABI) for the return.
|
||||
// Win32 requires us to put the sret argument to %eax as well.
|
||||
// Save the argument into a virtual register so that we can access it
|
||||
// from the return points.
|
||||
if (Is64Bit && MF.getFunction()->hasStructRetAttr()) {
|
||||
if (MF.getFunction()->hasStructRetAttr() &&
|
||||
(Subtarget->is64Bit() || Subtarget->isTargetWindows())) {
|
||||
X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
|
||||
unsigned Reg = FuncInfo->getSRetReturnReg();
|
||||
if (!Reg) {
|
||||
|
@ -1,28 +1,84 @@
|
||||
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN_X32
|
||||
; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X32
|
||||
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32
|
||||
; RUN: llc < %s -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86
|
||||
; RUN: llc < %s -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
|
||||
; RUN: llc < %s -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN_X32
|
||||
; RUN: llc < %s -O0 -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X32
|
||||
; RUN: llc < %s -O0 -mtriple=i686-pc-win32 | FileCheck %s -check-prefix=WIN32
|
||||
; RUN: llc < %s -O0 -mtriple=i686-pc-mingw32 | FileCheck %s -check-prefix=MINGW_X86
|
||||
; RUN: llc < %s -O0 -mtriple=i386-pc-linux | FileCheck %s -check-prefix=LINUX
|
||||
|
||||
; The SysV ABI used by most Unixes and Mingw on x86 specifies that an sret pointer
|
||||
; is callee-cleanup. However, in MSVC's cdecl calling convention, sret pointer
|
||||
; arguments are caller-cleanup like normal arguments.
|
||||
|
||||
define void @sret1(i8* sret) nounwind {
|
||||
define void @sret1(i8* sret %x) nounwind {
|
||||
entry:
|
||||
; WIN_X32: {{ret$}}
|
||||
; MINGW_X32: ret $4
|
||||
; WIN32: sret1
|
||||
; WIN32: movb $42, (%eax)
|
||||
; WIN32-NOT: popl %eax
|
||||
; WIN32: {{ret$}}
|
||||
|
||||
; MINGW_X86: sret1
|
||||
; MINGW_X86: ret $4
|
||||
|
||||
; LINUX: sret1
|
||||
; LINUX: ret $4
|
||||
|
||||
store i8 42, i8* %x, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sret2(i32* sret %x, i32 %y) nounwind {
|
||||
define void @sret2(i8* sret %x, i8 %y) nounwind {
|
||||
entry:
|
||||
; WIN_X32: {{ret$}}
|
||||
; MINGW_X32: ret $4
|
||||
; WIN32: sret2
|
||||
; WIN32: movb {{.*}}, (%eax)
|
||||
; WIN32-NOT: popl %eax
|
||||
; WIN32: {{ret$}}
|
||||
|
||||
; MINGW_X86: sret2
|
||||
; MINGW_X86: ret $4
|
||||
|
||||
; LINUX: sret2
|
||||
; LINUX: ret $4
|
||||
store i32 %y, i32* %x
|
||||
|
||||
store i8 %y, i8* %x
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sret3(i8* sret %x, i8* %y) nounwind {
|
||||
entry:
|
||||
; WIN32: sret3
|
||||
; WIN32: movb $42, (%eax)
|
||||
; WIN32-NOT: movb $13, (%eax)
|
||||
; WIN32-NOT: popl %eax
|
||||
; WIN32: {{ret$}}
|
||||
|
||||
; MINGW_X86: sret3
|
||||
; MINGW_X86: ret $4
|
||||
|
||||
; LINUX: sret3
|
||||
; LINUX: ret $4
|
||||
|
||||
store i8 42, i8* %x
|
||||
store i8 13, i8* %y
|
||||
ret void
|
||||
}
|
||||
|
||||
; PR15556
|
||||
%struct.S4 = type { i32, i32, i32 }
|
||||
|
||||
define void @sret4(%struct.S4* noalias sret %agg.result) {
|
||||
entry:
|
||||
; WIN32: sret4
|
||||
; WIN32: movl $42, (%eax)
|
||||
; WIN32-NOT: popl %eax
|
||||
; WIN32: {{ret$}}
|
||||
|
||||
; MINGW_X86: sret4
|
||||
; MINGW_X86: ret $4
|
||||
|
||||
; LINUX: sret4
|
||||
; LINUX: ret $4
|
||||
|
||||
%x = getelementptr inbounds %struct.S4* %agg.result, i32 0, i32 0
|
||||
store i32 42, i32* %x, align 4
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user