Skip to content

Commit

Permalink
[WebAssembly] Use a Symbol class heirarchy. NFC.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sbc100 committed Feb 14, 2018
1 parent 2ec8373 commit dfb0b2c
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 194 deletions.
35 changes: 20 additions & 15 deletions lld/wasm/InputFiles.cpp
Expand Up @@ -51,11 +51,14 @@ void ObjFile::dumpInfo() const {
}

uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const {
return getGlobalSymbol(GlobalIndex)->getVirtualAddress();
if (auto *DG = dyn_cast<DefinedGlobal>(getGlobalSymbol(GlobalIndex)))
return DG->getVirtualAddress();
else
return 0;
}

uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
const Symbol *Sym = getFunctionSymbol(Original);
const FunctionSymbol *Sym = getFunctionSymbol(Original);
uint32_t Index = Sym->getOutputIndex();
DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
<< Original << " -> " << Index << "\n");
Expand All @@ -68,7 +71,7 @@ uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
}

uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
const Symbol *Sym = getFunctionSymbol(Original);
const FunctionSymbol *Sym = getFunctionSymbol(Original);
uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
<< " -> " << Index << "\n");
Expand Down Expand Up @@ -249,7 +252,7 @@ void ObjFile::initializeSymbols() {
case WasmSymbol::SymbolType::FUNCTION_EXPORT: {
InputFunction *Function = getFunction(WasmSym);
if (!isExcludedByComdat(Function)) {
S = createDefined(WasmSym, Symbol::Kind::DefinedFunctionKind, Function);
S = createDefinedFunction(WasmSym, Function);
break;
} else {
Function->Live = false;
Expand All @@ -263,8 +266,7 @@ void ObjFile::initializeSymbols() {
case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
InputSegment *Segment = getSegment(WasmSym);
if (!isExcludedByComdat(Segment)) {
S = createDefined(WasmSym, Symbol::Kind::DefinedGlobalKind, Segment,
getGlobalValue(WasmSym));
S = createDefinedGlobal(WasmSym, Segment, getGlobalValue(WasmSym));
break;
} else {
Segment->Live = false;
Expand Down Expand Up @@ -302,15 +304,18 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym, Symbol::Kind Kind,
return Symtab->addUndefined(Sym.Name, Kind, Sym.Flags, this, Signature);
}

Symbol *ObjFile::createDefined(const WasmSymbol &Sym, Symbol::Kind Kind,
InputChunk *Chunk, uint32_t Address) {
Symbol *S;
if (Sym.isBindingLocal()) {
S = make<Symbol>(Sym.Name, true);
S->update(Kind, this, Sym.Flags, Chunk, Address);
return S;
}
return Symtab->addDefined(Sym.Name, Kind, Sym.Flags, this, Chunk, Address);
Symbol *ObjFile::createDefinedFunction(const WasmSymbol &Sym,
InputChunk *Chunk) {
if (Sym.isBindingLocal())
return make<DefinedFunction>(Sym.Name, Sym.Flags, this, Chunk);
return Symtab->addDefined(true, Sym.Name, Sym.Flags, this, Chunk);
}

Symbol *ObjFile::createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk,
uint32_t Address) {
if (Sym.isBindingLocal())
return make<DefinedGlobal>(Sym.Name, Sym.Flags, this, Chunk, Address);
return Symtab->addDefined(false, Sym.Name, Sym.Flags, this, Chunk, Address);
}

void ArchiveFile::parse() {
Expand Down
14 changes: 8 additions & 6 deletions lld/wasm/InputFiles.h
Expand Up @@ -107,21 +107,23 @@ class ObjFile : public InputFile {

ArrayRef<Symbol *> getSymbols() const { return Symbols; }

Symbol *getFunctionSymbol(uint32_t Index) const {
return FunctionSymbols[Index];
FunctionSymbol *getFunctionSymbol(uint32_t Index) const {
return cast<FunctionSymbol>(FunctionSymbols[Index]);
}

Symbol *getGlobalSymbol(uint32_t Index) const { return GlobalSymbols[Index]; }
GlobalSymbol *getGlobalSymbol(uint32_t Index) const {
return cast<GlobalSymbol>(GlobalSymbols[Index]);
}

private:
uint32_t relocateVirtualAddress(uint32_t Index) const;
uint32_t relocateTypeIndex(uint32_t Original) const;
uint32_t relocateGlobalIndex(uint32_t Original) const;
uint32_t relocateTableIndex(uint32_t Original) const;

Symbol *createDefined(const WasmSymbol &Sym, Symbol::Kind Kind,
InputChunk *Chunk = nullptr,
uint32_t Address = UINT32_MAX);
Symbol *createDefinedGlobal(const WasmSymbol &Sym, InputChunk *Chunk,
uint32_t Address);
Symbol *createDefinedFunction(const WasmSymbol &Sym, InputChunk *Chunk);
Symbol *createUndefined(const WasmSymbol &Sym, Symbol::Kind Kind,
const WasmSignature *Signature = nullptr);
void initializeSymbols();
Expand Down
113 changes: 54 additions & 59 deletions lld/wasm/SymbolTable.cpp
Expand Up @@ -66,7 +66,7 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
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};
}
Expand All @@ -80,13 +80,10 @@ void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
// 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) {
Expand All @@ -98,105 +95,102 @@ static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
}

// 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;
}
Expand All @@ -208,17 +202,19 @@ Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
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;
}
Expand All @@ -230,8 +226,7 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
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.
Expand Down
9 changes: 5 additions & 4 deletions lld/wasm/SymbolTable.h
Expand Up @@ -49,7 +49,7 @@ class SymbolTable {
Symbol *find(StringRef Name);
ObjFile *findComdat(StringRef Name) const;

Symbol *addDefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags,
Symbol *addDefined(bool IsFunction, StringRef Name, uint32_t Flags,
InputFile *F, InputChunk *Chunk = nullptr,
uint32_t Address = 0);
Symbol *addUndefined(StringRef Name, Symbol::Kind Kind, uint32_t Flags,
Expand All @@ -58,9 +58,10 @@ class SymbolTable {
void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
bool addComdat(StringRef Name, ObjFile *);

Symbol *addSyntheticGlobal(StringRef Name);
Symbol *addSyntheticFunction(StringRef Name, const WasmSignature *Type,
uint32_t Flags);
DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags = 0);
DefinedFunction *addSyntheticFunction(StringRef Name,
const WasmSignature *Type,
uint32_t Flags = 0);
private:
std::pair<Symbol *, bool> insert(StringRef Name);

Expand Down

0 comments on commit dfb0b2c

Please sign in to comment.