[cfe-commits] r67445 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/mangle.c
Chris Lattner
sabre at nondot.org
Sat Mar 21 02:16:49 PDT 2009
Author: lattner
Date: Sat Mar 21 04:16:30 2009
New Revision: 67445
URL: http://llvm.org/viewvc/llvm-project?rev=67445&view=rev
Log:
simplify and cleanup global variable creation stuff to all go through one
code path.
Modified:
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/test/CodeGen/mangle.c
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=67445&r1=67444&r2=67445&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Mar 21 04:16:30 2009
@@ -585,22 +585,29 @@
}
}
- llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D) {
+/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
+/// given global variable. If Ty is non-null and if the global doesn't exist,
+/// then it will be greated with the specified type instead of whatever the
+/// normal requested type would be.
+llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
+ const llvm::Type *Ty) {
assert(D->hasGlobalStorage() && "Not a global variable");
QualType ASTTy = D->getType();
- const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
+ if (Ty == 0)
+ Ty = getTypes().ConvertTypeForMem(ASTTy);
// Lookup the entry, lazily creating it if necessary.
const char *MangledName = getMangledName(D);
llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
if (Entry) {
- const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
-
+ if (Entry->getType()->getElementType() == Ty &&
+ Entry->getType()->getAddressSpace() == ASTTy.getAddressSpace())
+ return Entry;
+
// Make sure the result is of the correct type.
- if (Entry->getType() != PTy)
- return llvm::ConstantExpr::getBitCast(Entry, PTy);
- return Entry;
+ const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
+ return llvm::ConstantExpr::getBitCast(Entry, PTy);
}
llvm::GlobalVariable *GV =
@@ -630,16 +637,15 @@
void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::Constant *Init = 0;
QualType ASTTy = D->getType();
- const llvm::Type *VarTy = getTypes().ConvertTypeForMem(ASTTy);
if (D->getInit() == 0) {
// This is a tentative definition; tentative definitions are
// implicitly initialized with { 0 }
- const llvm::Type *InitTy = VarTy;
+ const llvm::Type *InitTy = getTypes().ConvertTypeForMem(ASTTy);
if (ASTTy->isIncompleteArrayType()) {
// An incomplete array is normally [ TYPE x 0 ], but we need
// to fix it to [ TYPE x 1 ].
- const llvm::ArrayType* ATy = cast<llvm::ArrayType>(VarTy);
+ const llvm::ArrayType* ATy = cast<llvm::ArrayType>(InitTy);
InitTy = llvm::ArrayType::get(ATy->getElementType(), 1);
}
Init = llvm::Constant::getNullValue(InitTy);
@@ -653,74 +659,70 @@
}
const llvm::Type* InitType = Init->getType();
- const char *MangledName = getMangledName(D);
- llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
- llvm::GlobalVariable *GV = cast_or_null<llvm::GlobalVariable>(Entry);
+ llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType);
- if (!GV) {
- GV = new llvm::GlobalVariable(InitType, false,
- llvm::GlobalValue::ExternalLinkage,
- 0, MangledName,
- &getModule(), 0, ASTTy.getAddressSpace());
-
- } else if (GV->hasInitializer() && !GV->getInitializer()->isNullValue()) {
- // If we already have this global and it has an initializer, then
- // we are in the rare situation where we emitted the defining
- // declaration of the global and are now being asked to emit a
- // definition which would be common. This occurs, for example, in
- // the following situation because statics can be emitted out of
- // order:
- //
- // static int x;
- // static int *y = &x;
- // static int x = 10;
- // int **z = &y;
- //
- // Bail here so we don't blow away the definition. Note that if we
- // can't distinguish here if we emitted a definition with a null
- // initializer, but this case is safe.
+ // Strip off a bitcast if we got one back.
+ if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
+ assert(CE->getOpcode() == llvm::Instruction::BitCast);
+ Entry = CE->getOperand(0);
+ }
+
+ // Entry is now either a Function or GlobalVariable.
+ llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Entry);
+
+ // If we already have this global and it has an initializer, then
+ // we are in the rare situation where we emitted the defining
+ // declaration of the global and are now being asked to emit a
+ // definition which would be common. This occurs, for example, in
+ // the following situation because statics can be emitted out of
+ // order:
+ //
+ // static int x;
+ // static int *y = &x;
+ // static int x = 10;
+ // int **z = &y;
+ //
+ // Bail here so we don't blow away the definition. Note that if we
+ // can't distinguish here if we emitted a definition with a null
+ // initializer, but this case is safe.
+ if (GV && GV->hasInitializer() && !GV->getInitializer()->isNullValue()) {
assert(!D->getInit() && "Emitting multiple definitions of a decl!");
return;
+ }
+
+ // We have a definition after a declaration with the wrong type.
+ // We must make a new GlobalVariable* and update everything that used OldGV
+ // (a declaration or tentative definition) with the new GlobalVariable*
+ // (which will be a definition).
+ //
+ // This happens if there is a prototype for a global (e.g.
+ // "extern int x[];") and then a definition of a different type (e.g.
+ // "int x[10];"). This also happens when an initializer has a different type
+ // from the type of the global (this happens with unions).
+ //
+ // FIXME: This also ends up happening if there's a definition followed by
+ // a tentative definition! (Although Sema rejects that construct
+ // at the moment.)
+ if (GV == 0 ||
+ GV->getType()->getElementType() != InitType ||
+ GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) {
+
+ // Remove the old entry from GlobalDeclMap so that we'll create a new one.
+ GlobalDeclMap.erase(getMangledName(D));
- } else if (GV->getType() !=
- llvm::PointerType::get(InitType, ASTTy.getAddressSpace())) {
- // We have a definition after a prototype with the wrong type.
- // We must make a new GlobalVariable* and update everything that used OldGV
- // (a declaration or tentative definition) with the new GlobalVariable*
- // (which will be a definition).
- //
- // This happens if there is a prototype for a global (e.g.
- // "extern int x[];") and then a definition of a different type (e.g.
- // "int x[10];"). This also happens when an initializer has a different type
- // from the type of the global (this happens with unions).
- //
- // FIXME: This also ends up happening if there's a definition followed by
- // a tentative definition! (Although Sema rejects that construct
- // at the moment.)
-
- // Save the old global
- llvm::GlobalVariable *OldGV = GV;
-
- // Make a new global with the correct type
- GV = new llvm::GlobalVariable(InitType, false,
- llvm::GlobalValue::ExternalLinkage,
- 0, MangledName,
- &getModule(), 0, ASTTy.getAddressSpace());
- // Steal the name of the old global
- GV->takeName(OldGV);
-
+ // Make a new global with the correct type, this is now guaranteed to work.
+ GV = cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, InitType));
+
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtrForOldDecl);
+ llvm::ConstantExpr::getBitCast(GV, Entry->getType());
+ Entry->replaceAllUsesWith(NewPtrForOldDecl);
// Erase the old global, since it is no longer used.
// FIXME: What if it was attribute used? Dangling pointer from LLVMUsed.
- OldGV->eraseFromParent();
+ cast<llvm::GlobalValue>(Entry)->eraseFromParent();
}
- Entry = GV;
-
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
SourceManager &SM = Context.getSourceManager();
AddAnnotation(EmitAnnotateAttr(GV, AA,
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=67445&r1=67444&r2=67445&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Mar 21 04:16:30 2009
@@ -175,8 +175,11 @@
const llvm::TargetData &getTargetData() const { return TheTargetData; }
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
- /// given global variable.
- llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D);
+ /// given global variable. If Ty is non-null and if the global doesn't exist,
+ /// then it will be greated with the specified type instead of whatever the
+ /// normal requested type would be.
+ llvm::Constant *GetAddrOfGlobalVar(const VarDecl *D,
+ const llvm::Type *Ty = 0);
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
Modified: cfe/trunk/test/CodeGen/mangle.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mangle.c?rev=67445&r1=67444&r2=67445&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/mangle.c (original)
+++ cfe/trunk/test/CodeGen/mangle.c Sat Mar 21 04:16:30 2009
@@ -26,3 +26,13 @@
return nux + nux2;
}
+
+
+// Function becomes a variable.
+void foo3() __asm__("var");
+
+void test2() {
+ foo3();
+}
+int foo4 __asm__("var") = 4;
+
More information about the cfe-commits
mailing list