Path: blob/main/contrib/llvm-project/llvm/lib/Object/RecordStreamer.cpp
35233 views
//===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "RecordStreamer.h"9#include "llvm/IR/Mangler.h"10#include "llvm/IR/Module.h"11#include "llvm/MC/MCContext.h"12#include "llvm/MC/MCSymbol.h"1314using namespace llvm;1516void RecordStreamer::markDefined(const MCSymbol &Symbol) {17State &S = Symbols[Symbol.getName()];18switch (S) {19case DefinedGlobal:20case Global:21S = DefinedGlobal;22break;23case NeverSeen:24case Defined:25case Used:26S = Defined;27break;28case DefinedWeak:29break;30case UndefinedWeak:31S = DefinedWeak;32}33}3435void RecordStreamer::markGlobal(const MCSymbol &Symbol,36MCSymbolAttr Attribute) {37State &S = Symbols[Symbol.getName()];38switch (S) {39case DefinedGlobal:40case Defined:41S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal;42break;4344case NeverSeen:45case Global:46case Used:47S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global;48break;49case UndefinedWeak:50case DefinedWeak:51break;52}53}5455void RecordStreamer::markUsed(const MCSymbol &Symbol) {56State &S = Symbols[Symbol.getName()];57switch (S) {58case DefinedGlobal:59case Defined:60case Global:61case DefinedWeak:62case UndefinedWeak:63break;6465case NeverSeen:66case Used:67S = Used;68break;69}70}7172void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }7374RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)75: MCStreamer(Context), M(M) {}7677RecordStreamer::const_iterator RecordStreamer::begin() {78return Symbols.begin();79}8081RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); }8283void RecordStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {84MCStreamer::emitLabel(Symbol);85markDefined(*Symbol);86}8788void RecordStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {89markDefined(*Symbol);90MCStreamer::emitAssignment(Symbol, Value);91}9293bool RecordStreamer::emitSymbolAttribute(MCSymbol *Symbol,94MCSymbolAttr Attribute) {95if (Attribute == MCSA_Global || Attribute == MCSA_Weak)96markGlobal(*Symbol, Attribute);97if (Attribute == MCSA_LazyReference)98markUsed(*Symbol);99return true;100}101102void RecordStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,103uint64_t Size, Align ByteAlignment,104SMLoc Loc) {105markDefined(*Symbol);106}107108void RecordStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,109Align ByteAlignment) {110markDefined(*Symbol);111}112113RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {114auto SI = Symbols.find(Sym->getName());115if (SI == Symbols.end())116return NeverSeen;117return SI->second;118}119120void RecordStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,121StringRef Name,122bool KeepOriginalSym) {123SymverAliasMap[OriginalSym].push_back(Name);124}125126iterator_range<RecordStreamer::const_symver_iterator>127RecordStreamer::symverAliases() {128return {SymverAliasMap.begin(), SymverAliasMap.end()};129}130131void RecordStreamer::flushSymverDirectives() {132// Mapping from mangled name to GV.133StringMap<const GlobalValue *> MangledNameMap;134// The name in the assembler will be mangled, but the name in the IR135// might not, so we first compute a mapping from mangled name to GV.136Mangler Mang;137SmallString<64> MangledName;138for (const GlobalValue &GV : M.global_values()) {139if (!GV.hasName())140continue;141MangledName.clear();142MangledName.reserve(GV.getName().size() + 1);143Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);144MangledNameMap[MangledName] = &GV;145}146147// Walk all the recorded .symver aliases, and set up the binding148// for each alias.149for (auto &Symver : SymverAliasMap) {150const MCSymbol *Aliasee = Symver.first;151MCSymbolAttr Attr = MCSA_Invalid;152bool IsDefined = false;153154// First check if the aliasee binding was recorded in the asm.155RecordStreamer::State state = getSymbolState(Aliasee);156switch (state) {157case RecordStreamer::Global:158case RecordStreamer::DefinedGlobal:159Attr = MCSA_Global;160break;161case RecordStreamer::UndefinedWeak:162case RecordStreamer::DefinedWeak:163Attr = MCSA_Weak;164break;165default:166break;167}168169switch (state) {170case RecordStreamer::Defined:171case RecordStreamer::DefinedGlobal:172case RecordStreamer::DefinedWeak:173IsDefined = true;174break;175case RecordStreamer::NeverSeen:176case RecordStreamer::Global:177case RecordStreamer::Used:178case RecordStreamer::UndefinedWeak:179break;180}181182if (Attr == MCSA_Invalid || !IsDefined) {183const GlobalValue *GV = M.getNamedValue(Aliasee->getName());184if (!GV) {185auto MI = MangledNameMap.find(Aliasee->getName());186if (MI != MangledNameMap.end())187GV = MI->second;188}189if (GV) {190// If we don't have a symbol attribute from assembly, then check if191// the aliasee was defined in the IR.192if (Attr == MCSA_Invalid) {193if (GV->hasExternalLinkage())194Attr = MCSA_Global;195else if (GV->hasLocalLinkage())196Attr = MCSA_Local;197else if (GV->isWeakForLinker())198Attr = MCSA_Weak;199}200IsDefined = IsDefined || !GV->isDeclarationForLinker();201}202}203204// Set the detected binding on each alias with this aliasee.205for (auto AliasName : Symver.second) {206std::pair<StringRef, StringRef> Split = AliasName.split("@@@");207SmallString<128> NewName;208if (!Split.second.empty() && !Split.second.starts_with("@")) {209// Special processing for "@@@" according210// https://sourceware.org/binutils/docs/as/Symver.html211const char *Separator = IsDefined ? "@@" : "@";212AliasName =213(Split.first + Separator + Split.second).toStringRef(NewName);214}215MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);216// TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be217// converted into @ or @@.218const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());219if (IsDefined)220markDefined(*Alias);221// Don't use EmitAssignment override as it always marks alias as defined.222MCStreamer::emitAssignment(Alias, Value);223if (Attr != MCSA_Invalid)224emitSymbolAttribute(Alias, Attr);225}226}227}228229230