[llvm-commits] [dragonegg] r92690 - /dragonegg/trunk/llvm-convert.cpp
Duncan Sands
baldrick at free.fr
Mon Jan 4 22:13:37 PST 2010
Author: baldrick
Date: Tue Jan 5 00:13:37 2010
New Revision: 92690
URL: http://llvm.org/viewvc/llvm-project?rev=92690&view=rev
Log:
Port commit 90914 (stuart) from llvm-gcc:
If a callee returns a structure in registers, but the stored image of
those registers is bigger than the destination, store the registers
into a temporary, and copy the desired (smaller) part to the
destination. <rdar://problem/7437022>
The original testcase returned an array of three 32-bit floats,
wrapped in a struct; the value was returned as two doubles in xmm0/1,
and stored as a 128-bit value.
Modified:
dragonegg/trunk/llvm-convert.cpp
Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=92690&r1=92689&r2=92690&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Tue Jan 5 00:13:37 2010
@@ -3070,9 +3070,27 @@
return 0;
if (Client.isAggrReturn()) {
- Value *Dest = Builder.CreateBitCast(DestLoc->Ptr,
- PointerType::getUnqual(Call->getType()));
- LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,Dest,DestLoc->Volatile,Builder);
+ if (TD.getTypeAllocSize(Call->getType()) <= TD.getTypeAllocSize(DestLoc->Ptr->getType())) {
+ Value *Dest = Builder.CreateBitCast(DestLoc->Ptr,
+ Call->getType()->getPointerTo());
+ LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,Dest,DestLoc->Volatile,Builder);
+ } else {
+ // The call will return an aggregate value in registers, but
+ // those registers are bigger than DestLoc. Allocate a
+ // temporary to match the registers, store the registers there,
+ // cast the temporary into the correct (smaller) type, and using
+ // the correct type, copy the value into DestLoc. Assume the
+ // optimizer will delete the temporary and clean this up.
+ AllocaInst *biggerTmp = CreateTemporary(Call->getType());
+ LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,biggerTmp,/*Volatile=*/false,
+ Builder);
+ EmitAggregateCopy(*DestLoc,
+ MemRef(Builder.CreateBitCast(biggerTmp,Call->getType()->
+ getPointerTo()),
+ DestLoc->getAlignment(),
+ DestLoc->Volatile),
+ gimple_call_return_type(stmt));
+ }
return 0;
}
More information about the llvm-commits
mailing list