summaryrefslogtreecommitdiff
path: root/wasm/Symbols.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wasm/Symbols.cpp')
-rw-r--r--wasm/Symbols.cpp240
1 files changed, 189 insertions, 51 deletions
diff --git a/wasm/Symbols.cpp b/wasm/Symbols.cpp
index 6bf5459c26633..a11081cbcf779 100644
--- a/wasm/Symbols.cpp
+++ b/wasm/Symbols.cpp
@@ -8,92 +8,224 @@
//===----------------------------------------------------------------------===//
#include "Symbols.h"
-
#include "Config.h"
+#include "InputChunks.h"
#include "InputFiles.h"
-#include "InputSegment.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;
-uint32_t Symbol::getGlobalIndex() const {
- assert(!Sym->isFunction());
- return Sym->ElementIndex;
+DefinedFunction *WasmSym::CallCtors;
+DefinedData *WasmSym::DsoHandle;
+DefinedData *WasmSym::DataEnd;
+DefinedData *WasmSym::HeapBase;
+DefinedGlobal *WasmSym::StackPointer;
+
+WasmSymbolType Symbol::getWasmType() const {
+ if (isa<FunctionSymbol>(this))
+ return WASM_SYMBOL_TYPE_FUNCTION;
+ if (isa<DataSymbol>(this))
+ return WASM_SYMBOL_TYPE_DATA;
+ if (isa<GlobalSymbol>(this))
+ return WASM_SYMBOL_TYPE_GLOBAL;
+ if (isa<SectionSymbol>(this))
+ return WASM_SYMBOL_TYPE_SECTION;
+ llvm_unreachable("invalid symbol kind");
+}
+
+InputChunk *Symbol::getChunk() const {
+ if (auto *F = dyn_cast<DefinedFunction>(this))
+ return F->Function;
+ if (auto *D = dyn_cast<DefinedData>(this))
+ return D->Segment;
+ return nullptr;
+}
+
+bool Symbol::isLive() const {
+ if (auto *G = dyn_cast<DefinedGlobal>(this))
+ return G->Global->Live;
+ if (InputChunk *C = getChunk())
+ return C->Live;
+ return Referenced;
}
-uint32_t Symbol::getFunctionIndex() const {
- assert(Sym->isFunction());
- return Sym->ElementIndex;
+void Symbol::markLive() {
+ if (auto *G = dyn_cast<DefinedGlobal>(this))
+ G->Global->Live = true;
+ if (InputChunk *C = getChunk())
+ C->Live = true;
+ Referenced = true;
}
-const WasmSignature &Symbol::getFunctionType() const {
- assert(FunctionType != nullptr);
- return *FunctionType;
+uint32_t Symbol::getOutputSymbolIndex() const {
+ assert(OutputSymbolIndex != INVALID_INDEX);
+ return OutputSymbolIndex;
}
-uint32_t Symbol::getVirtualAddress() const {
- assert(isGlobal());
- DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
- if (isUndefined())
- return UINT32_MAX;
- if (VirtualAddress.hasValue())
- return VirtualAddress.getValue();
+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;
+}
- assert(Sym != nullptr);
- ObjFile *Obj = cast<ObjFile>(File);
- const WasmGlobal &Global =
- Obj->getWasmObj()->globals()[getGlobalIndex() - Obj->NumGlobalImports()];
- assert(Global.Type == llvm::wasm::WASM_TYPE_I32);
- assert(Segment);
- return Segment->translateVA(Global.InitExpr.Value.Int32);
+bool Symbol::isLocal() const {
+ return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
}
-uint32_t Symbol::getOutputIndex() const {
- if (isUndefined() && isWeak())
- return 0;
- return OutputIndex.getValue();
+bool Symbol::isHidden() const {
+ return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
}
-void Symbol::setVirtualAddress(uint32_t Value) {
- DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
- assert(!VirtualAddress.hasValue());
- VirtualAddress = Value;
+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;
}
-void Symbol::setOutputIndex(uint32_t Index) {
- DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
- assert(!OutputIndex.hasValue());
- OutputIndex = Index;
+bool Symbol::isExported() const {
+ if (!isDefined() || isLocal())
+ return false;
+
+ if (ForceExport || Config->ExportAll)
+ return true;
+
+ return !isHidden();
}
-void Symbol::setTableIndex(uint32_t Index) {
- DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");
- assert(!TableIndex.hasValue());
+uint32_t FunctionSymbol::getFunctionIndex() const {
+ if (auto *F = dyn_cast<DefinedFunction>(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<DefinedFunction>(this))
+ return F->Function->hasFunctionIndex();
+ return FunctionIndex != INVALID_INDEX;
+}
+
+uint32_t FunctionSymbol::getTableIndex() const {
+ if (auto *F = dyn_cast<DefinedFunction>(this))
+ return F->Function->getTableIndex();
+ assert(TableIndex != INVALID_INDEX);
+ return TableIndex;
+}
+
+bool FunctionSymbol::hasTableIndex() const {
+ if (auto *F = dyn_cast<DefinedFunction>(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<DefinedFunction>(this)) {
+ F->Function->setTableIndex(Index);
+ return;
+ }
+ LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");
+ assert(TableIndex == INVALID_INDEX);
TableIndex = Index;
}
-void Symbol::update(Kind K, InputFile *F, const WasmSymbol *WasmSym,
- const InputSegment *Seg, const WasmSignature *Sig) {
- SymbolKind = K;
- File = F;
- Sym = WasmSym;
- Segment = Seg;
- FunctionType = Sig;
+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<DefinedGlobal>(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<DefinedGlobal>(this))
+ return F->Global->hasGlobalIndex();
+ return GlobalIndex != INVALID_INDEX;
}
-bool Symbol::isWeak() const { return Sym && Sym->isWeak(); }
+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;
+}
-bool Symbol::isHidden() const { return Sym && Sym->isHidden(); }
+void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
std::string lld::toString(const wasm::Symbol &Sym) {
if (Config->Demangle)
if (Optional<std::string> S = demangleItanium(Sym.getName()))
- return "`" + *S + "'";
+ return *S;
return Sym.getName();
}
@@ -101,14 +233,20 @@ 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!");
+ llvm_unreachable("invalid symbol kind");
}