Coverage Report

Created: 2018-06-25 02:00

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/Symbols.h
Line
Count
Source (jump to first uncovered line)
1
//===- Symbols.h ------------------------------------------------*- C++ -*-===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLD_WASM_SYMBOLS_H
11
#define LLD_WASM_SYMBOLS_H
12
13
#include "Config.h"
14
#include "lld/Common/LLVM.h"
15
#include "llvm/Object/Archive.h"
16
#include "llvm/Object/Wasm.h"
17
18
using llvm::object::Archive;
19
using llvm::object::WasmSymbol;
20
using llvm::wasm::WasmGlobal;
21
using llvm::wasm::WasmGlobalType;
22
using llvm::wasm::WasmSignature;
23
using llvm::wasm::WasmSymbolType;
24
25
namespace lld {
26
namespace wasm {
27
28
class InputFile;
29
class InputChunk;
30
class InputSegment;
31
class InputFunction;
32
class InputGlobal;
33
class InputSection;
34
35
0
#define INVALID_INDEX UINT32_MAX
36
37
// The base class for real symbol classes.
38
class Symbol {
39
public:
40
  enum Kind {
41
    DefinedFunctionKind,
42
    DefinedDataKind,
43
    DefinedGlobalKind,
44
    SectionKind,
45
    UndefinedFunctionKind,
46
    UndefinedDataKind,
47
    UndefinedGlobalKind,
48
    LazyKind,
49
  };
50
51
0
  Kind kind() const { return SymbolKind; }
52
53
0
  bool isDefined() const {
54
0
    return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
55
0
           SymbolKind == DefinedGlobalKind || SymbolKind == SectionKind;
56
0
  }
57
58
0
  bool isUndefined() const {
59
0
    return SymbolKind == UndefinedFunctionKind ||
60
0
           SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind;
61
0
  }
62
63
0
  bool isLazy() const { return SymbolKind == LazyKind; }
64
65
  bool isLocal() const;
66
  bool isWeak() const;
67
  bool isHidden() const;
68
69
  // Returns the symbol name.
70
0
  StringRef getName() const { return Name; }
71
72
  // Returns the file from which this symbol was created.
73
0
  InputFile *getFile() const { return File; }
74
75
  InputChunk *getChunk() const;
76
77
  // Indicates that the section or import for this symbol will be included in
78
  // the final image.
79
  bool isLive() const;
80
81
  // Marks the symbol's InputChunk as Live, so that it will be included in the
82
  // final image.
83
  void markLive();
84
85
  void setHidden(bool IsHidden);
86
87
  // Get/set the index in the output symbol table.  This is only used for
88
  // relocatable output.
89
  uint32_t getOutputSymbolIndex() const;
90
  void setOutputSymbolIndex(uint32_t Index);
91
92
  WasmSymbolType getWasmType() const;
93
94
  // True if this symbol was referenced by a regular (non-bitcode) object.
95
  unsigned IsUsedInRegularObj : 1;
96
97
protected:
98
  Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)
99
      : IsUsedInRegularObj(false), Name(Name), SymbolKind(K), Flags(Flags),
100
0
        File(F), Referenced(!Config->GcSections) {}
101
102
  StringRef Name;
103
  Kind SymbolKind;
104
  uint32_t Flags;
105
  InputFile *File;
106
  uint32_t OutputSymbolIndex = INVALID_INDEX;
107
  bool Referenced;
108
};
109
110
class FunctionSymbol : public Symbol {
111
public:
112
0
  static bool classof(const Symbol *S) {
113
0
    return S->kind() == DefinedFunctionKind ||
114
0
           S->kind() == UndefinedFunctionKind;
115
0
  }
116
117
0
  const WasmSignature *getFunctionType() const { return FunctionType; }
118
119
  // Get/set the table index
120
  void setTableIndex(uint32_t Index);
121
  uint32_t getTableIndex() const;
122
  bool hasTableIndex() const;
123
124
  // Get/set the function index
125
  uint32_t getFunctionIndex() const;
126
  void setFunctionIndex(uint32_t Index);
127
  bool hasFunctionIndex() const;
128
129
protected:
130
  FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
131
                 const WasmSignature *Type)
132
0
      : Symbol(Name, K, Flags, F), FunctionType(Type) {}
133
134
  uint32_t TableIndex = INVALID_INDEX;
135
  uint32_t FunctionIndex = INVALID_INDEX;
136
137
  const WasmSignature *FunctionType;
138
};
139
140
class DefinedFunction : public FunctionSymbol {
141
public:
142
  DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,
143
                  InputFunction *Function);
144
145
0
  static bool classof(const Symbol *S) {
146
0
    return S->kind() == DefinedFunctionKind;
147
0
  }
148
149
  InputFunction *Function;
150
};
151
152
class UndefinedFunction : public FunctionSymbol {
153
public:
154
  UndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File = nullptr,
155
                    const WasmSignature *Type = nullptr)
156
0
      : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type) {}
157
158
0
  static bool classof(const Symbol *S) {
159
0
    return S->kind() == UndefinedFunctionKind;
160
0
  }
161
};
162
163
class SectionSymbol : public Symbol {
164
public:
165
0
  static bool classof(const Symbol *S) { return S->kind() == SectionKind; }
166
167
  SectionSymbol(StringRef Name, uint32_t Flags, const InputSection *S,
168
                InputFile *F = nullptr)
169
0
      : Symbol(Name, SectionKind, Flags, F), Section(S) {}
170
171
  const InputSection *Section;
172
173
  uint32_t getOutputSectionIndex() const;
174
  void setOutputSectionIndex(uint32_t Index);
175
176
protected:
177
  uint32_t OutputSectionIndex = INVALID_INDEX;
178
};
179
180
class DataSymbol : public Symbol {
181
public:
182
0
  static bool classof(const Symbol *S) {
183
0
    return S->kind() == DefinedDataKind || S->kind() == UndefinedDataKind;
184
0
  }
185
186
protected:
187
  DataSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)
188
0
      : Symbol(Name, K, Flags, F) {}
189
};
190
191
class DefinedData : public DataSymbol {
192
public:
193
  // Constructor for regular data symbols originating from input files.
194
  DefinedData(StringRef Name, uint32_t Flags, InputFile *F,
195
              InputSegment *Segment, uint32_t Offset, uint32_t Size)
196
      : DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment),
197
0
        Offset(Offset), Size(Size) {}
198
199
  // Constructor for linker synthetic data symbols.
200
  DefinedData(StringRef Name, uint32_t Flags)
201
0
      : DataSymbol(Name, DefinedDataKind, Flags, nullptr) {}
202
203
0
  static bool classof(const Symbol *S) { return S->kind() == DefinedDataKind; }
204
205
  // Returns the output virtual address of a defined data symbol.
206
  uint32_t getVirtualAddress() const;
207
  void setVirtualAddress(uint32_t VA);
208
209
  // Returns the offset of a defined data symbol within its OutputSegment.
210
  uint32_t getOutputSegmentOffset() const;
211
  uint32_t getOutputSegmentIndex() const;
212
0
  uint32_t getSize() const { return Size; }
213
214
  InputSegment *Segment = nullptr;
215
216
protected:
217
  uint32_t Offset = 0;
218
  uint32_t Size = 0;
219
};
220
221
class UndefinedData : public DataSymbol {
222
public:
223
  UndefinedData(StringRef Name, uint32_t Flags, InputFile *File = nullptr)
224
0
      : DataSymbol(Name, UndefinedDataKind, Flags, File) {}
225
0
  static bool classof(const Symbol *S) {
226
0
    return S->kind() == UndefinedDataKind;
227
0
  }
228
};
229
230
class GlobalSymbol : public Symbol {
231
public:
232
0
  static bool classof(const Symbol *S) {
233
0
    return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind;
234
0
  }
235
236
0
  const WasmGlobalType *getGlobalType() const { return GlobalType; }
237
238
  // Get/set the global index
239
  uint32_t getGlobalIndex() const;
240
  void setGlobalIndex(uint32_t Index);
241
  bool hasGlobalIndex() const;
242
243
protected:
244
  GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,
245
               const WasmGlobalType *GlobalType)
246
0
      : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {}
247
248
  // Explicit function type, needed for undefined or synthetic functions only.
249
  // For regular defined globals this information comes from the InputChunk.
250
  const WasmGlobalType *GlobalType;
251
  uint32_t GlobalIndex = INVALID_INDEX;
252
};
253
254
class DefinedGlobal : public GlobalSymbol {
255
public:
256
  DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,
257
                InputGlobal *Global);
258
259
0
  static bool classof(const Symbol *S) {
260
0
    return S->kind() == DefinedGlobalKind;
261
0
  }
262
263
  InputGlobal *Global;
264
};
265
266
class UndefinedGlobal : public GlobalSymbol {
267
public:
268
  UndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File = nullptr,
269
                  const WasmGlobalType *Type = nullptr)
270
0
      : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type) {}
271
272
0
  static bool classof(const Symbol *S) {
273
0
    return S->kind() == UndefinedGlobalKind;
274
0
  }
275
};
276
277
class LazySymbol : public Symbol {
278
public:
279
  LazySymbol(StringRef Name, InputFile *File, const Archive::Symbol &Sym)
280
0
      : Symbol(Name, LazyKind, 0, File), ArchiveSymbol(Sym) {}
281
282
0
  static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
283
  void fetch();
284
285
private:
286
  Archive::Symbol ArchiveSymbol;
287
};
288
289
// linker-generated symbols
290
struct WasmSym {
291
  // __stack_pointer
292
  // Global that holds the address of the top of the explicit value stack in
293
  // linear memory.
294
  static DefinedGlobal *StackPointer;
295
296
  // __data_end
297
  // Symbol marking the end of the data and bss.
298
  static DefinedData *DataEnd;
299
300
  // __heap_base
301
  // Symbol marking the end of the data, bss and explicit stack.  Any linear
302
  // memory following this address is not used by the linked code and can
303
  // therefore be used as a backing store for brk()/malloc() implementations.
304
  static DefinedData *HeapBase;
305
306
  // __wasm_call_ctors
307
  // Function that directly calls all ctors in priority order.
308
  static DefinedFunction *CallCtors;
309
310
  // __dso_handle
311
  // Symbol used in calls to __cxa_atexit to determine current DLL
312
  static DefinedData *DsoHandle;
313
};
314
315
// A buffer class that is large enough to hold any Symbol-derived
316
// object. We allocate memory using this class and instantiate a symbol
317
// using the placement new.
318
union SymbolUnion {
319
  alignas(DefinedFunction) char A[sizeof(DefinedFunction)];
320
  alignas(DefinedData) char B[sizeof(DefinedData)];
321
  alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)];
322
  alignas(LazySymbol) char D[sizeof(LazySymbol)];
323
  alignas(UndefinedFunction) char E[sizeof(UndefinedFunction)];
324
  alignas(UndefinedData) char F[sizeof(UndefinedData)];
325
  alignas(UndefinedGlobal) char G[sizeof(UndefinedGlobal)];
326
  alignas(SectionSymbol) char I[sizeof(SectionSymbol)];
327
};
328
329
template <typename T, typename... ArgT>
330
0
T *replaceSymbol(Symbol *S, ArgT &&... Arg) {
331
0
  static_assert(std::is_trivially_destructible<T>(),
332
0
                "Symbol types must be trivially destructible");
333
0
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
334
0
  static_assert(alignof(T) <= alignof(SymbolUnion),
335
0
                "SymbolUnion not aligned enough");
336
0
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
337
0
         "Not a Symbol");
338
0
339
0
  Symbol SymCopy = *S;
340
0
341
0
  T *S2 = new (S) T(std::forward<ArgT>(Arg)...);
342
0
  S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj;
343
0
  return S2;
344
0
}
Unexecuted instantiation: lld::wasm::DefinedFunction* lld::wasm::replaceSymbol<lld::wasm::DefinedFunction, llvm::StringRef, unsigned int&, std::nullptr_t, lld::wasm::SyntheticFunction*&>(lld::wasm::Symbol*, llvm::StringRef&&, unsigned int&&&, std::nullptr_t&&, lld::wasm::SyntheticFunction*&&&)
Unexecuted instantiation: lld::wasm::UndefinedFunction* lld::wasm::replaceSymbol<lld::wasm::UndefinedFunction, llvm::StringRef, int>(lld::wasm::Symbol*, llvm::StringRef&&, int&&)
Unexecuted instantiation: lld::wasm::UndefinedData* lld::wasm::replaceSymbol<lld::wasm::UndefinedData, llvm::StringRef, int>(lld::wasm::Symbol*, llvm::StringRef&&, int&&)
Unexecuted instantiation: lld::wasm::DefinedFunction* lld::wasm::replaceSymbol<lld::wasm::DefinedFunction, llvm::StringRef&, unsigned int&, std::nullptr_t, lld::wasm::InputFunction*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, std::nullptr_t&&, lld::wasm::InputFunction*&&&)
Unexecuted instantiation: lld::wasm::DefinedData* lld::wasm::replaceSymbol<lld::wasm::DefinedData, llvm::StringRef&, unsigned int&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&)
Unexecuted instantiation: lld::wasm::DefinedGlobal* lld::wasm::replaceSymbol<lld::wasm::DefinedGlobal, llvm::StringRef&, unsigned int&, std::nullptr_t, lld::wasm::InputGlobal*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, std::nullptr_t&&, lld::wasm::InputGlobal*&&&)
Unexecuted instantiation: lld::wasm::DefinedFunction* lld::wasm::replaceSymbol<lld::wasm::DefinedFunction, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, lld::wasm::InputFunction*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, lld::wasm::InputFunction*&&&)
Unexecuted instantiation: lld::wasm::DefinedData* lld::wasm::replaceSymbol<lld::wasm::DefinedData, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, lld::wasm::InputSegment*&, unsigned int&, unsigned int&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, lld::wasm::InputSegment*&&&, unsigned int&&&, unsigned int&&&)
Unexecuted instantiation: lld::wasm::DefinedGlobal* lld::wasm::replaceSymbol<lld::wasm::DefinedGlobal, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, lld::wasm::InputGlobal*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, lld::wasm::InputGlobal*&&&)
Unexecuted instantiation: lld::wasm::UndefinedFunction* lld::wasm::replaceSymbol<lld::wasm::UndefinedFunction, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, llvm::wasm::WasmSignature const*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, llvm::wasm::WasmSignature const*&&&)
Unexecuted instantiation: lld::wasm::UndefinedData* lld::wasm::replaceSymbol<lld::wasm::UndefinedData, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&)
Unexecuted instantiation: lld::wasm::UndefinedGlobal* lld::wasm::replaceSymbol<lld::wasm::UndefinedGlobal, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, llvm::wasm::WasmGlobalType const*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, llvm::wasm::WasmGlobalType const*&&&)
Unexecuted instantiation: lld::wasm::LazySymbol* lld::wasm::replaceSymbol<lld::wasm::LazySymbol, llvm::StringRef&, lld::wasm::ArchiveFile*&, llvm::object::Archive::Symbol const&>(lld::wasm::Symbol*, llvm::StringRef&&&, lld::wasm::ArchiveFile*&&&, llvm::object::Archive::Symbol const&&&)
345
346
} // namespace wasm
347
348
// Returns a symbol name for an error message.
349
std::string toString(const wasm::Symbol &Sym);
350
std::string toString(wasm::Symbol::Kind Kind);
351
352
} // namespace lld
353
354
#endif