LCOV - code coverage report
Current view: top level - lib/Object - RecordStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 103 110 93.6 %
Date: 2018-06-17 00:07:59 Functions: 15 17 88.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13