[WebAssembly] Use a Symbol class heirarchy. NFC.
This brings wasm into line with ELF and COFF in terms of
symbol types are represented.
Differential Revision: https://reviews.llvm.org/D43112
llvm-svn: 325150
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index e14ebcf..a42cce7 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -66,7 +66,7 @@
Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
if (Sym)
return {Sym, false};
- Sym = make<Symbol>(Name, false);
+ Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
SymVector.emplace_back(Sym);
return {Sym, true};
}
@@ -80,13 +80,10 @@
// Check the type of new symbol matches that of the symbol is replacing.
// For functions this can also involve verifying that the signatures match.
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
- Symbol::Kind Kind, const WasmSignature *NewSig) {
+ bool NewIsFunction, const WasmSignature *NewSig) {
if (Existing.isLazy())
return;
- bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind ||
- Kind == Symbol::Kind::DefinedFunctionKind;
-
// First check the symbol types match (i.e. either both are function
// symbols or both are data symbols).
if (Existing.isFunction() != NewIsFunction) {
@@ -98,105 +95,102 @@
}
// For function symbols, optionally check the function signature matches too.
- if (!NewIsFunction || !Config->CheckSignatures)
+ auto *ExistingFunc = dyn_cast<FunctionSymbol>(&Existing);
+ if (!ExistingFunc || !Config->CheckSignatures)
return;
+
// Skip the signature check if the existing function has no signature (e.g.
// if it is an undefined symbol generated by --undefined command line flag).
- if (!Existing.hasFunctionType())
+ if (!ExistingFunc->hasFunctionType())
return;
- DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
+ DEBUG(dbgs() << "checkSymbolTypes: " << ExistingFunc->getName() << "\n");
assert(NewSig);
- const WasmSignature &OldSig = Existing.getFunctionType();
+ const WasmSignature &OldSig = ExistingFunc->getFunctionType();
if (*NewSig == OldSig)
return;
- error("function signature mismatch: " + Existing.getName() +
+ error("function signature mismatch: " + ExistingFunc->getName() +
"\n>>> defined as " + toString(OldSig) + " in " +
- toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) +
- " in " + F.getName());
+ toString(ExistingFunc->getFile()) + "\n>>> defined as " +
+ toString(*NewSig) + " in " + F.getName());
}
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
- Symbol::Kind Kind, const InputChunk *Chunk) {
+ bool IsFunction, const InputChunk *Chunk) {
const WasmSignature *Sig = nullptr;
if (auto *F = dyn_cast_or_null<InputFunction>(Chunk))
Sig = &F->Signature;
- return checkSymbolTypes(Existing, F, Kind, Sig);
+ return checkSymbolTypes(Existing, F, IsFunction, Sig);
}
-Symbol *SymbolTable::addSyntheticFunction(StringRef Name,
- const WasmSignature *Type,
- uint32_t Flags) {
+DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
+ const WasmSignature *Type,
+ uint32_t Flags) {
DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
assert(WasInserted);
- S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
- S->setFunctionType(Type);
- return S;
+ return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
}
-Symbol *SymbolTable::addSyntheticGlobal(StringRef Name) {
+DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags) {
DEBUG(dbgs() << "addSyntheticGlobal: " << Name << "\n");
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
assert(WasInserted);
- S->update(Symbol::DefinedGlobalKind);
- return S;
+ return replaceSymbol<DefinedGlobal>(S, Name, Flags);
}
-Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
- uint32_t Flags, InputFile *F, InputChunk *Chunk,
+Symbol *SymbolTable::addDefined(bool IsFunction, StringRef Name, uint32_t Flags,
+ InputFile *F, InputChunk *Chunk,
uint32_t Address) {
- DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
+ if (IsFunction)
+ DEBUG(dbgs() << "addDefined: func:" << Name << "\n");
+ else
+ DEBUG(dbgs() << "addDefined: global:" << Name << " addr:" << Address
+ << "\n");
Symbol *S;
bool WasInserted;
+ bool Replace = false;
+ bool CheckTypes = false;
std::tie(S, WasInserted) = insert(Name);
if (WasInserted) {
- S->update(Kind, F, Flags, Chunk, Address);
+ Replace = true;
} else if (S->isLazy()) {
- // The existing symbol is lazy. Replace it without checking types since
+ // Existing symbol is lazy. Replace it without checking types since
// lazy symbols don't have any type information.
DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
- S->update(Kind, F, Flags, Chunk, Address);
+ Replace = true;
} else if (!S->isDefined()) {
- // The existing symbol table entry is undefined. The new symbol replaces
- // it, after checking the type matches
+ // Existing symbol is undefined: replace it, while check types.
DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
- checkSymbolTypes(*S, *F, Kind, Chunk);
- S->update(Kind, F, Flags, Chunk, Address);
+ Replace = true;
+ CheckTypes = true;
} else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
// the new symbol is weak we can ignore it
DEBUG(dbgs() << "existing symbol takes precedence\n");
} else if (S->isWeak()) {
- // the new symbol is not weak and the existing symbol is, so we replace
- // it
+ // the existing symbol is, so we replace it
DEBUG(dbgs() << "replacing existing weak symbol\n");
- checkSymbolTypes(*S, *F, Kind, Chunk);
- S->update(Kind, F, Flags, Chunk, Address);
+ Replace = true;
+ CheckTypes = true;
} else {
// neither symbol is week. They conflict.
reportDuplicate(S, F);
}
- return S;
-}
-Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
- const WasmSignature *Type) {
- DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n");
- Symbol *S;
- bool WasInserted;
- std::tie(S, WasInserted) = insert(Name);
- if (WasInserted) {
- S->update(Symbol::UndefinedFunctionKind);
- S->setFunctionType(Type);
- } else if (!S->isFunction()) {
- error("symbol type mismatch: " + Name);
+ if (Replace) {
+ if (CheckTypes)
+ checkSymbolTypes(*S, *F, IsFunction, Chunk);
+ if (IsFunction)
+ replaceSymbol<DefinedFunction>(S, Name, Flags, F, Chunk);
+ else
+ replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Chunk, Address);
}
return S;
}
@@ -208,17 +202,19 @@
Symbol *S;
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
+ bool IsFunction = Kind == Symbol::UndefinedFunctionKind;
if (WasInserted) {
- S->update(Kind, F, Flags);
- if (Type)
- S->setFunctionType(Type);
- } else if (S->isLazy()) {
+ if (IsFunction)
+ replaceSymbol<UndefinedFunction>(S, Name, Flags, F, Type);
+ else
+ replaceSymbol<UndefinedGlobal>(S, Name, Flags, F);
+ } else if (auto *LazySym = dyn_cast<LazySymbol>(S)) {
DEBUG(dbgs() << "resolved by existing lazy\n");
- auto *AF = cast<ArchiveFile>(S->getFile());
- AF->addMember(&S->getArchiveSymbol());
+ auto *AF = cast<ArchiveFile>(LazySym->getFile());
+ AF->addMember(&LazySym->getArchiveSymbol());
} else if (S->isDefined()) {
DEBUG(dbgs() << "resolved by existing\n");
- checkSymbolTypes(*S, *F, Kind, Type);
+ checkSymbolTypes(*S, *F, IsFunction, Type);
}
return S;
}
@@ -230,8 +226,7 @@
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
if (WasInserted) {
- S->update(Symbol::LazyKind, F);
- S->setArchiveSymbol(*Sym);
+ replaceSymbol<LazySymbol>(S, Name, F, *Sym);
} else if (S->isUndefined()) {
// There is an existing undefined symbol. The can load from the
// archive.