1321369Sdim//===-- RecordStreamer.cpp - Record asm defined and used symbols ----------===// 2274955Ssvnmir// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6274955Ssvnmir// 7274955Ssvnmir//===----------------------------------------------------------------------===// 8274955Ssvnmir 9274955Ssvnmir#include "RecordStreamer.h" 10331366Sdim#include "llvm/IR/Mangler.h" 11331366Sdim#include "llvm/IR/Module.h" 12331366Sdim#include "llvm/MC/MCContext.h" 13274955Ssvnmir#include "llvm/MC/MCSymbol.h" 14321369Sdim 15274955Ssvnmirusing namespace llvm; 16274955Ssvnmir 17274955Ssvnmirvoid RecordStreamer::markDefined(const MCSymbol &Symbol) { 18274955Ssvnmir State &S = Symbols[Symbol.getName()]; 19274955Ssvnmir switch (S) { 20274955Ssvnmir case DefinedGlobal: 21274955Ssvnmir case Global: 22274955Ssvnmir S = DefinedGlobal; 23274955Ssvnmir break; 24274955Ssvnmir case NeverSeen: 25274955Ssvnmir case Defined: 26274955Ssvnmir case Used: 27274955Ssvnmir S = Defined; 28274955Ssvnmir break; 29314564Sdim case DefinedWeak: 30309124Sdim break; 31314564Sdim case UndefinedWeak: 32314564Sdim S = DefinedWeak; 33274955Ssvnmir } 34274955Ssvnmir} 35274955Ssvnmir 36309124Sdimvoid RecordStreamer::markGlobal(const MCSymbol &Symbol, 37309124Sdim MCSymbolAttr Attribute) { 38274955Ssvnmir State &S = Symbols[Symbol.getName()]; 39274955Ssvnmir switch (S) { 40274955Ssvnmir case DefinedGlobal: 41274955Ssvnmir case Defined: 42314564Sdim S = (Attribute == MCSA_Weak) ? DefinedWeak : DefinedGlobal; 43274955Ssvnmir break; 44274955Ssvnmir 45274955Ssvnmir case NeverSeen: 46274955Ssvnmir case Global: 47274955Ssvnmir case Used: 48314564Sdim S = (Attribute == MCSA_Weak) ? UndefinedWeak : Global; 49274955Ssvnmir break; 50314564Sdim case UndefinedWeak: 51314564Sdim case DefinedWeak: 52309124Sdim break; 53274955Ssvnmir } 54274955Ssvnmir} 55274955Ssvnmir 56274955Ssvnmirvoid RecordStreamer::markUsed(const MCSymbol &Symbol) { 57274955Ssvnmir State &S = Symbols[Symbol.getName()]; 58274955Ssvnmir switch (S) { 59274955Ssvnmir case DefinedGlobal: 60274955Ssvnmir case Defined: 61274955Ssvnmir case Global: 62314564Sdim case DefinedWeak: 63314564Sdim case UndefinedWeak: 64274955Ssvnmir break; 65274955Ssvnmir 66274955Ssvnmir case NeverSeen: 67274955Ssvnmir case Used: 68274955Ssvnmir S = Used; 69274955Ssvnmir break; 70274955Ssvnmir } 71274955Ssvnmir} 72274955Ssvnmir 73274955Ssvnmirvoid RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } 74274955Ssvnmir 75331366SdimRecordStreamer::RecordStreamer(MCContext &Context, const Module &M) 76331366Sdim : MCStreamer(Context), M(M) {} 77321369Sdim 78274955SsvnmirRecordStreamer::const_iterator RecordStreamer::begin() { 79274955Ssvnmir return Symbols.begin(); 80274955Ssvnmir} 81274955Ssvnmir 82274955SsvnmirRecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } 83274955Ssvnmir 84274955Ssvnmirvoid RecordStreamer::EmitInstruction(const MCInst &Inst, 85353358Sdim const MCSubtargetInfo &STI) { 86274955Ssvnmir MCStreamer::EmitInstruction(Inst, STI); 87274955Ssvnmir} 88274955Ssvnmir 89321369Sdimvoid RecordStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { 90274955Ssvnmir MCStreamer::EmitLabel(Symbol); 91274955Ssvnmir markDefined(*Symbol); 92274955Ssvnmir} 93274955Ssvnmir 94274955Ssvnmirvoid RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 95274955Ssvnmir markDefined(*Symbol); 96274955Ssvnmir MCStreamer::EmitAssignment(Symbol, Value); 97274955Ssvnmir} 98274955Ssvnmir 99274955Ssvnmirbool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 100274955Ssvnmir MCSymbolAttr Attribute) { 101309124Sdim if (Attribute == MCSA_Global || Attribute == MCSA_Weak) 102309124Sdim markGlobal(*Symbol, Attribute); 103314564Sdim if (Attribute == MCSA_LazyReference) 104314564Sdim markUsed(*Symbol); 105274955Ssvnmir return true; 106274955Ssvnmir} 107274955Ssvnmir 108288943Sdimvoid RecordStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 109341825Sdim uint64_t Size, unsigned ByteAlignment, 110341825Sdim SMLoc Loc) { 111274955Ssvnmir markDefined(*Symbol); 112274955Ssvnmir} 113274955Ssvnmir 114274955Ssvnmirvoid RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 115274955Ssvnmir unsigned ByteAlignment) { 116274955Ssvnmir markDefined(*Symbol); 117274955Ssvnmir} 118321369Sdim 119331366SdimRecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) { 120331366Sdim auto SI = Symbols.find(Sym->getName()); 121331366Sdim if (SI == Symbols.end()) 122331366Sdim return NeverSeen; 123331366Sdim return SI->second; 124331366Sdim} 125331366Sdim 126331366Sdimvoid RecordStreamer::emitELFSymverDirective(StringRef AliasName, 127321369Sdim const MCSymbol *Aliasee) { 128331366Sdim SymverAliasMap[Aliasee].push_back(AliasName); 129321369Sdim} 130331366Sdim 131341825Sdimiterator_range<RecordStreamer::const_symver_iterator> 132341825SdimRecordStreamer::symverAliases() { 133341825Sdim return {SymverAliasMap.begin(), SymverAliasMap.end()}; 134341825Sdim} 135341825Sdim 136331366Sdimvoid RecordStreamer::flushSymverDirectives() { 137331366Sdim // Mapping from mangled name to GV. 138331366Sdim StringMap<const GlobalValue *> MangledNameMap; 139331366Sdim // The name in the assembler will be mangled, but the name in the IR 140331366Sdim // might not, so we first compute a mapping from mangled name to GV. 141331366Sdim Mangler Mang; 142331366Sdim SmallString<64> MangledName; 143331366Sdim for (const GlobalValue &GV : M.global_values()) { 144331366Sdim if (!GV.hasName()) 145331366Sdim continue; 146331366Sdim MangledName.clear(); 147331366Sdim MangledName.reserve(GV.getName().size() + 1); 148331366Sdim Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); 149331366Sdim MangledNameMap[MangledName] = &GV; 150331366Sdim } 151331366Sdim 152331366Sdim // Walk all the recorded .symver aliases, and set up the binding 153331366Sdim // for each alias. 154331366Sdim for (auto &Symver : SymverAliasMap) { 155331366Sdim const MCSymbol *Aliasee = Symver.first; 156331366Sdim MCSymbolAttr Attr = MCSA_Invalid; 157331366Sdim bool IsDefined = false; 158331366Sdim 159331366Sdim // First check if the aliasee binding was recorded in the asm. 160331366Sdim RecordStreamer::State state = getSymbolState(Aliasee); 161331366Sdim switch (state) { 162331366Sdim case RecordStreamer::Global: 163331366Sdim case RecordStreamer::DefinedGlobal: 164331366Sdim Attr = MCSA_Global; 165331366Sdim break; 166331366Sdim case RecordStreamer::UndefinedWeak: 167331366Sdim case RecordStreamer::DefinedWeak: 168331366Sdim Attr = MCSA_Weak; 169331366Sdim break; 170331366Sdim default: 171331366Sdim break; 172331366Sdim } 173331366Sdim 174331366Sdim switch (state) { 175331366Sdim case RecordStreamer::Defined: 176331366Sdim case RecordStreamer::DefinedGlobal: 177331366Sdim case RecordStreamer::DefinedWeak: 178331366Sdim IsDefined = true; 179331366Sdim break; 180331366Sdim case RecordStreamer::NeverSeen: 181331366Sdim case RecordStreamer::Global: 182331366Sdim case RecordStreamer::Used: 183331366Sdim case RecordStreamer::UndefinedWeak: 184331366Sdim break; 185331366Sdim } 186331366Sdim 187331366Sdim if (Attr == MCSA_Invalid || !IsDefined) { 188331366Sdim const GlobalValue *GV = M.getNamedValue(Aliasee->getName()); 189331366Sdim if (!GV) { 190331366Sdim auto MI = MangledNameMap.find(Aliasee->getName()); 191331366Sdim if (MI != MangledNameMap.end()) 192331366Sdim GV = MI->second; 193331366Sdim } 194331366Sdim if (GV) { 195331366Sdim // If we don't have a symbol attribute from assembly, then check if 196331366Sdim // the aliasee was defined in the IR. 197331366Sdim if (Attr == MCSA_Invalid) { 198331366Sdim if (GV->hasExternalLinkage()) 199331366Sdim Attr = MCSA_Global; 200331366Sdim else if (GV->hasLocalLinkage()) 201331366Sdim Attr = MCSA_Local; 202331366Sdim else if (GV->isWeakForLinker()) 203331366Sdim Attr = MCSA_Weak; 204331366Sdim } 205331366Sdim IsDefined = IsDefined || !GV->isDeclarationForLinker(); 206331366Sdim } 207331366Sdim } 208331366Sdim 209331366Sdim // Set the detected binding on each alias with this aliasee. 210331366Sdim for (auto AliasName : Symver.second) { 211331366Sdim std::pair<StringRef, StringRef> Split = AliasName.split("@@@"); 212331366Sdim SmallString<128> NewName; 213331366Sdim if (!Split.second.empty() && !Split.second.startswith("@")) { 214331366Sdim // Special processing for "@@@" according 215331366Sdim // https://sourceware.org/binutils/docs/as/Symver.html 216331366Sdim const char *Separator = IsDefined ? "@@" : "@"; 217331366Sdim AliasName = 218331366Sdim (Split.first + Separator + Split.second).toStringRef(NewName); 219331366Sdim } 220331366Sdim MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName); 221331366Sdim // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be 222331366Sdim // converted into @ or @@. 223331366Sdim const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext()); 224341825Sdim if (IsDefined) 225341825Sdim markDefined(*Alias); 226341825Sdim // Don't use EmitAssignment override as it always marks alias as defined. 227341825Sdim MCStreamer::EmitAssignment(Alias, Value); 228331366Sdim if (Attr != MCSA_Invalid) 229331366Sdim EmitSymbolAttribute(Alias, Attr); 230331366Sdim } 231331366Sdim } 232331366Sdim} 233