diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 272 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 89 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 166 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 63 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 57 |
5 files changed, 254 insertions, 393 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index b643eaec8..1839c9cbd 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -35,6 +35,8 @@ void WasmBinaryWriter::prepare() { ModuleUtils::BinaryIndexes indexes(*wasm); mappedFunctions = std::move(indexes.functionIndexes); mappedGlobals = std::move(indexes.globalIndexes); + + importInfo = wasm::make_unique<ImportInfo>(*wasm); } void WasmBinaryWriter::write() { @@ -136,7 +138,7 @@ void WasmBinaryWriter::writeStart() { } void WasmBinaryWriter::writeMemory() { - if (!wasm->memory.exists || wasm->memory.imported) return; + if (!wasm->memory.exists || wasm->memory.imported()) return; if (debug) std::cerr << "== writeMemory" << std::endl; auto start = startSection(BinaryConsts::Section::Memory); o << U32LEB(1); // Define 1 memory @@ -176,46 +178,54 @@ int32_t WasmBinaryWriter::getFunctionTypeIndex(Name type) { } void WasmBinaryWriter::writeImports() { - if (wasm->imports.size() == 0) return; + auto num = importInfo->getNumImports(); + if (num == 0) return; if (debug) std::cerr << "== writeImports" << std::endl; auto start = startSection(BinaryConsts::Section::Import); - o << U32LEB(wasm->imports.size()); - for (auto& import : wasm->imports) { - if (debug) std::cerr << "write one" << std::endl; + o << U32LEB(num); + auto writeImportHeader = [&](Importable* import) { writeInlineString(import->module.str); writeInlineString(import->base.str); - o << U32LEB(int32_t(import->kind)); - switch (import->kind) { - case ExternalKind::Function: o << U32LEB(getFunctionTypeIndex(import->functionType)); break; - case ExternalKind::Table: { - o << S32LEB(BinaryConsts::EncodedType::AnyFunc); - writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false); - break; - } - case ExternalKind::Memory: { - writeResizableLimits(wasm->memory.initial, wasm->memory.max, - wasm->memory.max != Memory::kMaxSize, wasm->memory.shared); - break; - } - case ExternalKind::Global: - o << binaryType(import->globalType); - o << U32LEB(0); // Mutable global's can't be imported for now. - break; - default: WASM_UNREACHABLE(); - } + }; + ModuleUtils::iterImportedFunctions(*wasm, [&](Function* func) { + if (debug) std::cerr << "write one function" << std::endl; + writeImportHeader(func); + o << U32LEB(int32_t(ExternalKind::Function)); + o << U32LEB(getFunctionTypeIndex(func->type)); + }); + ModuleUtils::iterImportedGlobals(*wasm, [&](Global* global) { + if (debug) std::cerr << "write one global" << std::endl; + writeImportHeader(global); + o << U32LEB(int32_t(ExternalKind::Global)); + o << binaryType(global->type); + o << U32LEB(0); // Mutable globals can't be imported for now. + }); + if (wasm->memory.imported()) { + if (debug) std::cerr << "write one memory" << std::endl; + writeImportHeader(&wasm->memory); + o << U32LEB(int32_t(ExternalKind::Memory)); + writeResizableLimits(wasm->memory.initial, wasm->memory.max, + wasm->memory.max != Memory::kMaxSize, wasm->memory.shared); + } + if (wasm->table.imported()) { + if (debug) std::cerr << "write one table" << std::endl; + writeImportHeader(&wasm->table); + o << U32LEB(int32_t(ExternalKind::Table)); + o << S32LEB(BinaryConsts::EncodedType::AnyFunc); + writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false); } finishSection(start); } void WasmBinaryWriter::writeFunctionSignatures() { - if (wasm->functions.size() == 0) return; + if (importInfo->getNumDefinedFunctions() == 0) return; if (debug) std::cerr << "== writeFunctionSignatures" << std::endl; auto start = startSection(BinaryConsts::Section::Function); - o << U32LEB(wasm->functions.size()); - for (auto& curr : wasm->functions) { + o << U32LEB(importInfo->getNumDefinedFunctions()); + ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { if (debug) std::cerr << "write one" << std::endl; - o << U32LEB(getFunctionTypeIndex(curr->type)); - } + o << U32LEB(getFunctionTypeIndex(func->type)); + }); finishSection(start); } @@ -224,17 +234,15 @@ void WasmBinaryWriter::writeExpression(Expression* curr) { } void WasmBinaryWriter::writeFunctions() { - if (wasm->functions.size() == 0) return; + if (importInfo->getNumDefinedFunctions() == 0) return; if (debug) std::cerr << "== writeFunctions" << std::endl; auto start = startSection(BinaryConsts::Section::Code); - size_t total = wasm->functions.size(); - o << U32LEB(total); - for (size_t i = 0; i < total; i++) { + o << U32LEB(importInfo->getNumDefinedFunctions()); + ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size(); if (debug) std::cerr << "write one at" << o.size() << std::endl; size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); - Function* func = wasm->functions[i].get(); if (debug) std::cerr << "writing" << func->name << std::endl; // Emit Stack IR if present, and if we can if (func->stackIR && !sourceMap) { @@ -261,22 +269,23 @@ void WasmBinaryWriter::writeFunctions() { } } tableOfContents.functionBodies.emplace_back(func->name, sizePos + sizeFieldSize, size); - } + }); finishSection(start); } void WasmBinaryWriter::writeGlobals() { - if (wasm->globals.size() == 0) return; + if (importInfo->getNumDefinedGlobals() == 0) return; if (debug) std::cerr << "== writeglobals" << std::endl; auto start = startSection(BinaryConsts::Section::Global); - o << U32LEB(wasm->globals.size()); - for (auto& curr : wasm->globals) { + auto num = importInfo->getNumDefinedGlobals(); + o << U32LEB(num); + ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) { if (debug) std::cerr << "write one" << std::endl; - o << binaryType(curr->type); - o << U32LEB(curr->mutable_); - writeExpression(curr->init); + o << binaryType(global->type); + o << U32LEB(global->mutable_); + writeExpression(global->init); o << int8_t(BinaryConsts::End); - } + }); finishSection(start); } @@ -404,7 +413,7 @@ uint32_t WasmBinaryWriter::getGlobalIndex(Name name) { } void WasmBinaryWriter::writeFunctionTableDeclaration() { - if (!wasm->table.exists || wasm->table.imported) return; + if (!wasm->table.exists || wasm->table.imported()) return; if (debug) std::cerr << "== writeFunctionTableDeclaration" << std::endl; auto start = startSection(BinaryConsts::Section::Table); o << U32LEB(1); // Declare 1 table. @@ -436,14 +445,6 @@ void WasmBinaryWriter::writeNames() { if (wasm->functions.size() > 0) { hasContents = true; getFunctionIndex(wasm->functions[0]->name); // generate mappedFunctions - } else { - for (auto& import : wasm->imports) { - if (import->kind == ExternalKind::Function) { - hasContents = true; - getFunctionIndex(import->name); // generate mappedFunctions - break; - } - } } if (!hasContents) return; if (debug) std::cerr << "== writeNames" << std::endl; @@ -452,18 +453,13 @@ void WasmBinaryWriter::writeNames() { auto substart = startSubsection(BinaryConsts::UserSections::Subsection::NameFunction); o << U32LEB(mappedFunctions.size()); Index emitted = 0; - for (auto& import : wasm->imports) { - if (import->kind == ExternalKind::Function) { - o << U32LEB(emitted); - writeEscapedName(import->name.str); - emitted++; - } - } - for (auto& curr : wasm->functions) { + auto add = [&](Function* curr) { o << U32LEB(emitted); writeEscapedName(curr->name.str); emitted++; - } + }; + ModuleUtils::iterImportedFunctions(*wasm, add); + ModuleUtils::iterDefinedFunctions(*wasm, add); assert(emitted == mappedFunctions.size()); finishSubsection(substart); /* TODO: locals */ @@ -480,14 +476,11 @@ void WasmBinaryWriter::writeSourceMapUrl() { void WasmBinaryWriter::writeSymbolMap() { std::ofstream file(symbolMap); - for (auto& import : wasm->imports) { - if (import->kind == ExternalKind::Function) { - file << getFunctionIndex(import->name) << ":" << import->name.str << std::endl; - } - } - for (auto& func : wasm->functions) { + auto write = [&](Function* func) { file << getFunctionIndex(func->name) << ":" << func->name.str << std::endl; - } + }; + ModuleUtils::iterImportedFunctions(*wasm, write); + ModuleUtils::iterDefinedFunctions(*wasm, write); file.close(); } @@ -940,17 +933,7 @@ void WasmBinaryBuilder::readSignatures() { } Name WasmBinaryBuilder::getFunctionIndexName(Index i) { - if (i < functionImports.size()) { - auto* import = functionImports[i]; - assert(import->kind == ExternalKind::Function); - return import->name; - } else { - i -= functionImports.size(); - if (i >= wasm.functions.size()) { - throwError("bad function index"); - } - return wasm.functions[i]->name; - } + return wasm.functions[i]->name; } void WasmBinaryBuilder::getResizableLimits(Address& initial, Address& max, bool &shared, Address defaultIfNoMax) { @@ -968,61 +951,69 @@ void WasmBinaryBuilder::readImports() { if (debug) std::cerr << "== readImports" << std::endl; size_t num = getU32LEB(); if (debug) std::cerr << "num: " << num << std::endl; + Builder builder(wasm); for (size_t i = 0; i < num; i++) { if (debug) std::cerr << "read one" << std::endl; - auto curr = new Import; - curr->module = getInlineString(); - curr->base = getInlineString(); - curr->kind = (ExternalKind)getU32LEB(); + auto module = getInlineString(); + auto base = getInlineString(); + auto kind = (ExternalKind)getU32LEB(); // We set a unique prefix for the name based on the kind. This ensures no collisions // between them, which can't occur here (due to the index i) but could occur later // due to the names section. - switch (curr->kind) { + switch (kind) { case ExternalKind::Function: { - curr->name = Name(std::string("fimport$") + std::to_string(i)); + auto name = Name(std::string("fimport$") + std::to_string(i)); auto index = getU32LEB(); if (index >= wasm.functionTypes.size()) { throwError("invalid function index " + std::to_string(index) + " / " + std::to_string(wasm.functionTypes.size())); } - curr->functionType = wasm.functionTypes[index]->name; - assert(curr->functionType.is()); + auto* functionType = wasm.functionTypes[index].get(); + auto params = functionType->params; + auto result = functionType->result; + auto* curr = builder.makeFunction(name, std::move(params), result, {}); + curr->module = module; + curr->base = base; + curr->type = functionType->name; + wasm.addFunction(curr); functionImports.push_back(curr); - continue; // don't add the import yet, we add them later after we know their names break; } case ExternalKind::Table: { - curr->name = Name(std::string("timport$") + std::to_string(i)); + wasm.table.module = module; + wasm.table.base = base; + wasm.table.name = Name(std::string("timport$") + std::to_string(i)); auto elementType = getS32LEB(); WASM_UNUSED(elementType); if (elementType != BinaryConsts::EncodedType::AnyFunc) throwError("Imported table type is not AnyFunc"); wasm.table.exists = true; - wasm.table.imported = true; bool is_shared; getResizableLimits(wasm.table.initial, wasm.table.max, is_shared, Table::kMaxSize); if (is_shared) throwError("Tables may not be shared"); break; } case ExternalKind::Memory: { - curr->name = Name(std::string("mimport$") + std::to_string(i)); + wasm.memory.module = module; + wasm.memory.base = base; + wasm.memory.name = Name(std::to_string(i)); wasm.memory.exists = true; - wasm.memory.imported = true; getResizableLimits(wasm.memory.initial, wasm.memory.max, wasm.memory.shared, Memory::kMaxSize); break; } case ExternalKind::Global: { - curr->name = Name(std::string("gimport$") + std::to_string(i)); - curr->globalType = getConcreteType(); - auto globalMutable = getU32LEB(); - // TODO: actually use the globalMutable flag. Currently mutable global - // imports is a future feature, to be implemented with thread support. - (void)globalMutable; + auto name = Name(std::string("gimport$") + std::to_string(i)); + auto type = getConcreteType(); + auto mutable_ = getU32LEB(); + assert(!mutable_); // for now, until mutable globals + auto* curr = builder.makeGlobal(name, type, nullptr, mutable_ ? Builder::Mutable : Builder::Immutable); + curr->module = module; + curr->base = base; + wasm.addGlobal(curr); break; } default: { throwError("bad import kind"); } } - wasm.addImport(curr); } } @@ -1332,7 +1323,7 @@ void WasmBinaryBuilder::readGlobals() { if (mutable_ & ~1) throwError("Global mutability must be 0 or 1"); auto* init = readExpression(); wasm.addGlobal(Builder::makeGlobal( - "global$" + std::to_string(wasm.globals.size()), + "global$" + std::to_string(i), type, init, mutable_ ? Builder::Mutable : Builder::Immutable @@ -1460,15 +1451,12 @@ Expression* WasmBinaryBuilder::popNonVoidExpression() { Name WasmBinaryBuilder::getGlobalName(Index index) { if (!mappedGlobals.size()) { // Create name => index mapping. - for (auto& import : wasm.imports) { - if (import->kind != ExternalKind::Global) continue; - auto index = mappedGlobals.size(); - mappedGlobals[index] = import->name; - } - for (size_t i = 0; i < wasm.globals.size(); i++) { + auto add = [&](Global* curr) { auto index = mappedGlobals.size(); - mappedGlobals[index] = wasm.globals[i]->name; - } + mappedGlobals[index] = curr->name; + }; + ModuleUtils::iterImportedGlobals(wasm, add); + ModuleUtils::iterDefinedGlobals(wasm, add); } if (index == Index(-1)) return Name("null"); // just a force-rebuild if (mappedGlobals.count(index) == 0) { @@ -1482,17 +1470,6 @@ void WasmBinaryBuilder::processFunctions() { wasm.addFunction(func); } - for (auto* import : functionImports) { - wasm.addImport(import); - } - - // we should have seen all the functions - // we assume this later down in fact, when we read wasm.functions[index], - // as index was validated vs functionTypes.size() - if (wasm.functions.size() != functionTypes.size()) { - throwError("did not see the right number of functions"); - } - // now that we have names for each function, apply things if (startIndex != static_cast<Index>(-1)) { @@ -1518,15 +1495,7 @@ void WasmBinaryBuilder::processFunctions() { size_t index = iter.first; auto& calls = iter.second; for (auto* call : calls) { - call->target = wasm.functions[index]->name; - } - } - - for (auto& iter : functionImportCalls) { - size_t index = iter.first; - auto& calls = iter.second; - for (auto* call : calls) { - call->target = functionImports[index]->name; + call->target = getFunctionIndexName(index); } } @@ -1537,6 +1506,10 @@ void WasmBinaryBuilder::processFunctions() { wasm.table.segments[i].data.push_back(getFunctionIndexName(j)); } } + + // Everything now has its proper name. + + wasm.updateMaps(); } void WasmBinaryBuilder::readDataSegments() { @@ -1689,7 +1662,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { case BinaryConsts::Br: case BinaryConsts::BrIf: visitBreak((curr = allocator.alloc<Break>())->cast<Break>(), code); break; // code distinguishes br from br_if case BinaryConsts::TableSwitch: visitSwitch((curr = allocator.alloc<Switch>())->cast<Switch>()); break; - case BinaryConsts::CallFunction: curr = visitCall(); break; // we don't know if it's a call or call_import yet + case BinaryConsts::CallFunction: visitCall((curr = allocator.alloc<Call>())->cast<Call>()); break; case BinaryConsts::CallIndirect: visitCallIndirect((curr = allocator.alloc<CallIndirect>())->cast<CallIndirect>()); break; case BinaryConsts::GetLocal: visitGetLocal((curr = allocator.alloc<GetLocal>())->cast<GetLocal>()); break; case BinaryConsts::TeeLocal: @@ -1928,35 +1901,26 @@ void WasmBinaryBuilder::visitSwitch(Switch* curr) { curr->finalize(); } -Expression* WasmBinaryBuilder::visitCall() { +void WasmBinaryBuilder::visitCall(Call* curr) { if (debug) std::cerr << "zz node: Call" << std::endl; auto index = getU32LEB(); FunctionType* type; - Expression* ret; if (index < functionImports.size()) { - // this is a call of an imported function - auto* call = allocator.alloc<CallImport>(); auto* import = functionImports[index]; - type = wasm.getFunctionType(import->functionType); - functionImportCalls[index].push_back(call); - call->target = import->name; // name section may modify it - fillCall(call, type); - call->finalize(); - ret = call; + type = wasm.getFunctionType(import->type); } else { - // this is a call of a defined function - auto* call = allocator.alloc<Call>(); auto adjustedIndex = index - functionImports.size(); - if (adjustedIndex >= functionTypes.size()) { - throwError("bad call index"); - } type = functionTypes[adjustedIndex]; - fillCall(call, type); - functionCalls[adjustedIndex].push_back(call); // we don't know function names yet - call->finalize(); - ret = call; } - return ret; + assert(type); + auto num = type->params.size(); + curr->operands.resize(num); + for (size_t i = 0; i < num; i++) { + curr->operands[num - i - 1] = popNonVoidExpression(); + } + curr->type = type->result; + functionCalls[index].push_back(curr); // we don't know function names yet + curr->finalize(); } void WasmBinaryBuilder::visitCallIndirect(CallIndirect* curr) { @@ -2007,17 +1971,7 @@ void WasmBinaryBuilder::visitGetGlobal(GetGlobal* curr) { if (debug) std::cerr << "zz node: GetGlobal " << pos << std::endl; auto index = getU32LEB(); curr->name = getGlobalName(index); - auto* global = wasm.getGlobalOrNull(curr->name); - if (global) { - curr->type = global->type; - return; - } - auto* import = wasm.getImportOrNull(curr->name); - if (import && import->kind == ExternalKind::Global) { - curr->type = import->globalType; - return; - } - throwError("bad get_global"); + curr->type = wasm.getGlobal(curr->name)->type; } void WasmBinaryBuilder::visitSetGlobal(SetGlobal* curr) { diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 65d385870..635b5dfc5 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -24,6 +24,8 @@ #include "wasm-builder.h" #include "wasm-traversal.h" #include "wasm.h" +#include "ir/function-type-utils.h" +#include "ir/module-utils.h" namespace wasm { @@ -181,12 +183,7 @@ void EmscriptenGlueGenerator::generateDynCallThunks() { if (indirectFunc == dummyFunction) { continue; } - std::string sig; - if (auto import = wasm.getImportOrNull(indirectFunc)) { - sig = getSig(wasm.getFunctionType(import->functionType)); - } else { - sig = getSig(wasm.getFunction(indirectFunc)); - } + std::string sig = getSig(wasm.getFunction(indirectFunc)); auto* funcType = ensureFunctionType(sig, &wasm); if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. if (!sigs.insert(sig).second) continue; // Sig is already in the set @@ -269,12 +266,12 @@ void EmscriptenGlueGenerator::generateJSCallThunks( // function would have signature 'vii'.) std::string importSig = std::string(1, sig[0]) + 'i' + sig.substr(1); FunctionType *importType = ensureFunctionType(importSig, &wasm); - auto import = new Import; + auto import = new Function; import->name = import->base = "jsCall_" + sig; import->module = ENV; - import->functionType = importType->name; - import->kind = ExternalKind::Function; - wasm.addImport(import); + import->type = importType->name; + FunctionTypeUtils::fillFunction(import, importType); + wasm.addFunction(import); FunctionType *funcType = ensureFunctionType(sig, &wasm); // Create jsCall_sig_index thunks (e.g. jsCall_vi_0, jsCall_vi_1, ...) @@ -297,7 +294,7 @@ void EmscriptenGlueGenerator::generateJSCallThunks( args.push_back(builder.makeGetLocal(i, funcType->params[i])); } Expression* call = - builder.makeCallImport(import->name, args, funcType->result); + builder.makeCall(import->name, args, funcType->result); f->body = call; wasm.addFunction(f); tableSegmentData.push_back(f->name); @@ -378,7 +375,7 @@ struct AsmConstWalker : public PostWalker<AsmConstWalker> { : wasm(_wasm), segmentOffsets(getSegmentOffsets(wasm)) { } - void visitCallImport(CallImport* curr); + void visitCall(Call* curr); private: Literal idLiteralForCode(std::string code); @@ -387,9 +384,9 @@ private: void addImport(Name importName, std::string baseSig); }; -void AsmConstWalker::visitCallImport(CallImport* curr) { - Import* import = wasm.getImport(curr->target); - if (import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) { +void AsmConstWalker::visitCall(Call* curr) { + auto* import = wasm.getFunction(curr->target); + if (import->imported() && import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) { auto arg = curr->operands[0]->cast<Const>(); auto code = codeForConstAddr(wasm, segmentOffsets, arg); arg->value = idLiteralForCode(code); @@ -434,20 +431,19 @@ Name AsmConstWalker::nameForImportWithSig(std::string sig) { } void AsmConstWalker::addImport(Name importName, std::string baseSig) { - auto import = new Import; + auto import = new Function; import->name = import->base = importName; import->module = ENV; - import->functionType = ensureFunctionType(baseSig, &wasm)->name; - import->kind = ExternalKind::Function; - wasm.addImport(import); + import->type = ensureFunctionType(baseSig, &wasm)->name; + wasm.addFunction(import); } AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) { // Collect imports to remove // This would find our generated functions if we ran it later std::vector<Name> toRemove; - for (auto& import : wasm.imports) { - if (import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) { + for (auto& import : wasm.functions) { + if (import->imported() && import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) { toRemove.push_back(import->name); } } @@ -458,7 +454,7 @@ AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) { // Remove the base functions that we didn't generate for (auto importName : toRemove) { - wasm.removeImport(importName); + wasm.removeFunction(importName); } return walker; } @@ -590,19 +586,21 @@ struct FixInvokeFunctionNamesWalker : public PostWalker<FixInvokeFunctionNamesWa return fixEmExceptionInvoke(name, sig); } - void visitImport(Import* curr) { - if (curr->kind != ExternalKind::Function) + void visitFunction(Function* curr) { + if (!curr->imported()) { return; + } - FunctionType* func = wasm.getFunctionType(curr->functionType); + FunctionType* func = wasm.getFunctionType(curr->type); Name newname = fixEmEHSjLjNames(curr->base, getSig(func)); - if (newname == curr->base) + if (newname == curr->base) { return; + } assert(importRenames.count(curr->name) == 0); importRenames[curr->name] = newname; // Either rename or remove the existing import - if (wasm.getImportOrNull(newname) || !newImports.insert(newname).second) { + if (wasm.getFunctionOrNull(newname) || !newImports.insert(newname).second) { toRemove.push_back(curr->name); } else { curr->base = newname; @@ -621,16 +619,18 @@ struct FixInvokeFunctionNamesWalker : public PostWalker<FixInvokeFunctionNamesWa } } - void visitCallImport(CallImport* curr) { - auto it = importRenames.find(curr->target); - if (it != importRenames.end()) { - curr->target = it->second; + void visitCall(Call* curr) { + if (wasm.getFunction(curr->target)->imported()) { + auto it = importRenames.find(curr->target); + if (it != importRenames.end()) { + curr->target = it->second; + } } } void visitModule(Module* curr) { for (auto importName : toRemove) { - wasm.removeImport(importName); + wasm.removeFunction(importName); } wasm.updateMaps(); } @@ -731,25 +731,23 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata( // see. meta << ", \"declares\": ["; commaFirst = true; - for (const auto& import : wasm.imports) { - if (import->kind == ExternalKind::Function && - (emJsWalker.codeByName.count(import->base.str) == 0) && + ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) { + if (emJsWalker.codeByName.count(import->base.str) == 0 && !import->base.startsWith(EMSCRIPTEN_ASM_CONST.str) && !import->base.startsWith("invoke_") && !import->base.startsWith("jsCall_")) { - if (declares.insert(import->base.str).second) + if (declares.insert(import->base.str).second) { meta << maybeComma() << '"' << import->base.str << '"'; + } } - } + }); meta << "]"; meta << ", \"externs\": ["; commaFirst = true; - for (const auto& import : wasm.imports) { - if (import->kind == ExternalKind::Global) { - meta << maybeComma() << "\"_" << import->base.str << '"'; - } - } + ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) { + meta << maybeComma() << "\"_" << import->base.str << '"'; + }); meta << "]"; meta << ", \"implementedFunctions\": ["; @@ -770,12 +768,13 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata( meta << ", \"invokeFuncs\": ["; commaFirst = true; - for (const auto& import : wasm.imports) { + ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) { if (import->base.startsWith("invoke_")) { - if (invokeFuncs.insert(import->base.str).second) + if (invokeFuncs.insert(import->base.str).second) { meta << maybeComma() << '"' << import->base.str << '"'; + } } - } + }); meta << "]"; meta << " }\n"; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index e4c171b5c..7085666bb 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -23,6 +23,7 @@ #include "asm_v_wasm.h" #include "asmjs/shared-constants.h" #include "ir/branch-utils.h" +#include "ir/function-type-utils.h" #include "shared-constants.h" #include "wasm-binary.h" #include "wasm-builder.h" @@ -581,14 +582,15 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { if (importModule.is()) { // this is an import, actually if (!preParseImport) throw ParseException("!preParseImport in func"); - std::unique_ptr<Import> im = make_unique<Import>(); + auto im = make_unique<Function>(); im->name = name; im->module = importModule; im->base = importBase; - im->kind = ExternalKind::Function; - im->functionType = wasm.getFunctionType(type)->name; - if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); - wasm.addImport(im.release()); + im->type = type; + FunctionTypeUtils::fillFunction(im.get(), wasm.getFunctionType(type)); + functionTypes[name] = im->result; + if (wasm.getFunctionOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); + wasm.addFunction(im.release()); if (currFunction) throw ParseException("import module inside function dec"); currLocalTypes.clear(); nameMapper.clear(); @@ -821,7 +823,6 @@ Expression* SExpressionWasmBuilder::makeExpression(Element& s) { case 'c': { if (str[1] == 'a') { if (id == CALL) return makeCall(s); - if (id == CALL_IMPORT) return makeCallImport(s); if (id == CALL_INDIRECT) return makeCallIndirect(s); } else if (str[1] == 'u') return makeHost(s, HostOp::CurrentMemory); abort_on(str); @@ -1040,16 +1041,11 @@ Expression* SExpressionWasmBuilder::makeGetGlobal(Element& s) { auto ret = allocator.alloc<GetGlobal>(); ret->name = getGlobalName(*s[1]); auto* global = wasm.getGlobalOrNull(ret->name); - if (global) { - ret->type = global->type; - return ret; + if (!global) { + throw ParseException("bad get_global name", s.line, s.col); } - auto* import = wasm.getImportOrNull(ret->name); - if (import && import->kind == ExternalKind::Global) { - ret->type = import->globalType; - return ret; - } - throw ParseException("bad get_global name", s.line, s.col); + ret->type = global->type; + return ret; } Expression* SExpressionWasmBuilder::makeSetGlobal(Element& s) { @@ -1377,15 +1373,6 @@ Expression* SExpressionWasmBuilder::makeLoop(Element& s) { Expression* SExpressionWasmBuilder::makeCall(Element& s) { auto target = getFunctionName(*s[1]); - auto* import = wasm.getImportOrNull(target); - if (import && import->kind == ExternalKind::Function) { - auto ret = allocator.alloc<CallImport>(); - ret->target = target; - Import* import = wasm.getImport(ret->target); - ret->type = wasm.getFunctionType(import->functionType)->result; - parseCallOperands(s, 2, s.size(), ret); - return ret; - } auto ret = allocator.alloc<Call>(); ret->target = target; ret->type = functionTypes[ret->target]; @@ -1394,16 +1381,6 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s) { return ret; } -Expression* SExpressionWasmBuilder::makeCallImport(Element& s) { - auto ret = allocator.alloc<CallImport>(); - ret->target = s[1]->str(); - Import* import = wasm.getImport(ret->target); - ret->type = wasm.getFunctionType(import->functionType)->result; - parseCallOperands(s, 2, s.size(), ret); - ret->finalize(); - return ret; -} - Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) { if (!wasm.table.exists) throw ParseException("no table"); auto ret = allocator.alloc<CallIndirect>(); @@ -1543,7 +1520,6 @@ Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) { void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { if (wasm.memory.exists) throw ParseException("too many memories"); wasm.memory.exists = true; - wasm.memory.imported = preParseImport; wasm.memory.shared = false; Index i = 1; if (s[i]->dollared()) { @@ -1561,15 +1537,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { wasm.addExport(ex.release()); i++; } else if (inner[0]->str() == IMPORT) { - importModule = inner[1]->str(); - importBase = inner[2]->str(); - auto im = make_unique<Import>(); - im->kind = ExternalKind::Memory; - im->module = importModule; - im->base = importBase; - im->name = importModule; - if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); - wasm.addImport(im.release()); + wasm.memory.module = inner[1]->str(); + wasm.memory.base = inner[2]->str(); i++; } else if (inner[0]->str() == "shared") { wasm.memory.shared = true; @@ -1675,70 +1644,69 @@ void SExpressionWasmBuilder::parseExport(Element& s) { } void SExpressionWasmBuilder::parseImport(Element& s) { - std::unique_ptr<Import> im = make_unique<Import>(); size_t i = 1; bool newStyle = s.size() == 4 && s[3]->isList(); // (import "env" "STACKTOP" (global $stackTop i32)) + auto kind = ExternalKind::Invalid; if (newStyle) { if ((*s[3])[0]->str() == FUNC) { - im->kind = ExternalKind::Function; + kind = ExternalKind::Function; } else if ((*s[3])[0]->str() == MEMORY) { - im->kind = ExternalKind::Memory; + kind = ExternalKind::Memory; if (wasm.memory.exists) throw ParseException("more than one memory"); wasm.memory.exists = true; - wasm.memory.imported = true; } else if ((*s[3])[0]->str() == TABLE) { - im->kind = ExternalKind::Table; + kind = ExternalKind::Table; if (wasm.table.exists) throw ParseException("more than one table"); wasm.table.exists = true; - wasm.table.imported = true; } else if ((*s[3])[0]->str() == GLOBAL) { - im->kind = ExternalKind::Global; + kind = ExternalKind::Global; } else { newStyle = false; // either (param..) or (result..) } } Index newStyleInner = 1; + Name name; if (s.size() > 3 && s[3]->isStr()) { - im->name = s[i++]->str(); + name = s[i++]->str(); } else if (newStyle && newStyleInner < s[3]->size() && (*s[3])[newStyleInner]->dollared()) { - im->name = (*s[3])[newStyleInner++]->str(); - } - if (!im->name.is()) { - if (im->kind == ExternalKind::Function) { - im->name = Name("import$function$" + std::to_string(functionCounter++)); - functionNames.push_back(im->name); - } else if (im->kind == ExternalKind::Global) { - im->name = Name("import$global" + std::to_string(globalCounter++)); - globalNames.push_back(im->name); - } else if (im->kind == ExternalKind::Memory) { - im->name = Name("import$memory$" + std::to_string(0)); - } else if (im->kind == ExternalKind::Table) { - im->name = Name("import$table$" + std::to_string(0)); + name = (*s[3])[newStyleInner++]->str(); + } + if (!name.is()) { + if (kind == ExternalKind::Function) { + name = Name("import$function$" + std::to_string(functionCounter++)); + functionNames.push_back(name); + } else if (kind == ExternalKind::Global) { + name = Name("import$global" + std::to_string(globalCounter++)); + globalNames.push_back(name); + } else if (kind == ExternalKind::Memory) { + name = Name("import$memory$" + std::to_string(0)); + } else if (kind == ExternalKind::Table) { + name = Name("import$table$" + std::to_string(0)); } else { throw ParseException("invalid import"); } } if (!s[i]->quoted()) { if (s[i]->str() == MEMORY) { - im->kind = ExternalKind::Memory; + kind = ExternalKind::Memory; } else if (s[i]->str() == TABLE) { - im->kind = ExternalKind::Table; + kind = ExternalKind::Table; } else if (s[i]->str() == GLOBAL) { - im->kind = ExternalKind::Global; + kind = ExternalKind::Global; } else { throw ParseException("invalid ext import"); } i++; } else if (!newStyle) { - im->kind = ExternalKind::Function; + kind = ExternalKind::Function; } - im->module = s[i++]->str(); + auto module = s[i++]->str(); if (!s[i]->isStr()) throw ParseException("no name for import"); - im->base = s[i++]->str(); + auto base = s[i++]->str(); // parse internals Element& inner = newStyle ? *s[3] : s; Index j = newStyle ? newStyleInner : i; - if (im->kind == ExternalKind::Function) { + if (kind == ExternalKind::Function) { std::unique_ptr<FunctionType> type = make_unique<FunctionType>(); if (inner.size() > j) { Element& params = *inner[j]; @@ -1762,17 +1730,34 @@ void SExpressionWasmBuilder::parseImport(Element& s) { type->result = stringToType(result[1]->str()); } } - im->functionType = ensureFunctionType(getSig(type.get()), &wasm)->name; - } else if (im->kind == ExternalKind::Global) { + auto func = make_unique<Function>(); + func->name = name; + func->module = module; + func->base = base; + auto* functionType = ensureFunctionType(getSig(type.get()), &wasm); + func->type = functionType->name; + FunctionTypeUtils::fillFunction(func.get(), functionType); + functionTypes[name] = func->result; + wasm.addFunction(func.release()); + } else if (kind == ExternalKind::Global) { + Type type; if (inner[j]->isStr()) { - im->globalType = stringToType(inner[j]->str()); + type = stringToType(inner[j]->str()); } else { auto& inner2 = *inner[j]; if (inner2[0]->str() != MUT) throw ParseException("expected mut"); - im->globalType = stringToType(inner2[1]->str()); + type = stringToType(inner2[1]->str()); throw ParseException("cannot import a mutable global", s.line, s.col); } - } else if (im->kind == ExternalKind::Table) { + auto global = make_unique<Global>(); + global->name = name; + global->module = module; + global->base = base; + global->type = type; + wasm.addGlobal(global.release()); + } else if (kind == ExternalKind::Table) { + wasm.table.module = module; + wasm.table.base = base; if (j < inner.size() - 1) { wasm.table.initial = getCheckedAddress(inner[j++], "excessive table init size"); } @@ -1782,7 +1767,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) { wasm.table.max = Table::kMaxSize; } // ends with the table element type - } else if (im->kind == ExternalKind::Memory) { + } else if (kind == ExternalKind::Memory) { + wasm.memory.module = module; + wasm.memory.base = base; if (inner[j]->isList()) { auto& limits = *inner[j]; if (!(limits[0]->isStr() && limits[0]->str() == "shared")) throw ParseException("bad memory limit declaration"); @@ -1792,8 +1779,6 @@ void SExpressionWasmBuilder::parseImport(Element& s) { parseMemoryLimits(inner, j); } } - if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); - wasm.addImport(im.release()); } void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { @@ -1841,14 +1826,13 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { // this is an import, actually if (!preParseImport) throw ParseException("!preParseImport in global"); if (mutable_) throw ParseException("cannot import a mutable global", s.line, s.col); - std::unique_ptr<Import> im = make_unique<Import>(); + auto im = make_unique<Global>(); im->name = global->name; im->module = importModule; im->base = importBase; - im->kind = ExternalKind::Global; - im->globalType = type; - if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); - wasm.addImport(im.release()); + im->type = type; + if (wasm.getGlobalOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); + wasm.addGlobal(im.release()); return; } if (preParseImport) throw ParseException("preParseImport in global"); @@ -1868,7 +1852,6 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) { void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { if (wasm.table.exists) throw ParseException("more than one table"); wasm.table.exists = true; - wasm.table.imported = preParseImport; Index i = 1; if (i == s.size()) return; // empty table in old notation if (s[i]->dollared()) { @@ -1887,16 +1870,9 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { wasm.addExport(ex.release()); i++; } else if (inner[0]->str() == IMPORT) { - importModule = inner[1]->str(); - importBase = inner[2]->str(); if (!preParseImport) throw ParseException("!preParseImport in table"); - auto im = make_unique<Import>(); - im->kind = ExternalKind::Table; - im->module = importModule; - im->base = importBase; - im->name = importModule; - if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col); - wasm.addImport(im.release()); + wasm.table.module = inner[1]->str(); + wasm.table.base = inner[2]->str(); i++; } else { throw ParseException("invalid table"); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index d57607ce6..36069f8db 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -24,6 +24,7 @@ #include "wasm-validator.h" #include "ir/utils.h" #include "ir/branch-utils.h" +#include "ir/module-utils.h" #include "support/colors.h" @@ -233,7 +234,6 @@ public: void visitBreak(Break* curr); void visitSwitch(Switch* curr); void visitCall(Call* curr); - void visitCallImport(CallImport* curr); void visitCallIndirect(CallIndirect* curr); void visitGetLocal(GetLocal* curr); void visitSetLocal(SetLocal* curr); @@ -444,12 +444,7 @@ void FunctionValidator::visitSwitch(Switch* curr) { void FunctionValidator::visitCall(Call* curr) { if (!info.validateGlobally) return; auto* target = getModule()->getFunctionOrNull(curr->target); - if (!shouldBeTrue(!!target, curr, "call target must exist")) { - if (getModule()->getImportOrNull(curr->target) && !info.quiet) { - getStream() << "(perhaps it should be a CallImport instead of Call?)\n"; - } - return; - } + if (!shouldBeTrue(!!target, curr, "call target must exist")) return; if (!shouldBeTrue(curr->operands.size() == target->params.size(), curr, "call param number must match")) return; for (size_t i = 0; i < curr->operands.size(); i++) { if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type, target->params[i], curr, "call param types must match") && !info.quiet) { @@ -458,20 +453,6 @@ void FunctionValidator::visitCall(Call* curr) { } } -void FunctionValidator::visitCallImport(CallImport* curr) { - if (!info.validateGlobally) return; - auto* import = getModule()->getImportOrNull(curr->target); - if (!shouldBeTrue(!!import, curr, "call_import target must exist")) return; - if (!shouldBeTrue(!!import->functionType.is(), curr, "called import must be function")) return; - auto* type = getModule()->getFunctionType(import->functionType); - if (!shouldBeTrue(curr->operands.size() == type->params.size(), curr, "call param number must match")) return; - for (size_t i = 0; i < curr->operands.size(); i++) { - if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type, type->params[i], curr, "call param types must match") && !info.quiet) { - getStream() << "(on argument " << i << ")\n"; - } - } -} - void FunctionValidator::visitCallIndirect(CallIndirect* curr) { if (!info.validateGlobally) return; auto* type = getModule()->getFunctionTypeOrNull(curr->fullType); @@ -503,13 +484,13 @@ void FunctionValidator::visitSetLocal(SetLocal* curr) { void FunctionValidator::visitGetGlobal(GetGlobal* curr) { if (!info.validateGlobally) return; - shouldBeTrue(getModule()->getGlobalOrNull(curr->name) || getModule()->getImportOrNull(curr->name), curr, "get_global name must be valid"); + shouldBeTrue(getModule()->getGlobalOrNull(curr->name), curr, "get_global name must be valid"); } void FunctionValidator::visitSetGlobal(SetGlobal* curr) { if (!info.validateGlobally) return; auto* global = getModule()->getGlobalOrNull(curr->name); - if (shouldBeTrue(global != NULL, curr, "set_global name must be valid (and not an import; imports can't be modified)")) { + if (shouldBeTrue(global, curr, "set_global name must be valid (and not an import; imports can't be modified)")) { shouldBeTrue(global->mutable_, curr, "set_global global must be mutable"); shouldBeEqualOrFirstIsUnreachable(curr->value->type, global->type, curr, "set_global value must have right type"); } @@ -926,23 +907,15 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) { // Main validator class static void validateImports(Module& module, ValidationInfo& info) { - for (auto& curr : module.imports) { - if (curr->kind == ExternalKind::Function) { - if (info.validateWeb) { - auto* functionType = module.getFunctionType(curr->functionType); - info.shouldBeUnequal(functionType->result, i64, curr->name, "Imported function must not have i64 return type"); - for (Type param : functionType->params) { - info.shouldBeUnequal(param, i64, curr->name, "Imported function must not have i64 parameters"); - } + ModuleUtils::iterImportedFunctions(module, [&](Function* curr) { + if (info.validateWeb) { + auto* functionType = module.getFunctionType(curr->type); + info.shouldBeUnequal(functionType->result, i64, curr->name, "Imported function must not have i64 return type"); + for (Type param : functionType->params) { + info.shouldBeUnequal(param, i64, curr->name, "Imported function must not have i64 parameters"); } } - if (curr->kind == ExternalKind::Table) { - info.shouldBeTrue(module.table.imported, curr->name, "Table import record exists but table is not marked as imported"); - } - if (curr->kind == ExternalKind::Memory) { - info.shouldBeTrue(module.memory.imported, curr->name, "Memory import record exists but memory is not marked as imported"); - } - } + }); } static void validateExports(Module& module, ValidationInfo& info) { @@ -961,13 +934,9 @@ static void validateExports(Module& module, ValidationInfo& info) { for (auto& exp : module.exports) { Name name = exp->value; if (exp->kind == ExternalKind::Function) { - Import* imp; - info.shouldBeTrue(module.getFunctionOrNull(name) || - ((imp = module.getImportOrNull(name)) && imp->kind == ExternalKind::Function), name, "module function exports must be found"); + info.shouldBeTrue(module.getFunctionOrNull(name), name, "module function exports must be found"); } else if (exp->kind == ExternalKind::Global) { - Import* imp; - info.shouldBeTrue(module.getGlobalOrNull(name) || - ((imp = module.getImportOrNull(name)) && imp->kind == ExternalKind::Global), name, "module global exports must be found"); + info.shouldBeTrue(module.getGlobalOrNull(name), name, "module global exports must be found"); } else if (exp->kind == ExternalKind::Table) { info.shouldBeTrue(name == Name("0") || name == module.table.name, name, "module table exports must be found"); } else if (exp->kind == ExternalKind::Memory) { @@ -982,13 +951,13 @@ static void validateExports(Module& module, ValidationInfo& info) { } static void validateGlobals(Module& module, ValidationInfo& info) { - for (auto& curr : module.globals) { + ModuleUtils::iterDefinedGlobals(module, [&](Global* curr) { info.shouldBeTrue(curr->init != nullptr, curr->name, "global init must be non-null"); info.shouldBeTrue(curr->init->is<Const>() || curr->init->is<GetGlobal>(), curr->name, "global init must be valid"); if (!info.shouldBeEqual(curr->type, curr->init->type, curr->init, "global init must have correct type") && !info.quiet) { info.getStream(nullptr) << "(on global " << curr->name << ")\n"; } - } + }); } static void validateMemory(Module& module, ValidationInfo& info) { @@ -1016,7 +985,7 @@ static void validateTable(Module& module, ValidationInfo& info) { info.shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32"); info.shouldBeTrue(checkOffset(segment.offset, segment.data.size(), module.table.initial * Table::kPageSize), segment.offset, "segment offset should be reasonable"); for (auto name : segment.data) { - info.shouldBeTrue(module.getFunctionOrNull(name) || module.getImportOrNull(name), name, "segment name should be valid"); + info.shouldBeTrue(module.getFunctionOrNull(name), name, "segment name should be valid"); } } } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index ac3623cee..ad4d6343a 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -53,7 +53,6 @@ Name GROW_WASM_MEMORY("__growWasmMemory"), LOCAL("local"), TYPE("type"), CALL("call"), - CALL_IMPORT("call_import"), CALL_INDIRECT("call_indirect"), BLOCK("block"), BR_IF("br_if"), @@ -83,7 +82,6 @@ const char* getExpressionName(Expression* curr) { case Expression::Id::BreakId: return "break"; case Expression::Id::SwitchId: return "switch"; case Expression::Id::CallId: return "call"; - case Expression::Id::CallImportId: return "call_import"; case Expression::Id::CallIndirectId: return "call_indirect"; case Expression::Id::GetLocalId: return "get_local"; case Expression::Id::SetLocalId: return "set_local"; @@ -324,10 +322,6 @@ void Call::finalize() { handleUnreachableOperands(this); } -void CallImport::finalize() { - handleUnreachableOperands(this); -} - void CallIndirect::finalize() { handleUnreachableOperands(this); if (target->type == unreachable) { @@ -650,14 +644,6 @@ FunctionType* Module::getFunctionType(Name name) { return iter->second; } -Import* Module::getImport(Name name) { - auto iter = importsMap.find(name); - if (iter == importsMap.end()) { - Fatal() << "Module::getImport: " << name << " does not exist"; - } - return iter->second; -} - Export* Module::getExport(Name name) { auto iter = exportsMap.find(name); if (iter == exportsMap.end()) { @@ -690,14 +676,6 @@ FunctionType* Module::getFunctionTypeOrNull(Name name) { return iter->second; } -Import* Module::getImportOrNull(Name name) { - auto iter = importsMap.find(name); - if (iter == importsMap.end()) { - return nullptr; - } - return iter->second; -} - Export* Module::getExportOrNull(Name name) { auto iter = exportsMap.find(name); if (iter == exportsMap.end()) { @@ -733,17 +711,6 @@ void Module::addFunctionType(FunctionType* curr) { functionTypesMap[curr->name] = curr; } -void Module::addImport(Import* curr) { - if (!curr->name.is()) { - Fatal() << "Module::addImport: empty name"; - } - if (getImportOrNull(curr->name)) { - Fatal() << "Module::addImport: " << curr->name << " already exists"; - } - imports.push_back(std::unique_ptr<Import>(curr)); - importsMap[curr->name] = curr; -} - void Module::addExport(Export* curr) { if (!curr->name.is()) { Fatal() << "Module::addExport: empty name"; @@ -781,14 +748,14 @@ void Module::addStart(const Name& s) { start = s; } -void Module::removeImport(Name name) { - for (size_t i = 0; i < imports.size(); i++) { - if (imports[i]->name == name) { - imports.erase(imports.begin() + i); +void Module::removeFunctionType(Name name) { + for (size_t i = 0; i < functionTypes.size(); i++) { + if (functionTypes[i]->name == name) { + functionTypes.erase(functionTypes.begin() + i); break; } } - importsMap.erase(name); + functionTypesMap.erase(name); } void Module::removeExport(Name name) { @@ -811,14 +778,14 @@ void Module::removeFunction(Name name) { functionsMap.erase(name); } -void Module::removeFunctionType(Name name) { - for (size_t i = 0; i < functionTypes.size(); i++) { - if (functionTypes[i]->name == name) { - functionTypes.erase(functionTypes.begin() + i); +void Module::removeGlobal(Name name) { + for (size_t i = 0; i < globals.size(); i++) { + if (globals[i]->name == name) { + globals.erase(globals.begin() + i); break; } } - functionTypesMap.erase(name); + globalsMap.erase(name); } // TODO: remove* for other elements @@ -832,10 +799,6 @@ void Module::updateMaps() { for (auto& curr : functionTypes) { functionTypesMap[curr->name] = curr.get(); } - importsMap.clear(); - for (auto& curr : imports) { - importsMap[curr->name] = curr.get(); - } exportsMap.clear(); for (auto& curr : exports) { exportsMap[curr->name] = curr.get(); |