Coverage Report

Created: 2019-07-24 05:18

/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
// 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
#ifndef LLD_WASM_SYMBOLS_H
10
#define LLD_WASM_SYMBOLS_H
11
12
#include "Config.h"
13
#include "lld/Common/LLVM.h"
14
#include "llvm/Object/Archive.h"
15
#include "llvm/Object/Wasm.h"
16
17
namespace lld {
18
namespace wasm {
19
20
// Shared string constants
21
22
// The default module name to use for symbol imports.
23
extern const char *defaultModule;
24
25
// The name under which to import or export the wasm table.
26
extern const char *functionTableName;
27
28
using llvm::wasm::WasmSymbolType;
29
30
class InputFile;
31
class InputChunk;
32
class InputSegment;
33
class InputFunction;
34
class InputGlobal;
35
class InputEvent;
36
class InputSection;
37
class OutputSection;
38
39
32
#define INVALID_INDEX UINT32_MAX
40
41
// The base class for real symbol classes.
42
class Symbol {
43
public:
44
  enum Kind : uint8_t {
45
    DefinedFunctionKind,
46
    DefinedDataKind,
47
    DefinedGlobalKind,
48
    DefinedEventKind,
49
    SectionKind,
50
    OutputSectionKind,
51
    UndefinedFunctionKind,
52
    UndefinedDataKind,
53
    UndefinedGlobalKind,
54
    LazyKind,
55
  };
56
57
14.0k
  Kind kind() const { return symbolKind; }
58
59
2.27k
  bool isDefined() const { return !isLazy() && 
!isUndefined()2.25k
; }
60
61
4.30k
  bool isUndefined() const {
62
4.30k
    return symbolKind == UndefinedFunctionKind ||
63
4.30k
           
symbolKind == UndefinedDataKind4.09k
||
symbolKind == UndefinedGlobalKind4.04k
;
64
4.30k
  }
65
66
2.40k
  bool isLazy() const { return symbolKind == LazyKind; }
67
68
  bool isLocal() const;
69
  bool isWeak() const;
70
  bool isHidden() const;
71
72
  // Returns true if this symbol exists in a discarded (due to COMDAT) section
73
  bool isDiscarded() const;
74
75
  // True if this is an undefined weak symbol. This only works once
76
  // all input files have been added.
77
1.11k
  bool isUndefWeak() const {
78
1.11k
    // See comment on lazy symbols for details.
79
1.11k
    return isWeak() && 
(15
isUndefined()15
||
isLazy()6
);
80
1.11k
  }
81
82
  // Returns the symbol name.
83
703
  StringRef getName() const { return name; }
84
85
  // Returns the file from which this symbol was created.
86
127
  InputFile *getFile() const { return file; }
87
88
16
  uint32_t getFlags() const { return flags; }
89
90
  InputChunk *getChunk() const;
91
92
  // Indicates that the section or import for this symbol will be included in
93
  // the final image.
94
  bool isLive() const;
95
96
  // Marks the symbol's InputChunk as Live, so that it will be included in the
97
  // final image.
98
  void markLive();
99
100
  void setHidden(bool isHidden);
101
102
  // Get/set the index in the output symbol table.  This is only used for
103
  // relocatable output.
104
  uint32_t getOutputSymbolIndex() const;
105
  void setOutputSymbolIndex(uint32_t index);
106
107
  WasmSymbolType getWasmType() const;
108
  bool isExported() const;
109
110
  const WasmSignature* getSignature() const;
111
112
0
  bool isInGOT() const { return gotIndex != INVALID_INDEX; }
113
114
10
  uint32_t getGOTIndex() const {
115
10
    assert(gotIndex != INVALID_INDEX);
116
10
    return gotIndex;
117
10
  }
118
119
  void setGOTIndex(uint32_t index);
120
18
  bool hasGOTIndex() const { return gotIndex != INVALID_INDEX; }
121
122
protected:
123
  Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
124
      : name(name), file(f), flags(flags), symbolKind(k),
125
        referenced(!config->gcSections), isUsedInRegularObj(false),
126
1.72k
        forceExport(false), canInline(false), traced(false) {}
127
128
  StringRef name;
129
  InputFile *file;
130
  uint32_t flags;
131
  uint32_t outputSymbolIndex = INVALID_INDEX;
132
  uint32_t gotIndex = INVALID_INDEX;
133
  Kind symbolKind;
134
135
public:
136
  bool referenced : 1;
137
138
  // True if the symbol was used for linking and thus need to be added to the
139
  // output file's symbol table. This is true for all symbols except for
140
  // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
141
  // are unreferenced except by other bitcode objects.
142
  bool isUsedInRegularObj : 1;
143
144
  // True if ths symbol is explicity marked for export (i.e. via the -e/--export
145
  // command line flag)
146
  bool forceExport : 1;
147
148
  // False if LTO shouldn't inline whatever this symbol points to. If a symbol
149
  // is overwritten after LTO, LTO shouldn't inline the symbol because it
150
  // doesn't know the final contents of the symbol.
151
  bool canInline : 1;
152
153
  // True if this symbol is specified by --trace-symbol option.
154
  bool traced : 1;
155
};
156
157
class FunctionSymbol : public Symbol {
158
public:
159
1.88k
  static bool classof(const Symbol *s) {
160
1.88k
    return s->kind() == DefinedFunctionKind ||
161
1.88k
           
s->kind() == UndefinedFunctionKind821
;
162
1.88k
  }
163
164
  // Get/set the table index
165
  void setTableIndex(uint32_t index);
166
  uint32_t getTableIndex() const;
167
  bool hasTableIndex() const;
168
169
  // Get/set the function index
170
  uint32_t getFunctionIndex() const;
171
  void setFunctionIndex(uint32_t index);
172
  bool hasFunctionIndex() const;
173
174
  const WasmSignature *signature;
175
176
protected:
177
  FunctionSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
178
                 const WasmSignature *sig)
179
963
      : Symbol(name, k, flags, f), signature(sig) {}
180
181
  uint32_t tableIndex = INVALID_INDEX;
182
  uint32_t functionIndex = INVALID_INDEX;
183
};
184
185
class DefinedFunction : public FunctionSymbol {
186
public:
187
  DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
188
                  InputFunction *function);
189
190
3.72k
  static bool classof(const Symbol *s) {
191
3.72k
    return s->kind() == DefinedFunctionKind;
192
3.72k
  }
193
194
  InputFunction *function;
195
};
196
197
class UndefinedFunction : public FunctionSymbol {
198
public:
199
  UndefinedFunction(StringRef name, StringRef importName,
200
                    StringRef importModule, uint32_t flags,
201
                    InputFile *file = nullptr,
202
                    const WasmSignature *type = nullptr,
203
                    bool isCalledDirectly = true)
204
      : FunctionSymbol(name, UndefinedFunctionKind, flags, file, type),
205
133
        importName(importName), importModule(importModule), isCalledDirectly(isCalledDirectly) {}
206
207
391
  static bool classof(const Symbol *s) {
208
391
    return s->kind() == UndefinedFunctionKind;
209
391
  }
210
211
  StringRef importName;
212
  StringRef importModule;
213
  bool isCalledDirectly;
214
};
215
216
// Section symbols for output sections are different from those for input
217
// section.  These are generated by the linker and point the OutputSection
218
// rather than an InputSection.
219
class OutputSectionSymbol : public Symbol {
220
public:
221
  OutputSectionSymbol(const OutputSection *s)
222
      : Symbol("", OutputSectionKind, llvm::wasm::WASM_SYMBOL_BINDING_LOCAL,
223
               nullptr),
224
4
        section(s) {}
225
226
4
  static bool classof(const Symbol *s) {
227
4
    return s->kind() == OutputSectionKind;
228
4
  }
229
230
  const OutputSection *section;
231
};
232
233
class SectionSymbol : public Symbol {
234
public:
235
  SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr)
236
18
      : Symbol("", SectionKind, flags, f), section(s) {}
237
238
238
  static bool classof(const Symbol *s) { return s->kind() == SectionKind; }
239
240
  const OutputSectionSymbol *getOutputSectionSymbol() const;
241
242
  const InputSection *section;
243
};
244
245
class DataSymbol : public Symbol {
246
public:
247
477
  static bool classof(const Symbol *s) {
248
477
    return s->kind() == DefinedDataKind || 
s->kind() == UndefinedDataKind215
;
249
477
  }
250
251
protected:
252
  DataSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
253
427
      : Symbol(name, k, flags, f) {}
254
};
255
256
class DefinedData : public DataSymbol {
257
public:
258
  // Constructor for regular data symbols originating from input files.
259
  DefinedData(StringRef name, uint32_t flags, InputFile *f,
260
              InputSegment *segment, uint32_t offset, uint32_t size)
261
      : DataSymbol(name, DefinedDataKind, flags, f), segment(segment),
262
195
        offset(offset), size(size) {}
263
264
  // Constructor for linker synthetic data symbols.
265
  DefinedData(StringRef name, uint32_t flags)
266
211
      : DataSymbol(name, DefinedDataKind, flags, nullptr) {}
267
268
679
  static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
269
270
  // Returns the output virtual address of a defined data symbol.
271
  uint32_t getVirtualAddress() const;
272
  void setVirtualAddress(uint32_t va);
273
274
  // Returns the offset of a defined data symbol within its OutputSegment.
275
  uint32_t getOutputSegmentOffset() const;
276
  uint32_t getOutputSegmentIndex() const;
277
23
  uint32_t getSize() const { return size; }
278
279
  InputSegment *segment = nullptr;
280
281
protected:
282
  uint32_t offset = 0;
283
  uint32_t size = 0;
284
};
285
286
class UndefinedData : public DataSymbol {
287
public:
288
  UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr)
289
21
      : DataSymbol(name, UndefinedDataKind, flags, file) {}
290
212
  static bool classof(const Symbol *s) {
291
212
    return s->kind() == UndefinedDataKind;
292
212
  }
293
};
294
295
class GlobalSymbol : public Symbol {
296
public:
297
192
  static bool classof(const Symbol *s) {
298
192
    return s->kind() == DefinedGlobalKind || 
s->kind() == UndefinedGlobalKind138
;
299
192
  }
300
301
30
  const WasmGlobalType *getGlobalType() const { return globalType; }
302
303
  // Get/set the global index
304
  uint32_t getGlobalIndex() const;
305
  void setGlobalIndex(uint32_t index);
306
  bool hasGlobalIndex() const;
307
308
protected:
309
  GlobalSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
310
               const WasmGlobalType *globalType)
311
272
      : Symbol(name, k, flags, f), globalType(globalType) {}
312
313
  const WasmGlobalType *globalType;
314
  uint32_t globalIndex = INVALID_INDEX;
315
};
316
317
class DefinedGlobal : public GlobalSymbol {
318
public:
319
  DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
320
                InputGlobal *global);
321
322
2.32k
  static bool classof(const Symbol *s) {
323
2.32k
    return s->kind() == DefinedGlobalKind;
324
2.32k
  }
325
326
  InputGlobal *global;
327
};
328
329
class UndefinedGlobal : public GlobalSymbol {
330
public:
331
  UndefinedGlobal(StringRef name, StringRef importName, StringRef importModule,
332
                  uint32_t flags, InputFile *file = nullptr,
333
                  const WasmGlobalType *type = nullptr)
334
      : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type),
335
26
        importName(importName), importModule(importModule) {}
336
337
264
  static bool classof(const Symbol *s) {
338
264
    return s->kind() == UndefinedGlobalKind;
339
264
  }
340
341
  StringRef importName;
342
  StringRef importModule;
343
};
344
345
// Wasm events are features that suspend the current execution and transfer the
346
// control flow to a corresponding handler. Currently the only supported event
347
// kind is exceptions.
348
//
349
// Event tags are values to distinguish different events. For exceptions, they
350
// can be used to distinguish different language's exceptions, i.e., all C++
351
// exceptions have the same tag. Wasm can generate code capable of doing
352
// different handling actions based on the tag of caught exceptions.
353
//
354
// A single EventSymbol object represents a single tag. C++ exception event
355
// symbol is a weak symbol generated in every object file in which exceptions
356
// are used, and has name '__cpp_exception' for linking.
357
class EventSymbol : public Symbol {
358
public:
359
56
  static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; }
360
361
1
  const WasmEventType *getEventType() const { return eventType; }
362
363
  // Get/set the event index
364
  uint32_t getEventIndex() const;
365
  void setEventIndex(uint32_t index);
366
  bool hasEventIndex() const;
367
368
  const WasmSignature *signature;
369
370
protected:
371
  EventSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
372
              const WasmEventType *eventType, const WasmSignature *sig)
373
1
      : Symbol(name, k, flags, f), signature(sig), eventType(eventType) {}
374
375
  const WasmEventType *eventType;
376
  uint32_t eventIndex = INVALID_INDEX;
377
};
378
379
class DefinedEvent : public EventSymbol {
380
public:
381
  DefinedEvent(StringRef name, uint32_t flags, InputFile *file,
382
               InputEvent *event);
383
384
2.23k
  static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; }
385
386
  InputEvent *event;
387
};
388
389
// LazySymbol represents a symbol that is not yet in the link, but we know where
390
// to find it if needed. If the resolver finds both Undefined and Lazy for the
391
// same name, it will ask the Lazy to load a file.
392
//
393
// A special complication is the handling of weak undefined symbols. They should
394
// not load a file, but we have to remember we have seen both the weak undefined
395
// and the lazy. We represent that with a lazy symbol with a weak binding. This
396
// means that code looking for undefined symbols normally also has to take lazy
397
// symbols into consideration.
398
class LazySymbol : public Symbol {
399
public:
400
  LazySymbol(StringRef name, uint32_t flags, InputFile *file,
401
             const llvm::object::Archive::Symbol &sym)
402
36
      : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {}
403
404
226
  static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
405
  void fetch();
406
407
  // Lazy symbols can have a signature because they can replace an
408
  // UndefinedFunction which which case we need to be able to preserve the
409
  // signture.
410
  // TODO(sbc): This repetition of the signature field is inelegant.  Revisit
411
  // the use of class hierarchy to represent symbol taxonomy.
412
  const WasmSignature *signature = nullptr;
413
414
private:
415
  llvm::object::Archive::Symbol archiveSymbol;
416
};
417
418
// linker-generated symbols
419
struct WasmSym {
420
  // __global_base
421
  // Symbol marking the start of the global section.
422
  static DefinedData *globalBase;
423
424
  // __stack_pointer
425
  // Global that holds the address of the top of the explicit value stack in
426
  // linear memory.
427
  static GlobalSymbol *stackPointer;
428
429
  // __tls_base
430
  // Global that holds the address of the base of the current thread's
431
  // TLS block.
432
  static GlobalSymbol *tlsBase;
433
434
  // __tls_size
435
  // Symbol whose value is the size of the TLS block.
436
  static GlobalSymbol *tlsSize;
437
438
  // __tls_size
439
  // Symbol whose value is the alignment of the TLS block.
440
  static GlobalSymbol *tlsAlign;
441
442
  // __data_end
443
  // Symbol marking the end of the data and bss.
444
  static DefinedData *dataEnd;
445
446
  // __heap_base
447
  // Symbol marking the end of the data, bss and explicit stack.  Any linear
448
  // memory following this address is not used by the linked code and can
449
  // therefore be used as a backing store for brk()/malloc() implementations.
450
  static DefinedData *heapBase;
451
452
  // __wasm_call_ctors
453
  // Function that directly calls all ctors in priority order.
454
  static DefinedFunction *callCtors;
455
456
  // __wasm_init_memory
457
  // Function that initializes passive data segments post-instantiation.
458
  static DefinedFunction *initMemory;
459
460
  // __wasm_apply_relocs
461
  // Function that applies relocations to data segment post-instantiation.
462
  static DefinedFunction *applyRelocs;
463
464
  // __wasm_init_tls
465
  // Function that allocates thread-local storage and initializes it.
466
  static DefinedFunction *initTLS;
467
468
  // __dso_handle
469
  // Symbol used in calls to __cxa_atexit to determine current DLL
470
  static DefinedData *dsoHandle;
471
472
  // __table_base
473
  // Used in PIC code for offset of indirect function table
474
  static UndefinedGlobal *tableBase;
475
476
  // __memory_base
477
  // Used in PIC code for offset of global data
478
  static UndefinedGlobal *memoryBase;
479
};
480
481
// A buffer class that is large enough to hold any Symbol-derived
482
// object. We allocate memory using this class and instantiate a symbol
483
// using the placement new.
484
union SymbolUnion {
485
  alignas(DefinedFunction) char a[sizeof(DefinedFunction)];
486
  alignas(DefinedData) char b[sizeof(DefinedData)];
487
  alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)];
488
  alignas(DefinedEvent) char d[sizeof(DefinedEvent)];
489
  alignas(LazySymbol) char e[sizeof(LazySymbol)];
490
  alignas(UndefinedFunction) char f[sizeof(UndefinedFunction)];
491
  alignas(UndefinedData) char g[sizeof(UndefinedData)];
492
  alignas(UndefinedGlobal) char h[sizeof(UndefinedGlobal)];
493
  alignas(SectionSymbol) char i[sizeof(SectionSymbol)];
494
};
495
496
// It is important to keep the size of SymbolUnion small for performance and
497
// memory usage reasons. 96 bytes is a soft limit based on the size of
498
// UndefinedFunction on a 64-bit system.
499
static_assert(sizeof(SymbolUnion) <= 96, "SymbolUnion too large");
500
501
void printTraceSymbol(Symbol *sym);
502
void printTraceSymbolUndefined(StringRef name, const InputFile* file);
503
504
template <typename T, typename... ArgT>
505
1.60k
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
1.60k
  static_assert(std::is_trivially_destructible<T>(),
507
1.60k
                "Symbol types must be trivially destructible");
508
1.60k
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
1.60k
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
1.60k
                "SymbolUnion not aligned enough");
511
1.60k
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
1.60k
         "Not a Symbol");
513
1.60k
514
1.60k
  Symbol symCopy = *s;
515
1.60k
516
1.60k
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
1.60k
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
1.60k
  s2->forceExport = symCopy.forceExport;
519
1.60k
  s2->canInline = symCopy.canInline;
520
1.60k
  s2->traced = symCopy.traced;
521
1.60k
522
1.60k
  // Print out a log message if --trace-symbol was specified.
523
1.60k
  // This is for debugging.
524
1.60k
  if (s2->traced)
525
6
    printTraceSymbol(s2);
526
1.60k
527
1.60k
  return s2;
528
1.60k
}
lld::wasm::UndefinedFunction* lld::wasm::replaceSymbol<lld::wasm::UndefinedFunction, llvm::StringRef, llvm::StringRef, char const*&, int, lld::wasm::InputFile*, llvm::wasm::WasmSignature const*&>(lld::wasm::Symbol*, llvm::StringRef&&, llvm::StringRef&&, char const*&&&, int&&, lld::wasm::InputFile*&&, llvm::wasm::WasmSignature const*&&&)
Line
Count
Source
505
45
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
45
  static_assert(std::is_trivially_destructible<T>(),
507
45
                "Symbol types must be trivially destructible");
508
45
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
45
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
45
                "SymbolUnion not aligned enough");
511
45
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
45
         "Not a Symbol");
513
45
514
45
  Symbol symCopy = *s;
515
45
516
45
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
45
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
45
  s2->forceExport = symCopy.forceExport;
519
45
  s2->canInline = symCopy.canInline;
520
45
  s2->traced = symCopy.traced;
521
45
522
45
  // Print out a log message if --trace-symbol was specified.
523
45
  // This is for debugging.
524
45
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
45
527
45
  return s2;
528
45
}
lld::wasm::UndefinedData* lld::wasm::replaceSymbol<lld::wasm::UndefinedData, llvm::StringRef, int, lld::wasm::InputFile*>(lld::wasm::Symbol*, llvm::StringRef&&, int&&, lld::wasm::InputFile*&&)
Line
Count
Source
505
3
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
3
  static_assert(std::is_trivially_destructible<T>(),
507
3
                "Symbol types must be trivially destructible");
508
3
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
3
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
3
                "SymbolUnion not aligned enough");
511
3
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
3
         "Not a Symbol");
513
3
514
3
  Symbol symCopy = *s;
515
3
516
3
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
3
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
3
  s2->forceExport = symCopy.forceExport;
519
3
  s2->canInline = symCopy.canInline;
520
3
  s2->traced = symCopy.traced;
521
3
522
3
  // Print out a log message if --trace-symbol was specified.
523
3
  // This is for debugging.
524
3
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
3
527
3
  return s2;
528
3
}
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*&&&)
Line
Count
Source
505
538
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
538
  static_assert(std::is_trivially_destructible<T>(),
507
538
                "Symbol types must be trivially destructible");
508
538
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
538
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
538
                "SymbolUnion not aligned enough");
511
538
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
538
         "Not a Symbol");
513
538
514
538
  Symbol symCopy = *s;
515
538
516
538
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
538
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
538
  s2->forceExport = symCopy.forceExport;
519
538
  s2->canInline = symCopy.canInline;
520
538
  s2->traced = symCopy.traced;
521
538
522
538
  // Print out a log message if --trace-symbol was specified.
523
538
  // This is for debugging.
524
538
  if (s2->traced)
525
5
    printTraceSymbol(s2);
526
538
527
538
  return s2;
528
538
}
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&&&)
Line
Count
Source
505
150
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
150
  static_assert(std::is_trivially_destructible<T>(),
507
150
                "Symbol types must be trivially destructible");
508
150
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
150
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
150
                "SymbolUnion not aligned enough");
511
150
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
150
         "Not a Symbol");
513
150
514
150
  Symbol symCopy = *s;
515
150
516
150
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
150
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
150
  s2->forceExport = symCopy.forceExport;
519
150
  s2->canInline = symCopy.canInline;
520
150
  s2->traced = symCopy.traced;
521
150
522
150
  // Print out a log message if --trace-symbol was specified.
523
150
  // This is for debugging.
524
150
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
150
527
150
  return s2;
528
150
}
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*&&&)
Line
Count
Source
505
4
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
4
  static_assert(std::is_trivially_destructible<T>(),
507
4
                "Symbol types must be trivially destructible");
508
4
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
4
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
4
                "SymbolUnion not aligned enough");
511
4
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
4
         "Not a Symbol");
513
4
514
4
  Symbol symCopy = *s;
515
4
516
4
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
4
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
4
  s2->forceExport = symCopy.forceExport;
519
4
  s2->canInline = symCopy.canInline;
520
4
  s2->traced = symCopy.traced;
521
4
522
4
  // Print out a log message if --trace-symbol was specified.
523
4
  // This is for debugging.
524
4
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
4
527
4
  return s2;
528
4
}
lld::wasm::DefinedEvent* lld::wasm::replaceSymbol<lld::wasm::DefinedEvent, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, lld::wasm::InputEvent*&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, lld::wasm::InputEvent*&&&)
Line
Count
Source
505
1
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
1
  static_assert(std::is_trivially_destructible<T>(),
507
1
                "Symbol types must be trivially destructible");
508
1
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
1
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
1
                "SymbolUnion not aligned enough");
511
1
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
1
         "Not a Symbol");
513
1
514
1
  Symbol symCopy = *s;
515
1
516
1
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
1
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
1
  s2->forceExport = symCopy.forceExport;
519
1
  s2->canInline = symCopy.canInline;
520
1
  s2->traced = symCopy.traced;
521
1
522
1
  // Print out a log message if --trace-symbol was specified.
523
1
  // This is for debugging.
524
1
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
1
527
1
  return s2;
528
1
}
lld::wasm::UndefinedFunction* lld::wasm::replaceSymbol<lld::wasm::UndefinedFunction, llvm::StringRef&, llvm::StringRef&, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, llvm::wasm::WasmSignature const*&, bool&>(lld::wasm::Symbol*, llvm::StringRef&&&, llvm::StringRef&&&, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, llvm::wasm::WasmSignature const*&&&, bool&&&)
Line
Count
Source
505
88
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
88
  static_assert(std::is_trivially_destructible<T>(),
507
88
                "Symbol types must be trivially destructible");
508
88
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
88
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
88
                "SymbolUnion not aligned enough");
511
88
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
88
         "Not a Symbol");
513
88
514
88
  Symbol symCopy = *s;
515
88
516
88
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
88
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
88
  s2->forceExport = symCopy.forceExport;
519
88
  s2->canInline = symCopy.canInline;
520
88
  s2->traced = symCopy.traced;
521
88
522
88
  // Print out a log message if --trace-symbol was specified.
523
88
  // This is for debugging.
524
88
  if (s2->traced)
525
1
    printTraceSymbol(s2);
526
88
527
88
  return s2;
528
88
}
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*&&&)
Line
Count
Source
505
229
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
229
  static_assert(std::is_trivially_destructible<T>(),
507
229
                "Symbol types must be trivially destructible");
508
229
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
229
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
229
                "SymbolUnion not aligned enough");
511
229
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
229
         "Not a Symbol");
513
229
514
229
  Symbol symCopy = *s;
515
229
516
229
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
229
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
229
  s2->forceExport = symCopy.forceExport;
519
229
  s2->canInline = symCopy.canInline;
520
229
  s2->traced = symCopy.traced;
521
229
522
229
  // Print out a log message if --trace-symbol was specified.
523
229
  // This is for debugging.
524
229
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
229
527
229
  return s2;
528
229
}
lld::wasm::DefinedData* lld::wasm::replaceSymbol<lld::wasm::DefinedData, llvm::StringRef&, unsigned int&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int&&&)
Line
Count
Source
505
211
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
211
  static_assert(std::is_trivially_destructible<T>(),
507
211
                "Symbol types must be trivially destructible");
508
211
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
211
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
211
                "SymbolUnion not aligned enough");
511
211
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
211
         "Not a Symbol");
513
211
514
211
  Symbol symCopy = *s;
515
211
516
211
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
211
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
211
  s2->forceExport = symCopy.forceExport;
519
211
  s2->canInline = symCopy.canInline;
520
211
  s2->traced = symCopy.traced;
521
211
522
211
  // Print out a log message if --trace-symbol was specified.
523
211
  // This is for debugging.
524
211
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
211
527
211
  return s2;
528
211
}
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*&&&)
Line
Count
Source
505
242
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
242
  static_assert(std::is_trivially_destructible<T>(),
507
242
                "Symbol types must be trivially destructible");
508
242
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
242
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
242
                "SymbolUnion not aligned enough");
511
242
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
242
         "Not a Symbol");
513
242
514
242
  Symbol symCopy = *s;
515
242
516
242
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
242
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
242
  s2->forceExport = symCopy.forceExport;
519
242
  s2->canInline = symCopy.canInline;
520
242
  s2->traced = symCopy.traced;
521
242
522
242
  // Print out a log message if --trace-symbol was specified.
523
242
  // This is for debugging.
524
242
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
242
527
242
  return s2;
528
242
}
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*&&&)
Line
Count
Source
505
18
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
18
  static_assert(std::is_trivially_destructible<T>(),
507
18
                "Symbol types must be trivially destructible");
508
18
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
18
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
18
                "SymbolUnion not aligned enough");
511
18
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
18
         "Not a Symbol");
513
18
514
18
  Symbol symCopy = *s;
515
18
516
18
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
18
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
18
  s2->forceExport = symCopy.forceExport;
519
18
  s2->canInline = symCopy.canInline;
520
18
  s2->traced = symCopy.traced;
521
18
522
18
  // Print out a log message if --trace-symbol was specified.
523
18
  // This is for debugging.
524
18
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
18
527
18
  return s2;
528
18
}
lld::wasm::UndefinedGlobal* lld::wasm::replaceSymbol<lld::wasm::UndefinedGlobal, llvm::StringRef&, llvm::StringRef&, llvm::StringRef&, unsigned int&, lld::wasm::InputFile*&, llvm::wasm::WasmGlobalType const*&>(lld::wasm::Symbol*, llvm::StringRef&&&, llvm::StringRef&&&, llvm::StringRef&&&, unsigned int&&&, lld::wasm::InputFile*&&&, llvm::wasm::WasmGlobalType const*&&&)
Line
Count
Source
505
26
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
26
  static_assert(std::is_trivially_destructible<T>(),
507
26
                "Symbol types must be trivially destructible");
508
26
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
26
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
26
                "SymbolUnion not aligned enough");
511
26
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
26
         "Not a Symbol");
513
26
514
26
  Symbol symCopy = *s;
515
26
516
26
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
26
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
26
  s2->forceExport = symCopy.forceExport;
519
26
  s2->canInline = symCopy.canInline;
520
26
  s2->traced = symCopy.traced;
521
26
522
26
  // Print out a log message if --trace-symbol was specified.
523
26
  // This is for debugging.
524
26
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
26
527
26
  return s2;
528
26
}
lld::wasm::LazySymbol* lld::wasm::replaceSymbol<lld::wasm::LazySymbol, llvm::StringRef&, int, lld::wasm::ArchiveFile*&, llvm::object::Archive::Symbol const&>(lld::wasm::Symbol*, llvm::StringRef&&&, int&&, lld::wasm::ArchiveFile*&&&, llvm::object::Archive::Symbol const&&&)
Line
Count
Source
505
35
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
35
  static_assert(std::is_trivially_destructible<T>(),
507
35
                "Symbol types must be trivially destructible");
508
35
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
35
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
35
                "SymbolUnion not aligned enough");
511
35
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
35
         "Not a Symbol");
513
35
514
35
  Symbol symCopy = *s;
515
35
516
35
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
35
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
35
  s2->forceExport = symCopy.forceExport;
519
35
  s2->canInline = symCopy.canInline;
520
35
  s2->traced = symCopy.traced;
521
35
522
35
  // Print out a log message if --trace-symbol was specified.
523
35
  // This is for debugging.
524
35
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
35
527
35
  return s2;
528
35
}
lld::wasm::LazySymbol* lld::wasm::replaceSymbol<lld::wasm::LazySymbol, llvm::StringRef&, unsigned int const&, lld::wasm::ArchiveFile*&, llvm::object::Archive::Symbol const&>(lld::wasm::Symbol*, llvm::StringRef&&&, unsigned int const&&&, lld::wasm::ArchiveFile*&&&, llvm::object::Archive::Symbol const&&&)
Line
Count
Source
505
1
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
1
  static_assert(std::is_trivially_destructible<T>(),
507
1
                "Symbol types must be trivially destructible");
508
1
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
1
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
1
                "SymbolUnion not aligned enough");
511
1
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
1
         "Not a Symbol");
513
1
514
1
  Symbol symCopy = *s;
515
1
516
1
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
1
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
1
  s2->forceExport = symCopy.forceExport;
519
1
  s2->canInline = symCopy.canInline;
520
1
  s2->traced = symCopy.traced;
521
1
522
1
  // Print out a log message if --trace-symbol was specified.
523
1
  // This is for debugging.
524
1
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
1
527
1
  return s2;
528
1
}
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*&&&)
Line
Count
Source
505
16
T *replaceSymbol(Symbol *s, ArgT &&... arg) {
506
16
  static_assert(std::is_trivially_destructible<T>(),
507
16
                "Symbol types must be trivially destructible");
508
16
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
509
16
  static_assert(alignof(T) <= alignof(SymbolUnion),
510
16
                "SymbolUnion not aligned enough");
511
16
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
512
16
         "Not a Symbol");
513
16
514
16
  Symbol symCopy = *s;
515
16
516
16
  T *s2 = new (s) T(std::forward<ArgT>(arg)...);
517
16
  s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
518
16
  s2->forceExport = symCopy.forceExport;
519
16
  s2->canInline = symCopy.canInline;
520
16
  s2->traced = symCopy.traced;
521
16
522
16
  // Print out a log message if --trace-symbol was specified.
523
16
  // This is for debugging.
524
16
  if (s2->traced)
525
0
    printTraceSymbol(s2);
526
16
527
16
  return s2;
528
16
}
529
530
} // namespace wasm
531
532
// Returns a symbol name for an error message.
533
std::string toString(const wasm::Symbol &sym);
534
std::string toString(wasm::Symbol::Kind kind);
535
std::string maybeDemangleSymbol(StringRef name);
536
537
} // namespace lld
538
539
#endif