[WebAssembly] Use llvm::Optional to store optional symbol attributes. NFC.

The changes the in-memory representation of wasm symbols such that their
optional ImportName and ImportModule use llvm::Optional.

ImportName is set whenever WASM_SYMBOL_EXPLICIT_NAME flag is set.
ImportModule (for imports) is currently always set since it defaults to
"env".

In the future we can possibly extent to binary format distingish
import which have explit module names.

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D74109
This commit is contained in:
Sam Clegg
2020-02-05 21:18:55 -08:00
parent 878159038b
commit bd4812776b
14 changed files with 91 additions and 64 deletions

View File

@@ -452,7 +452,7 @@ static void handleLibcall(StringRef name) {
static UndefinedGlobal *
createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
auto *sym = cast<UndefinedGlobal>(symtab->addUndefinedGlobal(
name, name, defaultModule, WASM_SYMBOL_UNDEFINED, nullptr, type));
name, None, None, WASM_SYMBOL_UNDEFINED, nullptr, type));
config->allowUndefinedSymbols.insert(sym->getName());
sym->isUsedInRegularObj = true;
return sym;
@@ -590,7 +590,7 @@ struct WrappedSymbol {
};
static Symbol *addUndefined(StringRef name) {
return symtab->addUndefinedFunction(name, "", "", WASM_SYMBOL_UNDEFINED,
return symtab->addUndefinedFunction(name, None, None, WASM_SYMBOL_UNDEFINED,
nullptr, nullptr, false);
}

View File

@@ -526,7 +526,7 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
if (objSym.isUndefined() || excludedByComdat) {
flags |= WASM_SYMBOL_UNDEFINED;
if (objSym.isExecutable())
return symtab->addUndefinedFunction(name, "", "", flags, &f, nullptr,
return symtab->addUndefinedFunction(name, None, None, flags, &f, nullptr,
true);
return symtab->addUndefinedData(name, flags, &f);
}

View File

@@ -77,8 +77,8 @@ BitcodeCompiler::~BitcodeCompiler() = default;
static void undefine(Symbol *s) {
if (auto f = dyn_cast<DefinedFunction>(s))
replaceSymbol<UndefinedFunction>(f, f->getName(), "", "", 0, f->getFile(),
f->signature);
replaceSymbol<UndefinedFunction>(f, f->getName(), None, None, 0,
f->getFile(), f->signature);
else if (isa<DefinedData>(s))
replaceSymbol<UndefinedData>(s, s->getName(), 0, s->getFile());
else

View File

@@ -404,31 +404,33 @@ Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags,
// become available when the LTO object is read. In this case we silently
// replace the empty attributes with the valid ones.
template <typename T>
static void setImportAttributes(T *existing, StringRef importName,
StringRef importModule, InputFile *file) {
if (!importName.empty()) {
if (existing->importName.empty())
static void setImportAttributes(T *existing, Optional<StringRef> importName,
Optional<StringRef> importModule,
InputFile *file) {
if (importName) {
if (!existing->importName)
existing->importName = importName;
if (existing->importName != importName)
error("import name mismatch for symbol: " + toString(*existing) +
"\n>>> defined as " + existing->importName + " in " +
toString(existing->getFile()) + "\n>>> defined as " + importName +
"\n>>> defined as " + *existing->importName + " in " +
toString(existing->getFile()) + "\n>>> defined as " + *importName +
" in " + toString(file));
}
if (!importModule.empty()) {
if (existing->importModule.empty())
if (importModule) {
if (!existing->importModule)
existing->importModule = importModule;
if (existing->importModule != importModule)
error("import module mismatch for symbol: " + toString(*existing) +
"\n>>> defined as " + existing->importModule + " in " +
toString(existing->getFile()) + "\n>>> defined as " + importModule +
" in " + toString(file));
"\n>>> defined as " + *existing->importModule + " in " +
toString(existing->getFile()) + "\n>>> defined as " +
*importModule + " in " + toString(file));
}
}
Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
StringRef importModule,
Symbol *SymbolTable::addUndefinedFunction(StringRef name,
Optional<StringRef> importName,
Optional<StringRef> importModule,
uint32_t flags, InputFile *file,
const WasmSignature *sig,
bool isCalledDirectly) {
@@ -497,9 +499,10 @@ Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
return s;
}
Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName,
StringRef importModule, uint32_t flags,
InputFile *file,
Symbol *SymbolTable::addUndefinedGlobal(StringRef name,
Optional<StringRef> importName,
Optional<StringRef> importModule,
uint32_t flags, InputFile *file,
const WasmGlobalType *type) {
LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n");
assert(flags & WASM_SYMBOL_UNDEFINED);

View File

@@ -15,6 +15,7 @@
#include "lld/Common/LLVM.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
namespace lld {
namespace wasm {
@@ -59,14 +60,18 @@ public:
Symbol *addDefinedEvent(StringRef name, uint32_t flags, InputFile *file,
InputEvent *e);
Symbol *addUndefinedFunction(StringRef name, StringRef importName,
StringRef importModule, uint32_t flags,
InputFile *file, const WasmSignature *signature,
Symbol *addUndefinedFunction(StringRef name,
llvm::Optional<StringRef> importName,
llvm::Optional<StringRef> importModule,
uint32_t flags, InputFile *file,
const WasmSignature *signature,
bool isCalledDirectly);
Symbol *addUndefinedData(StringRef name, uint32_t flags, InputFile *file);
Symbol *addUndefinedGlobal(StringRef name, StringRef importName,
StringRef importModule, uint32_t flags,
InputFile *file, const WasmGlobalType *type);
Symbol *addUndefinedGlobal(StringRef name,
llvm::Optional<StringRef> importName,
llvm::Optional<StringRef> importModule,
uint32_t flags, InputFile *file,
const WasmGlobalType *type);
void addLazy(ArchiveFile *f, const llvm::object::Archive::Symbol *sym);

View File

@@ -11,6 +11,7 @@
#include "Config.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Wasm.h"
@@ -203,20 +204,21 @@ public:
class UndefinedFunction : public FunctionSymbol {
public:
UndefinedFunction(StringRef name, StringRef importName,
StringRef importModule, uint32_t flags,
UndefinedFunction(StringRef name, llvm::Optional<StringRef> importName,
llvm::Optional<StringRef> importModule, uint32_t flags,
InputFile *file = nullptr,
const WasmSignature *type = nullptr,
bool isCalledDirectly = true)
: FunctionSymbol(name, UndefinedFunctionKind, flags, file, type),
importName(importName), importModule(importModule), isCalledDirectly(isCalledDirectly) {}
importName(importName), importModule(importModule),
isCalledDirectly(isCalledDirectly) {}
static bool classof(const Symbol *s) {
return s->kind() == UndefinedFunctionKind;
}
StringRef importName;
StringRef importModule;
llvm::Optional<StringRef> importName;
llvm::Optional<StringRef> importModule;
bool isCalledDirectly;
};
@@ -335,8 +337,9 @@ public:
class UndefinedGlobal : public GlobalSymbol {
public:
UndefinedGlobal(StringRef name, StringRef importName, StringRef importModule,
uint32_t flags, InputFile *file = nullptr,
UndefinedGlobal(StringRef name, llvm::Optional<StringRef> importName,
llvm::Optional<StringRef> importModule, uint32_t flags,
InputFile *file = nullptr,
const WasmGlobalType *type = nullptr)
: GlobalSymbol(name, UndefinedGlobalKind, flags, file, type),
importName(importName), importModule(importModule) {}
@@ -345,8 +348,8 @@ public:
return s->kind() == UndefinedGlobalKind;
}
StringRef importName;
StringRef importModule;
llvm::Optional<StringRef> importName;
llvm::Optional<StringRef> importModule;
};
// Wasm events are features that suspend the current execution and transfer the
@@ -510,7 +513,7 @@ union SymbolUnion {
// It is important to keep the size of SymbolUnion small for performance and
// memory usage reasons. 96 bytes is a soft limit based on the size of
// UndefinedFunction on a 64-bit system.
static_assert(sizeof(SymbolUnion) <= 96, "SymbolUnion too large");
static_assert(sizeof(SymbolUnion) <= 112, "SymbolUnion too large");
void printTraceSymbol(Symbol *sym);
void printTraceSymbolUndefined(StringRef name, const InputFile* file);

View File

@@ -156,11 +156,11 @@ void ImportSection::writeBody() {
for (const Symbol *sym : importedSymbols) {
WasmImport import;
if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
import.Field = f->importName;
import.Module = f->importModule;
import.Field = f->importName ? *f->importName : sym->getName();
import.Module = f->importModule ? *f->importModule : defaultModule;
} else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
import.Field = g->importName;
import.Module = g->importModule;
import.Field = g->importName ? *g->importName : sym->getName();
import.Module = g->importModule ? *g->importModule : defaultModule;
} else {
import.Field = sym->getName();
import.Module = defaultModule;

View File

@@ -15,6 +15,7 @@
#define LLVM_BINARYFORMAT_WASM_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -178,9 +179,12 @@ struct WasmSymbolInfo {
StringRef Name;
uint8_t Kind;
uint32_t Flags;
StringRef ImportModule; // For undefined symbols the module of the import
StringRef ImportName; // For undefined symbols the name of the import
StringRef ExportName; // For symbols to be exported from the final module
// For undefined symbols the module of the import
Optional<StringRef> ImportModule;
// For undefined symbols the name of the import
Optional<StringRef> ImportName;
// For symbols to be exported from the final module
Optional<StringRef> ExportName;
union {
// For function or global symbols, the index in function or global index
// space.

View File

@@ -31,8 +31,6 @@ class MCSymbolWasm : public MCSymbol {
const MCExpr *SymbolSize = nullptr;
public:
// Use a module name of "env" for now, for compatibility with existing tools.
// This is temporary, and may change, as the ABI is not yet stable.
MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
: MCSymbol(SymbolKindWasm, Name, isTemporary) {}
static bool classof(const MCSymbol *S) { return S->isWasm(); }
@@ -71,10 +69,15 @@ public:
bool isComdat() const { return IsComdat; }
void setComdat(bool isComdat) { IsComdat = isComdat; }
bool hasImportModule() const { return ImportModule.hasValue(); }
const StringRef getImportModule() const {
if (ImportModule.hasValue()) {
return ImportModule.getValue();
}
// Use a default module name of "env" for now, for compatibility with
// existing tools.
// TODO(sbc): Find a way to specify a default value in the object format
// without picking a hardcoded value like this.
return "env";
}
void setImportModule(StringRef Name) {

View File

@@ -508,13 +508,16 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Function.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
else
Info.ImportName = Import.Field;
} else {
Info.Name = Import.Field;
}
Signature = &Signatures[Import.SigIndex];
Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
if (!Import.Module.empty()) {
Info.ImportModule = Import.Module;
}
}
break;
@@ -537,13 +540,17 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Global.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
else
Info.ImportName = Import.Field;
} else {
Info.Name = Import.Field;
}
GlobalType = &Import.Global;
Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
if (!Import.Module.empty()) {
Info.ImportModule = Import.Module;
}
}
break;
@@ -597,14 +604,17 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
} else {
wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
Info.Name = readString(Ctx);
else
Info.ImportName = Import.Field;
} else {
Info.Name = Import.Field;
}
EventType = &Import.Event;
Signature = &Signatures[EventType->SigIndex];
Info.ImportName = Import.Field;
Info.ImportModule = Import.Module;
if (!Import.Module.empty()) {
Info.ImportModule = Import.Module;
}
}
break;
}

View File

@@ -185,8 +185,6 @@
; CHECK-NEXT: Flags [ (0x10)
; CHECK-NEXT: UNDEFINED (0x10)
; CHECK-NEXT: ]
; CHECK-NEXT: ImportName:
; CHECK-NEXT: ImportModule:
; CHECK-NEXT: }
; CHECK-NEXT: Symbol {
; CHECK-NEXT: Name: ptr2

View File

@@ -26,7 +26,6 @@
# CHECK-NEXT: Flags [ (0x10)
# CHECK-NEXT: UNDEFINED (0x10)
# CHECK-NEXT: ]
# CHECK-NEXT: ImportName: puts
# CHECK-NEXT: ImportModule: env
# CHECK-NEXT: ElementIndex: 0x0
# CHECK-NEXT: }
@@ -44,7 +43,6 @@
# CHECK-NEXT: Flags [ (0x10)
# CHECK-NEXT: UNDEFINED (0x10)
# CHECK-NEXT: ]
# CHECK-NEXT: ImportName: SomeOtherFunction
# CHECK-NEXT: ImportModule: env
# CHECK-NEXT: ElementIndex: 0x1
# CHECK-NEXT: }

View File

@@ -107,7 +107,6 @@ Sections:
# CHECK-NEXT: Flags [ (0x10)
# CHECK-NEXT: UNDEFINED (0x10)
# CHECK-NEXT: ]
# CHECK-NEXT: ImportName: foo
# CHECK-NEXT: ImportModule: red
# CHECK-NEXT: ElementIndex: 0x0
# CHECK-NEXT: }

View File

@@ -227,8 +227,12 @@ void WasmDumper::printSymbol(const SymbolRef &Sym) {
W.printFlags("Flags", Symbol.Info.Flags, makeArrayRef(WasmSymbolFlags));
if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) {
W.printString("ImportName", Symbol.Info.ImportName);
W.printString("ImportModule", Symbol.Info.ImportModule);
if (Symbol.Info.ImportName) {
W.printString("ImportName", *Symbol.Info.ImportName);
}
if (Symbol.Info.ImportModule) {
W.printString("ImportModule", *Symbol.Info.ImportModule);
}
}
if (Symbol.Info.Kind != wasm::WASM_SYMBOL_TYPE_DATA) {
W.printHex("ElementIndex", Symbol.Info.ElementIndex);