summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
-rw-r--r--lib/CodeGen/CGDecl.cpp44
1 files changed, 35 insertions, 9 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1728c67..b1ceb46 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompileOptions.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/Target/TargetData.h"
@@ -316,6 +317,20 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
llvm::Value *DeclPtr;
if (Ty->isConstantSizeType()) {
if (!Target.useGlobalsForAutomaticVariables()) {
+
+ // All constant structs and arrays should be global if
+ // their initializer is constant and if the element type is POD.
+ if (CGM.getCompileOpts().MergeAllConstants) {
+ if (Ty.isConstant(getContext())
+ && (Ty->isArrayType() || Ty->isRecordType())
+ && (D.getInit()
+ && D.getInit()->isConstantInitializer(getContext()))
+ && Ty->isPODType()) {
+ EmitStaticBlockVarDecl(D);
+ return;
+ }
+ }
+
// A normal fixed sized variable becomes an alloca in the entry block.
const llvm::Type *LTy = ConvertTypeForMem(Ty);
Align = getContext().getDeclAlignInBytes(&D);
@@ -417,17 +432,18 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
+ bool isVolatile = (getContext().getCanonicalType(D.getType())
+ .isVolatileQualified());
if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true);
EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(),
- D.getType());
+ EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
} else if (Init->getType()->isAnyComplexType()) {
- EmitComplexExprIntoAddr(Init, Loc, D.getType().isVolatileQualified());
+ EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
- EmitAggExpr(Init, Loc, D.getType().isVolatileQualified());
+ EmitAggExpr(Init, Loc, isVolatile);
}
}
@@ -492,16 +508,25 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
// Handle CXX destruction of variables.
QualType DtorTy(Ty);
if (const ArrayType *Array = DtorTy->getAs<ArrayType>())
- DtorTy = Array->getElementType();
+ DtorTy = getContext().getBaseElementType(Array);
if (const RecordType *RT = DtorTy->getAs<RecordType>())
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
if (!ClassDecl->hasTrivialDestructor()) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul");
- assert(!Ty->getAs<ArrayType>() && "FIXME - destruction of arrays NYI");
-
+
CleanupScope scope(*this);
- EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
+ if (const ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(Ty)) {
+ QualType BaseElementTy = getContext().getBaseElementType(Array);
+ const llvm::Type *BasePtr = ConvertType(BaseElementTy);
+ BasePtr = llvm::PointerType::getUnqual(BasePtr);
+ llvm::Value *BaseAddrPtr =
+ Builder.CreateBitCast(DeclPtr, BasePtr);
+ EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
+ }
+ else
+ EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
}
}
@@ -547,6 +572,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
assert((isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)) &&
"Invalid argument to EmitParmDecl");
QualType Ty = D.getType();
+ CanQualType CTy = getContext().getCanonicalType(Ty);
llvm::Value *DeclPtr;
if (!Ty->isConstantSizeType()) {
@@ -563,7 +589,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DeclPtr->setName(Name.c_str());
// Store the initial value into the alloca.
- EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(), Ty);
+ EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
} else {
// Otherwise, if this is an aggregate, just use the input pointer.
DeclPtr = Arg;
OpenPOWER on IntegriCloud