brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 9442bec Raw
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