[LLD][COFF] Fix TypeServerSource matcher with more than one collision
[llvm-project.git] / lld / wasm / Symbols.cpp
blob2ad21c8947f365c3bb327f64009f16d2f7168396
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 //===----------------------------------------------------------------------===//
9 #include "Symbols.h"
10 #include "Config.h"
11 #include "InputChunks.h"
12 #include "InputElement.h"
13 #include "InputFiles.h"
14 #include "OutputSections.h"
15 #include "OutputSegment.h"
16 #include "lld/Common/ErrorHandler.h"
17 #include "lld/Common/Memory.h"
18 #include "lld/Common/Strings.h"
20 #define DEBUG_TYPE "lld"
22 using namespace llvm;
23 using namespace llvm::object;
24 using namespace llvm::wasm;
25 using namespace lld::wasm;
27 namespace lld {
28 std::string toString(const wasm::Symbol &sym) {
29 return maybeDemangleSymbol(sym.getName());
32 std::string maybeDemangleSymbol(StringRef name) {
33 // WebAssembly requires caller and callee signatures to match, so we mangle
34 // `main` in the case where we need to pass it arguments.
35 if (name == "__main_argc_argv")
36 return "main";
38 return demangle(name, config->demangle);
41 std::string toString(wasm::Symbol::Kind kind) {
42 switch (kind) {
43 case wasm::Symbol::DefinedFunctionKind:
44 return "DefinedFunction";
45 case wasm::Symbol::DefinedDataKind:
46 return "DefinedData";
47 case wasm::Symbol::DefinedGlobalKind:
48 return "DefinedGlobal";
49 case wasm::Symbol::DefinedTableKind:
50 return "DefinedTable";
51 case wasm::Symbol::DefinedTagKind:
52 return "DefinedTag";
53 case wasm::Symbol::UndefinedFunctionKind:
54 return "UndefinedFunction";
55 case wasm::Symbol::UndefinedDataKind:
56 return "UndefinedData";
57 case wasm::Symbol::UndefinedGlobalKind:
58 return "UndefinedGlobal";
59 case wasm::Symbol::UndefinedTableKind:
60 return "UndefinedTable";
61 case wasm::Symbol::UndefinedTagKind:
62 return "UndefinedTag";
63 case wasm::Symbol::LazyKind:
64 return "LazyKind";
65 case wasm::Symbol::SectionKind:
66 return "SectionKind";
67 case wasm::Symbol::OutputSectionKind:
68 return "OutputSectionKind";
70 llvm_unreachable("invalid symbol kind");
73 namespace wasm {
74 DefinedFunction *WasmSym::callCtors;
75 DefinedFunction *WasmSym::callDtors;
76 DefinedFunction *WasmSym::initMemory;
77 DefinedFunction *WasmSym::applyDataRelocs;
78 DefinedFunction *WasmSym::applyGlobalRelocs;
79 DefinedFunction *WasmSym::applyGlobalTLSRelocs;
80 DefinedFunction *WasmSym::initTLS;
81 DefinedFunction *WasmSym::startFunction;
82 DefinedData *WasmSym::dsoHandle;
83 DefinedData *WasmSym::dataEnd;
84 DefinedData *WasmSym::globalBase;
85 DefinedData *WasmSym::heapBase;
86 DefinedData *WasmSym::initMemoryFlag;
87 GlobalSymbol *WasmSym::stackPointer;
88 GlobalSymbol *WasmSym::tlsBase;
89 GlobalSymbol *WasmSym::tlsSize;
90 GlobalSymbol *WasmSym::tlsAlign;
91 UndefinedGlobal *WasmSym::tableBase;
92 DefinedData *WasmSym::definedTableBase;
93 UndefinedGlobal *WasmSym::tableBase32;
94 DefinedData *WasmSym::definedTableBase32;
95 UndefinedGlobal *WasmSym::memoryBase;
96 DefinedData *WasmSym::definedMemoryBase;
97 TableSymbol *WasmSym::indirectFunctionTable;
99 WasmSymbolType Symbol::getWasmType() const {
100 if (isa<FunctionSymbol>(this))
101 return WASM_SYMBOL_TYPE_FUNCTION;
102 if (isa<DataSymbol>(this))
103 return WASM_SYMBOL_TYPE_DATA;
104 if (isa<GlobalSymbol>(this))
105 return WASM_SYMBOL_TYPE_GLOBAL;
106 if (isa<TagSymbol>(this))
107 return WASM_SYMBOL_TYPE_TAG;
108 if (isa<TableSymbol>(this))
109 return WASM_SYMBOL_TYPE_TABLE;
110 if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
111 return WASM_SYMBOL_TYPE_SECTION;
112 llvm_unreachable("invalid symbol kind");
115 const WasmSignature *Symbol::getSignature() const {
116 if (auto* f = dyn_cast<FunctionSymbol>(this))
117 return f->signature;
118 if (auto *t = dyn_cast<TagSymbol>(this))
119 return t->signature;
120 if (auto *l = dyn_cast<LazySymbol>(this))
121 return l->signature;
122 return nullptr;
125 InputChunk *Symbol::getChunk() const {
126 if (auto *f = dyn_cast<DefinedFunction>(this))
127 return f->function;
128 if (auto *f = dyn_cast<UndefinedFunction>(this))
129 if (f->stubFunction)
130 return f->stubFunction->function;
131 if (auto *d = dyn_cast<DefinedData>(this))
132 return d->segment;
133 return nullptr;
136 bool Symbol::isDiscarded() const {
137 if (InputChunk *c = getChunk())
138 return c->discarded;
139 return false;
142 bool Symbol::isLive() const {
143 if (auto *g = dyn_cast<DefinedGlobal>(this))
144 return g->global->live;
145 if (auto *t = dyn_cast<DefinedTag>(this))
146 return t->tag->live;
147 if (auto *t = dyn_cast<DefinedTable>(this))
148 return t->table->live;
149 if (InputChunk *c = getChunk())
150 return c->live;
151 return referenced;
154 void Symbol::markLive() {
155 assert(!isDiscarded());
156 referenced = true;
157 if (file != nullptr && isDefined())
158 file->markLive();
159 if (auto *g = dyn_cast<DefinedGlobal>(this))
160 g->global->live = true;
161 if (auto *t = dyn_cast<DefinedTag>(this))
162 t->tag->live = true;
163 if (auto *t = dyn_cast<DefinedTable>(this))
164 t->table->live = true;
165 if (InputChunk *c = getChunk()) {
166 // Usually, a whole chunk is marked as live or dead, but in mergeable
167 // (splittable) sections, each piece of data has independent liveness bit.
168 // So we explicitly tell it which offset is in use.
169 if (auto *d = dyn_cast<DefinedData>(this)) {
170 if (auto *ms = dyn_cast<MergeInputChunk>(c)) {
171 ms->getSectionPiece(d->value)->live = true;
174 c->live = true;
178 uint32_t Symbol::getOutputSymbolIndex() const {
179 assert(outputSymbolIndex != INVALID_INDEX);
180 return outputSymbolIndex;
183 void Symbol::setOutputSymbolIndex(uint32_t index) {
184 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index
185 << "\n");
186 assert(outputSymbolIndex == INVALID_INDEX);
187 outputSymbolIndex = index;
190 void Symbol::setGOTIndex(uint32_t index) {
191 LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n");
192 assert(gotIndex == INVALID_INDEX);
193 gotIndex = index;
196 bool Symbol::isWeak() const {
197 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
200 bool Symbol::isLocal() const {
201 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
204 bool Symbol::isHidden() const {
205 return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
208 bool Symbol::isTLS() const { return flags & WASM_SYMBOL_TLS; }
210 void Symbol::setHidden(bool isHidden) {
211 LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n");
212 flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
213 if (isHidden)
214 flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
215 else
216 flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
219 bool Symbol::isExported() const {
220 // Shared libraries must export all weakly defined symbols
221 // in case they contain the version that will be chosen by
222 // the dynamic linker.
223 if (config->shared && isLive() && isDefined() && isWeak())
224 return true;
226 if (!isDefined() || isLocal())
227 return false;
229 if (config->exportAll || (config->exportDynamic && !isHidden()))
230 return true;
232 return isExportedExplicit();
235 bool Symbol::isExportedExplicit() const {
236 return forceExport || flags & WASM_SYMBOL_EXPORTED;
239 bool Symbol::isNoStrip() const {
240 return flags & WASM_SYMBOL_NO_STRIP;
243 uint32_t FunctionSymbol::getFunctionIndex() const {
244 if (const auto *u = dyn_cast<UndefinedFunction>(this))
245 if (u->stubFunction)
246 return u->stubFunction->getFunctionIndex();
247 if (functionIndex != INVALID_INDEX)
248 return functionIndex;
249 auto *f = cast<DefinedFunction>(this);
250 return f->function->getFunctionIndex();
253 void FunctionSymbol::setFunctionIndex(uint32_t index) {
254 LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n");
255 assert(functionIndex == INVALID_INDEX);
256 functionIndex = index;
259 bool FunctionSymbol::hasFunctionIndex() const {
260 if (auto *f = dyn_cast<DefinedFunction>(this))
261 return f->function->hasFunctionIndex();
262 return functionIndex != INVALID_INDEX;
265 uint32_t FunctionSymbol::getTableIndex() const {
266 if (auto *f = dyn_cast<DefinedFunction>(this))
267 return f->function->getTableIndex();
268 assert(tableIndex != INVALID_INDEX);
269 return tableIndex;
272 bool FunctionSymbol::hasTableIndex() const {
273 if (auto *f = dyn_cast<DefinedFunction>(this))
274 return f->function->hasTableIndex();
275 return tableIndex != INVALID_INDEX;
278 void FunctionSymbol::setTableIndex(uint32_t index) {
279 // For imports, we set the table index here on the Symbol; for defined
280 // functions we set the index on the InputFunction so that we don't export
281 // the same thing twice (keeps the table size down).
282 if (auto *f = dyn_cast<DefinedFunction>(this)) {
283 f->function->setTableIndex(index);
284 return;
286 LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n");
287 assert(tableIndex == INVALID_INDEX);
288 tableIndex = index;
291 DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
292 InputFunction *function)
293 : FunctionSymbol(name, DefinedFunctionKind, flags, f,
294 function ? &function->signature : nullptr),
295 function(function) {}
297 uint32_t DefinedFunction::getExportedFunctionIndex() const {
298 return function->getFunctionIndex();
301 uint64_t DefinedData::getVA() const {
302 LLVM_DEBUG(dbgs() << "getVA: " << getName() << "\n");
303 // In the shared memory case, TLS symbols are relative to the start of the TLS
304 // output segment (__tls_base). When building without shared memory, TLS
305 // symbols absolute, just like non-TLS.
306 if (isTLS() && config->sharedMemory)
307 return getOutputSegmentOffset() + value;
308 if (segment)
309 return segment->getVA(value);
310 return value;
313 void DefinedData::setVA(uint64_t value_) {
314 LLVM_DEBUG(dbgs() << "setVA " << name << " -> " << value_ << "\n");
315 assert(!segment);
316 value = value_;
319 uint64_t DefinedData::getOutputSegmentOffset() const {
320 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
321 return segment->getChunkOffset(value);
324 uint64_t DefinedData::getOutputSegmentIndex() const {
325 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
326 return segment->outputSeg->index;
329 uint32_t GlobalSymbol::getGlobalIndex() const {
330 if (auto *f = dyn_cast<DefinedGlobal>(this))
331 return f->global->getAssignedIndex();
332 assert(globalIndex != INVALID_INDEX);
333 return globalIndex;
336 void GlobalSymbol::setGlobalIndex(uint32_t index) {
337 LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n");
338 assert(globalIndex == INVALID_INDEX);
339 globalIndex = index;
342 bool GlobalSymbol::hasGlobalIndex() const {
343 if (auto *f = dyn_cast<DefinedGlobal>(this))
344 return f->global->hasAssignedIndex();
345 return globalIndex != INVALID_INDEX;
348 DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
349 InputGlobal *global)
350 : GlobalSymbol(name, DefinedGlobalKind, flags, file,
351 global ? &global->getType() : nullptr),
352 global(global) {}
354 uint32_t TagSymbol::getTagIndex() const {
355 if (auto *f = dyn_cast<DefinedTag>(this))
356 return f->tag->getAssignedIndex();
357 assert(tagIndex != INVALID_INDEX);
358 return tagIndex;
361 void TagSymbol::setTagIndex(uint32_t index) {
362 LLVM_DEBUG(dbgs() << "setTagIndex " << name << " -> " << index << "\n");
363 assert(tagIndex == INVALID_INDEX);
364 tagIndex = index;
367 bool TagSymbol::hasTagIndex() const {
368 if (auto *f = dyn_cast<DefinedTag>(this))
369 return f->tag->hasAssignedIndex();
370 return tagIndex != INVALID_INDEX;
373 DefinedTag::DefinedTag(StringRef name, uint32_t flags, InputFile *file,
374 InputTag *tag)
375 : TagSymbol(name, DefinedTagKind, flags, file,
376 tag ? &tag->signature : nullptr),
377 tag(tag) {}
379 void TableSymbol::setLimits(const WasmLimits &limits) {
380 if (auto *t = dyn_cast<DefinedTable>(this))
381 t->table->setLimits(limits);
382 auto *newType = make<WasmTableType>(*tableType);
383 newType->Limits = limits;
384 tableType = newType;
387 uint32_t TableSymbol::getTableNumber() const {
388 if (const auto *t = dyn_cast<DefinedTable>(this))
389 return t->table->getAssignedIndex();
390 assert(tableNumber != INVALID_INDEX);
391 return tableNumber;
394 void TableSymbol::setTableNumber(uint32_t number) {
395 if (const auto *t = dyn_cast<DefinedTable>(this))
396 return t->table->assignIndex(number);
397 LLVM_DEBUG(dbgs() << "setTableNumber " << name << " -> " << number << "\n");
398 assert(tableNumber == INVALID_INDEX);
399 tableNumber = number;
402 bool TableSymbol::hasTableNumber() const {
403 if (const auto *t = dyn_cast<DefinedTable>(this))
404 return t->table->hasAssignedIndex();
405 return tableNumber != INVALID_INDEX;
408 DefinedTable::DefinedTable(StringRef name, uint32_t flags, InputFile *file,
409 InputTable *table)
410 : TableSymbol(name, DefinedTableKind, flags, file,
411 table ? &table->getType() : nullptr),
412 table(table) {}
414 const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
415 assert(section->outputSec && section->outputSec->sectionSym);
416 return section->outputSec->sectionSym;
419 void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
421 void LazySymbol::setWeak() {
422 flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
425 MemoryBufferRef LazySymbol::getMemberBuffer() {
426 Archive::Child c =
427 CHECK(archiveSymbol.getMember(),
428 "could not get the member for symbol " + toString(*this));
430 return CHECK(c.getMemoryBufferRef(),
431 "could not get the buffer for the member defining symbol " +
432 toString(*this));
435 void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
436 message(toString(file) + ": reference to " + name);
439 // Print out a log message for --trace-symbol.
440 void printTraceSymbol(Symbol *sym) {
441 // Undefined symbols are traced via printTraceSymbolUndefined
442 if (sym->isUndefined())
443 return;
445 std::string s;
446 if (sym->isLazy())
447 s = ": lazy definition of ";
448 else
449 s = ": definition of ";
451 message(toString(sym->getFile()) + s + sym->getName());
454 const char *defaultModule = "env";
455 const char *functionTableName = "__indirect_function_table";
457 } // namespace wasm
458 } // namespace lld