return S;
}
-llvm::GlobalValue *
-CodeGenFunction::GenerateStaticCXXBlockVarDecl(const VarDecl &D)
-{
+void
+CodeGenFunction::GenerateStaticCXXBlockVarDeclInit(const VarDecl &D,
+ llvm::GlobalVariable *GV) {
+ // FIXME: This should use __cxa_guard_{acquire,release}?
+
assert(!getContext().getLangOptions().ThreadsafeStatics &&
"thread safe statics are currently not supported!");
- const llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(D.getType());
- // FIXME: If the function is inline, the linkage should be weak.
- llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::InternalLinkage;
-
// Create the guard variable.
llvm::GlobalValue *GuardV =
new llvm::GlobalVariable(llvm::Type::Int64Ty, false,
- linkage,
+ GV->getLinkage(),
llvm::Constant::getNullValue(llvm::Type::Int64Ty),
mangleGuardVariable(D),
&CGM.getModule());
- // FIXME: Address space.
- const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
-
// Load the first byte of the guard variable.
+ const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy),
"tmp");
EmitBlock(InitBlock);
- llvm::GlobalValue *GV =
- new llvm::GlobalVariable(LTy, false,
- llvm::GlobalValue::InternalLinkage,
- llvm::Constant::getNullValue(LTy),
- mangleVarDecl(D),
- &CGM.getModule(), 0,
- D.getType().getAddressSpace());
+ // Patch the name. FIXME: We shouldn't need to do this.
+ GV->setName(mangleVarDecl(D));
const Expr *Init = D.getInit();
if (!hasAggregateLLVMType(Init->getType())) {
Builder.CreateBitCast(GuardV, PtrTy));
EmitBlock(EndBlock);
- return GV;
}
}
}
-llvm::GlobalValue *
+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");
+
+ std::string ContextName;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
+ ContextName = CGM.getMangledName(FD);
+ else if (isa<ObjCMethodDecl>(CurFuncDecl))
+ ContextName = std::string(CurFn->getNameStart(),
+ CurFn->getNameStart() + CurFn->getNameLen());
+ else
+ assert(0 && "Unknown context for block var decl");
+
+ 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) {
- 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);
+ 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) {
+ if (!getContext().getLangOptions().CPlusPlus)
CGM.ErrorUnsupported(D.getInit(), "constant l-value expression");
- Init = llvm::Constant::getNullValue(LTy);
- } else {
- return GenerateStaticCXXBlockVarDecl(D);
- }
- }
- }
+ 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());
- assert(Init && "Unable to create initialiser for static decl");
+ // Steal the name of the old global
+ GV->takeName(OldGV);
- std::string ContextName;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl))
- ContextName = CGM.getMangledName(FD);
- else if (isa<ObjCMethodDecl>(CurFuncDecl))
- ContextName = std::string(CurFn->getNameStart(),
- CurFn->getNameStart() + CurFn->getNameLen());
- else
- assert(0 && "Unknown context for block var decl");
+ // 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();
+ }
- llvm::GlobalValue *GV =
- new llvm::GlobalVariable(Init->getType(), Ty.isConstant(getContext()),
- Linkage,
- Init, ContextName + Separator +D.getNameAsString(),
- &CGM.getModule(), 0, Ty.getAddressSpace());
+ GV->setInitializer(Init);
+ }
+ }
return GV;
}
/// LoadComplexFromAddr - Load a complex number from the specified address.
ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
+ /// CreateStaticBlockVarDecl - Create a zero-initialized LLVM global
+ /// for a static block var decl.
+ llvm::GlobalVariable * CreateStaticBlockVarDecl(const VarDecl &D,
+ const char *Separator,
+ llvm::GlobalValue::LinkageTypes
+ Linkage);
+
/// GenerateStaticBlockVarDecl - Return the the static declaration of local
/// variable.
- llvm::GlobalValue * GenerateStaticBlockVarDecl(const VarDecl &D,
- bool NoInit,
- const char *Separator,
- llvm::GlobalValue
- ::LinkageTypes Linkage);
-
- /// GenerateStaticCXXBlockVarDecl - Return the static declaration of a local
- /// variable. Performs initialization of the variable if necessary.
- llvm::GlobalValue *GenerateStaticCXXBlockVarDecl(const VarDecl &D);
+ llvm::GlobalVariable * GenerateStaticBlockVarDecl(const VarDecl &D,
+ bool NoInit,
+ const char *Separator,
+ llvm::GlobalValue
+ ::LinkageTypes Linkage);
+
+ /// GenerateStaticCXXBlockVarDecl - Create the initializer for a C++
+ /// runtime initialized static block var decl.
+ void GenerateStaticCXXBlockVarDeclInit(const VarDecl &D,
+ llvm::GlobalVariable *GV);
//===--------------------------------------------------------------------===//
// Internal Helpers