
This moves the registry higher in the LLVM library dependency stack. Every client of the target registry needs to link against MC anyway to actually use the target, so we might as well move this out of Support. This allows us to ensure that Support doesn't have includes from MC/*. Differential Revision: https://reviews.llvm.org/D111454
230 lines
7.1 KiB
C++
230 lines
7.1 KiB
C++
//===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This class represents a symbol table built from in-memory IR. It provides
|
|
// access to GlobalValues and should only be used if such access is required
|
|
// (e.g. in the LTO implementation).
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Object/ModuleSymbolTable.h"
|
|
#include "RecordStreamer.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/GlobalAlias.h"
|
|
#include "llvm/IR/GlobalValue.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/InlineAsm.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCDirectives.h"
|
|
#include "llvm/MC/MCInstrInfo.h"
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
|
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
#include "llvm/MC/MCSymbol.h"
|
|
#include "llvm/MC/MCTargetOptions.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
#include "llvm/Object/SymbolicFile.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include "llvm/Support/CodeGen.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/SMLoc.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
using namespace llvm;
|
|
using namespace object;
|
|
|
|
void ModuleSymbolTable::addModule(Module *M) {
|
|
if (FirstMod)
|
|
assert(FirstMod->getTargetTriple() == M->getTargetTriple());
|
|
else
|
|
FirstMod = M;
|
|
|
|
for (GlobalValue &GV : M->global_values())
|
|
SymTab.push_back(&GV);
|
|
|
|
CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {
|
|
SymTab.push_back(new (AsmSymbols.Allocate())
|
|
AsmSymbol(std::string(Name), Flags));
|
|
});
|
|
}
|
|
|
|
static void
|
|
initializeRecordStreamer(const Module &M,
|
|
function_ref<void(RecordStreamer &)> Init) {
|
|
StringRef InlineAsm = M.getModuleInlineAsm();
|
|
if (InlineAsm.empty())
|
|
return;
|
|
|
|
std::string Err;
|
|
const Triple TT(M.getTargetTriple());
|
|
const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
|
|
assert(T && T->hasMCAsmParser());
|
|
|
|
std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
|
|
if (!MRI)
|
|
return;
|
|
|
|
MCTargetOptions MCOptions;
|
|
std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str(), MCOptions));
|
|
if (!MAI)
|
|
return;
|
|
|
|
std::unique_ptr<MCSubtargetInfo> STI(
|
|
T->createMCSubtargetInfo(TT.str(), "", ""));
|
|
if (!STI)
|
|
return;
|
|
|
|
std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
|
|
if (!MCII)
|
|
return;
|
|
|
|
std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
|
|
SourceMgr SrcMgr;
|
|
SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
|
|
|
|
MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
|
|
std::unique_ptr<MCObjectFileInfo> MOFI(
|
|
T->createMCObjectFileInfo(MCCtx, /*PIC=*/false));
|
|
MOFI->setSDKVersion(M.getSDKVersion());
|
|
MCCtx.setObjectFileInfo(MOFI.get());
|
|
RecordStreamer Streamer(MCCtx, M);
|
|
T->createNullTargetStreamer(Streamer);
|
|
|
|
std::unique_ptr<MCAsmParser> Parser(
|
|
createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
|
|
|
|
std::unique_ptr<MCTargetAsmParser> TAP(
|
|
T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
|
|
if (!TAP)
|
|
return;
|
|
|
|
// Module-level inline asm is assumed to use At&t syntax (see
|
|
// AsmPrinter::doInitialization()).
|
|
Parser->setAssemblerDialect(InlineAsm::AD_ATT);
|
|
|
|
Parser->setTargetParser(*TAP);
|
|
if (Parser->Run(false))
|
|
return;
|
|
|
|
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));
|
|
}
|
|
});
|
|
}
|
|
|
|
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 {
|
|
if (S.is<AsmSymbol *>()) {
|
|
OS << S.get<AsmSymbol *>()->first;
|
|
return;
|
|
}
|
|
|
|
auto *GV = S.get<GlobalValue *>();
|
|
if (GV->hasDLLImportStorageClass())
|
|
OS << "__imp_";
|
|
|
|
Mang.getNameWithPrefix(OS, GV, false);
|
|
}
|
|
|
|
uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
|
|
if (S.is<AsmSymbol *>())
|
|
return S.get<AsmSymbol *>()->second;
|
|
|
|
auto *GV = S.get<GlobalValue *>();
|
|
|
|
uint32_t Res = BasicSymbolRef::SF_None;
|
|
if (GV->isDeclarationForLinker())
|
|
Res |= BasicSymbolRef::SF_Undefined;
|
|
else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
|
|
Res |= BasicSymbolRef::SF_Hidden;
|
|
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
|
|
if (GVar->isConstant())
|
|
Res |= BasicSymbolRef::SF_Const;
|
|
}
|
|
if (isa_and_nonnull<Function>(GV->getAliaseeObject()) || isa<GlobalIFunc>(GV))
|
|
Res |= BasicSymbolRef::SF_Executable;
|
|
if (isa<GlobalAlias>(GV))
|
|
Res |= BasicSymbolRef::SF_Indirect;
|
|
if (GV->hasPrivateLinkage())
|
|
Res |= BasicSymbolRef::SF_FormatSpecific;
|
|
if (!GV->hasLocalLinkage())
|
|
Res |= BasicSymbolRef::SF_Global;
|
|
if (GV->hasCommonLinkage())
|
|
Res |= BasicSymbolRef::SF_Common;
|
|
if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
|
|
GV->hasExternalWeakLinkage())
|
|
Res |= BasicSymbolRef::SF_Weak;
|
|
|
|
if (GV->getName().startswith("llvm."))
|
|
Res |= BasicSymbolRef::SF_FormatSpecific;
|
|
else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
|
|
if (Var->getSection() == "llvm.metadata")
|
|
Res |= BasicSymbolRef::SF_FormatSpecific;
|
|
}
|
|
|
|
return Res;
|
|
}
|