[cfe-commits] r92142 - in /cfe/trunk: lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCall.cpp lib/CodeGen/CGCall.h lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/x86-64-struct-return-gc.m test/CodeGenObjC/x86_64-struct-return-gc.m

Anders Carlsson andersca at mac.com
Thu Dec 24 12:40:37 PST 2009


Author: andersca
Date: Thu Dec 24 14:40:36 2009
New Revision: 92142

URL: http://llvm.org/viewvc/llvm-project?rev=92142&view=rev
Log:
Fill in the return value slot in CGExprAgg::VisitCallExpr. This takes us halfway towards fixing PR5824.

Added:
    cfe/trunk/test/CodeGenObjC/x86_64-struct-return-gc.m
      - copied unchanged from r92140, cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m
Removed:
    cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m
Modified:
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGCall.h
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Dec 24 14:40:36 2009
@@ -581,6 +581,7 @@
       getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
     return EmitCall(E->getCallee()->getType(),
                     CGM.getBuiltinLibFunction(FD, BuiltinID),
+                    ReturnValueSlot(),
                     E->arg_begin(), E->arg_end());
 
   // See if we have a target specific intrinsic.

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Thu Dec 24 14:40:36 2009
@@ -89,7 +89,7 @@
     // The method is static, emit it as we would a regular call.
     llvm::Value *Callee = CGM.GetAddrOfFunction(MD);
     return EmitCall(getContext().getPointerType(MD->getType()), Callee,
-                    CE->arg_begin(), CE->arg_end());
+                    ReturnValueSlot(), CE->arg_begin(), CE->arg_end());
   }
   
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Thu Dec 24 14:40:36 2009
@@ -346,6 +346,7 @@
 /// destination type; the upper bits of the src will be lost.
 static void CreateCoercedStore(llvm::Value *Src,
                                llvm::Value *DstPtr,
+                               bool DstIsVolatile,
                                CodeGenFunction &CGF) {
   const llvm::Type *SrcTy = Src->getType();
   const llvm::Type *DstTy =
@@ -359,7 +360,7 @@
     llvm::Value *Casted =
       CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
     // FIXME: Use better alignment / avoid requiring aligned store.
-    CGF.Builder.CreateStore(Src, Casted)->setAlignment(1);
+    CGF.Builder.CreateStore(Src, Casted, DstIsVolatile)->setAlignment(1);
   } else {
     // Otherwise do coercion through memory. This is stupid, but
     // simple.
@@ -377,7 +378,7 @@
     llvm::LoadInst *Load = CGF.Builder.CreateLoad(Casted);
     // FIXME: Use better alignment / avoid requiring aligned load.
     Load->setAlignment(1);
-    CGF.Builder.CreateStore(Load, DstPtr);
+    CGF.Builder.CreateStore(Load, DstPtr, DstIsVolatile);
   }
 }
 
@@ -732,7 +733,7 @@
       // result in a new alloca anyway, so we could just store into that
       // directly if we broke the abstraction down more.
       llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(Ty), "coerce");
-      CreateCoercedStore(AI, V, *this);
+      CreateCoercedStore(AI, V, /*DestIsVolatile=*/false, *this);
       // Match to what EmitParmDecl is expecting for this type.
       if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
         V = EmitLoadOfScalar(V, false, Ty);
@@ -822,9 +823,13 @@
 
 
   // If the call returns a temporary with struct return, create a temporary
-  // alloca to hold the result.
-  if (CGM.ReturnTypeUsesSret(CallInfo))
-    Args.push_back(CreateTempAlloca(ConvertTypeForMem(RetTy)));
+  // alloca to hold the result, unless one is given to us.
+  if (CGM.ReturnTypeUsesSret(CallInfo)) {
+    llvm::Value *Value = ReturnValue.getValue();
+    if (!Value)
+      Value = CreateTempAlloca(ConvertTypeForMem(RetTy));
+    Args.push_back(Value);
+  }
 
   assert(CallInfo.arg_size() == CallArgs.size() &&
          "Mismatch between function signature & arguments.");
@@ -973,9 +978,15 @@
       return RValue::getComplex(std::make_pair(Real, Imag));
     }
     if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
-      llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(RetTy), "agg.tmp");
-      Builder.CreateStore(CI, V);
-      return RValue::getAggregate(V);
+      llvm::Value *DestPtr = ReturnValue.getValue();
+      bool DestIsVolatile = ReturnValue.isVolatile();
+
+      if (!DestPtr) {
+        DestPtr = CreateTempAlloca(ConvertTypeForMem(RetTy), "agg.tmp");
+        DestIsVolatile = false;
+      }
+      Builder.CreateStore(CI, DestPtr, DestIsVolatile);
+      return RValue::getAggregate(DestPtr);
     }
     return RValue::get(CI);
 
@@ -985,14 +996,20 @@
     return GetUndefRValue(RetTy);
 
   case ABIArgInfo::Coerce: {
-    // FIXME: Avoid the conversion through memory if possible.
-    llvm::Value *V = CreateTempAlloca(ConvertTypeForMem(RetTy), "coerce");
-    CreateCoercedStore(CI, V, *this);
+    llvm::Value *DestPtr = ReturnValue.getValue();
+    bool DestIsVolatile = ReturnValue.isVolatile();
+    
+    if (!DestPtr) {
+      DestPtr = CreateTempAlloca(ConvertTypeForMem(RetTy), "coerce");
+      DestIsVolatile = false;
+    }
+    
+    CreateCoercedStore(CI, DestPtr, DestIsVolatile, *this);
     if (RetTy->isAnyComplexType())
-      return RValue::getComplex(LoadComplexFromAddr(V, false));
+      return RValue::getComplex(LoadComplexFromAddr(DestPtr, false));
     if (CodeGenFunction::hasAggregateLLVMType(RetTy))
-      return RValue::getAggregate(V);
-    return RValue::get(EmitLoadOfScalar(V, false, RetTy));
+      return RValue::getAggregate(DestPtr);
+    return RValue::get(EmitLoadOfScalar(DestPtr, false, RetTy));
   }
 
   case ABIArgInfo::Expand:

Modified: cfe/trunk/lib/CodeGen/CGCall.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.h?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.h (original)
+++ cfe/trunk/lib/CodeGen/CGCall.h Thu Dec 24 14:40:36 2009
@@ -125,6 +125,8 @@
     }
   };
   
+  /// ReturnValueSlot - Contains the address where the return value of a 
+  /// function can be stored, and whether the address is volatile or not.
   class ReturnValueSlot {
     llvm::PointerIntPair<llvm::Value *, 1, bool> Value;
 

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Dec 24 14:40:36 2009
@@ -1518,7 +1518,8 @@
 //===--------------------------------------------------------------------===//
 
 
-RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
+RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, 
+                                     ReturnValueSlot ReturnValue) {
   // Builtins never have block type.
   if (E->getCallee()->getType()->isBlockPointerType())
     return EmitBlockCallExpr(E);
@@ -1551,7 +1552,7 @@
   }
 
   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
-  return EmitCall(E->getCallee()->getType(), Callee,
+  return EmitCall(E->getCallee()->getType(), Callee, ReturnValue,
                   E->arg_begin(), E->arg_end(), TargetDecl);
 }
 
@@ -1713,6 +1714,7 @@
 }
 
 RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
+                                 ReturnValueSlot ReturnValue,
                                  CallExpr::const_arg_iterator ArgBeg,
                                  CallExpr::const_arg_iterator ArgEnd,
                                  const Decl *TargetDecl) {
@@ -1737,7 +1739,7 @@
     CallingConvention = F->getCallingConv();
   return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
                                                  CallingConvention),
-                  Callee, ReturnValueSlot(), Args, TargetDecl);
+                  Callee, ReturnValue, Args, TargetDecl);
 }
 
 LValue CodeGenFunction::

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Dec 24 14:40:36 2009
@@ -272,6 +272,13 @@
     return;
   }
 
+  // If the struct doesn't require GC, we can just pass the destination
+  // directly to EmitCall.
+  if (!RequiresGCollection) {
+    CGF.EmitCallExpr(E, ReturnValueSlot(DestPtr, VolatileDest));
+    return;
+  }
+  
   RValue RV = CGF.EmitCallExpr(E);
   EmitFinalDestCopy(E, RV);
 }

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=92142&r1=92141&r2=92142&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Dec 24 14:40:36 2009
@@ -1041,10 +1041,12 @@
                   const Decl *TargetDecl = 0);
 
   RValue EmitCall(QualType FnType, llvm::Value *Callee,
+                  ReturnValueSlot ReturnValue,
                   CallExpr::const_arg_iterator ArgBeg,
                   CallExpr::const_arg_iterator ArgEnd,
                   const Decl *TargetDecl = 0);
-  RValue EmitCallExpr(const CallExpr *E);
+  RValue EmitCallExpr(const CallExpr *E, 
+                      ReturnValueSlot ReturnValue = ReturnValueSlot());
 
   llvm::Value *BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *This,
                                 const llvm::Type *Ty);

Removed: cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m?rev=92141&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m (original)
+++ cfe/trunk/test/CodeGenObjC/x86-64-struct-return-gc.m (removed)
@@ -1,31 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o - %s | FileCheck %s
-struct Coerce {
-  id a;
-};
-
-struct Coerce coerce_func(void);
-
-// CHECK: define void @Coerce_test()
-void Coerce_test(void) {
-  struct Coerce c;
-  
-  // CHECK: call i64 @coerce_func
-  // CHECK: call i8* @objc_memmove_collectable(
-  c = coerce_func();
-}
-
-struct Indirect {
-  id a;
-  int b[10];
-};
-
-struct Indirect indirect_func(void);
-
-// CHECK: define void @Indirect_test()
-void Indirect_test(void) {
-  struct Indirect i;
-  
-  // CHECK: call void @indirect_func(%struct.Indirect* noalias sret
-  // CHECK: call i8* @objc_memmove_collectable(
-  i = indirect_func();
-}





More information about the cfe-commits mailing list