//===- Symbols.cpp --------------------------------------------------------===// // // The LLVM Linker // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Symbols.h" #include "Config.h" #include "InputChunks.h" #include "InputFiles.h" #include "InputGlobal.h" #include "OutputSegment.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" #define DEBUG_TYPE "lld" using namespace llvm; using namespace llvm::wasm; using namespace lld; using namespace lld::wasm; DefinedFunction *WasmSym::CallCtors; DefinedData *WasmSym::DsoHandle; DefinedData *WasmSym::DataEnd; DefinedData *WasmSym::HeapBase; DefinedGlobal *WasmSym::StackPointer; WasmSymbolType Symbol::getWasmType() const { if (isa(this)) return WASM_SYMBOL_TYPE_FUNCTION; if (isa(this)) return WASM_SYMBOL_TYPE_DATA; if (isa(this)) return WASM_SYMBOL_TYPE_GLOBAL; if (isa(this)) return WASM_SYMBOL_TYPE_SECTION; llvm_unreachable("invalid symbol kind"); } InputChunk *Symbol::getChunk() const { if (auto *F = dyn_cast(this)) return F->Function; if (auto *D = dyn_cast(this)) return D->Segment; return nullptr; } bool Symbol::isLive() const { if (auto *G = dyn_cast(this)) return G->Global->Live; if (InputChunk *C = getChunk()) return C->Live; return Referenced; } void Symbol::markLive() { if (auto *G = dyn_cast(this)) G->Global->Live = true; if (InputChunk *C = getChunk()) C->Live = true; Referenced = true; } uint32_t Symbol::getOutputSymbolIndex() const { assert(OutputSymbolIndex != INVALID_INDEX); return OutputSymbolIndex; } void Symbol::setOutputSymbolIndex(uint32_t Index) { LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index << "\n"); assert(OutputSymbolIndex == INVALID_INDEX); OutputSymbolIndex = Index; } bool Symbol::isWeak() const { return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK; } bool Symbol::isLocal() const { return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL; } bool Symbol::isHidden() const { return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN; } void Symbol::setHidden(bool IsHidden) { LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n"); Flags &= ~WASM_SYMBOL_VISIBILITY_MASK; if (IsHidden) Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; else Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT; } bool Symbol::isExported() const { if (!isDefined() || isLocal()) return false; if (ForceExport || Config->ExportAll) return true; return !isHidden(); } uint32_t FunctionSymbol::getFunctionIndex() const { if (auto *F = dyn_cast(this)) return F->Function->getFunctionIndex(); assert(FunctionIndex != INVALID_INDEX); return FunctionIndex; } void FunctionSymbol::setFunctionIndex(uint32_t Index) { LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n"); assert(FunctionIndex == INVALID_INDEX); FunctionIndex = Index; } bool FunctionSymbol::hasFunctionIndex() const { if (auto *F = dyn_cast(this)) return F->Function->hasFunctionIndex(); return FunctionIndex != INVALID_INDEX; } uint32_t FunctionSymbol::getTableIndex() const { if (auto *F = dyn_cast(this)) return F->Function->getTableIndex(); assert(TableIndex != INVALID_INDEX); return TableIndex; } bool FunctionSymbol::hasTableIndex() const { if (auto *F = dyn_cast(this)) return F->Function->hasTableIndex(); return TableIndex != INVALID_INDEX; } void FunctionSymbol::setTableIndex(uint32_t Index) { // For imports, we set the table index here on the Symbol; for defined // functions we set the index on the InputFunction so that we don't export // the same thing twice (keeps the table size down). if (auto *F = dyn_cast(this)) { F->Function->setTableIndex(Index); return; } LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); assert(TableIndex == INVALID_INDEX); TableIndex = Index; } DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F, InputFunction *Function) : FunctionSymbol(Name, DefinedFunctionKind, Flags, F, Function ? &Function->Signature : nullptr), Function(Function) {} uint32_t DefinedData::getVirtualAddress() const { LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n"); if (Segment) return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset; return Offset; } void DefinedData::setVirtualAddress(uint32_t Value) { LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n"); assert(!Segment); Offset = Value; } uint32_t DefinedData::getOutputSegmentOffset() const { LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n"); return Segment->OutputSegmentOffset + Offset; } uint32_t DefinedData::getOutputSegmentIndex() const { LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n"); return Segment->OutputSeg->Index; } uint32_t GlobalSymbol::getGlobalIndex() const { if (auto *F = dyn_cast(this)) return F->Global->getGlobalIndex(); assert(GlobalIndex != INVALID_INDEX); return GlobalIndex; } void GlobalSymbol::setGlobalIndex(uint32_t Index) { LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n"); assert(GlobalIndex == INVALID_INDEX); GlobalIndex = Index; } bool GlobalSymbol::hasGlobalIndex() const { if (auto *F = dyn_cast(this)) return F->Global->hasGlobalIndex(); return GlobalIndex != INVALID_INDEX; } DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, InputGlobal *Global) : GlobalSymbol(Name, DefinedGlobalKind, Flags, File, Global ? &Global->getType() : nullptr), Global(Global) {} uint32_t SectionSymbol::getOutputSectionIndex() const { LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n"); assert(OutputSectionIndex != INVALID_INDEX); return OutputSectionIndex; } void SectionSymbol::setOutputSectionIndex(uint32_t Index) { LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index << "\n"); assert(Index != INVALID_INDEX); OutputSectionIndex = Index; } void LazySymbol::fetch() { cast(File)->addMember(&ArchiveSymbol); } std::string lld::toString(const wasm::Symbol &Sym) { if (Config->Demangle) if (Optional S = demangleItanium(Sym.getName())) return *S; return Sym.getName(); } std::string lld::toString(wasm::Symbol::Kind Kind) { switch (Kind) { case wasm::Symbol::DefinedFunctionKind: return "DefinedFunction"; case wasm::Symbol::DefinedDataKind: return "DefinedData"; case wasm::Symbol::DefinedGlobalKind: return "DefinedGlobal"; case wasm::Symbol::UndefinedFunctionKind: return "UndefinedFunction"; case wasm::Symbol::UndefinedDataKind: return "UndefinedData"; case wasm::Symbol::UndefinedGlobalKind: return "UndefinedGlobal"; case wasm::Symbol::LazyKind: return "LazyKind"; case wasm::Symbol::SectionKind: return "SectionKind"; } llvm_unreachable("invalid symbol kind"); }