brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 6e8d0c4 Raw
229 lines · cpp
1//===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===//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#include "RecordStreamer.h"10#include "llvm/IR/Mangler.h"11#include "llvm/IR/Module.h"12#include "llvm/MC/MCContext.h"13#include "llvm/MC/MCSymbol.h"14 15using namespace llvm;16 17void RecordStreamer::markDefined(const MCSymbol &Symbol) {18  State &S = Symbols[Symbol.getName()];19  switch (S) {20  case DefinedGlobal:21  case Global:22    S = DefinedGlobal;23    break;24  case NeverSeen:25  case Defined:26  case Used:27    S = Defined;28    break;29  case DefinedWeak:30    break;31  case UndefinedWeak:32    S = DefinedWeak;33  }34}35 36void RecordStreamer::markGlobal(const MCSymbol &Symbol,37                                MCSymbolAttr Attribute) {38  State &S = Symbols[Symbol.getName()];39  switch (S) {40  case DefinedGlobal:41  case Defined:42    S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;43    break;44 45  case NeverSeen:46  case Global:47  case Used:48    S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;49    break;50  case UndefinedWeak:51  case DefinedWeak:52    break;53  }54}55 56void RecordStreamer::markUsed(const MCSymbol &Symbol) {57  State &S = Symbols[Symbol.getName()];58  switch (S) {59  case DefinedGlobal:60  case Defined:61  case Global:62  case DefinedWeak:63  case UndefinedWeak:64    break;65 66  case NeverSeen:67  case Used:68    S = Used;69    break;70  }71}72 73void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }74 75RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)76    : MCStreamer(Context), M(M) {}77 78RecordStreamer::const_iterator RecordStreamer::begin() {79  return Symbols.begin();80}81 82RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); }83 84void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {85  MCStreamer::emitLabel(Symbol);86  markDefined(*Symbol);87}88 89void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {90  markDefined(*Symbol);91  MCStreamer::emitAssignment(Symbol, Value);92}93 94bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol,95                                         MCSymbolAttr Attribute) {96  if (Attribute == MCSA_Global || Attribute == MCSA_Weak)97    markGlobal(*Symbol, Attribute);98  if (Attribute == MCSA_LazyReference)99    markUsed(*Symbol);100  return true;101}102 103void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,104                                  uint64_t Size, Align ByteAlignment,105                                  SMLoc Loc) {106  markDefined(*Symbol);107}108 109void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,110                                      Align ByteAlignment) {111  markDefined(*Symbol);112}113 114RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {115  auto SI = Symbols.find(Sym->getName());116  if (SI == Symbols.end())117    return NeverSeen;118  return SI->second;119}120 121void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,122                                            StringRef Name,123                                            bool KeepOriginalSym) {124  SymverAliasMap[OriginalSym].push_back(Name);125}126 127iterator_range<RecordStreamer::const_symver_iterator>128RecordStreamer::symverAliases() {129  return SymverAliasMap;130}131 132void RecordStreamer::flushSymverDirectives() {133  // Mapping from mangled name to GV.134  StringMap<const GlobalValue *> MangledNameMap;135  // The name in the assembler will be mangled, but the name in the IR136  // might not, so we first compute a mapping from mangled name to GV.137  Mangler Mang;138  SmallString<64> MangledName;139  for (const GlobalValue &GV : M.global_values()) {140    if (!GV.hasName())141      continue;142    MangledName.clear();143    MangledName.reserve(GV.getName().size() + 1);144    Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);145    MangledNameMap[MangledName] = &GV;146  }147 148  // Walk all the recorded .symver aliases, and set up the binding149  // for each alias.150  for (auto &Symver : SymverAliasMap) {151    const MCSymbol *Aliasee = Symver.first;152    MCSymbolAttr Attr = MCSA_Invalid;153    bool IsDefined = false;154 155    // First check if the aliasee binding was recorded in the asm.156    RecordStreamer::State state = getSymbolState(Aliasee);157    switch (state) {158    case RecordStreamer::Global:159    case RecordStreamer::DefinedGlobal:160      Attr = MCSA_Global;161      break;162    case RecordStreamer::UndefinedWeak:163    case RecordStreamer::DefinedWeak:164      Attr = MCSA_Weak;165      break;166    default:167      break;168    }169 170    switch (state) {171    case RecordStreamer::Defined:172    case RecordStreamer::DefinedGlobal:173    case RecordStreamer::DefinedWeak:174      IsDefined = true;175      break;176    case RecordStreamer::NeverSeen:177    case RecordStreamer::Global:178    case RecordStreamer::Used:179    case RecordStreamer::UndefinedWeak:180      break;181    }182 183    if (Attr == MCSA_Invalid || !IsDefined) {184      const GlobalValue *GV = M.getNamedValue(Aliasee->getName());185      if (!GV) {186        auto MI = MangledNameMap.find(Aliasee->getName());187        if (MI != MangledNameMap.end())188          GV = MI->second;189      }190      if (GV) {191        // If we don't have a symbol attribute from assembly, then check if192        // the aliasee was defined in the IR.193        if (Attr == MCSA_Invalid) {194          if (GV->hasExternalLinkage())195            Attr = MCSA_Global;196          else if (GV->hasLocalLinkage())197            Attr = MCSA_Local;198          else if (GV->isWeakForLinker())199            Attr = MCSA_Weak;200        }201        IsDefined = IsDefined || !GV->isDeclarationForLinker();202      }203    }204 205    // Set the detected binding on each alias with this aliasee.206    for (auto AliasName : Symver.second) {207      std::pair<StringRef, StringRef> Split = AliasName.split("@@@");208      SmallString<128> NewName;209      if (!Split.second.empty() && !Split.second.starts_with("@")) {210        // Special processing for "@@@" according211        // https://sourceware.org/binutils/docs/as/Symver.html212        const char *Separator = IsDefined ? "@@" : "@";213        AliasName =214            (Split.first + Separator + Split.second).toStringRef(NewName);215      }216      MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);217      // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be218      // converted into @ or @@.219      const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());220      if (IsDefined)221        markDefined(*Alias);222      // Don't use EmitAssignment override as it always marks alias as defined.223      MCStreamer::emitAssignment(Alias, Value);224      if (Attr != MCSA_Invalid)225        emitSymbolAttribute(Alias, Attr);226    }227  }228}229