1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00
llvm-mirror/lib/Object/ModuleSymbolTable.cpp
Philipp Krones df7a8b162e [MC] Refactor MCObjectFileInfo initialization and allow targets to create MCObjectFileInfo
This makes it possible for targets to define their own MCObjectFileInfo.
This MCObjectFileInfo is then used to determine things like section alignment.

This is a follow up to D101462 and prepares for the RISCV backend defining the
text section alignment depending on the enabled extensions.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D101921
2021-05-23 14:15:23 -07:00

229 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/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/TargetRegistry.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;
MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get());
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<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
SourceMgr SrcMgr;
SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
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 (dyn_cast_or_null<Function>(GV->getBaseObject()))
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;
}