Coverage Report

Created: 2019-05-22 02:55

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/Symbols.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- Symbols.cpp --------------------------------------------------------===//
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 "Symbols.h"
10
#include "Config.h"
11
#include "InputChunks.h"
12
#include "InputEvent.h"
13
#include "InputFiles.h"
14
#include "InputGlobal.h"
15
#include "OutputSections.h"
16
#include "OutputSegment.h"
17
#include "lld/Common/ErrorHandler.h"
18
#include "lld/Common/Strings.h"
19
20
#define DEBUG_TYPE "lld"
21
22
using namespace llvm;
23
using namespace llvm::wasm;
24
using namespace lld;
25
using namespace lld::wasm;
26
27
DefinedFunction *WasmSym::CallCtors;
28
DefinedFunction *WasmSym::ApplyRelocs;
29
DefinedData *WasmSym::DsoHandle;
30
DefinedData *WasmSym::DataEnd;
31
DefinedData *WasmSym::HeapBase;
32
GlobalSymbol *WasmSym::StackPointer;
33
UndefinedGlobal *WasmSym::TableBase;
34
UndefinedGlobal *WasmSym::MemoryBase;
35
36
210
WasmSymbolType Symbol::getWasmType() const {
37
210
  if (isa<FunctionSymbol>(this))
38
191
    return WASM_SYMBOL_TYPE_FUNCTION;
39
19
  if (isa<DataSymbol>(this))
40
17
    return WASM_SYMBOL_TYPE_DATA;
41
2
  if (isa<GlobalSymbol>(this))
42
2
    return WASM_SYMBOL_TYPE_GLOBAL;
43
0
  if (isa<EventSymbol>(this))
44
0
    return WASM_SYMBOL_TYPE_EVENT;
45
0
  if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
46
0
    return WASM_SYMBOL_TYPE_SECTION;
47
0
  llvm_unreachable("invalid symbol kind");
48
0
}
49
50
343
const WasmSignature *Symbol::getSignature() const {
51
343
  if (auto* F = dyn_cast<FunctionSymbol>(this))
52
332
    return F->Signature;
53
11
  if (auto *L = dyn_cast<LazySymbol>(this))
54
10
    return L->Signature;
55
1
  return nullptr;
56
1
}
57
58
1.46k
InputChunk *Symbol::getChunk() const {
59
1.46k
  if (auto *F = dyn_cast<DefinedFunction>(this))
60
675
    return F->Function;
61
793
  if (auto *D = dyn_cast<DefinedData>(this))
62
729
    return D->Segment;
63
64
  return nullptr;
64
64
}
65
66
988
bool Symbol::isLive() const {
67
988
  if (auto *G = dyn_cast<DefinedGlobal>(this))
68
7
    return G->Global->Live;
69
981
  if (auto *E = dyn_cast<DefinedEvent>(this))
70
0
    return E->Event->Live;
71
981
  if (InputChunk *C = getChunk())
72
656
    return C->Live;
73
325
  return Referenced;
74
325
}
75
76
244
void Symbol::markLive() {
77
244
  if (auto *G = dyn_cast<DefinedGlobal>(this))
78
1
    G->Global->Live = true;
79
244
  if (auto *E = dyn_cast<DefinedEvent>(this))
80
0
    E->Event->Live = true;
81
244
  if (InputChunk *C = getChunk())
82
106
    C->Live = true;
83
244
  Referenced = true;
84
244
}
85
86
206
uint32_t Symbol::getOutputSymbolIndex() const {
87
206
  assert(OutputSymbolIndex != INVALID_INDEX);
88
206
  return OutputSymbolIndex;
89
206
}
90
91
210
void Symbol::setOutputSymbolIndex(uint32_t Index) {
92
210
  LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index
93
210
                    << "\n");
94
210
  assert(OutputSymbolIndex == INVALID_INDEX);
95
210
  OutputSymbolIndex = Index;
96
210
}
97
98
0
void Symbol::setGOTIndex(uint32_t Index) {
99
0
  LLVM_DEBUG(dbgs() << "setGOTIndex " << Name << " -> " << Index << "\n");
100
0
  assert(GOTIndex == INVALID_INDEX);
101
0
  // Any symbol that is assigned a GOT entry must be exported othewise the
102
0
  // dynamic linker won't be able create the entry that contains it.
103
0
  ForceExport = true;
104
0
  GOTIndex = Index;
105
0
}
106
107
814
bool Symbol::isWeak() const {
108
814
  return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
109
814
}
110
111
1.39k
bool Symbol::isLocal() const {
112
1.39k
  return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
113
1.39k
}
114
115
311
bool Symbol::isHidden() const {
116
311
  return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
117
311
}
118
119
59
void Symbol::setHidden(bool IsHidden) {
120
59
  LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n");
121
59
  Flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
122
59
  if (IsHidden)
123
3
    Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
124
56
  else
125
56
    Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
126
59
}
127
128
1.00k
bool Symbol::isExported() const {
129
1.00k
  if (!isDefined() || 
isLocal()975
)
130
34
    return false;
131
975
132
975
  if (ForceExport || 
Config->ExportAll584
)
133
391
    return true;
134
584
135
584
  if (Config->ExportDynamic && 
!isHidden()101
)
136
45
    return true;
137
539
138
539
  return Flags & WASM_SYMBOL_EXPORTED;
139
539
}
140
141
370
uint32_t FunctionSymbol::getFunctionIndex() const {
142
370
  if (auto *F = dyn_cast<DefinedFunction>(this))
143
336
    return F->Function->getFunctionIndex();
144
34
  assert(FunctionIndex != INVALID_INDEX);
145
34
  return FunctionIndex;
146
34
}
147
148
13
void FunctionSymbol::setFunctionIndex(uint32_t Index) {
149
13
  LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n");
150
13
  assert(FunctionIndex == INVALID_INDEX);
151
13
  FunctionIndex = Index;
152
13
}
153
154
0
bool FunctionSymbol::hasFunctionIndex() const {
155
0
  if (auto *F = dyn_cast<DefinedFunction>(this))
156
0
    return F->Function->hasFunctionIndex();
157
0
  return FunctionIndex != INVALID_INDEX;
158
0
}
159
160
26
uint32_t FunctionSymbol::getTableIndex() const {
161
26
  if (auto *F = dyn_cast<DefinedFunction>(this))
162
24
    return F->Function->getTableIndex();
163
2
  assert(TableIndex != INVALID_INDEX);
164
2
  return TableIndex;
165
2
}
166
167
35
bool FunctionSymbol::hasTableIndex() const {
168
35
  if (auto *F = dyn_cast<DefinedFunction>(this))
169
33
    return F->Function->hasTableIndex();
170
2
  return TableIndex != INVALID_INDEX;
171
2
}
172
173
23
void FunctionSymbol::setTableIndex(uint32_t Index) {
174
23
  // For imports, we set the table index here on the Symbol; for defined
175
23
  // functions we set the index on the InputFunction so that we don't export
176
23
  // the same thing twice (keeps the table size down).
177
23
  if (auto *F = dyn_cast<DefinedFunction>(this)) {
178
21
    F->Function->setTableIndex(Index);
179
21
    return;
180
21
  }
181
2
  LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");
182
2
  assert(TableIndex == INVALID_INDEX);
183
2
  TableIndex = Index;
184
2
}
185
186
DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,
187
                                 InputFunction *Function)
188
    : FunctionSymbol(Name, DefinedFunctionKind, Flags, F,
189
                     Function ? &Function->Signature : nullptr),
190
455
      Function(Function) {}
191
192
304
uint32_t DefinedData::getVirtualAddress() const {
193
304
  LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
194
304
  if (Segment)
195
158
    return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset;
196
146
  return Offset;
197
146
}
198
199
220
void DefinedData::setVirtualAddress(uint32_t Value) {
200
220
  LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
201
220
  assert(!Segment);
202
220
  Offset = Value;
203
220
}
204
205
14
uint32_t DefinedData::getOutputSegmentOffset() const {
206
14
  LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
207
14
  return Segment->OutputSegmentOffset + Offset;
208
14
}
209
210
14
uint32_t DefinedData::getOutputSegmentIndex() const {
211
14
  LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
212
14
  return Segment->OutputSeg->Index;
213
14
}
214
215
18
uint32_t GlobalSymbol::getGlobalIndex() const {
216
18
  if (auto *F = dyn_cast<DefinedGlobal>(this))
217
8
    return F->Global->getGlobalIndex();
218
10
  assert(GlobalIndex != INVALID_INDEX);
219
10
  return GlobalIndex;
220
10
}
221
222
4
void GlobalSymbol::setGlobalIndex(uint32_t Index) {
223
4
  LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n");
224
4
  assert(GlobalIndex == INVALID_INDEX);
225
4
  GlobalIndex = Index;
226
4
}
227
228
0
bool GlobalSymbol::hasGlobalIndex() const {
229
0
  if (auto *F = dyn_cast<DefinedGlobal>(this))
230
0
    return F->Global->hasGlobalIndex();
231
0
  return GlobalIndex != INVALID_INDEX;
232
0
}
233
234
DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
235
                             InputGlobal *Global)
236
    : GlobalSymbol(Name, DefinedGlobalKind, Flags, File,
237
                   Global ? &Global->getType() : nullptr),
238
92
      Global(Global) {}
239
240
0
uint32_t EventSymbol::getEventIndex() const {
241
0
  if (auto *F = dyn_cast<DefinedEvent>(this))
242
0
    return F->Event->getEventIndex();
243
0
  assert(EventIndex != INVALID_INDEX);
244
0
  return EventIndex;
245
0
}
246
247
0
void EventSymbol::setEventIndex(uint32_t Index) {
248
0
  LLVM_DEBUG(dbgs() << "setEventIndex " << Name << " -> " << Index << "\n");
249
0
  assert(EventIndex == INVALID_INDEX);
250
0
  EventIndex = Index;
251
0
}
252
253
0
bool EventSymbol::hasEventIndex() const {
254
0
  if (auto *F = dyn_cast<DefinedEvent>(this))
255
0
    return F->Event->hasEventIndex();
256
0
  return EventIndex != INVALID_INDEX;
257
0
}
258
259
DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,
260
                           InputEvent *Event)
261
    : EventSymbol(Name, DefinedEventKind, Flags, File,
262
                  Event ? &Event->getType() : nullptr,
263
                  Event ? &Event->Signature : nullptr),
264
0
      Event(Event) {}
265
266
0
const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
267
0
  assert(Section->OutputSec && Section->OutputSec->SectionSym);
268
0
  return Section->OutputSec->SectionSym;
269
0
}
270
271
7
void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
272
273
24
std::string lld::toString(const wasm::Symbol &Sym) {
274
24
  return lld::maybeDemangleSymbol(Sym.getName());
275
24
}
276
277
314
std::string lld::maybeDemangleSymbol(StringRef Name) {
278
314
  if (Config->Demangle)
279
314
    if (Optional<std::string> S = demangleItanium(Name))
280
2
      return *S;
281
312
  return Name;
282
312
}
283
284
0
std::string lld::toString(wasm::Symbol::Kind Kind) {
285
0
  switch (Kind) {
286
0
  case wasm::Symbol::DefinedFunctionKind:
287
0
    return "DefinedFunction";
288
0
  case wasm::Symbol::DefinedDataKind:
289
0
    return "DefinedData";
290
0
  case wasm::Symbol::DefinedGlobalKind:
291
0
    return "DefinedGlobal";
292
0
  case wasm::Symbol::DefinedEventKind:
293
0
    return "DefinedEvent";
294
0
  case wasm::Symbol::UndefinedFunctionKind:
295
0
    return "UndefinedFunction";
296
0
  case wasm::Symbol::UndefinedDataKind:
297
0
    return "UndefinedData";
298
0
  case wasm::Symbol::UndefinedGlobalKind:
299
0
    return "UndefinedGlobal";
300
0
  case wasm::Symbol::LazyKind:
301
0
    return "LazyKind";
302
0
  case wasm::Symbol::SectionKind:
303
0
    return "SectionKind";
304
0
  case wasm::Symbol::OutputSectionKind:
305
0
    return "OutputSectionKind";
306
0
  }
307
0
  llvm_unreachable("invalid symbol kind");
308
0
}
309
310
// Print out a log message for --trace-symbol.
311
4
void lld::wasm::printTraceSymbol(Symbol *Sym) {
312
4
  std::string S;
313
4
  if (Sym->isUndefined())
314
1
    S = ": reference to ";
315
3
  else if (Sym->isLazy())
316
0
    S = ": lazy definition of ";
317
3
  else
318
3
    S = ": definition of ";
319
4
320
4
  message(toString(Sym->getFile()) + S + Sym->getName());
321
4
}
322
323
const char *lld::wasm::DefaultModule = "env";
324
const char *lld::wasm::FunctionTableName = "__indirect_function_table";