LCOV - code coverage report
Current view: top level - lib/Object - RecordStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 102 108 94.4 %
Date: 2018-10-20 13:21:21 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         156 : void RecordStreamer::markUsed(const MCSymbol &Symbol) {
      58         156 :   State &S = Symbols[Symbol.getName()];
      59         156 :   switch (S) {
      60             :   case DefinedGlobal:
      61             :   case Defined:
      62             :   case Global:
      63             :   case DefinedWeak:
      64             :   case UndefinedWeak:
      65             :     break;
      66             : 
      67         129 :   case NeverSeen:
      68             :   case Used:
      69         129 :     S = Used;
      70         129 :     break;
      71             :   }
      72         156 : }
      73             : 
      74         154 : void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); }
      75             : 
      76          98 : RecordStreamer::RecordStreamer(MCContext &Context, const Module &M)
      77          98 :     : MCStreamer(Context), M(M) {}
      78             : 
      79          96 : RecordStreamer::const_iterator RecordStreamer::begin() {
      80          96 :   return Symbols.begin();
      81             : }
      82             : 
      83         192 : 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             :                                   SMLoc Loc) {
     112           0 :   markDefined(*Symbol);
     113           0 : }
     114             : 
     115           0 : void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     116             :                                       unsigned ByteAlignment) {
     117           0 :   markDefined(*Symbol);
     118           0 : }
     119             : 
     120          62 : RecordStreamer::State RecordStreamer::getSymbolState(const MCSymbol *Sym) {
     121         124 :   auto SI = Symbols.find(Sym->getName());
     122         124 :   if (SI == Symbols.end())
     123             :     return NeverSeen;
     124          26 :   return SI->second;
     125             : }
     126             : 
     127          72 : void RecordStreamer::emitELFSymverDirective(StringRef AliasName,
     128             :                                             const MCSymbol *Aliasee) {
     129          72 :   SymverAliasMap[Aliasee].push_back(AliasName);
     130          72 : }
     131             : 
     132             : iterator_range<RecordStreamer::const_symver_iterator>
     133           2 : RecordStreamer::symverAliases() {
     134           2 :   return {SymverAliasMap.begin(), SymverAliasMap.end()};
     135             : }
     136             : 
     137          96 : void RecordStreamer::flushSymverDirectives() {
     138             :   // Mapping from mangled name to GV.
     139          96 :   StringMap<const GlobalValue *> MangledNameMap;
     140             :   // The name in the assembler will be mangled, but the name in the IR
     141             :   // might not, so we first compute a mapping from mangled name to GV.
     142             :   Mangler Mang;
     143             :   SmallString<64> MangledName;
     144         453 :   for (const GlobalValue &GV : M.global_values()) {
     145         261 :     if (!GV.hasName())
     146             :       continue;
     147             :     MangledName.clear();
     148         261 :     MangledName.reserve(GV.getName().size() + 1);
     149         261 :     Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false);
     150         261 :     MangledNameMap[MangledName] = &GV;
     151             :   }
     152             : 
     153             :   // Walk all the recorded .symver aliases, and set up the binding
     154             :   // for each alias.
     155         158 :   for (auto &Symver : SymverAliasMap) {
     156          62 :     const MCSymbol *Aliasee = Symver.first;
     157             :     MCSymbolAttr Attr = MCSA_Invalid;
     158             :     bool IsDefined = false;
     159             : 
     160             :     // First check if the aliasee binding was recorded in the asm.
     161          62 :     RecordStreamer::State state = getSymbolState(Aliasee);
     162          62 :     switch (state) {
     163          10 :     case RecordStreamer::Global:
     164             :     case RecordStreamer::DefinedGlobal:
     165             :       Attr = MCSA_Global;
     166          10 :       break;
     167           7 :     case RecordStreamer::UndefinedWeak:
     168             :     case RecordStreamer::DefinedWeak:
     169             :       Attr = MCSA_Weak;
     170           7 :       break;
     171             :     default:
     172             :       break;
     173             :     }
     174             : 
     175          62 :     switch (state) {
     176          25 :     case RecordStreamer::Defined:
     177             :     case RecordStreamer::DefinedGlobal:
     178             :     case RecordStreamer::DefinedWeak:
     179             :       IsDefined = true;
     180          25 :       break;
     181             :     case RecordStreamer::NeverSeen:
     182             :     case RecordStreamer::Global:
     183             :     case RecordStreamer::Used:
     184             :     case RecordStreamer::UndefinedWeak:
     185             :       break;
     186             :     }
     187             : 
     188          62 :     if (Attr == MCSA_Invalid || !IsDefined) {
     189          92 :       const GlobalValue *GV = M.getNamedValue(Aliasee->getName());
     190          46 :       if (!GV) {
     191          17 :         auto MI = MangledNameMap.find(Aliasee->getName());
     192          34 :         if (MI != MangledNameMap.end())
     193           7 :           GV = MI->second;
     194             :       }
     195          46 :       if (GV) {
     196             :         // If we don't have a symbol attribute from assembly, then check if
     197             :         // the aliasee was defined in the IR.
     198          36 :         if (Attr == MCSA_Invalid) {
     199          36 :           if (GV->hasExternalLinkage())
     200             :             Attr = MCSA_Global;
     201             :           else if (GV->hasLocalLinkage())
     202             :             Attr = MCSA_Local;
     203             :           else if (GV->isWeakForLinker())
     204             :             Attr = MCSA_Weak;
     205             :         }
     206          72 :         IsDefined = IsDefined || !GV->isDeclarationForLinker();
     207             :       }
     208             :     }
     209             : 
     210             :     // Set the detected binding on each alias with this aliasee.
     211         131 :     for (auto AliasName : Symver.second) {
     212          69 :       std::pair<StringRef, StringRef> Split = AliasName.split("@@@");
     213             :       SmallString<128> NewName;
     214          69 :       if (!Split.second.empty() && !Split.second.startswith("@")) {
     215             :         // Special processing for "@@@" according
     216             :         // https://sourceware.org/binutils/docs/as/Symver.html
     217           7 :         const char *Separator = IsDefined ? "@@" : "@";
     218             :         AliasName =
     219           7 :             (Split.first + Separator + Split.second).toStringRef(NewName);
     220             :       }
     221         138 :       MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
     222             :       // TODO: Handle "@@@". Depending on SymbolAttribute value it needs to be
     223             :       // converted into @ or @@.
     224          69 :       const MCExpr *Value = MCSymbolRefExpr::create(Aliasee, getContext());
     225          69 :       if (IsDefined)
     226          63 :         markDefined(*Alias);
     227             :       // Don't use EmitAssignment override as it always marks alias as defined.
     228          69 :       MCStreamer::EmitAssignment(Alias, Value);
     229          69 :       if (Attr != MCSA_Invalid)
     230          60 :         EmitSymbolAttribute(Alias, Attr);
     231             :     }
     232             :   }
     233          96 : }

Generated by: LCOV version 1.13