X86 ABI fix for return values > 24 bytes.

The return value's address must be returned in %rax.
i.e. the callee needs to copy the sret argument (%rdi)
into the return value (%rax).

This probably won't manifest as a bug when the caller is LLVM-compiled
code. But it is an ABI guarantee and tools expect it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228321 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2015-02-05 18:09:05 +00:00
parent 916b91acf1
commit c4ae8cbc5d
3 changed files with 20 additions and 8 deletions

View File

@ -2107,14 +2107,15 @@ X86TargetLowering::LowerReturn(SDValue Chain,
// 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 (DAG.getMachineFunction().getFunction()->hasStructRetAttr() &&
(Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC())) {
MachineFunction &MF = DAG.getMachineFunction();
X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
unsigned Reg = FuncInfo->getSRetReturnReg();
assert(Reg &&
"SRetReturnReg should have been set in LowerFormalArguments().");
SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy());
//
// Checking Function.hasStructRetAttr() here is insufficient because the IR
// may not have an explicit sret argument. If FuncInfo.CanLowerReturn is
// false, then an sret argument may be implicitly inserted in the SelDAG. In
// either case FuncInfo->setSRetReturnReg() will have been called.
if (unsigned SRetReg = FuncInfo->getSRetReturnReg()) {
assert((Subtarget->is64Bit() || Subtarget->isTargetKnownWindowsMSVC()) &&
"No need for an sret register");
SDValue Val = DAG.getCopyFromReg(Chain, dl, SRetReg, getPointerTy());
unsigned RetValReg
= (Subtarget->is64Bit() && !Subtarget->isTarget64BitILP32()) ?

View File

@ -0,0 +1,10 @@
; RUN: llc -mtriple=x86_64-apple-darwin8 < %s | FileCheck %s
; RUN: llc -mtriple=x86_64-pc-linux < %s | FileCheck %s
; CHECK-LABEL: return32
; CHECK-DAG: movq $0, (%rdi)
; CHECK-DAG: movq %rdi, %rax
; CHECK: retq
define i256 @return32() {
ret i256 0
}

View File

@ -275,6 +275,7 @@ define <16 x double> @select_illegal(<16 x double> %a, <16 x double> %b) {
; CHECK-NEXT: movaps %xmm2, 32(%rdi)
; CHECK-NEXT: movaps %xmm1, 16(%rdi)
; CHECK-NEXT: movaps %xmm0, (%rdi)
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: retq
%sel = select <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false, i1 false>, <16 x double> %a, <16 x double> %b
ret <16 x double> %sel