[cfe-commits] r97733 - in /cfe/trunk: lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGen/attr-weakref.c test/CodeGen/attr-weakref2.c test/CodeGen/attributes.c

Rafael Espindola rafael.espindola at gmail.com
Thu Mar 4 10:17:24 PST 2010


Author: rafael
Date: Thu Mar  4 12:17:24 2010
New Revision: 97733

URL: http://llvm.org/viewvc/llvm-project?rev=97733&view=rev
Log:
Fix PR6473.

Clang's support for weakref is now better than llvm-gcc's :-)

We don't introduce a new symbol and we correctly mark undefined references weak only if there is no
definition or regular undefined references in the same file.


Added:
    cfe/trunk/test/CodeGen/attr-weakref.c
    cfe/trunk/test/CodeGen/attr-weakref2.c
Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/test/CodeGen/attributes.c

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=97733&r1=97732&r2=97733&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Mar  4 12:17:24 2010
@@ -1062,6 +1062,16 @@
 LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
   const NamedDecl *ND = E->getDecl();
 
+  if (ND->hasAttr<WeakRefAttr>()) {
+    const ValueDecl* VD = cast<ValueDecl>(ND);
+    llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
+
+    Qualifiers Quals = MakeQualifiers(E->getType());
+    LValue LV = LValue::MakeAddr(Aliasee, Quals);
+
+    return LV;
+  }
+
   if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
     
     // Check if this is a global variable.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=97733&r1=97732&r2=97733&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Mar  4 12:17:24 2010
@@ -619,9 +619,41 @@
   return false;
 }
 
+llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
+  const AliasAttr *AA = VD->getAttr<AliasAttr>();
+  assert(AA && "No alias?");
+
+  const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType());
+
+  // Unique the name through the identifier table.
+  const char *AliaseeName =
+    getContext().Idents.get(AA->getAliasee()).getNameStart();
+
+  // See if there is already something with the target's name in the module.
+  llvm::GlobalValue *Entry = GlobalDeclMap[AliaseeName];
+
+  llvm::Constant *Aliasee;
+  if (isa<llvm::FunctionType>(DeclTy))
+    Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl());
+  else
+    Aliasee = GetOrCreateLLVMGlobal(AliaseeName,
+                                    llvm::PointerType::getUnqual(DeclTy), 0);
+  if (!Entry) {
+    llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee);
+    F->setLinkage(llvm::Function::ExternalWeakLinkage);    
+    WeakRefReferences.insert(F);
+  }
+
+  return Aliasee;
+}
+
 void CodeGenModule::EmitGlobal(GlobalDecl GD) {
   const ValueDecl *Global = cast<ValueDecl>(GD.getDecl());
 
+  // Weak references don't produce any output by themselves.
+  if (Global->hasAttr<WeakRefAttr>())
+    return;
+
   // If this is an alias definition (which otherwise looks like a declaration)
   // emit it now.
   if (Global->hasAttr<AliasAttr>())
@@ -708,6 +740,14 @@
   // Lookup the entry, lazily creating it if necessary.
   llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
   if (Entry) {
+    if (WeakRefReferences.count(Entry)) {
+      const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl());
+      if (FD && !FD->hasAttr<WeakAttr>())
+	Entry->setLinkage(llvm::Function::ExternalLinkage);
+
+      WeakRefReferences.erase(Entry);
+    }
+
     if (Entry->getType()->getElementType() == Ty)
       return Entry;
 
@@ -817,6 +857,13 @@
   // Lookup the entry, lazily creating it if necessary.
   llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
   if (Entry) {
+    if (WeakRefReferences.count(Entry)) {
+      if (D && !D->hasAttr<WeakAttr>())
+	Entry->setLinkage(llvm::Function::ExternalLinkage);
+
+      WeakRefReferences.erase(Entry);
+    }
+
     if (Entry->getType() == Ty)
       return Entry;
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=97733&r1=97732&r2=97733&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Mar  4 12:17:24 2010
@@ -29,6 +29,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/ValueHandle.h"
 #include <list>
 
@@ -117,6 +118,11 @@
   /// pointer lookups instead of full string lookups.
   llvm::DenseMap<const char*, llvm::GlobalValue*> GlobalDeclMap;
 
+  // WeakRefReferences - A set of references that have only been seen via
+  // a weakref so far. This is used to remove the weak of the reference if we ever
+  // see a direct reference or a definition.
+  llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences;
+
   /// \brief Contains the strings used for mangled names.
   ///
   /// FIXME: Eventually, this should map from the semantic/canonical
@@ -243,6 +249,9 @@
   void BuildThunksForVirtual(GlobalDecl GD);
   void BuildThunksForVirtualRecursive(GlobalDecl GD, GlobalDecl BaseOGD);
 
+  /// GetWeakRefReference - Get a reference to the target of VD.
+  llvm::Constant *GetWeakRefReference(const ValueDecl *VD);
+
   /// BuildThunk - Build a thunk for the given method.
   llvm::Constant *BuildThunk(GlobalDecl GD, bool Extern, 
                              const ThunkAdjustment &ThisAdjustment);

Added: cfe/trunk/test/CodeGen/attr-weakref.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-weakref.c?rev=97733&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/attr-weakref.c (added)
+++ cfe/trunk/test/CodeGen/attr-weakref.c Thu Mar  4 12:17:24 2010
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s
+// RUN: FileCheck --input-file=%t %s
+
+// CHECK: declare extern_weak void @test1_f()
+void test1_f(void);
+static void test1_g(void) __attribute__((weakref("test1_f")));
+void test1_h(void) {
+  test1_g();
+}
+
+// CHECK: define void @test2_f()
+void test2_f(void) {}
+static void test2_g(void) __attribute__((weakref("test2_f")));
+void test2_h(void) {
+  test2_g();
+}
+
+// CHECK: declare void @test3_f()
+void test3_f(void);
+static void test3_g(void) __attribute__((weakref("test3_f")));
+void test3_foo(void) {
+  test3_f();
+}
+void test3_h(void) {
+  test3_g();
+}
+
+// CHECK: define void @test4_f()
+void test4_f(void);
+static void test4_g(void) __attribute__((weakref("test4_f")));
+void test4_h(void) {
+  test4_g();
+}
+void test4_f(void) {}
+
+// CHECK: declare void @test5_f()
+void test5_f(void);
+static void test5_g(void) __attribute__((weakref("test5_f")));
+void test5_h(void) {
+  test5_g();
+}
+void test5_foo(void) {
+  test5_f();
+}
+
+// CHECK: declare extern_weak void @test6_f()
+void test6_f(void) __attribute__((weak));
+static void test6_g(void) __attribute__((weakref("test6_f")));
+void test6_h(void) {
+  test6_g();
+}
+void test6_foo(void) {
+  test6_f();
+}

Added: cfe/trunk/test/CodeGen/attr-weakref2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-weakref2.c?rev=97733&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/attr-weakref2.c (added)
+++ cfe/trunk/test/CodeGen/attr-weakref2.c Thu Mar  4 12:17:24 2010
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -emit-llvm -triple i386-linux-gnu -o %t %s
+// RUN: FileCheck --input-file=%t %s
+
+// CHECK: @test1_f = extern_weak global i32
+extern int test1_f;
+static int test1_g __attribute__((weakref("test1_f")));
+int test1_h(void) {
+  return test1_g;
+}
+
+// CHECK: @test2_f = common global i32 0, align 4
+int test2_f;
+static int test2_g __attribute__((weakref("test2_f")));
+int test2_h(void) {
+  return test2_g;
+}
+
+// CHECK: @test3_f = external global i32
+extern int test3_f;
+static int test3_g __attribute__((weakref("test3_f")));
+int test3_foo(void) {
+  return test3_f;
+}
+int test3_h(void) {
+  return test3_g;
+}
+
+// CHECK: @test4_f = common global i32 0, align 4
+extern int test4_f;
+static int test4_g __attribute__((weakref("test4_f")));
+int test4_h(void) {
+  return test4_g;
+}
+int test4_f;
+
+// CHECK: @test5_f = external global i32
+extern int test5_f;
+static int test5_g __attribute__((weakref("test5_f")));
+int test5_h(void) {
+  return test5_g;
+}
+int test5_foo(void) {
+  return test5_f;
+}
+
+// CHECK: @test6_f = extern_weak global i32
+extern int test6_f __attribute__((weak));
+static int test6_g __attribute__((weakref("test6_f")));
+int test6_h(void) {
+  return test6_g;
+}
+int test6_foo(void) {
+  return test6_f;
+}

Modified: cfe/trunk/test/CodeGen/attributes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attributes.c?rev=97733&r1=97732&r2=97733&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attributes.c (original)
+++ cfe/trunk/test/CodeGen/attributes.c Thu Mar  4 12:17:24 2010
@@ -30,12 +30,6 @@
 void __t8() {}
 void t9() __attribute__((weak, alias("__t8")));
 
-static void t22(void) __attribute__((weakref("t8")));
-// CHECK: @t22 = alias weak void ()* @t8
-
-static void t23(void) __attribute__((weakref, alias("t8")));
-// CHECK: @t23 = alias weak void ()* @t8
-
 // CHECK: declare extern_weak i32 @t15()
 int __attribute__((weak_import)) t15(void);
 int t17() {





More information about the cfe-commits mailing list