[cfe-commits] r55966 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/PR2743-reference-missing-static.c test/CodeGen/rdr-6095112-alias-references-inline.c test/CodeGen/rdr-6140807-alias-references-forward.c

Daniel Dunbar daniel at zuster.org
Mon Sep 8 16:44:32 PDT 2008


Author: ddunbar
Date: Mon Sep  8 18:44:31 2008
New Revision: 55966

URL: http://llvm.org/viewvc/llvm-project?rev=55966&view=rev
Log:
Fix a number of issues w.r.t. emission of global for functions and
aliases.
 - Attributes specific to a definition are only set when the
   definition is seen.
 - Alias generation is delayed until the end of the module; necessary
   since the alias may reference forward.
 - Fixes: PR2743, <rdr://6140807&6094512>
 - Improves: <rdr://6095112> (added XFAIL)

Also, print module on verification failures.

Added:
    cfe/trunk/test/CodeGen/PR2743-reference-missing-static.c
    cfe/trunk/test/CodeGen/rdr-6095112-alias-references-inline.c
    cfe/trunk/test/CodeGen/rdr-6140807-alias-references-forward.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=55966&r1=55965&r2=55966&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Sep  8 18:44:31 2008
@@ -56,6 +56,7 @@
 
 void CodeGenModule::Release() {
   EmitStatics();
+  EmitAliases();
   if (Runtime)
     if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
       AddGlobalCtor(ObjCInitFunction);
@@ -63,7 +64,10 @@
   EmitCtorList(GlobalDtors, "llvm.global_dtors");
   EmitAnnotations();
   // Run the verifier to check that the generated code is consistent.
-  assert(!verifyModule(TheModule));
+  if (verifyModule(TheModule, llvm::PrintMessageAction)) {
+    TheModule.dump();
+    assert(0 && "Module failed verification!");
+  }
 }
 
 /// ErrorUnsupported - Print out an error that codegen doesn't support the
@@ -176,18 +180,25 @@
 static void SetGlobalValueAttributes(const Decl *D, 
                                      bool IsInternal,
                                      bool IsInline,
-                                     llvm::GlobalValue *GV) {
+                                     llvm::GlobalValue *GV,
+                                     bool ForDefinition) {
   // TODO: Set up linkage and many other things.  Note, this is a simple 
   // approximation of what we really want.
-  if (IsInternal) {
-    GV->setLinkage(llvm::Function::InternalLinkage);
-  } else {
+  if (!ForDefinition) {
+    // Only a few attributes are set on declarations.
     if (D->getAttr<DLLImportAttr>())
       GV->setLinkage(llvm::Function::DLLImportLinkage);
-    else if (D->getAttr<DLLExportAttr>())
-      GV->setLinkage(llvm::Function::DLLExportLinkage);
-    else if (D->getAttr<WeakAttr>() || IsInline)
-      GV->setLinkage(llvm::Function::WeakLinkage);
+  } else {
+    if (IsInternal) {
+      GV->setLinkage(llvm::Function::InternalLinkage);
+    } else {
+      if (D->getAttr<DLLImportAttr>())
+        GV->setLinkage(llvm::Function::DLLImportLinkage);
+      else if (D->getAttr<DLLExportAttr>())
+        GV->setLinkage(llvm::Function::DLLExportLinkage);
+      else if (D->getAttr<WeakAttr>() || IsInline)
+        GV->setLinkage(llvm::Function::WeakLinkage);
+    }
   }
 
   if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>())
@@ -201,7 +212,7 @@
   }
 }
 
-static void SetFunctionAttrs(const CGFunctionInfo &Info, llvm::Function *F) {
+static void SetFunctionParamAttrs(const CGFunctionInfo &Info, llvm::Function *F) {
   ParamAttrListType ParamAttrList;
   Info.constructParamAttrList(ParamAttrList);
 
@@ -215,26 +226,79 @@
 
 /// SetFunctionAttributesForDefinition - Set function attributes
 /// specific to a function definition.
-void CodeGenModule::SetFunctionAttributesForDefinition(llvm::Function *F) {
+void CodeGenModule::SetFunctionAttributesForDefinition(const Decl *D,
+                                                       llvm::Function *F) {
+  if (isa<ObjCMethodDecl>(D)) {
+    SetGlobalValueAttributes(D, true, false, F, true);
+  } else {
+    const FunctionDecl *FD = cast<FunctionDecl>(D);
+    SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
+                             FD->isInline(), F, true);
+  }
+                             
   if (!Features.Exceptions)
     F->addParamAttr(0, llvm::ParamAttr::NoUnwind);  
 }
 
 void CodeGenModule::SetMethodAttributes(const ObjCMethodDecl *MD,
                                         llvm::Function *F) {
-  SetFunctionAttrs(CGFunctionInfo(MD, Context), F);
+  SetFunctionParamAttrs(CGFunctionInfo(MD, Context), F);
   
-  SetFunctionAttributesForDefinition(F);
-
-  SetGlobalValueAttributes(MD, true, false, F);
+  SetFunctionAttributesForDefinition(MD, F);
 }
 
 void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD,
                                           llvm::Function *F) {
-  SetFunctionAttrs(CGFunctionInfo(FD), F);
+  SetFunctionParamAttrs(CGFunctionInfo(FD), F);
+
+  SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static,
+                           FD->isInline(), F, false);
+}
+
+void CodeGenModule::EmitAliases() {
+  for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
+    const FunctionDecl *D = Aliases[i];
+    const AliasAttr *AA = D->getAttr<AliasAttr>();
+
+    // This is something of a hack, if the FunctionDecl got overridden
+    // then its attributes will be moved to the new declaration. In
+    // this case the current decl has no alias attribute, but we will
+    // eventually see it.
+    if (!AA)
+      continue;
+
+    const std::string& aliaseeName = AA->getAliasee();
+    llvm::Function *aliasee = getModule().getFunction(aliaseeName);
+    if (!aliasee) {
+      // FIXME: This isn't unsupported, this is just an error, which
+      // sema should catch, but...
+      ErrorUnsupported(D, "alias referencing a missing function");
+      continue;
+    }
+
+    llvm::GlobalValue *GA = 
+      new llvm::GlobalAlias(aliasee->getType(),
+                            llvm::Function::ExternalLinkage,
+                            D->getName(),
+                            aliasee,
+                            &getModule());
+    
+    llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
+    if (Entry) {
+      // If we created a dummy function for this then replace it.
+      GA->takeName(Entry);
+            
+      llvm::Value *Casted = 
+        llvm::ConstantExpr::getBitCast(GA, Entry->getType());
+      Entry->replaceAllUsesWith(Casted);
+      Entry->eraseFromParent();
+
+      Entry = GA;
+    }
 
-  SetGlobalValueAttributes(FD, FD->getStorageClass() == FunctionDecl::Static, 
-                           FD->isInline(), F);
+    // Alias should never be internal or inline.
+    SetGlobalValueAttributes(D, false, false, GA, true);
+  }
 }
 
 void CodeGenModule::EmitStatics() {
@@ -250,6 +314,8 @@
       // Check if we have used a decl with the same name
       // FIXME: The AST should have some sort of aggregate decls or
       // global symbol map.
+      // FIXME: This is missing some important cases. For example, we
+      // need to check for uses in an alias and in a constructor.
       if (!GlobalDeclMap.count(D->getIdentifier()))
         continue;
 
@@ -316,8 +382,16 @@
   bool isDef, isStatic;
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
-    isDef = (FD->isThisDeclarationADefinition() ||
-             FD->getAttr<AliasAttr>());
+    // Aliases are deferred until code for everything else has been
+    // emitted.
+    if (FD->getAttr<AliasAttr>()) {
+      assert(!FD->isThisDeclarationADefinition() && 
+             "Function alias cannot have a definition!");
+      Aliases.push_back(FD);
+      return;
+    }
+
+    isDef = FD->isThisDeclarationADefinition();
     isStatic = FD->getStorageClass() == FunctionDecl::Static;
   } else if (const VarDecl *VD = cast<VarDecl>(Global)) {
     assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
@@ -512,29 +586,12 @@
 
 llvm::GlobalValue *
 CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) {
-  // FIXME: param attributes for sext/zext etc.
-  if (const AliasAttr *AA = D->getAttr<AliasAttr>()) {
-    assert(!D->getBody() && "Unexpected alias attr on function with body.");
-    
-    const std::string& aliaseeName = AA->getAliasee();
-    llvm::Function *aliasee = getModule().getFunction(aliaseeName);
-    llvm::GlobalValue *alias = new llvm::GlobalAlias(aliasee->getType(),
-                                              llvm::Function::ExternalLinkage,
-                                                     D->getName(),
-                                                     aliasee,
-                                                     &getModule());
-    // Alias should never be internal
-    SetGlobalValueAttributes(D, false, false, alias);
-    return alias;
-  } else {
-    const llvm::Type *Ty = getTypes().ConvertType(D->getType());
-    llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
-                                               llvm::Function::ExternalLinkage,
-                                               D->getName(), &getModule());
-    
-    SetFunctionAttributes(D, F);
-    return F;
-  }
+  const llvm::Type *Ty = getTypes().ConvertType(D->getType());
+  llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), 
+                                             llvm::Function::ExternalLinkage,
+                                             D->getName(), &getModule());
+  SetFunctionAttributes(D, F);
+  return F;
 }
 
 llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
@@ -575,33 +632,22 @@
       Entry->replaceAllUsesWith(NewPtrForOldDecl);
             
       // Ok, delete the old function now, which is dead.
-      // FIXME: Add GlobalValue->eraseFromParent().
       assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
-      if (llvm::Function *F = dyn_cast<llvm::Function>(Entry)) {
-        F->eraseFromParent();
-      } else if (llvm::GlobalAlias *GA = dyn_cast<llvm::GlobalAlias>(Entry)) {
-        GA->eraseFromParent();
-      } else {
-        assert(0 && "Invalid global variable type.");
-      }
+      Entry->eraseFromParent();
       
       Entry = NewFn;
     }
   }
 
-  if (D->getAttr<AliasAttr>()) {
-    ;
-  } else {
-    llvm::Function *Fn = cast<llvm::Function>(Entry);    
-    CodeGenFunction(*this).GenerateCode(D, Fn);
-
-    SetFunctionAttributesForDefinition(Fn);
+  llvm::Function *Fn = cast<llvm::Function>(Entry);    
+  CodeGenFunction(*this).GenerateCode(D, Fn);
 
-    if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
-      AddGlobalCtor(Fn, CA->getPriority());
-    } else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
-      AddGlobalDtor(Fn, DA->getPriority());
-    }
+  SetFunctionAttributesForDefinition(D, Fn);
+  
+  if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) {
+    AddGlobalCtor(Fn, CA->getPriority());
+  } else if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) {
+    AddGlobalDtor(Fn, DA->getPriority());
   }
 }
 

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Sep  8 18:44:31 2008
@@ -79,11 +79,16 @@
   /// (which may change with attributes such as asm-labels).
   llvm::DenseMap<IdentifierInfo*, llvm::GlobalValue*> GlobalDeclMap;
 
-  /// List of static global for which code generation is delayed. When
-  /// the translation unit has been fully processed we will lazily
-  /// emit definitions for only the decls that were actually used.
-  /// This should contain only Function and Var decls, and only those
-  /// which actually define something.
+  /// Aliases - List of aliases in module. These cannot be emitted
+  /// until all the code has been seen, as they reference things by
+  /// name instead of directly and may reference forward.
+  std::vector<const FunctionDecl*> Aliases;
+
+  /// StaticDecls - List of static global for which code generation is
+  /// delayed. When the translation unit has been fully processed we
+  /// will lazily emit definitions for only the decls that were
+  /// actually used.  This should contain only Function and Var decls,
+  /// and only those which actually define something.
   std::vector<const ValueDecl*> StaticDecls;
   
   /// GlobalCtors - Store the list of global constructors and their
@@ -213,7 +218,9 @@
 private:
   /// SetFunctionAttributesForDefinition - Set function attributes
   /// specific to a function definition.
-  void SetFunctionAttributesForDefinition(llvm::Function *F);
+  /// \param D - The ObjCMethodDecl or FunctionDecl defining \arg F.
+  void SetFunctionAttributesForDefinition(const Decl *D,
+                                          llvm::Function *F);
 
   void SetFunctionAttributes(const FunctionDecl *FD,
                              llvm::Function *F);
@@ -238,9 +245,9 @@
   /// or destructor array.
   void EmitCtorList(const CtorList &Fns, const char *GlobalName);
 
+  void EmitAliases(void);
   void EmitAnnotations(void);
   void EmitStatics(void);
-
 };
 }  // end namespace CodeGen
 }  // end namespace clang

Added: cfe/trunk/test/CodeGen/PR2743-reference-missing-static.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/PR2743-reference-missing-static.c?rev=55966&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/PR2743-reference-missing-static.c (added)
+++ cfe/trunk/test/CodeGen/PR2743-reference-missing-static.c Mon Sep  8 18:44:31 2008
@@ -0,0 +1,16 @@
+// RUN: clang -emit-llvm -o %t %s
+// PR2743
+// <rdr://6094512>
+
+/* CodeGen should handle this even if it makes it past
+   sema. Unfortunately this test will become useless once sema starts
+   rejecting this. */
+
+static void e0();
+void f0() { e0(); }
+
+inline void e1();
+void f1() { e1(); }
+
+void e2() __attribute__((weak));
+void f2() { e2(); }

Added: cfe/trunk/test/CodeGen/rdr-6095112-alias-references-inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/rdr-6095112-alias-references-inline.c?rev=55966&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/rdr-6095112-alias-references-inline.c (added)
+++ cfe/trunk/test/CodeGen/rdr-6095112-alias-references-inline.c Mon Sep  8 18:44:31 2008
@@ -0,0 +1,6 @@
+// RUN: clang --emit-llvm -o %t %s &&
+// RUN: grep -e "alias" %t
+// XFAIL
+
+static inline int foo () { return 0; }
+int bar () __attribute__ ((alias ("foo")));

Added: cfe/trunk/test/CodeGen/rdr-6140807-alias-references-forward.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/rdr-6140807-alias-references-forward.c?rev=55966&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/rdr-6140807-alias-references-forward.c (added)
+++ cfe/trunk/test/CodeGen/rdr-6140807-alias-references-forward.c Mon Sep  8 18:44:31 2008
@@ -0,0 +1,14 @@
+// RUN: clang -emit-llvm -o %t %s &&
+// RUN: grep -e "@f = alias" %t | count 1 &&
+// RUN: grep -e "bitcast (i32 (i32)\\* @f to i32 (float)\\*)" %t | count 1
+// <rdar://problem/6140807>
+
+int f(float) __attribute__((weak, alias("x")));
+
+// Make sure we replace uses properly...
+int y() {
+  return f(1.);
+}
+
+int x(int) {
+}





More information about the cfe-commits mailing list