[llvm] r330387 - LowerTypeTests: Propagate symver directives
    Vlad Tsyrklevich via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Thu Apr 19 18:36:48 PDT 2018
    
    
  
Author: vlad.tsyrklevich
Date: Thu Apr 19 18:36:48 2018
New Revision: 330387
URL: http://llvm.org/viewvc/llvm-project?rev=330387&view=rev
Log:
LowerTypeTests: Propagate symver directives
Summary:
This change fixes https://crbug.com/834474, a build failure caused by
LowerTypeTests not preserving .symver symbol versioning directives for
exported functions. Emit symver information to ThinLTO summary data and
then propagate symver directives for exported functions to the merged
module.
Emitting symver information to the summaries increases the size of
intermediate build artifacts for a Chromium build by less than 0.2%.
Reviewers: pcc
Reviewed By: pcc
Subscribers: tejohnson, mehdi_amini, eraman, llvm-commits, eugenis, kcc
Differential Revision: https://reviews.llvm.org/D45798
Added:
    llvm/trunk/test/Transforms/LowerTypeTests/export-symver.ll
    llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll
Modified:
    llvm/trunk/include/llvm/Object/ModuleSymbolTable.h
    llvm/trunk/lib/Object/ModuleSymbolTable.cpp
    llvm/trunk/lib/Object/RecordStreamer.cpp
    llvm/trunk/lib/Object/RecordStreamer.h
    llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp
    llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
Modified: llvm/trunk/include/llvm/Object/ModuleSymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ModuleSymbolTable.h?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ModuleSymbolTable.h (original)
+++ llvm/trunk/include/llvm/Object/ModuleSymbolTable.h Thu Apr 19 18:36:48 2018
@@ -57,6 +57,15 @@ public:
   static void CollectAsmSymbols(
       const Module &M,
       function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol);
+
+  /// Parse inline ASM and collect the symvers directives that are defined in
+  /// the current module.
+  ///
+  /// For each found symbol, call \p AsmSymver with the name of the symbol and
+  /// its alias.
+  static void
+  CollectAsmSymvers(const Module &M,
+                    function_ref<void(StringRef, StringRef)> AsmSymver);
 };
 
 } // end namespace llvm
Modified: llvm/trunk/lib/Object/ModuleSymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ModuleSymbolTable.cpp?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ModuleSymbolTable.cpp (original)
+++ llvm/trunk/lib/Object/ModuleSymbolTable.cpp Thu Apr 19 18:36:48 2018
@@ -68,9 +68,9 @@ void ModuleSymbolTable::addModule(Module
   });
 }
 
-void ModuleSymbolTable::CollectAsmSymbols(
-    const Module &M,
-    function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
+static void
+initializeRecordStreamer(const Module &M,
+                         function_ref<void(RecordStreamer &)> Init) {
   StringRef InlineAsm = M.getModuleInlineAsm();
   if (InlineAsm.empty())
     return;
@@ -119,36 +119,53 @@ void ModuleSymbolTable::CollectAsmSymbol
   if (Parser->Run(false))
     return;
 
-  Streamer.flushSymverDirectives();
+  Init(Streamer);
+}
+
+void ModuleSymbolTable::CollectAsmSymbols(
+    const Module &M,
+    function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
+  initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
+    Streamer.flushSymverDirectives();
 
-  for (auto &KV : Streamer) {
-    StringRef Key = KV.first();
-    RecordStreamer::State Value = KV.second;
-    // FIXME: For now we just assume that all asm symbols are executable.
-    uint32_t Res = BasicSymbolRef::SF_Executable;
-    switch (Value) {
-    case RecordStreamer::NeverSeen:
-      llvm_unreachable("NeverSeen should have been replaced earlier");
-    case RecordStreamer::DefinedGlobal:
-      Res |= BasicSymbolRef::SF_Global;
-      break;
-    case RecordStreamer::Defined:
-      break;
-    case RecordStreamer::Global:
-    case RecordStreamer::Used:
-      Res |= BasicSymbolRef::SF_Undefined;
-      Res |= BasicSymbolRef::SF_Global;
-      break;
-    case RecordStreamer::DefinedWeak:
-      Res |= BasicSymbolRef::SF_Weak;
-      Res |= BasicSymbolRef::SF_Global;
-      break;
-    case RecordStreamer::UndefinedWeak:
-      Res |= BasicSymbolRef::SF_Weak;
-      Res |= BasicSymbolRef::SF_Undefined;
+    for (auto &KV : Streamer) {
+      StringRef Key = KV.first();
+      RecordStreamer::State Value = KV.second;
+      // FIXME: For now we just assume that all asm symbols are executable.
+      uint32_t Res = BasicSymbolRef::SF_Executable;
+      switch (Value) {
+      case RecordStreamer::NeverSeen:
+        llvm_unreachable("NeverSeen should have been replaced earlier");
+      case RecordStreamer::DefinedGlobal:
+        Res |= BasicSymbolRef::SF_Global;
+        break;
+      case RecordStreamer::Defined:
+        break;
+      case RecordStreamer::Global:
+      case RecordStreamer::Used:
+        Res |= BasicSymbolRef::SF_Undefined;
+        Res |= BasicSymbolRef::SF_Global;
+        break;
+      case RecordStreamer::DefinedWeak:
+        Res |= BasicSymbolRef::SF_Weak;
+        Res |= BasicSymbolRef::SF_Global;
+        break;
+      case RecordStreamer::UndefinedWeak:
+        Res |= BasicSymbolRef::SF_Weak;
+        Res |= BasicSymbolRef::SF_Undefined;
+      }
+      AsmSymbol(Key, BasicSymbolRef::Flags(Res));
     }
-    AsmSymbol(Key, BasicSymbolRef::Flags(Res));
-  }
+  });
+}
+
+void ModuleSymbolTable::CollectAsmSymvers(
+    const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {
+  initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
+    for (auto &KV : Streamer.symverAliases())
+      for (auto &Alias : KV.second)
+        AsmSymver(KV.first->getName(), Alias);
+  });
 }
 
 void ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {
Modified: llvm/trunk/lib/Object/RecordStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/RecordStreamer.cpp?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/lib/Object/RecordStreamer.cpp (original)
+++ llvm/trunk/lib/Object/RecordStreamer.cpp Thu Apr 19 18:36:48 2018
@@ -128,6 +128,11 @@ void RecordStreamer::emitELFSymverDirect
   SymverAliasMap[Aliasee].push_back(AliasName);
 }
 
+iterator_range<RecordStreamer::const_symver_iterator>
+RecordStreamer::symverAliases() {
+  return {SymverAliasMap.begin(), SymverAliasMap.end()};
+}
+
 void RecordStreamer::flushSymverDirectives() {
   // Mapping from mangled name to GV.
   StringMap<const GlobalValue *> MangledNameMap;
Modified: llvm/trunk/lib/Object/RecordStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/RecordStreamer.h?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/lib/Object/RecordStreamer.h (original)
+++ llvm/trunk/lib/Object/RecordStreamer.h Thu Apr 19 18:36:48 2018
@@ -47,10 +47,6 @@ private:
 public:
   RecordStreamer(MCContext &Context, const Module &M);
 
-  using const_iterator = StringMap<State>::const_iterator;
-
-  const_iterator begin();
-  const_iterator end();
   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
                        bool) override;
   void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
@@ -63,9 +59,19 @@ public:
   /// Record .symver aliases for later processing.
   void emitELFSymverDirective(StringRef AliasName,
                               const MCSymbol *Aliasee) override;
+
   // Emit ELF .symver aliases and ensure they have the same binding as the
   // defined symbol they alias with.
   void flushSymverDirectives();
+
+  // Symbols iterators
+  using const_iterator = StringMap<State>::const_iterator;
+  const_iterator begin();
+  const_iterator end();
+
+  // SymverAliasMap iterators
+  using const_symver_iterator = decltype(SymverAliasMap)::const_iterator;
+  iterator_range<const_symver_iterator> symverAliases();
 };
 
 } // end namespace llvm
Modified: llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp Thu Apr 19 18:36:48 2018
@@ -1947,6 +1947,24 @@ bool LowerTypeTestsModule::lower() {
     }
   }
 
+  // Emit .symver directives for exported functions, if they exist.
+  if (ExportSummary) {
+    if (NamedMDNode *SymversMD = M.getNamedMetadata("symvers")) {
+      for (auto Symver : SymversMD->operands()) {
+        assert(Symver->getNumOperands() >= 2);
+        StringRef SymbolName =
+            cast<MDString>(Symver->getOperand(0))->getString();
+        StringRef Alias = cast<MDString>(Symver->getOperand(1))->getString();
+
+        if (!ExportedFunctions.count(SymbolName))
+          continue;
+
+        M.appendModuleInlineAsm(
+            (llvm::Twine(".symver ") + SymbolName + ", " + Alias).str());
+      }
+    }
+  }
+
   return true;
 }
 
Modified: llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp?rev=330387&r1=330386&r2=330387&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp Thu Apr 19 18:36:48 2018
@@ -18,6 +18,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PassManager.h"
+#include "llvm/Object/ModuleSymbolTable.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/raw_ostream.h"
@@ -301,13 +302,13 @@ void splitAndWriteThinLTOBitcode(
   promoteInternals(*MergedM, M, ModuleId, CfiFunctions);
   promoteInternals(M, *MergedM, ModuleId, CfiFunctions);
 
+  auto &Ctx = MergedM->getContext();
   SmallVector<MDNode *, 8> CfiFunctionMDs;
   for (auto V : CfiFunctions) {
     Function &F = *cast<Function>(V);
     SmallVector<MDNode *, 2> Types;
     F.getMetadata(LLVMContext::MD_type, Types);
 
-    auto &Ctx = MergedM->getContext();
     SmallVector<Metadata *, 4> Elts;
     Elts.push_back(MDString::get(Ctx, F.getName()));
     CfiFunctionLinkage Linkage;
@@ -336,7 +337,6 @@ void splitAndWriteThinLTOBitcode(
       continue;
 
     auto *F = cast<Function>(A.getAliasee());
-    auto &Ctx = MergedM->getContext();
     SmallVector<Metadata *, 4> Elts;
 
     Elts.push_back(MDString::get(Ctx, A.getName()));
@@ -355,6 +355,25 @@ void splitAndWriteThinLTOBitcode(
       NMD->addOperand(MD);
   }
 
+  SmallVector<MDNode *, 8> Symvers;
+  ModuleSymbolTable::CollectAsmSymvers(M, [&](StringRef Name, StringRef Alias) {
+    Function *F = M.getFunction(Name);
+    if (!F || F->use_empty())
+      return;
+
+    SmallVector<Metadata *, 2> Elts;
+    Elts.push_back(MDString::get(Ctx, Name));
+    Elts.push_back(MDString::get(Ctx, Alias));
+
+    Symvers.push_back(MDTuple::get(Ctx, Elts));
+  });
+
+  if (!Symvers.empty()) {
+    NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("symvers");
+    for (auto MD : Symvers)
+      NMD->addOperand(MD);
+  }
+
   simplifyExternals(*MergedM);
 
   // FIXME: Try to re-use BSI and PFI from the original module here.
Added: llvm/trunk/test/Transforms/LowerTypeTests/export-symver.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/export-symver.ll?rev=330387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/export-symver.ll (added)
+++ llvm/trunk/test/Transforms/LowerTypeTests/export-symver.ll Thu Apr 19 18:36:48 2018
@@ -0,0 +1,16 @@
+; RUN: opt -S %s -lowertypetests -lowertypetests-summary-action=export -lowertypetests-read-summary=%S/Inputs/use-typeid1-typeid2.yaml | FileCheck %s
+;
+; CHECK: module asm ".symver exported_and_symver, alias1"
+; CHECK-NOT: .symver exported
+; CHECK-NOT: .symver symver
+
+target triple = "x86_64-unknown-linux"
+
+!cfi.functions = !{!0, !1}
+!symvers = !{!3, !4}
+
+!0 = !{!"exported_and_symver", i8 2, !2}
+!1 = !{!"exported", i8 2, !2}
+!2 = !{i64 0, !"typeid1"}
+!3 = !{!"exported_and_symver", !"alias1"}
+!4 = !{!"symver", !"alias2"}
Added: llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll?rev=330387&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll (added)
+++ llvm/trunk/test/Transforms/ThinLTOBitcodeWriter/symver.ll Thu Apr 19 18:36:48 2018
@@ -0,0 +1,22 @@
+; RUN: opt -thinlto-bc -o %t %s
+; RUN: llvm-modextract -n 1 -o - %t | llvm-dis | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+module asm ".symver used, used at VER"
+module asm ".symver unused, unused at VER"
+module asm ".symver variable, variable at VER"
+
+declare !type !0 void @used()
+declare !type !0 void @unused()
+ at variable = global i32 0
+
+define i32* @use() {
+  call void @used()
+  ret i32* @variable
+}
+
+; CHECK: !symvers = !{![[SYMVER:[0-9]+]]}
+; CHECK: ![[SYMVER]] = !{!"used", !"used at VER"}
+
+!0 = !{i64 0, !"_ZTSFvvE"}
    
    
More information about the llvm-commits
mailing list