251 lines · cpp
1//===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This class represents a symbol table built from in-memory IR. It provides10// access to GlobalValues and should only be used if such access is required11// (e.g. in the LTO implementation).12//13//===----------------------------------------------------------------------===//14 15#include "llvm/Object/ModuleSymbolTable.h"16#include "RecordStreamer.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/IR/DiagnosticInfo.h"19#include "llvm/IR/Function.h"20#include "llvm/IR/GlobalAlias.h"21#include "llvm/IR/GlobalValue.h"22#include "llvm/IR/GlobalVariable.h"23#include "llvm/IR/InlineAsm.h"24#include "llvm/IR/Module.h"25#include "llvm/MC/MCAsmInfo.h"26#include "llvm/MC/MCContext.h"27#include "llvm/MC/MCInstrInfo.h"28#include "llvm/MC/MCObjectFileInfo.h"29#include "llvm/MC/MCParser/MCAsmParser.h"30#include "llvm/MC/MCParser/MCTargetAsmParser.h"31#include "llvm/MC/MCRegisterInfo.h"32#include "llvm/MC/MCSubtargetInfo.h"33#include "llvm/MC/MCSymbol.h"34#include "llvm/MC/MCTargetOptions.h"35#include "llvm/MC/TargetRegistry.h"36#include "llvm/Object/SymbolicFile.h"37#include "llvm/Support/Casting.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/MemoryBuffer.h"40#include "llvm/Support/SMLoc.h"41#include "llvm/Support/SourceMgr.h"42#include "llvm/Support/raw_ostream.h"43#include "llvm/TargetParser/Triple.h"44#include <cassert>45#include <cstdint>46#include <memory>47#include <string>48 49using namespace llvm;50using namespace object;51 52void ModuleSymbolTable::addModule(Module *M) {53 if (FirstMod)54 assert(FirstMod->getTargetTriple() == M->getTargetTriple());55 else56 FirstMod = M;57 58 for (GlobalValue &GV : M->global_values())59 SymTab.push_back(&GV);60 61 CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {62 SymTab.push_back(new (AsmSymbols.Allocate())63 AsmSymbol(std::string(Name), Flags));64 });65}66 67static void68initializeRecordStreamer(const Module &M,69 function_ref<void(RecordStreamer &)> Init) {70 // This function may be called twice, once for ModuleSummaryIndexAnalysis and71 // the other when writing the IR symbol table. If parsing inline assembly has72 // caused errors in the first run, suppress the second run.73 if (M.getContext().getDiagHandlerPtr()->HasErrors)74 return;75 StringRef InlineAsm = M.getModuleInlineAsm();76 if (InlineAsm.empty())77 return;78 79 std::string Err;80 const Triple TT(M.getTargetTriple());81 const Target *T = TargetRegistry::lookupTarget(TT, Err);82 assert(T && T->hasMCAsmParser());83 84 std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT));85 if (!MRI)86 return;87 88 MCTargetOptions MCOptions;89 std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT, MCOptions));90 if (!MAI)91 return;92 93 std::unique_ptr<MCSubtargetInfo> STI(T->createMCSubtargetInfo(TT, "", ""));94 if (!STI)95 return;96 97 std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());98 if (!MCII)99 return;100 101 std::unique_ptr<MemoryBuffer> Buffer(102 MemoryBuffer::getMemBuffer(InlineAsm, "<inline asm>"));103 SourceMgr SrcMgr;104 SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());105 106 MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr);107 std::unique_ptr<MCObjectFileInfo> MOFI(108 T->createMCObjectFileInfo(MCCtx, /*PIC=*/false));109 MCCtx.setObjectFileInfo(MOFI.get());110 RecordStreamer Streamer(MCCtx, M);111 T->createNullTargetStreamer(Streamer);112 113 std::unique_ptr<MCAsmParser> Parser(114 createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));115 116 std::unique_ptr<MCTargetAsmParser> TAP(117 T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));118 if (!TAP)119 return;120 121 MCCtx.setDiagnosticHandler([&](const SMDiagnostic &SMD, bool IsInlineAsm,122 const SourceMgr &SrcMgr,123 std::vector<const MDNode *> &LocInfos) {124 M.getContext().diagnose(125 DiagnosticInfoSrcMgr(SMD, M.getName(), IsInlineAsm, /*LocCookie=*/0));126 });127 128 // Module-level inline asm is assumed to use At&t syntax (see129 // AsmPrinter::doInitialization()).130 Parser->setAssemblerDialect(InlineAsm::AD_ATT);131 132 Parser->setTargetParser(*TAP);133 if (Parser->Run(false))134 return;135 136 Init(Streamer);137}138 139void ModuleSymbolTable::CollectAsmSymbols(140 const Module &M,141 function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {142 initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {143 Streamer.flushSymverDirectives();144 145 for (auto &KV : Streamer) {146 StringRef Key = KV.first();147 RecordStreamer::State Value = KV.second;148 // FIXME: For now we just assume that all asm symbols are executable.149 uint32_t Res = BasicSymbolRef::SF_Executable;150 switch (Value) {151 case RecordStreamer::NeverSeen:152 llvm_unreachable("NeverSeen should have been replaced earlier");153 case RecordStreamer::DefinedGlobal:154 Res |= BasicSymbolRef::SF_Global;155 break;156 case RecordStreamer::Defined:157 break;158 case RecordStreamer::Global:159 case RecordStreamer::Used:160 Res |= BasicSymbolRef::SF_Undefined;161 Res |= BasicSymbolRef::SF_Global;162 break;163 case RecordStreamer::DefinedWeak:164 Res |= BasicSymbolRef::SF_Weak;165 Res |= BasicSymbolRef::SF_Global;166 break;167 case RecordStreamer::UndefinedWeak:168 Res |= BasicSymbolRef::SF_Weak;169 Res |= BasicSymbolRef::SF_Undefined;170 }171 AsmSymbol(Key, BasicSymbolRef::Flags(Res));172 }173 });174 175 // In ELF, object code generated for x86-32 and some code models of x86-64 may176 // reference the special symbol _GLOBAL_OFFSET_TABLE_ that is not used in the177 // IR. Record it like inline asm symbols.178 Triple TT(M.getTargetTriple());179 if (!TT.isOSBinFormatELF() || !TT.isX86())180 return;181 auto CM = M.getCodeModel();182 if (TT.getArch() == Triple::x86 || CM == CodeModel::Medium ||183 CM == CodeModel::Large) {184 AsmSymbol("_GLOBAL_OFFSET_TABLE_",185 BasicSymbolRef::Flags(BasicSymbolRef::SF_Undefined |186 BasicSymbolRef::SF_Global));187 }188}189 190void ModuleSymbolTable::CollectAsmSymvers(191 const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {192 initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {193 for (auto &KV : Streamer.symverAliases())194 for (auto &Alias : KV.second)195 AsmSymver(KV.first->getName(), Alias);196 });197}198 199void ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {200 if (isa<AsmSymbol *>(S)) {201 OS << cast<AsmSymbol *>(S)->first;202 return;203 }204 205 auto *GV = cast<GlobalValue *>(S);206 if (GV->hasDLLImportStorageClass())207 OS << "__imp_";208 209 Mang.getNameWithPrefix(OS, GV, false);210}211 212uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {213 if (isa<AsmSymbol *>(S))214 return cast<AsmSymbol *>(S)->second;215 216 auto *GV = cast<GlobalValue *>(S);217 218 uint32_t Res = BasicSymbolRef::SF_None;219 if (GV->isDeclarationForLinker())220 Res |= BasicSymbolRef::SF_Undefined;221 else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())222 Res |= BasicSymbolRef::SF_Hidden;223 if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {224 if (GVar->isConstant())225 Res |= BasicSymbolRef::SF_Const;226 }227 if (const GlobalObject *GO = GV->getAliaseeObject())228 if (isa<Function>(GO) || isa<GlobalIFunc>(GO))229 Res |= BasicSymbolRef::SF_Executable;230 if (isa<GlobalAlias>(GV))231 Res |= BasicSymbolRef::SF_Indirect;232 if (GV->hasPrivateLinkage())233 Res |= BasicSymbolRef::SF_FormatSpecific;234 if (!GV->hasLocalLinkage())235 Res |= BasicSymbolRef::SF_Global;236 if (GV->hasCommonLinkage())237 Res |= BasicSymbolRef::SF_Common;238 if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||239 GV->hasExternalWeakLinkage())240 Res |= BasicSymbolRef::SF_Weak;241 242 if (GV->getName().starts_with("llvm."))243 Res |= BasicSymbolRef::SF_FormatSpecific;244 else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {245 if (Var->getSection() == "llvm.metadata")246 Res |= BasicSymbolRef::SF_FormatSpecific;247 }248 249 return Res;250}251