Pull COdeGenFunction::CreateStaticBlockVarDecl (just for creating the
global variable) out of GenerateStaticBlockVarDecl.
- No intended functionality change.
- Prep for some mild cleanups and PR3662.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65466 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 0ca2ad3..c0f2054 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -74,35 +74,13 @@
}
}
-llvm::GlobalValue *
-CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
- bool NoInit,
- const char *Separator,
- llvm::GlobalValue
- ::LinkageTypes Linkage) {
+llvm::GlobalVariable *
+CodeGenFunction::CreateStaticBlockVarDecl(const VarDecl &D,
+ const char *Separator,
+ llvm::GlobalValue::LinkageTypes
+ Linkage) {
QualType Ty = D.getType();
assert(Ty->isConstantSizeType() && "VLAs can't be static");
-
- const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
- llvm::Constant *Init = 0;
- if ((D.getInit() == 0) || NoInit) {
- Init = llvm::Constant::getNullValue(LTy);
- } else {
- Init = CGM.EmitConstantExpr(D.getInit(), this);
-
- // If constant emission failed, then this should be a C++ static
- // initializer.
- if (!Init) {
- if (!getContext().getLangOptions().CPlusPlus) {
- CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
- Init = llvm::Constant::getNullValue(LTy);
- } else {
- return GenerateStaticCXXBlockVarDecl(D);
- }
- }
- }
-
- assert(Init && "Unable to create initialiser for static decl");
std::string ContextName;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
@@ -113,11 +91,61 @@
else
assert(0 && "Unknown context for block var decl");
- llvm::GlobalValue *GV =
- new llvm::GlobalVariable(Init->getType(), Ty.isConstant(getContext()),
- Linkage,
- Init, ContextName + Separator +D.getNameAsString(),
- &CGM.getModule(), 0, Ty.getAddressSpace());
+ const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
+ return new llvm::GlobalVariable(LTy, Ty.isConstant(getContext()), Linkage,
+ llvm::Constant::getNullValue(LTy),
+ ContextName + Separator + D.getNameAsString(),
+ &CGM.getModule(), 0, Ty.getAddressSpace());
+}
+
+llvm::GlobalVariable *
+CodeGenFunction::GenerateStaticBlockVarDecl(const VarDecl &D,
+ bool NoInit,
+ const char *Separator,
+ llvm::GlobalValue
+ ::LinkageTypes Linkage) {
+ llvm::GlobalVariable *GV = CreateStaticBlockVarDecl(D, Separator, Linkage);
+
+ if (D.getInit() && !NoInit) {
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), this);
+
+ // If constant emission failed, then this should be a C++ static
+ // initializer.
+ if (!Init) {
+ if (!getContext().getLangOptions().CPlusPlus)
+ CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
+ else
+ GenerateStaticCXXBlockVarDeclInit(D, GV);
+ } else {
+ // The initializer may differ in type from the global. Rewrite
+ // the global to match the initializer!?
+ //
+ // FIXME: This matches what we have been doing historically, but
+ // it seems bad. Shouldn't the init expression have the right
+ // type?
+ if (GV->getType() != Init->getType()) {
+ llvm::GlobalVariable *OldGV = GV;
+
+ GV = new llvm::GlobalVariable(Init->getType(), OldGV->isConstant(),
+ OldGV->getLinkage(), Init, "",
+ &CGM.getModule(), 0,
+ D.getType().getAddressSpace());
+
+ // Steal the name of the old global
+ GV->takeName(OldGV);
+
+ // Replace all uses of the old global with the new global
+ llvm::Constant *NewPtrForOldDecl =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtrForOldDecl);
+
+ // Erase the old global, since it is no longer used.
+ OldGV->eraseFromParent();
+ }
+
+ GV->setInitializer(Init);
+ }
+ }
return GV;
}