diff options
author | John McCall <rjmccall@apple.com> | 2011-03-08 09:11:50 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-03-08 09:11:50 +0000 |
commit | 60d3365b46eb826fba44483583c0051ac5c41fe3 (patch) | |
tree | 9a89bc2766349d5d235ef851b0f49786cdd66ec0 /lib/CodeGen/CGDecl.cpp | |
parent | ff676cb48fe8bf7be2feaa251dc7c5fb15af4730 (diff) |
Extract a function to emit an arbitrary expression as if it were the initializer
for a local variable.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127227 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 130 |
1 files changed, 77 insertions, 53 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 46a76edd0a..2cd4c87d3f 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -877,67 +877,91 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { llvm::Value *Loc = capturedByInit ? emission.Address : emission.getObjectAddress(*this); - bool isVolatile = type.isVolatileQualified(); - + if (!emission.IsConstantAggregate) + return EmitExprAsInit(Init, &D, Loc, alignment, capturedByInit); + // If this is a simple aggregate initialization, we can optimize it // in various ways. - if (emission.IsConstantAggregate) { - assert(!capturedByInit && "constant init contains a capturing block?"); - - llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), type, this); - assert(Init != 0 && "Wasn't a simple constant init?"); - - llvm::Value *SizeVal = - llvm::ConstantInt::get(IntPtrTy, - getContext().getTypeSizeInChars(type).getQuantity()); - - const llvm::Type *BP = Int8PtrTy; - if (Loc->getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP, "tmp"); - - // If the initializer is all or mostly zeros, codegen with memset then do - // a few stores afterward. - if (shouldUseMemSetPlusStoresToInitialize(Init, - CGM.getTargetData().getTypeAllocSize(Init->getType()))) { - Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, - alignment.getQuantity(), isVolatile); - if (!Init->isNullValue()) { - Loc = Builder.CreateBitCast(Loc, Init->getType()->getPointerTo()); - emitStoresForInitAfterMemset(Init, Loc, isVolatile, Builder); - } - } else { - // Otherwise, create a temporary global with the initializer then - // memcpy from the global to the alloca. - std::string Name = GetStaticDeclName(*this, D, "."); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true, - llvm::GlobalValue::InternalLinkage, - Init, Name, 0, false, 0); - GV->setAlignment(alignment.getQuantity()); - - llvm::Value *SrcPtr = GV; - if (SrcPtr->getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + assert(!capturedByInit && "constant init contains a capturing block?"); + + bool isVolatile = type.isVolatileQualified(); - Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(), - isVolatile); + llvm::Constant *constant = CGM.EmitConstantExpr(D.getInit(), type, this); + assert(constant != 0 && "Wasn't a simple constant init?"); + + llvm::Value *SizeVal = + llvm::ConstantInt::get(IntPtrTy, + getContext().getTypeSizeInChars(type).getQuantity()); + + const llvm::Type *BP = Int8PtrTy; + if (Loc->getType() != BP) + Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + + // If the initializer is all or mostly zeros, codegen with memset then do + // a few stores afterward. + if (shouldUseMemSetPlusStoresToInitialize(constant, + CGM.getTargetData().getTypeAllocSize(constant->getType()))) { + Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, 0), SizeVal, + alignment.getQuantity(), isVolatile); + if (!constant->isNullValue()) { + Loc = Builder.CreateBitCast(Loc, constant->getType()->getPointerTo()); + emitStoresForInitAfterMemset(constant, Loc, isVolatile, Builder); } - } else if (type->isReferenceType()) { - RValue RV = EmitReferenceBindingToExpr(Init, &D); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - EmitStoreOfScalar(RV.getScalarVal(), Loc, false, alignment.getQuantity(), - type); + } else { + // Otherwise, create a temporary global with the initializer then + // memcpy from the global to the alloca. + std::string Name = GetStaticDeclName(*this, D, "."); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true, + llvm::GlobalValue::InternalLinkage, + constant, Name, 0, false, 0); + GV->setAlignment(alignment.getQuantity()); + + llvm::Value *SrcPtr = GV; + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + + Builder.CreateMemCpy(Loc, SrcPtr, SizeVal, alignment.getQuantity(), + isVolatile); + } +} + +/// Emit an expression as an initializer for a variable at the given +/// location. The expression is not necessarily the normal +/// initializer for the variable, and the address is not necessarily +/// its normal location. +/// +/// \param init the initializing expression +/// \param var the variable to act as if we're initializing +/// \param loc the address to initialize; its type is a pointer +/// to the LLVM mapping of the variable's type +/// \param alignment the alignment of the address +/// \param capturedByInit true if the variable is a __block variable +/// whose address is potentially changed by the initializer +void CodeGenFunction::EmitExprAsInit(const Expr *init, + const VarDecl *var, + llvm::Value *loc, + CharUnits alignment, + bool capturedByInit) { + QualType type = var->getType(); + bool isVolatile = type.isVolatileQualified(); + + if (type->isReferenceType()) { + RValue RV = EmitReferenceBindingToExpr(init, var); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + EmitStoreOfScalar(RV.getScalarVal(), loc, false, + alignment.getQuantity(), type); } else if (!hasAggregateLLVMType(type)) { - llvm::Value *V = EmitScalarExpr(Init); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - EmitStoreOfScalar(V, Loc, isVolatile, alignment.getQuantity(), type); + llvm::Value *V = EmitScalarExpr(init); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + EmitStoreOfScalar(V, loc, isVolatile, alignment.getQuantity(), type); } else if (type->isAnyComplexType()) { - ComplexPairTy complex = EmitComplexExpr(Init); - if (capturedByInit) Loc = BuildBlockByrefAddress(Loc, &D); - StoreComplexToAddr(complex, Loc, isVolatile); + ComplexPairTy complex = EmitComplexExpr(init); + if (capturedByInit) loc = BuildBlockByrefAddress(loc, var); + StoreComplexToAddr(complex, loc, isVolatile); } else { // TODO: how can we delay here if D is captured by its initializer? - EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true, false)); + EmitAggExpr(init, AggValueSlot::forAddr(loc, isVolatile, true, false)); } } |