Coverage Report

Created: 2019-07-24 05:18

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