summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Object/ModuleSymbolTable.cpp81
-rw-r--r--llvm/lib/Object/RecordStreamer.cpp5
-rw-r--r--llvm/lib/Object/RecordStreamer.h14
-rw-r--r--llvm/lib/Transforms/IPO/LowerTypeTests.cpp18
-rw-r--r--llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp23
5 files changed, 103 insertions, 38 deletions
diff --git a/llvm/lib/Object/ModuleSymbolTable.cpp b/llvm/lib/Object/ModuleSymbolTable.cpp
index f0d70aefd42..b353ef3c835 100644
--- a/llvm/lib/Object/ModuleSymbolTable.cpp
+++ b/llvm/lib/Object/ModuleSymbolTable.cpp
@@ -68,9 +68,9 @@ void ModuleSymbolTable::addModule(Module *M) {
});
}
-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::CollectAsmSymbols(
if (Parser->Run(false))
return;
- 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;
+ 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;
+ }
+ 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 {
diff --git a/llvm/lib/Object/RecordStreamer.cpp b/llvm/lib/Object/RecordStreamer.cpp
index 21577bb5696..f49c823c068 100644
--- a/llvm/lib/Object/RecordStreamer.cpp
+++ b/llvm/lib/Object/RecordStreamer.cpp
@@ -128,6 +128,11 @@ void RecordStreamer::emitELFSymverDirective(StringRef AliasName,
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;
diff --git a/llvm/lib/Object/RecordStreamer.h b/llvm/lib/Object/RecordStreamer.h
index 60b2d3ec3e8..13eac028a28 100644
--- a/llvm/lib/Object/RecordStreamer.h
+++ b/llvm/lib/Object/RecordStreamer.h
@@ -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
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index b568445b724..925d8f87b3f 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -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;
}
diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index 9bca88a54b3..2ba27af43a9 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -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.
OpenPOWER on IntegriCloud