mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
6f0d069409
build version load commands in the object file This commit introduces a new metadata node called "SDK Version". It will be set by the frontend to mark the platform SDK (macOS/iOS/etc) version which was used during that particular compilation. This node is used when machine code is emitted, by either saving the SDK version into the appropriate macho load command (version min/build version), or by emitting the assembly for these load commands with the SDK version specified as well. The assembly for both load commands is extended by allowing it to contain the sdk_version X, Y [, Z] trailing directive to represent the SDK version respectively. rdar://45774000 Differential Revision: https://reviews.llvm.org/D55612 llvm-svn: 349119
223 lines
6.8 KiB
C++
223 lines
6.8 KiB
C++
//===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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/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(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;
|
|
|
|
std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str()));
|
|
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;
|
|
|
|
MCObjectFileInfo MOFI;
|
|
MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
|
|
MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx);
|
|
MOFI.setSDKVersion(M.getSDKVersion());
|
|
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));
|
|
|
|
MCTargetOptions MCOptions;
|
|
std::unique_ptr<MCTargetAsmParser> TAP(
|
|
T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
|
|
if (!TAP)
|
|
return;
|
|
|
|
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;
|
|
}
|