================
@@ -187,13 +161,174 @@ void ModuleSymbolTable::CollectAsmSymbols(
}
}
+static void
+addSymbols(RecordStreamer &Streamer,
+ function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
+ Streamer.flushSymverDirectives();
+
+ for (const auto &[Name, State] : Streamer) {
+ // FIXME: For now we just assume that all asm symbols are executable.
+ uint32_t Res = BasicSymbolRef::SF_Executable;
+ switch (State) {
+ 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(Name, BasicSymbolRef::Flags(Res));
+ }
+}
+
+void ModuleSymbolTable::CollectAsmSymbols(
+ const Module &M,
+ function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
+
+ MDTuple *SymbolsMD =
+ dyn_cast_if_present<MDTuple>(M.getModuleFlag("global-asm-symbols"));
+
+ if (SymbolsMD) {
+ for (const Metadata *MD : SymbolsMD->operands()) {
+ const MDTuple *SymMD = cast<MDTuple>(MD);
+ const MDString *Name = cast<MDString>(SymMD->getOperand(0));
+ const ConstantInt *Flags =
+ mdconst::extract<ConstantInt>(SymMD->getOperand(1));
+ AsmSymbol(Name->getString(),
+ static_cast<BasicSymbolRef::Flags>(Flags->getZExtValue()));
+ }
+ addSpecialSymbols(M, AsmSymbol);
+ return;
+ }
+
+ initializeRecordStreamer(
+ M, /*CPU=*/"", /*Features=*/"",
+ [&](RecordStreamer &Streamer) { addSymbols(Streamer, AsmSymbol); },
+ /*DiagHandler=*/nullptr);
+
+ addSpecialSymbols(M, AsmSymbol);
+}
+
+static void addSymvers(RecordStreamer &Streamer,
+ function_ref<void(StringRef, StringRef)> AsmSymver) {
+ for (const auto &[Name, Aliases] : Streamer.symverAliases())
+ for (StringRef Alias : Aliases)
+ AsmSymver(Name->getName(), Alias);
+}
+
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);
- });
+
+ MDTuple *SymversMD =
+ dyn_cast_if_present<MDTuple>(M.getModuleFlag("global-asm-symvers"));
+
+ if (SymversMD) {
+ for (const Metadata *MD : SymversMD->operands()) {
+ const MDTuple *SymverMD = cast<MDTuple>(MD);
+ StringRef Name = cast<MDString>(SymverMD->getOperand(0))->getString();
+ for (size_t i = 1, End = SymverMD->getNumOperands(); i < End; ++i) {
+ AsmSymver(Name, cast<MDString>(SymverMD->getOperand(i))->getString());
+ }
+ }
+ return;
+ }
+
+ initializeRecordStreamer(
+ M, /*CPU=*/"", /*Features=*/"",
+ [&](RecordStreamer &Streamer) { addSymvers(Streamer, AsmSymver); },
+ /*DiagHandler=*/nullptr);
+}
+
+bool ModuleSymbolTable::EmitModuleFlags(Module &M, StringRef CPU,
+ StringRef Features) {
+ bool Changed = false;
+ llvm::LLVMContext &Ctx = M.getContext();
+
+ bool HaveErrors = false;
+ auto DiagHandler = [&](const llvm::DiagnosticInfo &DI) {
+ // Ignore diagnostics from the assembly parser.
+ //
+ // Errors in assembly mean that we cannot build a symbol table
+ // from it. However, we do not diagnose them here, because we
+ // don't know if the Module is ever going to actually reach
+ // CodeGen where this would matter.
+ if (DI.getSeverity() == llvm::DS_Error)
+ HaveErrors = true;
+ };
+
+ // Build global-asm-symbols as a list of pairs (name, flags bitmask).
+ SmallVector<llvm::Metadata *, 16> Symbols;
+
+ auto AsmSymbol = [&](StringRef Name,
+ llvm::object::BasicSymbolRef::Flags Flags) {
+ Symbols.push_back(llvm::MDNode::get(
+ Ctx, {llvm::MDString::get(Ctx, Name),
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(Ctx), Flags))}));
+ };
+
+ // Build global-asm-symvers as a list of lists (name, followed by all
+ // aliases).
+ llvm::MapVector<StringRef, SmallVector<llvm::Metadata *, 2>> SymversMap;
+
+ auto AsmSymver = [&](StringRef Name, StringRef Alias) {
+ auto ItNew = SymversMap.try_emplace(Name);
+ SmallVector<llvm::Metadata *, 2> &Aliases = ItNew.first->second;
+
+ // If it is a new list, insert the primary name at the front.
+ if (ItNew.second)
+ Aliases.push_back(llvm::MDString::get(Ctx, Name));
+
+ Aliases.push_back(llvm::MDString::get(Ctx, Alias));
+ };
+
+ // Parse global inline assembly and collect all symbols and symvers.
+ initializeRecordStreamer(
+ M, CPU, Features,
+ [&](RecordStreamer &Streamer) {
+ addSymvers(Streamer, AsmSymver);
+ addSymbols(Streamer, AsmSymbol);
+ },
+ DiagHandler);
+
+ if (HaveErrors)
+ return false;
+
+ // Emit a symbol table as module flags, so they can be traversed
+ // later with CollectAsmSymbols and CollectAsmSymvers.
+
+ if (!Symbols.empty()) {
+ M.addModuleFlag(llvm::Module::Append, "global-asm-symbols",
+ llvm::MDNode::get(Ctx, Symbols));
+ Changed = true;
+ }
+
+ if (!SymversMap.empty()) {
+ SmallVector<llvm::Metadata *, 16> Symvers;
+ Symvers.reserve(SymversMap.size());
+ for (const auto &KV : SymversMap) {
----------------
mysterymath wrote:
nit: no braces on single line block
https://github.com/llvm/llvm-project/pull/174995
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits