Mercurial > hg > CbC > CbC_llvm
comparison lld/wasm/Symbols.h @ 207:2e18cbf3894f
LLVM12
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 08 Jun 2021 06:07:14 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
comparison
equal
deleted
inserted
replaced
173:0572611fdcc8 | 207:2e18cbf3894f |
---|---|
33 class InputSegment; | 33 class InputSegment; |
34 class InputFunction; | 34 class InputFunction; |
35 class InputGlobal; | 35 class InputGlobal; |
36 class InputEvent; | 36 class InputEvent; |
37 class InputSection; | 37 class InputSection; |
38 class InputTable; | |
38 class OutputSection; | 39 class OutputSection; |
39 | 40 |
40 #define INVALID_INDEX UINT32_MAX | 41 #define INVALID_INDEX UINT32_MAX |
41 | 42 |
42 // The base class for real symbol classes. | 43 // The base class for real symbol classes. |
45 enum Kind : uint8_t { | 46 enum Kind : uint8_t { |
46 DefinedFunctionKind, | 47 DefinedFunctionKind, |
47 DefinedDataKind, | 48 DefinedDataKind, |
48 DefinedGlobalKind, | 49 DefinedGlobalKind, |
49 DefinedEventKind, | 50 DefinedEventKind, |
51 DefinedTableKind, | |
50 SectionKind, | 52 SectionKind, |
51 OutputSectionKind, | 53 OutputSectionKind, |
52 UndefinedFunctionKind, | 54 UndefinedFunctionKind, |
53 UndefinedDataKind, | 55 UndefinedDataKind, |
54 UndefinedGlobalKind, | 56 UndefinedGlobalKind, |
57 UndefinedTableKind, | |
55 LazyKind, | 58 LazyKind, |
56 }; | 59 }; |
57 | 60 |
58 Kind kind() const { return symbolKind; } | 61 Kind kind() const { return symbolKind; } |
59 | 62 |
60 bool isDefined() const { return !isLazy() && !isUndefined(); } | 63 bool isDefined() const { return !isLazy() && !isUndefined(); } |
61 | 64 |
62 bool isUndefined() const { | 65 bool isUndefined() const { |
63 return symbolKind == UndefinedFunctionKind || | 66 return symbolKind == UndefinedFunctionKind || |
64 symbolKind == UndefinedDataKind || symbolKind == UndefinedGlobalKind; | 67 symbolKind == UndefinedDataKind || |
68 symbolKind == UndefinedGlobalKind || | |
69 symbolKind == UndefinedTableKind; | |
65 } | 70 } |
66 | 71 |
67 bool isLazy() const { return symbolKind == LazyKind; } | 72 bool isLazy() const { return symbolKind == LazyKind; } |
68 | 73 |
69 bool isLocal() const; | 74 bool isLocal() const; |
103 uint32_t getOutputSymbolIndex() const; | 108 uint32_t getOutputSymbolIndex() const; |
104 void setOutputSymbolIndex(uint32_t index); | 109 void setOutputSymbolIndex(uint32_t index); |
105 | 110 |
106 WasmSymbolType getWasmType() const; | 111 WasmSymbolType getWasmType() const; |
107 bool isExported() const; | 112 bool isExported() const; |
113 bool isExportedExplicit() const; | |
108 | 114 |
109 // Indicates that the symbol is used in an __attribute__((used)) directive | 115 // Indicates that the symbol is used in an __attribute__((used)) directive |
110 // or similar. | 116 // or similar. |
111 bool isNoStrip() const; | 117 bool isNoStrip() const; |
112 | 118 |
122 | 128 |
123 protected: | 129 protected: |
124 Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f) | 130 Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f) |
125 : name(name), file(f), symbolKind(k), referenced(!config->gcSections), | 131 : name(name), file(f), symbolKind(k), referenced(!config->gcSections), |
126 requiresGOT(false), isUsedInRegularObj(false), forceExport(false), | 132 requiresGOT(false), isUsedInRegularObj(false), forceExport(false), |
127 canInline(false), traced(false), flags(flags) {} | 133 canInline(false), traced(false), isStub(false), flags(flags) {} |
128 | 134 |
129 StringRef name; | 135 StringRef name; |
130 InputFile *file; | 136 InputFile *file; |
131 uint32_t outputSymbolIndex = INVALID_INDEX; | 137 uint32_t outputSymbolIndex = INVALID_INDEX; |
132 uint32_t gotIndex = INVALID_INDEX; | 138 uint32_t gotIndex = INVALID_INDEX; |
154 // doesn't know the final contents of the symbol. | 160 // doesn't know the final contents of the symbol. |
155 bool canInline : 1; | 161 bool canInline : 1; |
156 | 162 |
157 // True if this symbol is specified by --trace-symbol option. | 163 // True if this symbol is specified by --trace-symbol option. |
158 bool traced : 1; | 164 bool traced : 1; |
165 | |
166 // True if this symbol is a linker-synthesized stub function (traps when | |
167 // called) and should otherwise be treated as missing/undefined. See | |
168 // SymbolTable::replaceWithUndefined. | |
169 // These stubs never appear in the table and any table index relocations | |
170 // against them will produce address 0 (The table index representing | |
171 // the null function pointer). | |
172 bool isStub : 1; | |
159 | 173 |
160 uint32_t flags; | 174 uint32_t flags; |
161 }; | 175 }; |
162 | 176 |
163 class FunctionSymbol : public Symbol { | 177 class FunctionSymbol : public Symbol { |
215 return s->kind() == UndefinedFunctionKind; | 229 return s->kind() == UndefinedFunctionKind; |
216 } | 230 } |
217 | 231 |
218 llvm::Optional<StringRef> importName; | 232 llvm::Optional<StringRef> importName; |
219 llvm::Optional<StringRef> importModule; | 233 llvm::Optional<StringRef> importModule; |
234 DefinedFunction *stubFunction = nullptr; | |
220 bool isCalledDirectly; | 235 bool isCalledDirectly; |
221 }; | 236 }; |
222 | 237 |
223 // Section symbols for output sections are different from those for input | 238 // Section symbols for output sections are different from those for input |
224 // section. These are generated by the linker and point the OutputSection | 239 // section. These are generated by the linker and point the OutputSection |
237 const OutputSection *section; | 252 const OutputSection *section; |
238 }; | 253 }; |
239 | 254 |
240 class SectionSymbol : public Symbol { | 255 class SectionSymbol : public Symbol { |
241 public: | 256 public: |
242 SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr) | 257 SectionSymbol(uint32_t flags, const InputChunk *s, InputFile *f = nullptr) |
243 : Symbol("", SectionKind, flags, f), section(s) {} | 258 : Symbol("", SectionKind, flags, f), section(s) {} |
244 | 259 |
245 static bool classof(const Symbol *s) { return s->kind() == SectionKind; } | 260 static bool classof(const Symbol *s) { return s->kind() == SectionKind; } |
246 | 261 |
247 const OutputSectionSymbol *getOutputSectionSymbol() const; | 262 const OutputSectionSymbol *getOutputSectionSymbol() const; |
248 | 263 |
249 const InputSection *section; | 264 const InputChunk *section; |
250 }; | 265 }; |
251 | 266 |
252 class DataSymbol : public Symbol { | 267 class DataSymbol : public Symbol { |
253 public: | 268 public: |
254 static bool classof(const Symbol *s) { | 269 static bool classof(const Symbol *s) { |
261 }; | 276 }; |
262 | 277 |
263 class DefinedData : public DataSymbol { | 278 class DefinedData : public DataSymbol { |
264 public: | 279 public: |
265 // Constructor for regular data symbols originating from input files. | 280 // Constructor for regular data symbols originating from input files. |
266 DefinedData(StringRef name, uint32_t flags, InputFile *f, | 281 DefinedData(StringRef name, uint32_t flags, InputFile *f, InputChunk *segment, |
267 InputSegment *segment, uint32_t offset, uint32_t size) | 282 uint64_t value, uint64_t size) |
268 : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), | 283 : DataSymbol(name, DefinedDataKind, flags, f), segment(segment), |
269 offset(offset), size(size) {} | 284 value(value), size(size) {} |
270 | 285 |
271 // Constructor for linker synthetic data symbols. | 286 // Constructor for linker synthetic data symbols. |
272 DefinedData(StringRef name, uint32_t flags) | 287 DefinedData(StringRef name, uint32_t flags) |
273 : DataSymbol(name, DefinedDataKind, flags, nullptr) {} | 288 : DataSymbol(name, DefinedDataKind, flags, nullptr) {} |
274 | 289 |
275 static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; } | 290 static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; } |
276 | 291 |
277 // Returns the output virtual address of a defined data symbol. | 292 // Returns the output virtual address of a defined data symbol. |
278 uint32_t getVirtualAddress() const; | 293 uint64_t getVA() const; |
279 void setVirtualAddress(uint32_t va); | 294 void setVA(uint64_t va); |
280 | 295 |
281 // Returns the offset of a defined data symbol within its OutputSegment. | 296 // Returns the offset of a defined data symbol within its OutputSegment. |
282 uint32_t getOutputSegmentOffset() const; | 297 uint64_t getOutputSegmentOffset() const; |
283 uint32_t getOutputSegmentIndex() const; | 298 uint64_t getOutputSegmentIndex() const; |
284 uint32_t getSize() const { return size; } | 299 uint64_t getSize() const { return size; } |
285 | 300 |
286 InputSegment *segment = nullptr; | 301 InputChunk *segment = nullptr; |
302 uint64_t value = 0; | |
287 | 303 |
288 protected: | 304 protected: |
289 uint32_t offset = 0; | 305 uint64_t size = 0; |
290 uint32_t size = 0; | |
291 }; | 306 }; |
292 | 307 |
293 class UndefinedData : public DataSymbol { | 308 class UndefinedData : public DataSymbol { |
294 public: | 309 public: |
295 UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr) | 310 UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr) |
342 : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type), | 357 : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type), |
343 importName(importName), importModule(importModule) {} | 358 importName(importName), importModule(importModule) {} |
344 | 359 |
345 static bool classof(const Symbol *s) { | 360 static bool classof(const Symbol *s) { |
346 return s->kind() == UndefinedGlobalKind; | 361 return s->kind() == UndefinedGlobalKind; |
362 } | |
363 | |
364 llvm::Optional<StringRef> importName; | |
365 llvm::Optional<StringRef> importModule; | |
366 }; | |
367 | |
368 class TableSymbol : public Symbol { | |
369 public: | |
370 static bool classof(const Symbol *s) { | |
371 return s->kind() == DefinedTableKind || s->kind() == UndefinedTableKind; | |
372 } | |
373 | |
374 const WasmTableType *getTableType() const { return tableType; } | |
375 void setLimits(const WasmLimits &limits); | |
376 | |
377 // Get/set the table number | |
378 uint32_t getTableNumber() const; | |
379 void setTableNumber(uint32_t number); | |
380 bool hasTableNumber() const; | |
381 | |
382 protected: | |
383 TableSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f, | |
384 const WasmTableType *type) | |
385 : Symbol(name, k, flags, f), tableType(type) {} | |
386 | |
387 const WasmTableType *tableType; | |
388 uint32_t tableNumber = INVALID_INDEX; | |
389 }; | |
390 | |
391 class DefinedTable : public TableSymbol { | |
392 public: | |
393 DefinedTable(StringRef name, uint32_t flags, InputFile *file, | |
394 InputTable *table); | |
395 | |
396 static bool classof(const Symbol *s) { return s->kind() == DefinedTableKind; } | |
397 | |
398 InputTable *table; | |
399 }; | |
400 | |
401 class UndefinedTable : public TableSymbol { | |
402 public: | |
403 UndefinedTable(StringRef name, llvm::Optional<StringRef> importName, | |
404 llvm::Optional<StringRef> importModule, uint32_t flags, | |
405 InputFile *file, const WasmTableType *type) | |
406 : TableSymbol(name, UndefinedTableKind, flags, file, type), | |
407 importName(importName), importModule(importModule) {} | |
408 | |
409 static bool classof(const Symbol *s) { | |
410 return s->kind() == UndefinedTableKind; | |
347 } | 411 } |
348 | 412 |
349 llvm::Optional<StringRef> importName; | 413 llvm::Optional<StringRef> importName; |
350 llvm::Optional<StringRef> importModule; | 414 llvm::Optional<StringRef> importModule; |
351 }; | 415 }; |
409 const llvm::object::Archive::Symbol &sym) | 473 const llvm::object::Archive::Symbol &sym) |
410 : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {} | 474 : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {} |
411 | 475 |
412 static bool classof(const Symbol *s) { return s->kind() == LazyKind; } | 476 static bool classof(const Symbol *s) { return s->kind() == LazyKind; } |
413 void fetch(); | 477 void fetch(); |
478 void setWeak(); | |
414 MemoryBufferRef getMemberBuffer(); | 479 MemoryBufferRef getMemberBuffer(); |
415 | 480 |
416 // Lazy symbols can have a signature because they can replace an | 481 // Lazy symbols can have a signature because they can replace an |
417 // UndefinedFunction which which case we need to be able to preserve the | 482 // UndefinedFunction which which case we need to be able to preserve the |
418 // signature. | 483 // signature. |
468 | 533 |
469 // __wasm_call_ctors | 534 // __wasm_call_ctors |
470 // Function that directly calls all ctors in priority order. | 535 // Function that directly calls all ctors in priority order. |
471 static DefinedFunction *callCtors; | 536 static DefinedFunction *callCtors; |
472 | 537 |
473 // __wasm_apply_relocs | 538 // __wasm_call_dtors |
539 // Function that calls the libc/etc. cleanup function. | |
540 static DefinedFunction *callDtors; | |
541 | |
542 // __wasm_apply_data_relocs | |
474 // Function that applies relocations to data segment post-instantiation. | 543 // Function that applies relocations to data segment post-instantiation. |
475 static DefinedFunction *applyRelocs; | 544 static DefinedFunction *applyDataRelocs; |
545 | |
546 // __wasm_apply_global_relocs | |
547 // Function that applies relocations to data segment post-instantiation. | |
548 // Unlike __wasm_apply_data_relocs this needs to run on every thread. | |
549 static DefinedFunction *applyGlobalRelocs; | |
476 | 550 |
477 // __wasm_init_tls | 551 // __wasm_init_tls |
478 // Function that allocates thread-local storage and initializes it. | 552 // Function that allocates thread-local storage and initializes it. |
479 static DefinedFunction *initTLS; | 553 static DefinedFunction *initTLS; |
554 | |
555 // Pointer to the function that is to be used in the start section. | |
556 // (normally an alias of initMemory, or applyGlobalRelocs). | |
557 static DefinedFunction *startFunction; | |
480 | 558 |
481 // __dso_handle | 559 // __dso_handle |
482 // Symbol used in calls to __cxa_atexit to determine current DLL | 560 // Symbol used in calls to __cxa_atexit to determine current DLL |
483 static DefinedData *dsoHandle; | 561 static DefinedData *dsoHandle; |
484 | 562 |
485 // __table_base | 563 // __table_base |
486 // Used in PIC code for offset of indirect function table | 564 // Used in PIC code for offset of indirect function table |
487 static UndefinedGlobal *tableBase; | 565 static UndefinedGlobal *tableBase; |
488 static DefinedData *definedTableBase; | 566 static DefinedData *definedTableBase; |
567 // 32-bit copy in wasm64 to work around init expr limitations. | |
568 // These can potentially be removed again once we have | |
569 // https://github.com/WebAssembly/extended-const | |
570 static UndefinedGlobal *tableBase32; | |
571 static DefinedData *definedTableBase32; | |
489 | 572 |
490 // __memory_base | 573 // __memory_base |
491 // Used in PIC code for offset of global data | 574 // Used in PIC code for offset of global data |
492 static UndefinedGlobal *memoryBase; | 575 static UndefinedGlobal *memoryBase; |
493 static DefinedData *definedMemoryBase; | 576 static DefinedData *definedMemoryBase; |
577 | |
578 // __indirect_function_table | |
579 // Used as an address space for function pointers, with each function that is | |
580 // used as a function pointer being allocated a slot. | |
581 static TableSymbol *indirectFunctionTable; | |
494 }; | 582 }; |
495 | 583 |
496 // A buffer class that is large enough to hold any Symbol-derived | 584 // A buffer class that is large enough to hold any Symbol-derived |
497 // object. We allocate memory using this class and instantiate a symbol | 585 // object. We allocate memory using this class and instantiate a symbol |
498 // using the placement new. | 586 // using the placement new. |
499 union SymbolUnion { | 587 union SymbolUnion { |
500 alignas(DefinedFunction) char a[sizeof(DefinedFunction)]; | 588 alignas(DefinedFunction) char a[sizeof(DefinedFunction)]; |
501 alignas(DefinedData) char b[sizeof(DefinedData)]; | 589 alignas(DefinedData) char b[sizeof(DefinedData)]; |
502 alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)]; | 590 alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)]; |
503 alignas(DefinedEvent) char d[sizeof(DefinedEvent)]; | 591 alignas(DefinedEvent) char d[sizeof(DefinedEvent)]; |
504 alignas(LazySymbol) char e[sizeof(LazySymbol)]; | 592 alignas(DefinedTable) char e[sizeof(DefinedTable)]; |
505 alignas(UndefinedFunction) char f[sizeof(UndefinedFunction)]; | 593 alignas(LazySymbol) char f[sizeof(LazySymbol)]; |
506 alignas(UndefinedData) char g[sizeof(UndefinedData)]; | 594 alignas(UndefinedFunction) char g[sizeof(UndefinedFunction)]; |
507 alignas(UndefinedGlobal) char h[sizeof(UndefinedGlobal)]; | 595 alignas(UndefinedData) char h[sizeof(UndefinedData)]; |
508 alignas(SectionSymbol) char i[sizeof(SectionSymbol)]; | 596 alignas(UndefinedGlobal) char i[sizeof(UndefinedGlobal)]; |
597 alignas(UndefinedTable) char j[sizeof(UndefinedTable)]; | |
598 alignas(SectionSymbol) char k[sizeof(SectionSymbol)]; | |
509 }; | 599 }; |
510 | 600 |
511 // It is important to keep the size of SymbolUnion small for performance and | 601 // It is important to keep the size of SymbolUnion small for performance and |
512 // memory usage reasons. 96 bytes is a soft limit based on the size of | 602 // memory usage reasons. 96 bytes is a soft limit based on the size of |
513 // UndefinedFunction on a 64-bit system. | 603 // UndefinedFunction on a 64-bit system. |
514 static_assert(sizeof(SymbolUnion) <= 112, "SymbolUnion too large"); | 604 static_assert(sizeof(SymbolUnion) <= 120, "SymbolUnion too large"); |
515 | 605 |
516 void printTraceSymbol(Symbol *sym); | 606 void printTraceSymbol(Symbol *sym); |
517 void printTraceSymbolUndefined(StringRef name, const InputFile* file); | 607 void printTraceSymbolUndefined(StringRef name, const InputFile* file); |
518 | 608 |
519 template <typename T, typename... ArgT> | 609 template <typename T, typename... ArgT> |