[cfe-commits] r69030 - in /cfe/trunk: lib/CodeGen/CodeGenModule.cpp test/CodeGen/inline.c

Chris Lattner sabre at nondot.org
Mon Apr 13 23:27:57 PDT 2009


Author: lattner
Date: Tue Apr 14 01:27:57 2009
New Revision: 69030

URL: http://llvm.org/viewvc/llvm-project?rev=69030&view=rev
Log:
set the linkage of an inline function according to its language rules.


Added:
    cfe/trunk/test/CodeGen/inline.c
Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Apr 14 01:27:57 2009
@@ -262,8 +262,32 @@
     }
   } else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>()) {
     GV->setLinkage(llvm::Function::WeakAnyLinkage);
-  } else if (Linkage == GVA_Inline || Linkage == GVA_ExternInline) {
-    GV->setLinkage(llvm::Function::WeakAnyLinkage);
+  } else if (Linkage == GVA_ExternInline) {
+    // "extern inline" always gets available_externally linkage, which is the
+    // strongest linkage type we can give an inline function: we don't have to
+    // codegen the definition at all, yet we know that it is "ODR".
+    GV->setLinkage(llvm::Function::AvailableExternallyLinkage);
+  } else if (Linkage == GVA_Inline) {
+    // The definition of inline changes based on the language.  Note that we
+    // have already handled "static inline" above, with the GVA_Internal case.
+    if (Features.CPlusPlus) {
+      // In C++, the compiler has to emit a definition in every translation unit
+      // that references the function.  We should use linkonce_odr because
+      // a) if all references in this translation unit are optimized away, we
+      // don't need to codegen it.  b) if the function persists, it needs to be
+      // merged with other definitions. c) C++ has the ODR, so we know the
+      // definition is dependable.
+      GV->setLinkage(llvm::Function::LinkOnceODRLinkage);
+    } else if (Features.C99) {
+      // In C99 mode, 'inline' functions are guaranteed to have a strong
+      // definition somewhere else, so we can use available_externally linkage.
+      GV->setLinkage(llvm::Function::AvailableExternallyLinkage);
+    } else {
+      // In C89 mode, an 'inline' function may only occur in one translation
+      // unit in the program, but may be extern'd in others.  Give it strong
+      // external linkage.
+      GV->setLinkage(llvm::Function::ExternalLinkage);
+    }
   }
 
   if (ForDefinition) {

Added: cfe/trunk/test/CodeGen/inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/inline.c?rev=69030&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/inline.c (added)
+++ cfe/trunk/test/CodeGen/inline.c Tue Apr 14 01:27:57 2009
@@ -0,0 +1,29 @@
+// RUN: clang %s -emit-llvm -S -o %t -std=c89 &&
+// RUN: grep "define available_externally i32 @ei()" %t &&
+// RUN: grep "define i32 @foo()" %t &&
+// RUN: grep "define i32 @bar()" %t &&
+// RUN: grep "define void @unreferenced()" %t &&
+
+// RUN: clang %s -emit-llvm -S -o %t -std=c99 &&
+// RUN: grep "define available_externally i32 @ei()" %t &&
+// RUN: grep "define available_externally i32 @foo()" %t &&
+// RUN: grep "define i32 @bar()" %t &&
+// RUN: grep "define available_externally void @unreferenced()" %t &&
+
+// RUN: clang %s -emit-llvm -S -o %t -std=c++98 &&
+// RUN: grep "define available_externally i32 @_Z2eiv()" %t &&
+// RUN: grep "define linkonce_odr i32 @_Z3foov()" %t &&
+// RUN: grep "define i32 @_Z3barv()" %t &&
+// RUN: grep "define linkonce_odr void @_Z12unreferencedv()" %t
+
+extern inline int ei() { return 123; }
+
+inline int foo() {
+  return ei();
+}
+
+int bar() { return foo(); }
+
+
+inline void unreferenced() {}
+





More information about the cfe-commits mailing list