diff options
Diffstat (limited to 'lld/wasm/SymbolTable.cpp')
-rw-r--r-- | lld/wasm/SymbolTable.cpp | 750 |
1 files changed, 375 insertions, 375 deletions
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 35ceed6d2a9..b6181252340 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -24,37 +24,37 @@ using namespace llvm::object; using namespace lld; using namespace lld::wasm; -SymbolTable *lld::wasm::Symtab; +SymbolTable *lld::wasm::symtab; -void SymbolTable::addFile(InputFile *File) { - log("Processing: " + toString(File)); +void SymbolTable::addFile(InputFile *file) { + log("Processing: " + toString(file)); // .a file - if (auto *F = dyn_cast<ArchiveFile>(File)) { - F->parse(); + if (auto *f = dyn_cast<ArchiveFile>(file)) { + f->parse(); return; } // .so file - if (auto *F = dyn_cast<SharedFile>(File)) { - SharedFiles.push_back(F); + if (auto *f = dyn_cast<SharedFile>(file)) { + sharedFiles.push_back(f); return; } - if (Config->Trace) - message(toString(File)); + if (config->trace) + message(toString(file)); // LLVM bitcode file - if (auto *F = dyn_cast<BitcodeFile>(File)) { - F->parse(); - BitcodeFiles.push_back(F); + if (auto *f = dyn_cast<BitcodeFile>(file)) { + f->parse(); + bitcodeFiles.push_back(f); return; } // Regular object file - auto *F = cast<ObjFile>(File); - F->parse(false); - ObjectFiles.push_back(F); + auto *f = cast<ObjFile>(file); + f->parse(false); + objectFiles.push_back(f); } // This function is where all the optimizations of link-time @@ -65,512 +65,512 @@ void SymbolTable::addFile(InputFile *File) { // Because all bitcode files that the program consists of are passed // to the compiler at once, it can do whole-program optimization. void SymbolTable::addCombinedLTOObject() { - if (BitcodeFiles.empty()) + if (bitcodeFiles.empty()) return; // Compile bitcode files and replace bitcode symbols. - LTO.reset(new BitcodeCompiler); - for (BitcodeFile *F : BitcodeFiles) - LTO->add(*F); - - for (StringRef Filename : LTO->compile()) { - auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"), ""); - Obj->parse(true); - ObjectFiles.push_back(Obj); + lto.reset(new BitcodeCompiler); + for (BitcodeFile *f : bitcodeFiles) + lto->add(*f); + + for (StringRef filename : lto->compile()) { + auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), ""); + obj->parse(true); + objectFiles.push_back(obj); } } -Symbol *SymbolTable::find(StringRef Name) { - auto It = SymMap.find(CachedHashStringRef(Name)); - if (It == SymMap.end() || It->second == -1) +Symbol *SymbolTable::find(StringRef name) { + auto it = symMap.find(CachedHashStringRef(name)); + if (it == symMap.end() || it->second == -1) return nullptr; - return SymVector[It->second]; + return symVector[it->second]; } -void SymbolTable::replace(StringRef Name, Symbol* Sym) { - auto It = SymMap.find(CachedHashStringRef(Name)); - SymVector[It->second] = Sym; +void SymbolTable::replace(StringRef name, Symbol* sym) { + auto it = symMap.find(CachedHashStringRef(name)); + symVector[it->second] = sym; } -std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { - bool Trace = false; - auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); - int &SymIndex = P.first->second; - bool IsNew = P.second; - if (SymIndex == -1) { - SymIndex = SymVector.size(); - Trace = true; - IsNew = true; +std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) { + bool trace = false; + auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); + int &symIndex = p.first->second; + bool isNew = p.second; + if (symIndex == -1) { + symIndex = symVector.size(); + trace = true; + isNew = true; } - if (!IsNew) - return {SymVector[SymIndex], false}; + if (!isNew) + return {symVector[symIndex], false}; - Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); - Sym->IsUsedInRegularObj = false; - Sym->CanInline = true; - Sym->Traced = Trace; - SymVector.emplace_back(Sym); - return {Sym, true}; + Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); + sym->isUsedInRegularObj = false; + sym->canInline = true; + sym->traced = trace; + symVector.emplace_back(sym); + return {sym, true}; } -std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, - const InputFile *File) { - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insertName(Name); +std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, + const InputFile *file) { + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insertName(name); - if (!File || File->kind() == InputFile::ObjectKind) - S->IsUsedInRegularObj = true; + if (!file || file->kind() == InputFile::ObjectKind) + s->isUsedInRegularObj = true; - return {S, WasInserted}; + return {s, wasInserted}; } -static void reportTypeError(const Symbol *Existing, const InputFile *File, - llvm::wasm::WasmSymbolType Type) { - error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + - toString(Existing->getWasmType()) + " in " + - toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + - " in " + toString(File)); +static void reportTypeError(const Symbol *existing, const InputFile *file, + llvm::wasm::WasmSymbolType type) { + error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " + + toString(existing->getWasmType()) + " in " + + toString(existing->getFile()) + "\n>>> defined as " + toString(type) + + " in " + toString(file)); } // Check the type of new symbol matches that of the symbol is replacing. // Returns true if the function types match, false is there is a singature // mismatch. -static bool signatureMatches(FunctionSymbol *Existing, - const WasmSignature *NewSig) { - const WasmSignature *OldSig = Existing->Signature; +static bool signatureMatches(FunctionSymbol *existing, + const WasmSignature *newSig) { + const WasmSignature *oldSig = existing->signature; // If either function is missing a signature (this happend for bitcode // symbols) then assume they match. Any mismatch will be reported later // when the LTO objects are added. - if (!NewSig || !OldSig) + if (!newSig || !oldSig) return true; - return *NewSig == *OldSig; + return *newSig == *oldSig; } -static void checkGlobalType(const Symbol *Existing, const InputFile *File, - const WasmGlobalType *NewType) { - if (!isa<GlobalSymbol>(Existing)) { - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); +static void checkGlobalType(const Symbol *existing, const InputFile *file, + const WasmGlobalType *newType) { + if (!isa<GlobalSymbol>(existing)) { + reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL); return; } - const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); - if (*NewType != *OldType) { - error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + - toString(*OldType) + " in " + toString(Existing->getFile()) + - "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); + const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType(); + if (*newType != *oldType) { + error("Global type mismatch: " + existing->getName() + "\n>>> defined as " + + toString(*oldType) + " in " + toString(existing->getFile()) + + "\n>>> defined as " + toString(*newType) + " in " + toString(file)); } } -static void checkEventType(const Symbol *Existing, const InputFile *File, - const WasmEventType *NewType, - const WasmSignature *NewSig) { - auto ExistingEvent = dyn_cast<EventSymbol>(Existing); - if (!isa<EventSymbol>(Existing)) { - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); +static void checkEventType(const Symbol *existing, const InputFile *file, + const WasmEventType *newType, + const WasmSignature *newSig) { + auto existingEvent = dyn_cast<EventSymbol>(existing); + if (!isa<EventSymbol>(existing)) { + reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT); return; } - const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); - const WasmSignature *OldSig = ExistingEvent->Signature; - if (NewType->Attribute != OldType->Attribute) - error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + - toString(*OldType) + " in " + toString(Existing->getFile()) + - "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); - if (*NewSig != *OldSig) - warn("Event signature mismatch: " + Existing->getName() + - "\n>>> defined as " + toString(*OldSig) + " in " + - toString(Existing->getFile()) + "\n>>> defined as " + - toString(*NewSig) + " in " + toString(File)); + const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType(); + const WasmSignature *oldSig = existingEvent->signature; + if (newType->Attribute != oldType->Attribute) + error("Event type mismatch: " + existing->getName() + "\n>>> defined as " + + toString(*oldType) + " in " + toString(existing->getFile()) + + "\n>>> defined as " + toString(*newType) + " in " + toString(file)); + if (*newSig != *oldSig) + warn("Event signature mismatch: " + existing->getName() + + "\n>>> defined as " + toString(*oldSig) + " in " + + toString(existing->getFile()) + "\n>>> defined as " + + toString(*newSig) + " in " + toString(file)); } -static void checkDataType(const Symbol *Existing, const InputFile *File) { - if (!isa<DataSymbol>(Existing)) - reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); +static void checkDataType(const Symbol *existing, const InputFile *file) { + if (!isa<DataSymbol>(existing)) + reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA); } -DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, - uint32_t Flags, - InputFunction *Function) { - LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); - assert(!find(Name)); - SyntheticFunctions.emplace_back(Function); - return replaceSymbol<DefinedFunction>(insertName(Name).first, Name, - Flags, nullptr, Function); +DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name, + uint32_t flags, + InputFunction *function) { + LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n"); + assert(!find(name)); + syntheticFunctions.emplace_back(function); + return replaceSymbol<DefinedFunction>(insertName(name).first, name, + flags, nullptr, function); } // Adds an optional, linker generated, data symbols. The symbol will only be // added if there is an undefine reference to it, or if it is explictly exported // via the --export flag. Otherwise we don't add the symbol and return nullptr. -DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value, - uint32_t Flags) { - Symbol *S = find(Name); - if (!S && (Config->ExportAll || Config->ExportedSymbols.count(Name) != 0)) - S = insertName(Name).first; - else if (!S || S->isDefined()) +DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, uint32_t value, + uint32_t flags) { + Symbol *s = find(name); + if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0)) + s = insertName(name).first; + else if (!s || s->isDefined()) return nullptr; - LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n"); - auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags); - rtn->setVirtualAddress(Value); - rtn->Referenced = true; + LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n"); + auto *rtn = replaceSymbol<DefinedData>(s, name, flags); + rtn->setVirtualAddress(value); + rtn->referenced = true; return rtn; } -DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, - uint32_t Flags) { - LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); - assert(!find(Name)); - return replaceSymbol<DefinedData>(insertName(Name).first, Name, Flags); +DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name, + uint32_t flags) { + LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n"); + assert(!find(name)); + return replaceSymbol<DefinedData>(insertName(name).first, name, flags); } -DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, - InputGlobal *Global) { - LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global +DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags, + InputGlobal *global) { + LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global << "\n"); - assert(!find(Name)); - SyntheticGlobals.emplace_back(Global); - return replaceSymbol<DefinedGlobal>(insertName(Name).first, Name, Flags, - nullptr, Global); + assert(!find(name)); + syntheticGlobals.emplace_back(global); + return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags, + nullptr, global); } -static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, - uint32_t NewFlags) { +static bool shouldReplace(const Symbol *existing, InputFile *newFile, + uint32_t newFlags) { // If existing symbol is undefined, replace it. - if (!Existing->isDefined()) { + if (!existing->isDefined()) { LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " - << Existing->getName() << "\n"); + << existing->getName() << "\n"); return true; } // Now we have two defined symbols. If the new one is weak, we can ignore it. - if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { + if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); return false; } // If the existing symbol is weak, we should replace it. - if (Existing->isWeak()) { + if (existing->isWeak()) { LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); return true; } // Neither symbol is week. They conflict. - error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + - toString(Existing->getFile()) + "\n>>> defined in " + - toString(NewFile)); + error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " + + toString(existing->getFile()) + "\n>>> defined in " + + toString(newFile)); return true; } -Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, - InputFile *File, - InputFunction *Function) { - LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" - << (Function ? toString(Function->Signature) : "none") +Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags, + InputFile *file, + InputFunction *function) { + LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " [" + << (function ? toString(function->signature) : "none") << "]\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&](Symbol *Sym) { + auto replaceSym = [&](Symbol *sym) { // If the new defined function doesn't have signture (i.e. bitcode // functions) but the old symbol does, then preserve the old signature - const WasmSignature *OldSig = S->getSignature(); - auto* NewSym = replaceSymbol<DefinedFunction>(Sym, Name, Flags, File, Function); - if (!NewSym->Signature) - NewSym->Signature = OldSig; + const WasmSignature *oldSig = s->getSignature(); + auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function); + if (!newSym->signature) + newSym->signature = oldSig; }; - if (WasInserted || S->isLazy()) { - ReplaceSym(S); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(s); + return s; } - auto ExistingFunction = dyn_cast<FunctionSymbol>(S); - if (!ExistingFunction) { - reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); - return S; + auto existingFunction = dyn_cast<FunctionSymbol>(s); + if (!existingFunction) { + reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); + return s; } - bool CheckSig = true; - if (auto UD = dyn_cast<UndefinedFunction>(ExistingFunction)) - CheckSig = UD->IsCalledDirectly; + bool checkSig = true; + if (auto ud = dyn_cast<UndefinedFunction>(existingFunction)) + checkSig = ud->isCalledDirectly; - if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) { - Symbol* Variant; - if (getFunctionVariant(S, &Function->Signature, File, &Variant)) + if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) { + Symbol* variant; + if (getFunctionVariant(s, &function->signature, file, &variant)) // New variant, always replace - ReplaceSym(Variant); - else if (shouldReplace(S, File, Flags)) + replaceSym(variant); + else if (shouldReplace(s, file, flags)) // Variant already exists, replace it after checking shouldReplace - ReplaceSym(Variant); + replaceSym(variant); // This variant we found take the place in the symbol table as the primary // variant. - replace(Name, Variant); - return Variant; + replace(name, variant); + return variant; } // Existing function with matching signature. - if (shouldReplace(S, File, Flags)) - ReplaceSym(S); + if (shouldReplace(s, file, flags)) + replaceSym(s); - return S; + return s; } -Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, - InputFile *File, InputSegment *Segment, - uint32_t Address, uint32_t Size) { - LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address +Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags, + InputFile *file, InputSegment *segment, + uint32_t address, uint32_t size) { + LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); + auto replaceSym = [&]() { + replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; } - checkDataType(S, File); + checkDataType(s, file); - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; } -Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, - InputFile *File, InputGlobal *Global) { - LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); +Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags, + InputFile *file, InputGlobal *global) { + LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); + auto replaceSym = [&]() { + replaceSymbol<DefinedGlobal>(s, name, flags, file, global); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; } - checkGlobalType(S, File, &Global->getType()); + checkGlobalType(s, file, &global->getType()); - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; } -Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, - InputFile *File, InputEvent *Event) { - LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); +Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags, + InputFile *file, InputEvent *event) { + LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); - auto ReplaceSym = [&]() { - replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); + auto replaceSym = [&]() { + replaceSymbol<DefinedEvent>(s, name, flags, file, event); }; - if (WasInserted || S->isLazy()) { - ReplaceSym(); - return S; + if (wasInserted || s->isLazy()) { + replaceSym(); + return s; } - checkEventType(S, File, &Event->getType(), &Event->Signature); + checkEventType(s, file, &event->getType(), &event->signature); - if (shouldReplace(S, File, Flags)) - ReplaceSym(); - return S; + if (shouldReplace(s, file, flags)) + replaceSym(); + return s; } -Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, - StringRef ImportModule, - uint32_t Flags, InputFile *File, - const WasmSignature *Sig, - bool IsCalledDirectly) { - LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " [" - << (Sig ? toString(*Sig) : "none") - << "] IsCalledDirectly:" << IsCalledDirectly << "\n"); +Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName, + StringRef importModule, + uint32_t flags, InputFile *file, + const WasmSignature *sig, + bool isCalledDirectly) { + LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " [" + << (sig ? toString(*sig) : "none") + << "] IsCalledDirectly:" << isCalledDirectly << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); - auto ReplaceSym = [&]() { - replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags, - File, Sig, IsCalledDirectly); + auto replaceSym = [&]() { + replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags, + file, sig, isCalledDirectly); }; - if (WasInserted) - ReplaceSym(); - else if (auto *Lazy = dyn_cast<LazySymbol>(S)) - Lazy->fetch(); + if (wasInserted) + replaceSym(); + else if (auto *lazy = dyn_cast<LazySymbol>(s)) + lazy->fetch(); else { - auto ExistingFunction = dyn_cast<FunctionSymbol>(S); - if (!ExistingFunction) { - reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); - return S; + auto existingFunction = dyn_cast<FunctionSymbol>(s); + if (!existingFunction) { + reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION); + return s; } - if (!ExistingFunction->Signature && Sig) - ExistingFunction->Signature = Sig; - if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig)) - if (getFunctionVariant(S, Sig, File, &S)) - ReplaceSym(); + if (!existingFunction->signature && sig) + existingFunction->signature = sig; + if (isCalledDirectly && !signatureMatches(existingFunction, sig)) + if (getFunctionVariant(s, sig, file, &s)) + replaceSym(); } - return S; + return s; } -Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, - InputFile *File) { - LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); +Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags, + InputFile *file) { + LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); - if (WasInserted) - replaceSymbol<UndefinedData>(S, Name, Flags, File); - else if (auto *Lazy = dyn_cast<LazySymbol>(S)) - Lazy->fetch(); - else if (S->isDefined()) - checkDataType(S, File); - return S; + if (wasInserted) + replaceSymbol<UndefinedData>(s, name, flags, file); + else if (auto *lazy = dyn_cast<LazySymbol>(s)) + lazy->fetch(); + else if (s->isDefined()) + checkDataType(s, file); + return s; } -Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, - StringRef ImportModule, uint32_t Flags, - InputFile *File, - const WasmGlobalType *Type) { - LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); +Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName, + StringRef importModule, uint32_t flags, + InputFile *file, + const WasmGlobalType *type) { + LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n"); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insert(Name, File); - if (S->Traced) - printTraceSymbolUndefined(Name, File); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insert(name, file); + if (s->traced) + printTraceSymbolUndefined(name, file); - if (WasInserted) - replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags, - File, Type); - else if (auto *Lazy = dyn_cast<LazySymbol>(S)) - Lazy->fetch(); - else if (S->isDefined()) - checkGlobalType(S, File, Type); - return S; + if (wasInserted) + replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags, + file, type); + else if (auto *lazy = dyn_cast<LazySymbol>(s)) + lazy->fetch(); + else if (s->isDefined()) + checkGlobalType(s, file, type); + return s; } -void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { - LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); - StringRef Name = Sym->getName(); +void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) { + LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n"); + StringRef name = sym->getName(); - Symbol *S; - bool WasInserted; - std::tie(S, WasInserted) = insertName(Name); + Symbol *s; + bool wasInserted; + std::tie(s, wasInserted) = insertName(name); - if (WasInserted) { - replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym); + if (wasInserted) { + replaceSymbol<LazySymbol>(s, name, 0, file, *sym); return; } - if (!S->isUndefined()) + if (!s->isUndefined()) return; // The existing symbol is undefined, load a new one from the archive, // unless the the existing symbol is weak in which case replace the undefined // symbols with a LazySymbol. - if (S->isWeak()) { - const WasmSignature *OldSig = nullptr; + if (s->isWeak()) { + const WasmSignature *oldSig = nullptr; // In the case of an UndefinedFunction we need to preserve the expected // signature. - if (auto *F = dyn_cast<UndefinedFunction>(S)) - OldSig = F->Signature; + if (auto *f = dyn_cast<UndefinedFunction>(s)) + oldSig = f->signature; LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); - auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK, - File, *Sym); - NewSym->Signature = OldSig; + auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK, + file, *sym); + newSym->signature = oldSig; return; } LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); - File->addMember(Sym); + file->addMember(sym); } -bool SymbolTable::addComdat(StringRef Name) { - return ComdatGroups.insert(CachedHashStringRef(Name)).second; +bool SymbolTable::addComdat(StringRef name) { + return comdatGroups.insert(CachedHashStringRef(name)).second; } // The new signature doesn't match. Create a variant to the symbol with the // signature encoded in the name and return that instead. These symbols are // then unified later in handleSymbolVariants. -bool SymbolTable::getFunctionVariant(Symbol* Sym, const WasmSignature *Sig, - const InputFile *File, Symbol **Out) { - LLVM_DEBUG(dbgs() << "getFunctionVariant: " << Sym->getName() << " -> " - << " " << toString(*Sig) << "\n"); - Symbol *Variant = nullptr; +bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig, + const InputFile *file, Symbol **out) { + LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> " + << " " << toString(*sig) << "\n"); + Symbol *variant = nullptr; // Linear search through symbol variants. Should never be more than two // or three entries here. - auto &Variants = SymVariants[CachedHashStringRef(Sym->getName())]; - if (Variants.empty()) - Variants.push_back(Sym); + auto &variants = symVariants[CachedHashStringRef(sym->getName())]; + if (variants.empty()) + variants.push_back(sym); - for (Symbol* V : Variants) { - if (*V->getSignature() == *Sig) { - Variant = V; + for (Symbol* v : variants) { + if (*v->getSignature() == *sig) { + variant = v; break; } } - bool WasAdded = !Variant; - if (WasAdded) { + bool wasAdded = !variant; + if (wasAdded) { // Create a new variant; LLVM_DEBUG(dbgs() << "added new variant\n"); - Variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); - Variants.push_back(Variant); + variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); + variants.push_back(variant); } else { - LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*Variant) << "\n"); - assert(*Variant->getSignature() == *Sig); + LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n"); + assert(*variant->getSignature() == *sig); } - *Out = Variant; - return WasAdded; + *out = variant; + return wasAdded; } // Set a flag for --trace-symbol so that we can print out a log message // if a new symbol with the same name is inserted into the symbol table. -void SymbolTable::trace(StringRef Name) { - SymMap.insert({CachedHashStringRef(Name), -1}); +void SymbolTable::trace(StringRef name) { + symMap.insert({CachedHashStringRef(name), -1}); } -void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { +void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { // Swap symbols as instructed by -wrap. - int &OrigIdx = SymMap[CachedHashStringRef(Sym->getName())]; - int &RealIdx= SymMap[CachedHashStringRef(Real->getName())]; - int &WrapIdx = SymMap[CachedHashStringRef(Wrap->getName())]; - LLVM_DEBUG(dbgs() << "wrap: " << Sym->getName() << "\n"); + int &origIdx = symMap[CachedHashStringRef(sym->getName())]; + int &realIdx= symMap[CachedHashStringRef(real->getName())]; + int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())]; + LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n"); // Anyone looking up __real symbols should get the original - RealIdx = OrigIdx; + realIdx = origIdx; // Anyone looking up the original should get the __wrap symbol - OrigIdx = WrapIdx; + origIdx = wrapIdx; } -static const uint8_t UnreachableFn[] = { +static const uint8_t unreachableFn[] = { 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 0x00 /* opcode unreachable */, 0x0b /* opcode end */ }; @@ -579,15 +579,15 @@ static const uint8_t UnreachableFn[] = { // This is used by handleWeakUndefines in order to generate a callable // equivalent of an undefined function and also handleSymbolVariants for // undefined functions that don't match the signature of the definition. -InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, - const WasmSignature &Sig, - StringRef DebugName) { - auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName); - Func->setBody(UnreachableFn); - SyntheticFunctions.emplace_back(Func); - replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr, - Func); - return Func; +InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym, + const WasmSignature &sig, + StringRef debugName) { + auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName); + func->setBody(unreachableFn); + syntheticFunctions.emplace_back(func); + replaceSymbol<DefinedFunction>(sym, sym->getName(), sym->getFlags(), nullptr, + func); + return func; } // For weak undefined functions, there may be "call" instructions that reference @@ -595,41 +595,41 @@ InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, // will abort at runtime, so that relocations can still provided an operand to // the call instruction that passes Wasm validation. void SymbolTable::handleWeakUndefines() { - for (Symbol *Sym : getSymbols()) { - if (!Sym->isUndefWeak()) + for (Symbol *sym : getSymbols()) { + if (!sym->isUndefWeak()) continue; - const WasmSignature *Sig = Sym->getSignature(); - if (!Sig) { + const WasmSignature *sig = sym->getSignature(); + if (!sig) { // It is possible for undefined functions not to have a signature (eg. if // added via "--undefined"), but weak undefined ones do have a signature. // Lazy symbols may not be functions and therefore Sig can still be null // in some circumstantce. - assert(!isa<FunctionSymbol>(Sym)); + assert(!isa<FunctionSymbol>(sym)); continue; } // Add a synthetic dummy for weak undefined functions. These dummies will // be GC'd if not used as the target of any "call" instructions. - StringRef DebugName = Saver.save("undefined:" + toString(*Sym)); - InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName); + StringRef debugName = saver.save("undefined:" + toString(*sym)); + InputFunction* func = replaceWithUnreachable(sym, *sig, debugName); // Ensure it compares equal to the null pointer, and so that table relocs // don't pull in the stub body (only call-operand relocs should do that). - Func->setTableIndex(0); + func->setTableIndex(0); // Hide our dummy to prevent export. - Sym->setHidden(true); + sym->setHidden(true); } } -static void reportFunctionSignatureMismatch(StringRef SymName, - FunctionSymbol *A, - FunctionSymbol *B, bool IsError) { - std::string msg = ("function signature mismatch: " + SymName + - "\n>>> defined as " + toString(*A->Signature) + " in " + - toString(A->getFile()) + "\n>>> defined as " + - toString(*B->Signature) + " in " + toString(B->getFile())) +static void reportFunctionSignatureMismatch(StringRef symName, + FunctionSymbol *a, + FunctionSymbol *b, bool isError) { + std::string msg = ("function signature mismatch: " + symName + + "\n>>> defined as " + toString(*a->signature) + " in " + + toString(a->getFile()) + "\n>>> defined as " + + toString(*b->signature) + " in " + toString(b->getFile())) .str(); - if (IsError) + if (isError) error(msg); else warn(msg); @@ -638,26 +638,26 @@ static void reportFunctionSignatureMismatch(StringRef SymName, // Remove any variant symbols that were created due to function signature // mismatches. void SymbolTable::handleSymbolVariants() { - for (auto Pair : SymVariants) { + for (auto pair : symVariants) { // Push the initial symbol onto the list of variants. - StringRef SymName = Pair.first.val(); - std::vector<Symbol *> &Variants = Pair.second; + StringRef symName = pair.first.val(); + std::vector<Symbol *> &variants = pair.second; #ifndef NDEBUG - LLVM_DEBUG(dbgs() << "symbol with (" << Variants.size() - << ") variants: " << SymName << "\n"); - for (auto *S: Variants) { - auto *F = cast<FunctionSymbol>(S); - LLVM_DEBUG(dbgs() << " variant: " + F->getName() << " " - << toString(*F->Signature) << "\n"); + LLVM_DEBUG(dbgs() << "symbol with (" << variants.size() + << ") variants: " << symName << "\n"); + for (auto *s: variants) { + auto *f = cast<FunctionSymbol>(s); + LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " " + << toString(*f->signature) << "\n"); } #endif // Find the one definition. - DefinedFunction *Defined = nullptr; - for (auto *Symbol : Variants) { - if (auto F = dyn_cast<DefinedFunction>(Symbol)) { - Defined = F; + DefinedFunction *defined = nullptr; + for (auto *symbol : variants) { + if (auto f = dyn_cast<DefinedFunction>(symbol)) { + defined = f; break; } } @@ -665,19 +665,19 @@ void SymbolTable::handleSymbolVariants() { // If there are no definitions, and the undefined symbols disagree on // the signature, there is not we can do since we don't know which one // to use as the signature on the import. - if (!Defined) { - reportFunctionSignatureMismatch(SymName, - cast<FunctionSymbol>(Variants[0]), - cast<FunctionSymbol>(Variants[1]), true); + if (!defined) { + reportFunctionSignatureMismatch(symName, + cast<FunctionSymbol>(variants[0]), + cast<FunctionSymbol>(variants[1]), true); return; } - for (auto *Symbol : Variants) { - if (Symbol != Defined) { - auto *F = cast<FunctionSymbol>(Symbol); - reportFunctionSignatureMismatch(SymName, F, Defined, false); - StringRef DebugName = Saver.save("unreachable:" + toString(*F)); - replaceWithUnreachable(F, *F->Signature, DebugName); + for (auto *symbol : variants) { + if (symbol != defined) { + auto *f = cast<FunctionSymbol>(symbol); + reportFunctionSignatureMismatch(symName, f, defined, false); + StringRef debugName = saver.save("unreachable:" + toString(*f)); + replaceWithUnreachable(f, *f->signature, debugName); } } } |