[llvm-commits] [dragonegg] r117649 - in /dragonegg/trunk: llvm-abi-default.cpp llvm-abi.h llvm-convert.cpp

Duncan Sands baldrick at free.fr
Fri Oct 29 07:09:20 PDT 2010


Author: baldrick
Date: Fri Oct 29 09:09:20 2010
New Revision: 117649

URL: http://llvm.org/viewvc/llvm-project?rev=117649&view=rev
Log:
Fix the way complex numbers are returned from functions: before,
it was not being done in an ABI conformant way.  Complex numbers
are treated as scalar types in dragonegg, while llvm-gcc considers
them to be aggregates.  While I correctly modified the llvm-gcc
ABI code so that complex parameters were passed right, I got the
returning of complex numbers from functions wrong.  Fixes PR8472.

Modified:
    dragonegg/trunk/llvm-abi-default.cpp
    dragonegg/trunk/llvm-abi.h
    dragonegg/trunk/llvm-convert.cpp

Modified: dragonegg/trunk/llvm-abi-default.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-abi-default.cpp?rev=117649&r1=117648&r2=117649&view=diff
==============================================================================
--- dragonegg/trunk/llvm-abi-default.cpp (original)
+++ dragonegg/trunk/llvm-abi-default.cpp Fri Oct 29 09:09:20 2010
@@ -34,13 +34,15 @@
 
 /// isSingleElementStructOrArray - If this is (recursively) a structure with one
 /// field or an array with one element, return the field type, otherwise return
-/// null.  If ignoreZeroLength, the struct (recursively) may include zero-length
-/// fields in addition to the single element that has data.  If
-/// rejectFatBitField, and the single element is a bitfield of a type that's
-/// bigger than the struct, return null anyway.
+/// null.  Returns null for complex number types.  If ignoreZeroLength, the
+/// struct (recursively) may include zero-length fields in addition to the
+/// single element that has data.  If rejectFatBitField, and the single element
+/// is a bitfield of a type that's bigger than the struct, return null anyway.
 tree isSingleElementStructOrArray(tree type, bool ignoreZeroLength,
                                   bool rejectFatBitfield) {
-  // Scalars are good.
+  // Complex numbers have two fields.
+  if (TREE_CODE(type) == COMPLEX_TYPE) return 0;
+  // All other scalars are good.
   if (!AGGREGATE_TYPE_P(type)) return type;
 
   tree FoundField = 0;

Modified: dragonegg/trunk/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-abi.h?rev=117649&r1=117648&r2=117649&view=diff
==============================================================================
--- dragonegg/trunk/llvm-abi.h (original)
+++ dragonegg/trunk/llvm-abi.h Fri Oct 29 09:09:20 2010
@@ -136,10 +136,10 @@
 
 /// isSingleElementStructOrArray - If this is (recursively) a structure with one
 /// field or an array with one element, return the field type, otherwise return
-/// null.  If ignoreZeroLength, the struct (recursively) may include zero-length
-/// fields in addition to the single element that has data.  If
-/// rejectFatBitField, and the single element is a bitfield of a type that's
-/// bigger than the struct, return null anyway.
+/// null.  Returns null for complex number types.  If ignoreZeroLength, the
+/// struct (recursively) may include zero-length fields in addition to the
+/// single element that has data.  If rejectFatBitField, and the single element
+/// is a bitfield of a type that's bigger than the struct, return null anyway.
 extern tree_node *isSingleElementStructOrArray(tree_node *type,
                                                bool ignoreZeroLength,
                                                bool rejectFatBitfield);

Modified: dragonegg/trunk/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-convert.cpp?rev=117649&r1=117648&r2=117649&view=diff
==============================================================================
--- dragonegg/trunk/llvm-convert.cpp (original)
+++ dragonegg/trunk/llvm-convert.cpp Fri Oct 29 09:09:20 2010
@@ -952,15 +952,16 @@
 
   // If the function returns a value, get it into a register and return it now.
   if (!Fn->getReturnType()->isVoidTy()) {
-    if (!AGGREGATE_TYPE_P(TREE_TYPE(DECL_RESULT(FnDecl)))) {
+    tree TreeRetVal = DECL_RESULT(FnDecl);
+    if (!AGGREGATE_TYPE_P(TREE_TYPE(TreeRetVal)) &&
+        TREE_CODE(TREE_TYPE(TreeRetVal)) != COMPLEX_TYPE) {
       // If the DECL_RESULT is a scalar type, just load out the return value
       // and return it.
-      tree TreeRetVal = DECL_RESULT(FnDecl);
       Value *RetVal = Builder.CreateLoad(DECL_LOCAL(TreeRetVal), "retval");
       RetVal = Builder.CreateBitCast(RetVal, Fn->getReturnType());
       RetVals.push_back(RetVal);
     } else {
-      Value *RetVal = DECL_LOCAL(DECL_RESULT(FnDecl));
+      Value *RetVal = DECL_LOCAL(TreeRetVal);
       if (const StructType *STy = dyn_cast<StructType>(Fn->getReturnType())) {
         Value *R1 = Builder.CreateBitCast(RetVal, STy->getPointerTo());
 
@@ -2911,30 +2912,39 @@
     return 0;
 
   if (Client.isAggrReturn()) {
+    MemRef Target;
+    if (DestLoc)
+      Target = *DestLoc;
+    else
+      // Destination is a first class value (eg: a complex number).  Extract to
+      // a temporary then load the value out later.
+      Target = CreateTempLoc(ConvertType(gimple_call_return_type(stmt)));
+
     if (TD.getTypeAllocSize(Call->getType()) <=
-        TD.getTypeAllocSize(cast<PointerType>(DestLoc->Ptr->getType())
+        TD.getTypeAllocSize(cast<PointerType>(Target.Ptr->getType())
                                              ->getElementType())) {
-      Value *Dest = Builder.CreateBitCast(DestLoc->Ptr,
+      Value *Dest = Builder.CreateBitCast(Target.Ptr,
                                           Call->getType()->getPointerTo());
-      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,Dest,DestLoc->Volatile,Builder);
+      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call, Dest, Target.Volatile,
+                                         Builder);
     } else {
       // The call will return an aggregate value in registers, but
-      // those registers are bigger than DestLoc.  Allocate a
+      // those registers are bigger than Target.  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
+      // the correct type, copy the value into Target.  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,
+      EmitAggregateCopy(Target,
                         MemRef(Builder.CreateBitCast(biggerTmp,Call->getType()->
                                                      getPointerTo()),
-                               DestLoc->getAlignment(),
-                               DestLoc->Volatile),
+                               Target.getAlignment(), Target.Volatile),
                         gimple_call_return_type(stmt));
     }
-    return 0;
+
+    return DestLoc ? 0 : Builder.CreateLoad(Target.Ptr);
   }
 
   // If the caller expects an aggregate, we have a situation where the ABI for
@@ -2943,8 +2953,23 @@
   // to the destination aggregate type.  We do this by casting the DestLoc
   // pointer and storing into it.  The store does not necessarily start at the
   // beginning of the aggregate (x86-64).
-  if (!DestLoc)
-    return Call;   // Normal scalar return.
+  if (!DestLoc) {
+    const Type *RetTy = ConvertType(gimple_call_return_type(stmt));
+    if (Call->getType() == RetTy)
+      return Call;   // Normal scalar return.
+
+    // May be something as simple as a float being returned as an integer, or
+    // something trickier like a complex int type { i32, i32 } being returned
+    // as an i64.
+    if (Call->getType()->canLosslesslyBitCastTo(RetTy))
+      return Builder.CreateBitCast(Call, RetTy); // Simple case.
+    // Probably a scalar to complex conversion.
+    assert(TD.getTypeAllocSize(Call->getType()) == TD.getTypeAllocSize(RetTy) &&
+           "Size mismatch in scalar to scalar conversion!");
+    Value *Tmp = CreateTemporary(Call->getType());
+    Builder.CreateStore(Call, Tmp);
+    return Builder.CreateLoad(Builder.CreateBitCast(Tmp,RetTy->getPointerTo()));
+  }
 
   Value *Ptr = DestLoc->Ptr;
   if (Client.Offset) {





More information about the llvm-commits mailing list