[cfe-commits] r54211 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c

Daniel Dunbar daniel at zuster.org
Wed Jul 30 09:32:28 PDT 2008


Author: ddunbar
Date: Wed Jul 30 11:32:24 2008
New Revision: 54211

URL: http://llvm.org/viewvc/llvm-project?rev=54211&view=rev
Log:
Change CodeGenModule GlobalDeclMap to directly reference globals
instead of mapping the decl to a bitcast of the global to the correct
type.
 
 - GetAddrOf{Function,GlobalVar} introduce the bitcast on every use now.

 - This solves a problem where a dangling pointer could be introduced
   by the RAUW done when replacing a forward or tentative
   definition. See testcase for more details.

 - Fixes <rdar://problem/6108358>

Added:
    cfe/trunk/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c
Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=54211&r1=54210&r2=54211&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Wed Jul 30 11:32:24 2008
@@ -476,9 +476,9 @@
 /// ReplaceMapValuesWith - This is a really slow and bad function that
 /// searches for any entries in GlobalDeclMap that point to OldVal, changing
 /// them to point to NewVal.  This is badbadbad, FIXME!
-void CodeGenModule::ReplaceMapValuesWith(llvm::Constant *OldVal,
-                                         llvm::Constant *NewVal) {
-  for (llvm::DenseMap<const Decl*, llvm::Constant*>::iterator 
+void CodeGenModule::ReplaceMapValuesWith(llvm::GlobalValue *OldVal,
+                                         llvm::GlobalValue *NewVal) {
+  for (llvm::DenseMap<const Decl*, llvm::GlobalValue*>::iterator 
        I = GlobalDeclMap.begin(), E = GlobalDeclMap.end(); I != E; ++I)
     if (I->second == OldVal) I->second = NewVal;
 }
@@ -525,38 +525,41 @@
   }
 }
 
-llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D) {
+ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D) {
   assert(D->hasGlobalStorage() && "Not a global variable");
 
-  // See if it is already in the map.
-  llvm::Constant *&Entry = GlobalDeclMap[D];
-  if (Entry) return Entry;
-
   QualType ASTTy = D->getType();
   const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
+  const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
 
-  // Check to see if the global already exists.
-  llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
+  // See if it is already in the map.
+  llvm::GlobalValue *&Entry = GlobalDeclMap[D];
 
-  // If it doesn't already exist, just create and return an entry.
-  if (GV == 0) {
-    return Entry = new llvm::GlobalVariable(Ty, false, 
-                                            llvm::GlobalValue::ExternalLinkage,
-                                            0, D->getName(), &getModule(), 0,
-                                            ASTTy.getAddressSpace());
+  // If not look for an existing global (if this decl shadows another
+  // one) or lazily create a forward declaration.
+  if (!Entry) {
+    // Check to see if the global already exists.
+    llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
+
+    // Create it if not.
+    if (!GV)
+      GV = new llvm::GlobalVariable(Ty, false, 
+                                    llvm::GlobalValue::ExternalLinkage,
+                                    0, D->getName(), &getModule(), 0,
+                                    ASTTy.getAddressSpace());
+
+    // Cache the entry.
+    Entry = GV;
   }
 
-  // Otherwise, it already exists; return the existing version
-  llvm::PointerType *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
-  return Entry = llvm::ConstantExpr::getBitCast(GV, PTy);
+  // Make sure the result is of the correct type.
+  return llvm::ConstantExpr::getBitCast(Entry, PTy);
 }
 
 void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   llvm::Constant *Init = 0;
   QualType ASTTy = D->getType();
   const llvm::Type *VarTy = getTypes().ConvertTypeForMem(ASTTy);
-  const llvm::Type *VarPtrTy =
-      llvm::PointerType::get(VarTy, ASTTy.getAddressSpace());
 
   if (D->getInit() == 0) {
     // This is a tentative definition; tentative definitions are
@@ -617,13 +620,13 @@
     // Make sure we don't keep around any stale references to globals
     // FIXME: This is really slow; we need a better way to walk all
     // the decls with the same name
-    ReplaceMapValuesWith(OldGV, NewPtrForOldDecl);
+    ReplaceMapValuesWith(OldGV, GV);
 
     // Erase the old global, since it is no longer used.
     OldGV->eraseFromParent();
   }
 
-  GlobalDeclMap[D] = llvm::ConstantExpr::getBitCast(GV, VarPtrTy);
+  GlobalDeclMap[D] = GV;
 
   if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
     SourceManager &SM = Context.getSourceManager();
@@ -713,26 +716,32 @@
 }
 
 llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
-  // See if it is already in the map.  If so, just return it.
-  llvm::Constant *&Entry = GlobalDeclMap[D];
-  if (Entry) return Entry;
-  
-  // Check to see if the function already exists; this occurs when
-  // this decl shadows a previous one. If it exists we bitcast it to
-  // the proper type for this decl and return.
-  llvm::Function *F = getModule().getFunction(D->getName());
-  if (F) {
-    const llvm::Type *Ty = getTypes().ConvertType(D->getType());
-    llvm::Type *PFTy = llvm::PointerType::getUnqual(Ty);
-    return Entry = llvm::ConstantExpr::getBitCast(F, PFTy);
+  QualType ASTTy = D->getType();
+  const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
+  const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
+
+  // See if it is already in the map.  
+  llvm::GlobalValue *&Entry = GlobalDeclMap[D];
+
+  // If not look for an existing global (if this decl shadows another
+  // one) or lazily create a forward declaration.
+  if (!Entry) {  
+    // Check to see if the global already exists.
+    llvm::GlobalValue *GV = getModule().getFunction(D->getName());
+
+    // Create it if not.
+    if (!GV)
+      GV = EmitForwardFunctionDefinition(D);
+
+    // Cache the entry.
+    Entry = GV;
   }
 
-  // It doesn't exist; create and return an entry.
-  return Entry = EmitForwardFunctionDefinition(D);
+  return llvm::ConstantExpr::getBitCast(Entry, PTy);
 }
 
 void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
-  llvm::Constant *&Entry = GlobalDeclMap[D];
+  llvm::GlobalValue *&Entry = GlobalDeclMap[D];
 
   const llvm::Type *Ty = getTypes().ConvertType(D->getType());
   const llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
@@ -770,7 +779,7 @@
       // FIXME: Update the globaldeclmap for the previous decl of this name.  We
       // really want a way to walk all of these, but we don't have it yet.  This
       // is incredibly slow!
-      ReplaceMapValuesWith(F, NewPtrForOldDecl);
+      ReplaceMapValuesWith(F, NewFn);
       
       // Ok, delete the old function now, which is dead.
       assert(F->isDeclaration() && "Shouldn't replace non-declaration");

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=54211&r1=54210&r2=54211&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Wed Jul 30 11:32:24 2008
@@ -66,7 +66,12 @@
   llvm::Function *MemCpyFn;
   llvm::Function *MemMoveFn;
   llvm::Function *MemSetFn;
-  llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap;
+
+  /// GlobalDeclMap - Mapping of decls to global variables we have
+  /// already emitted. Note that the entries in this map are the
+  /// actual global and therefore may not be of the same type as the
+  /// decl, they should be bitcasted on retrieval.
+  llvm::DenseMap<const Decl*, llvm::GlobalValue*> GlobalDeclMap;
 
   /// List of static global for which code generation is delayed. When
   /// the translation unit has been fully processed we will lazily
@@ -155,7 +160,7 @@
   /// ReplaceMapValuesWith - This is a really slow and bad function that
   /// searches for any entries in GlobalDeclMap that point to OldVal, changing
   /// them to point to NewVal.  This is badbadbad, FIXME!
-  void ReplaceMapValuesWith(llvm::Constant *OldVal, llvm::Constant *NewVal);
+  void ReplaceMapValuesWith(llvm::GlobalValue *OldVal, llvm::GlobalValue *NewVal);
 
   void SetFunctionAttributes(const FunctionDecl *FD,
                              llvm::Function *F,

Added: cfe/trunk/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c?rev=54211&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c (added)
+++ cfe/trunk/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c Wed Jul 30 11:32:24 2008
@@ -0,0 +1,28 @@
+// RUN: clang --emit-llvm -o - %s
+// <rdar://problem/6108358>
+
+/* For posterity, the issue here begins initial "char []" decl for
+ * s. This is a tentative definition and so a global was being
+ * emitted, however the mapping in GlobalDeclMap referred to a bitcast
+ * of this global.
+ *
+ * The problem was that later when the correct definition for s is
+ * emitted we were doing a RAUW on the old global which was destroying
+ * the bitcast in the GlobalDeclMap (since it cannot be replaced
+ * properly), leaving a dangling pointer.
+ *
+ * The purpose of bar is just to trigger a use of the old decl
+ * sometime after the dangling pointer has been introduced.
+ */
+
+char s[];
+
+static void bar(void *db) {
+  eek(s);
+}
+
+char s[5] = "hi";
+
+int foo() {
+  bar(0);
+}





More information about the cfe-commits mailing list