10b57cec5SDimitry Andric //===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class represents a symbol table built from in-memory IR. It provides
100b57cec5SDimitry Andric // access to GlobalValues and should only be used if such access is required
110b57cec5SDimitry Andric // (e.g. in the LTO implementation).
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "llvm/Object/ModuleSymbolTable.h"
160b57cec5SDimitry Andric #include "RecordStreamer.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
210b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
220b57cec5SDimitry Andric #include "llvm/IR/Function.h"
230b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
240b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
250b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
265ffd83dbSDimitry Andric #include "llvm/IR/InlineAsm.h"
270b57cec5SDimitry Andric #include "llvm/IR/Module.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
390b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
400b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
410b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
420b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
430b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
440b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
450b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
460b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
470b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
480b57cec5SDimitry Andric #include <algorithm>
490b57cec5SDimitry Andric #include <cassert>
500b57cec5SDimitry Andric #include <cstdint>
510b57cec5SDimitry Andric #include <memory>
520b57cec5SDimitry Andric #include <string>
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric using namespace llvm;
550b57cec5SDimitry Andric using namespace object;
560b57cec5SDimitry Andric
addModule(Module * M)570b57cec5SDimitry Andric void ModuleSymbolTable::addModule(Module *M) {
580b57cec5SDimitry Andric if (FirstMod)
590b57cec5SDimitry Andric assert(FirstMod->getTargetTriple() == M->getTargetTriple());
600b57cec5SDimitry Andric else
610b57cec5SDimitry Andric FirstMod = M;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric for (GlobalValue &GV : M->global_values())
640b57cec5SDimitry Andric SymTab.push_back(&GV);
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {
675ffd83dbSDimitry Andric SymTab.push_back(new (AsmSymbols.Allocate())
685ffd83dbSDimitry Andric AsmSymbol(std::string(Name), Flags));
690b57cec5SDimitry Andric });
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric static void
initializeRecordStreamer(const Module & M,function_ref<void (RecordStreamer &)> Init)730b57cec5SDimitry Andric initializeRecordStreamer(const Module &M,
740b57cec5SDimitry Andric function_ref<void(RecordStreamer &)> Init) {
750b57cec5SDimitry Andric StringRef InlineAsm = M.getModuleInlineAsm();
760b57cec5SDimitry Andric if (InlineAsm.empty())
770b57cec5SDimitry Andric return;
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric std::string Err;
800b57cec5SDimitry Andric const Triple TT(M.getTargetTriple());
810b57cec5SDimitry Andric const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
820b57cec5SDimitry Andric assert(T && T->hasMCAsmParser());
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
850b57cec5SDimitry Andric if (!MRI)
860b57cec5SDimitry Andric return;
870b57cec5SDimitry Andric
88480093f4SDimitry Andric MCTargetOptions MCOptions;
89480093f4SDimitry Andric std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str(), MCOptions));
900b57cec5SDimitry Andric if (!MAI)
910b57cec5SDimitry Andric return;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric std::unique_ptr<MCSubtargetInfo> STI(
940b57cec5SDimitry Andric T->createMCSubtargetInfo(TT.str(), "", ""));
950b57cec5SDimitry Andric if (!STI)
960b57cec5SDimitry Andric return;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
990b57cec5SDimitry Andric if (!MCII)
1000b57cec5SDimitry Andric return;
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
1030b57cec5SDimitry Andric SourceMgr SrcMgr;
1040b57cec5SDimitry Andric SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
105*5f7ddb14SDimitry Andric
106*5f7ddb14SDimitry Andric MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
107*5f7ddb14SDimitry Andric std::unique_ptr<MCObjectFileInfo> MOFI(
108*5f7ddb14SDimitry Andric T->createMCObjectFileInfo(MCCtx, /*PIC=*/false));
109*5f7ddb14SDimitry Andric MOFI->setSDKVersion(M.getSDKVersion());
110*5f7ddb14SDimitry Andric MCCtx.setObjectFileInfo(MOFI.get());
111*5f7ddb14SDimitry Andric RecordStreamer Streamer(MCCtx, M);
112*5f7ddb14SDimitry Andric T->createNullTargetStreamer(Streamer);
113*5f7ddb14SDimitry Andric
1140b57cec5SDimitry Andric std::unique_ptr<MCAsmParser> Parser(
1150b57cec5SDimitry Andric createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric std::unique_ptr<MCTargetAsmParser> TAP(
1180b57cec5SDimitry Andric T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
1190b57cec5SDimitry Andric if (!TAP)
1200b57cec5SDimitry Andric return;
1210b57cec5SDimitry Andric
1225ffd83dbSDimitry Andric // Module-level inline asm is assumed to use At&t syntax (see
1235ffd83dbSDimitry Andric // AsmPrinter::doInitialization()).
1245ffd83dbSDimitry Andric Parser->setAssemblerDialect(InlineAsm::AD_ATT);
1255ffd83dbSDimitry Andric
1260b57cec5SDimitry Andric Parser->setTargetParser(*TAP);
1270b57cec5SDimitry Andric if (Parser->Run(false))
1280b57cec5SDimitry Andric return;
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric Init(Streamer);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
CollectAsmSymbols(const Module & M,function_ref<void (StringRef,BasicSymbolRef::Flags)> AsmSymbol)1330b57cec5SDimitry Andric void ModuleSymbolTable::CollectAsmSymbols(
1340b57cec5SDimitry Andric const Module &M,
1350b57cec5SDimitry Andric function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
1360b57cec5SDimitry Andric initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
1370b57cec5SDimitry Andric Streamer.flushSymverDirectives();
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric for (auto &KV : Streamer) {
1400b57cec5SDimitry Andric StringRef Key = KV.first();
1410b57cec5SDimitry Andric RecordStreamer::State Value = KV.second;
1420b57cec5SDimitry Andric // FIXME: For now we just assume that all asm symbols are executable.
1430b57cec5SDimitry Andric uint32_t Res = BasicSymbolRef::SF_Executable;
1440b57cec5SDimitry Andric switch (Value) {
1450b57cec5SDimitry Andric case RecordStreamer::NeverSeen:
1460b57cec5SDimitry Andric llvm_unreachable("NeverSeen should have been replaced earlier");
1470b57cec5SDimitry Andric case RecordStreamer::DefinedGlobal:
1480b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Global;
1490b57cec5SDimitry Andric break;
1500b57cec5SDimitry Andric case RecordStreamer::Defined:
1510b57cec5SDimitry Andric break;
1520b57cec5SDimitry Andric case RecordStreamer::Global:
1530b57cec5SDimitry Andric case RecordStreamer::Used:
1540b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Undefined;
1550b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Global;
1560b57cec5SDimitry Andric break;
1570b57cec5SDimitry Andric case RecordStreamer::DefinedWeak:
1580b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Weak;
1590b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Global;
1600b57cec5SDimitry Andric break;
1610b57cec5SDimitry Andric case RecordStreamer::UndefinedWeak:
1620b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Weak;
1630b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Undefined;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric AsmSymbol(Key, BasicSymbolRef::Flags(Res));
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric });
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric
CollectAsmSymvers(const Module & M,function_ref<void (StringRef,StringRef)> AsmSymver)1700b57cec5SDimitry Andric void ModuleSymbolTable::CollectAsmSymvers(
1710b57cec5SDimitry Andric const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {
1720b57cec5SDimitry Andric initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
1730b57cec5SDimitry Andric for (auto &KV : Streamer.symverAliases())
1740b57cec5SDimitry Andric for (auto &Alias : KV.second)
1750b57cec5SDimitry Andric AsmSymver(KV.first->getName(), Alias);
1760b57cec5SDimitry Andric });
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
printSymbolName(raw_ostream & OS,Symbol S) const1790b57cec5SDimitry Andric void ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {
1800b57cec5SDimitry Andric if (S.is<AsmSymbol *>()) {
1810b57cec5SDimitry Andric OS << S.get<AsmSymbol *>()->first;
1820b57cec5SDimitry Andric return;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric auto *GV = S.get<GlobalValue *>();
1860b57cec5SDimitry Andric if (GV->hasDLLImportStorageClass())
1870b57cec5SDimitry Andric OS << "__imp_";
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric Mang.getNameWithPrefix(OS, GV, false);
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
getSymbolFlags(Symbol S) const1920b57cec5SDimitry Andric uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
1930b57cec5SDimitry Andric if (S.is<AsmSymbol *>())
1940b57cec5SDimitry Andric return S.get<AsmSymbol *>()->second;
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric auto *GV = S.get<GlobalValue *>();
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric uint32_t Res = BasicSymbolRef::SF_None;
1990b57cec5SDimitry Andric if (GV->isDeclarationForLinker())
2000b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Undefined;
2010b57cec5SDimitry Andric else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
2020b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Hidden;
2030b57cec5SDimitry Andric if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
2040b57cec5SDimitry Andric if (GVar->isConstant())
2050b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Const;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric if (dyn_cast_or_null<Function>(GV->getBaseObject()))
2080b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Executable;
2090b57cec5SDimitry Andric if (isa<GlobalAlias>(GV))
2100b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Indirect;
2110b57cec5SDimitry Andric if (GV->hasPrivateLinkage())
2120b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_FormatSpecific;
2130b57cec5SDimitry Andric if (!GV->hasLocalLinkage())
2140b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Global;
2150b57cec5SDimitry Andric if (GV->hasCommonLinkage())
2160b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Common;
2170b57cec5SDimitry Andric if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
2180b57cec5SDimitry Andric GV->hasExternalWeakLinkage())
2190b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_Weak;
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric if (GV->getName().startswith("llvm."))
2220b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_FormatSpecific;
2230b57cec5SDimitry Andric else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
2240b57cec5SDimitry Andric if (Var->getSection() == "llvm.metadata")
2250b57cec5SDimitry Andric Res |= BasicSymbolRef::SF_FormatSpecific;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric return Res;
2290b57cec5SDimitry Andric }
230