[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