Add a new "available_externally" linkage type.  This is intended
to support C99 inline, GNU extern inline, etc.  Related bugzilla's
include PR3517, PR3100, & PR2933.  Nothing uses this yet, but it
appears to work.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68940 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 457a56a..8ec1123 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -509,6 +509,17 @@
   '<tt>static</tt>' keyword in C.
   </dd>
 
+  <dt><tt><b><a name="available_externally">available_externally</a></b></tt>:
+  </dt>
+
+  <dd>Globals with "<tt>available_externally</tt>" linkage are never emitted
+  into the object file corresponding to the LLVM module.  They exist to
+  allow inlining and other optimizations to take place given knowledge of the
+  definition of the global, which is known to be somewhere outside the module.
+  Globals with <tt>available_externally</tt> linkage are allowed to be discarded
+  at will, and are otherwise the same as <tt>linkonce_odr</tt>.  This linkage
+  type is only allowed on definitions, not declarations.</dd>
+
   <dt><tt><b><a name="linkage_linkonce">linkonce</a></b></tt>: </dt>
 
   <dd>Globals with "<tt>linkonce</tt>" linkage are merged with other globals of
@@ -554,10 +565,10 @@
 
   <dt><tt><b><a name="linkage_linkonce">linkonce_odr</a></b></tt>: </dt>
   <dt><tt><b><a name="linkage_weak">weak_odr</a></b></tt>: </dt>
-  <dd>Some languages allow inequivalent globals to be merged, such as two
+  <dd>Some languages allow differing globals to be merged, such as two
     functions with different semantics.  Other languages, such as <tt>C++</tt>,
     ensure that only equivalent globals are ever merged (the "one definition
-    rule" - <tt>odr</tt>).  Such languages can use the <tt>linkonce_odr</tt>
+    rule" - "ODR").  Such languages can use the <tt>linkonce_odr</tt>
     and <tt>weak_odr</tt> linkage types to indicate that the global will only
     be merged with equivalent globals.  These linkage types are otherwise the
     same as their non-<tt>odr</tt> versions.
diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h
index 95bb2bf..6b5e64a 100644
--- a/include/llvm/CodeGen/MachineFunctionPass.h
+++ b/include/llvm/CodeGen/MachineFunctionPass.h
@@ -24,8 +24,9 @@
 
 namespace llvm {
 
+  // FIXME: This pass should declare that the pass does not invalidate any LLVM
+  // passes.
 struct MachineFunctionPass : public FunctionPass {
-
   explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {}
   explicit MachineFunctionPass(void *ID) : FunctionPass(ID) {}
 
@@ -36,14 +37,7 @@
   virtual bool runOnMachineFunction(MachineFunction &MF) = 0;
 
 public:
-  // FIXME: This pass should declare that the pass does not invalidate any LLVM
-  // passes.
-  bool runOnFunction(Function &F) {
-    return runOnMachineFunction(MachineFunction::get(&F));
-  }
-  
-private:
-  virtual void virtfn();  // out of line virtual fn to give class a home.
+  bool runOnFunction(Function &F);
 };
 
 } // End llvm namespace
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index e6a82ef..50c613e 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -31,6 +31,7 @@
   /// @brief An enumeration for the kinds of linkage for global values.
   enum LinkageTypes {
     ExternalLinkage = 0,///< Externally visible function
+    AvailableExternallyLinkage, ///< Available for inspection, not emission.
     LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline)
     LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent.
     WeakAnyLinkage,     ///< Keep one copy of named function when linking (weak)
@@ -109,6 +110,9 @@
   }
 
   bool hasExternalLinkage() const { return Linkage == ExternalLinkage; }
+  bool hasAvailableExternallyLinkage() const {
+    return Linkage == AvailableExternallyLinkage;
+  }
   bool hasLinkOnceLinkage() const {
     return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage;
   }
@@ -119,7 +123,8 @@
   bool hasInternalLinkage() const { return Linkage == InternalLinkage; }
   bool hasPrivateLinkage() const { return Linkage == PrivateLinkage; }
   bool hasLocalLinkage() const {
-    return Linkage == InternalLinkage || Linkage == PrivateLinkage;
+    return Linkage == InternalLinkage || Linkage == PrivateLinkage ||
+           Linkage == AvailableExternallyLinkage;
   }
   bool hasDLLImportLinkage() const { return Linkage == DLLImportLinkage; }
   bool hasDLLExportLinkage() const { return Linkage == DLLExportLinkage; }
@@ -141,9 +146,10 @@
   }
 
   /// isWeakForLinker - Whether the definition of this global may be replaced at
-  /// link time, whether the replacement is equivalent to the original or not.
+  /// link time.
   bool isWeakForLinker() const {
-    return (Linkage == WeakAnyLinkage ||
+    return (Linkage == AvailableExternallyLinkage ||
+            Linkage == WeakAnyLinkage ||
             Linkage == WeakODRLinkage ||
             Linkage == LinkOnceAnyLinkage ||
             Linkage == LinkOnceODRLinkage ||
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index d4815d8..b227af2 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -487,6 +487,7 @@
 
   KEYWORD(private);
   KEYWORD(internal);
+  KEYWORD(available_externally);
   KEYWORD(linkonce);
   KEYWORD(linkonce_odr);
   KEYWORD(weak);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 177161e..d92957a 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -764,6 +764,9 @@
   case lltok::kw_weak_odr:     Res = GlobalValue::WeakODRLinkage; break;
   case lltok::kw_linkonce:     Res = GlobalValue::LinkOnceAnyLinkage; break;
   case lltok::kw_linkonce_odr: Res = GlobalValue::LinkOnceODRLinkage; break;
+  case lltok::kw_available_externally:
+    Res = GlobalValue::AvailableExternallyLinkage;
+    break;
   case lltok::kw_appending:    Res = GlobalValue::AppendingLinkage; break;
   case lltok::kw_dllexport:    Res = GlobalValue::DLLExportLinkage; break;
   case lltok::kw_common:       Res = GlobalValue::CommonLinkage; break;
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 35cb4db..d8bd38a 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -37,7 +37,7 @@
     kw_global,  kw_constant,
 
     kw_private, kw_internal, kw_linkonce, kw_linkonce_odr, kw_weak, kw_weak_odr,
-    kw_appending, kw_dllimport, kw_dllexport, kw_common,
+    kw_appending, kw_dllimport, kw_dllexport, kw_common,kw_available_externally,
     kw_default, kw_hidden, kw_protected,
     kw_extern_weak,
     kw_external, kw_thread_local,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 6f91dda..8079acd 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -70,6 +70,7 @@
   case 9: return GlobalValue::PrivateLinkage;
   case 10: return GlobalValue::WeakODRLinkage;
   case 11: return GlobalValue::LinkOnceODRLinkage;
+  case 12: return GlobalValue::AvailableExternallyLinkage;
   }
 }
 
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index c836d39..1937c7e 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -287,6 +287,7 @@
   case GlobalValue::PrivateLinkage:      return 9;
   case GlobalValue::WeakODRLinkage:      return 10;
   case GlobalValue::LinkOnceODRLinkage:  return 11;
+  case GlobalValue::AvailableExternallyLinkage:  return 12;
   }
 }
 
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d19e9af..0979ced 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -443,7 +443,9 @@
   }
 
   // Ignore debug and non-emitted data.
-  if (GV->getSection() == "llvm.metadata") return true;
+  if (GV->getSection() == "llvm.metadata" ||
+      GV->hasAvailableExternallyLinkage())
+    return true;
   
   if (!GV->hasAppendingLinkage()) return false;
 
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index d59609b..4582f4a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -3519,6 +3519,9 @@
   ///
   void EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
     Function::LinkageTypes linkage = EHFrameInfo.function->getLinkage();
+    
+    assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && 
+           "Should not emit 'available externally' functions at all");
 
     Asm->SwitchToTextSection(TAI->getDwarfEHFrameSection());
 
diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index bd7105f..18a040e 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -38,8 +38,14 @@
 static AnnotationID MF_AID(
   AnnotationManager::getID("CodeGen::MachineCodeForFunction"));
 
-// Out of line virtual function to home classes.
-void MachineFunctionPass::virtfn() {}
+bool MachineFunctionPass::runOnFunction(Function &F) {
+  // Do not codegen any 'available_externally' functions at all, they have
+  // definitions outside the translation unit.
+  if (F.hasAvailableExternallyLinkage())
+    return false;
+  
+  return runOnMachineFunction(MachineFunction::get(&F));
+}
 
 namespace {
   struct VISIBILITY_HIDDEN Printer : public MachineFunctionPass {
diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp
index 0ca4e10..4a15d88 100644
--- a/lib/Linker/LinkModules.cpp
+++ b/lib/Linker/LinkModules.cpp
@@ -480,9 +480,10 @@
   } else if (Src->isWeakForLinker()) {
     // At this point we know that Dest has LinkOnce, External*, Weak, Common,
     // or DLL* linkage.
-    if ((Dest->hasLinkOnceLinkage() &&
-          (Src->hasWeakLinkage() || Src->hasCommonLinkage())) ||
-        Dest->hasExternalWeakLinkage()) {
+    if (Dest->hasExternalWeakLinkage() ||
+        Dest->hasAvailableExternallyLinkage() ||
+        (Dest->hasLinkOnceLinkage() &&
+         (Src->hasWeakLinkage() || Src->hasCommonLinkage()))) {
       LinkFromSrc = true;
       LT = Src->getLinkage();
     } else {
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 8262408..e89d5f9 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -294,6 +294,8 @@
       Out << "GlobalValue::InternalLinkage"; break;
     case GlobalValue::PrivateLinkage:
       Out << "GlobalValue::PrivateLinkage"; break;
+    case GlobalValue::AvailableExternallyLinkage:
+      Out << "GlobalValue::AvailableExternallyLinkage "; break;
     case GlobalValue::LinkOnceAnyLinkage:
       Out << "GlobalValue::LinkOnceAnyLinkage "; break;
     case GlobalValue::LinkOnceODRLinkage:
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index b1bf42e..e4dd9d6 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -1225,6 +1225,9 @@
   switch (LT) {
   case GlobalValue::PrivateLinkage:     Out << "private "; break;
   case GlobalValue::InternalLinkage:    Out << "internal "; break;
+  case GlobalValue::AvailableExternallyLinkage:
+    Out << "available_externally ";
+    break;
   case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
   case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
   case GlobalValue::WeakAnyLinkage:     Out << "weak "; break;
diff --git a/test/CodeGen/Generic/externally_available.ll b/test/CodeGen/Generic/externally_available.ll
new file mode 100644
index 0000000..73b6b98
--- /dev/null
+++ b/test/CodeGen/Generic/externally_available.ll
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | llc | not grep test_
+
+; test_function should not be emitted to the .s file.
+define available_externally i32 @test_function() {
+  ret i32 4
+}
+
+; test_global should not be emitted to the .s file.
+@test_global = available_externally global i32 4
+
diff --git a/test/Transforms/GlobalDCE/externally_available.ll b/test/Transforms/GlobalDCE/externally_available.ll
new file mode 100644
index 0000000..ccdf7e1
--- /dev/null
+++ b/test/Transforms/GlobalDCE/externally_available.ll
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | opt -globaldce | llvm-dis | not grep test_
+
+; test_function should not be emitted to the .s file.
+define available_externally i32 @test_function() {
+  ret i32 4
+}
+
+; test_global should not be emitted to the .s file.
+@test_global = available_externally global i32 4
+
diff --git a/test/Transforms/Inline/externally_available.ll b/test/Transforms/Inline/externally_available.ll
new file mode 100644
index 0000000..68f7d65
--- /dev/null
+++ b/test/Transforms/Inline/externally_available.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -inline -constprop | llvm-dis > %t
+; RUN: not grep test_function %t
+; RUN: grep {ret i32 5} %t
+
+
+; test_function should not be emitted to the .s file.
+define available_externally i32 @test_function() {
+  ret i32 4
+}
+
+
+define i32 @result() {
+  %A = call i32 @test_function()
+  %B = add i32 %A, 1
+  ret i32 %B
+}
\ No newline at end of file
diff --git a/test/Transforms/InstCombine/odr-linkage.ll b/test/Transforms/InstCombine/odr-linkage.ll
new file mode 100644
index 0000000..96f8833
--- /dev/null
+++ b/test/Transforms/InstCombine/odr-linkage.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i32 10}
+
+@g1 = available_externally constant i32 1
+@g2 = linkonce_odr constant i32 2
+@g3 = weak_odr constant i32 3
+@g4 = internal constant i32 4
+
+define i32 @test() {
+  %A = load i32* @g1
+  %B = load i32* @g2
+  %C = load i32* @g3
+  %D = load i32* @g4
+  
+  %a = add i32 %A, %B
+  %b = add i32 %a, %C
+  %c = add i32 %b, %D
+  ret i32 %c
+}
+   
\ No newline at end of file
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 3449510..324e0f6 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -69,7 +69,6 @@
 }
 
 static char TypeCharForSymbol(GlobalValue &GV) {
-  /* FIXME: what to do with private linkage? */
   if (GV.isDeclaration())                                  return 'U';
   if (GV.hasLinkOnceLinkage())                             return 'C';
   if (GV.hasCommonLinkage())                               return 'C';
@@ -87,8 +86,11 @@
 }
 
 static void DumpSymbolNameForGlobalValue(GlobalValue &GV) {
+  // Private linkage and available_externally linkage don't exist in symtab.
+  if (GV.hasPrivateLinkage() || GV.hasAvailableExternallyLinkage()) return;
+  
   const std::string SymbolAddrStr = "        "; // Not used yet...
-  char TypeChar = TypeCharForSymbol (GV);
+  char TypeChar = TypeCharForSymbol(GV);
   if ((TypeChar != 'U') && UndefinedOnly)
     return;
   if ((TypeChar == 'U') && DefinedOnly)
@@ -96,17 +98,17 @@
   if (GV.hasLocalLinkage () && ExternalOnly)
     return;
   if (OutputFormat == posix) {
-    std::cout << GV.getName () << " " << TypeCharForSymbol (GV) << " "
+    std::cout << GV.getName () << " " << TypeCharForSymbol(GV) << " "
               << SymbolAddrStr << "\n";
   } else if (OutputFormat == bsd) {
-    std::cout << SymbolAddrStr << " " << TypeCharForSymbol (GV) << " "
+    std::cout << SymbolAddrStr << " " << TypeCharForSymbol(GV) << " "
               << GV.getName () << "\n";
   } else if (OutputFormat == sysv) {
     std::string PaddedName (GV.getName ());
     while (PaddedName.length () < 20)
       PaddedName += " ";
     std::cout << PaddedName << "|" << SymbolAddrStr << "|   "
-              << TypeCharForSymbol (GV)
+              << TypeCharForSymbol(GV)
               << "  |                  |      |     |\n";
   }
 }
@@ -122,10 +124,10 @@
               << "Name                  Value   Class        Type"
               << "         Size   Line  Section\n";
   }
-  std::for_each (M->begin (), M->end (), DumpSymbolNameForGlobalValue);
-  std::for_each (M->global_begin (), M->global_end (),
+  std::for_each (M->begin(), M->end(), DumpSymbolNameForGlobalValue);
+  std::for_each (M->global_begin(), M->global_end(),
                  DumpSymbolNameForGlobalValue);
-  std::for_each (M->alias_begin (), M->alias_end (),
+  std::for_each (M->alias_begin(), M->alias_end(),
                  DumpSymbolNameForGlobalValue);
 }