[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