]> granicus.if.org Git - clang/commitdiff
Fill in the return value slot in CGExprAgg::VisitCallExpr. This takes us halfway...
authorAnders Carlsson <andersca@mac.com>
Thu, 24 Dec 2009 20:40:36 +0000 (20:40 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 24 Dec 2009 20:40:36 +0000 (20:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92142 91177308-0d34-0410-b5e6-96231b3b80d8

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 [moved from test/CodeGenObjC/x86-64-struct-return-gc.m with 100% similarity]

index 2fe11a1d07fd98f42afaaf75f0516d1d9c2218ec..a2328e4a498aab7eb0b24dd651f7c959b1f07695 100644 (file)
@@ -581,6 +581,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
       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.
index 40d41d9165dad2893671575ace05ce8fe52f7ebf..ba83087ebc4b24fc64b6ab6a682b59363794a222 100644 (file)
@@ -89,7 +89,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
     // 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>();
index 33692ca35afa54df62d2efa08067a8b1a5178695..2dda0b883f04e55ee9b584286a8ad81850b28cf9 100644 (file)
@@ -346,6 +346,7 @@ static llvm::Value *CreateCoercedLoad(llvm::Value *SrcPtr,
 /// 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 @@ static void CreateCoercedStore(llvm::Value *Src,
     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 @@ static void CreateCoercedStore(llvm::Value *Src,
     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 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
       // 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 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
 
 
   // 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 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
       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 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
     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:
index 041d1df0b03d071b6460c2a6e82b6dd084ff6d84..427ab5f4cbc8b85ff2a76b3ad7abae13b31c5c16 100644 (file)
@@ -125,6 +125,8 @@ namespace CodeGen {
     }
   };
   
+  /// 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;
 
index add6dc5310fc0fdef0b90eb28fc1b96fae202c68..059b3827e6b002ba75148004508955b91db8cc04 100644 (file)
@@ -1518,7 +1518,8 @@ LValue CodeGenFunction::EmitNullInitializationLValue(
 //===--------------------------------------------------------------------===//
 
 
-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 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E) {
   }
 
   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 @@ LValue CodeGenFunction::EmitPointerToDataMemberLValue(const FieldDecl *Field) {
 }
 
 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 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
     CallingConvention = F->getCallingConv();
   return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args,
                                                  CallingConvention),
-                  Callee, ReturnValueSlot(), Args, TargetDecl);
+                  Callee, ReturnValue, Args, TargetDecl);
 }
 
 LValue CodeGenFunction::
index 0802e905eae9fb141d4864955cae27f52cb97d14..16249e4aab579a7d697b389aa62f19c86f2d3dd3 100644 (file)
@@ -272,6 +272,13 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
     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);
 }
index b530a919ef306bc3839e59b0ef4c95c3020fe979..487a797b724d0f5af8363b054a4a5a62b84a5065 100644 (file)
@@ -1041,10 +1041,12 @@ public:
                   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);