diff options
author | Anders Carlsson <andersca@mac.com> | 2009-12-24 20:40:36 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-12-24 20:40:36 +0000 |
commit | d2490a91341b57df7a7e54f8a707e7ecde2eeb4e (patch) | |
tree | 52d2846d052172a17ff27e241f6158594c5395a1 /lib/CodeGen | |
parent | 8aa5f407d9e4787ff08bd66e1a2fe39be174fddc (diff) |
Fill in the return value slot in CGExprAgg::VisitCallExpr. This takes us halfway towards fixing PR5824.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92142 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 47 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 4 |
7 files changed, 51 insertions, 20 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 2fe11a1d07..a2328e4a49 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -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. diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 40d41d9165..ba83087ebc 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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>(); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 33692ca35a..2dda0b883f 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -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: diff --git a/lib/CodeGen/CGCall.h b/lib/CodeGen/CGCall.h index 041d1df0b0..427ab5f4cb 100644 --- a/lib/CodeGen/CGCall.h +++ b/lib/CodeGen/CGCall.h @@ -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; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index add6dc5310..059b3827e6 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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:: diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0802e905ea..16249e4aab 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -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); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index b530a919ef..487a797b72 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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); |