diff options
Diffstat (limited to 'src/parser/context-decls.cpp')
-rw-r--r-- | src/parser/context-decls.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/parser/context-decls.cpp b/src/parser/context-decls.cpp new file mode 100644 index 000000000..f668c67ae --- /dev/null +++ b/src/parser/context-decls.cpp @@ -0,0 +1,194 @@ +/* + * Copyright 2023 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "contexts.h" + +namespace wasm::WATParser { + +namespace { + +void applyImportNames(Importable& item, ImportNames* names) { + if (names) { + item.module = names->mod; + item.base = names->nm; + } +} + +Result<> addExports(ParseInput& in, + Module& wasm, + const Named* item, + const std::vector<Name>& exports, + ExternalKind kind) { + for (auto name : exports) { + if (wasm.getExportOrNull(name)) { + // TODO: Fix error location + return in.err("repeated export name"); + } + wasm.addExport(Builder(wasm).makeExport(name, item->name, kind)); + } + return Ok{}; +} + +} // anonymous namespace + +Result<Function*> +ParseDeclsCtx::addFuncDecl(Index pos, Name name, ImportNames* importNames) { + auto f = std::make_unique<Function>(); + if (name.is()) { + if (wasm.getFunctionOrNull(name)) { + // TDOO: if the existing function is not explicitly named, fix its name + // and continue. + return in.err(pos, "repeated function name"); + } + f->setExplicitName(name); + } else { + name = (importNames ? "fimport$" : "") + std::to_string(funcCounter++); + name = Names::getValidFunctionName(wasm, name); + f->name = name; + } + applyImportNames(*f, importNames); + return wasm.addFunction(std::move(f)); +} + +Result<> ParseDeclsCtx::addFunc(Name name, + const std::vector<Name>& exports, + ImportNames* import, + TypeUseT type, + std::optional<LocalsT>, + std::optional<InstrsT>, + Index pos) { + if (import && hasNonImport) { + return in.err(pos, "import after non-import"); + } + auto f = addFuncDecl(pos, name, import); + CHECK_ERR(f); + CHECK_ERR(addExports(in, wasm, *f, exports, ExternalKind::Function)); + funcDefs.push_back({name, pos, Index(funcDefs.size())}); + return Ok{}; +} + +Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos, + Name name, + ImportNames* importNames, + MemType type) { + auto m = std::make_unique<Memory>(); + m->indexType = type.type; + m->initial = type.limits.initial; + m->max = type.limits.max; + m->shared = type.shared; + if (name) { + // TODO: if the existing memory is not explicitly named, fix its name + // and continue. + if (wasm.getMemoryOrNull(name)) { + return in.err(pos, "repeated memory name"); + } + m->setExplicitName(name); + } else { + name = (importNames ? "mimport$" : "") + std::to_string(memoryCounter++); + name = Names::getValidMemoryName(wasm, name); + m->name = name; + } + applyImportNames(*m, importNames); + return wasm.addMemory(std::move(m)); +} + +Result<> ParseDeclsCtx::addMemory(Name name, + const std::vector<Name>& exports, + ImportNames* import, + MemType type, + Index pos) { + if (import && hasNonImport) { + return in.err(pos, "import after non-import"); + } + auto m = addMemoryDecl(pos, name, import, type); + CHECK_ERR(m); + CHECK_ERR(addExports(in, wasm, *m, exports, ExternalKind::Memory)); + memoryDefs.push_back({name, pos, Index(memoryDefs.size())}); + return Ok{}; +} + +Result<> ParseDeclsCtx::addImplicitData(DataStringT&& data) { + auto& mem = *wasm.memories.back(); + auto d = std::make_unique<DataSegment>(); + d->memory = mem.name; + d->isPassive = false; + d->offset = Builder(wasm).makeConstPtr(0, mem.indexType); + d->data = std::move(data); + d->name = Names::getValidDataSegmentName(wasm, "implicit-data"); + wasm.addDataSegment(std::move(d)); + return Ok{}; +} + +Result<Global*> +ParseDeclsCtx::addGlobalDecl(Index pos, Name name, ImportNames* importNames) { + auto g = std::make_unique<Global>(); + if (name) { + if (wasm.getGlobalOrNull(name)) { + // TODO: if the existing global is not explicitly named, fix its name + // and continue. + return in.err(pos, "repeated global name"); + } + g->setExplicitName(name); + } else { + name = (importNames ? "gimport$" : "") + std::to_string(globalCounter++); + name = Names::getValidGlobalName(wasm, name); + g->name = name; + } + applyImportNames(*g, importNames); + return wasm.addGlobal(std::move(g)); +} + +Result<> ParseDeclsCtx::addGlobal(Name name, + const std::vector<Name>& exports, + ImportNames* import, + GlobalTypeT, + std::optional<ExprT>, + Index pos) { + if (import && hasNonImport) { + return in.err(pos, "import after non-import"); + } + auto g = addGlobalDecl(pos, name, import); + CHECK_ERR(g); + CHECK_ERR(addExports(in, wasm, *g, exports, ExternalKind::Global)); + globalDefs.push_back({name, pos, Index(globalDefs.size())}); + return Ok{}; +} + +Result<> ParseDeclsCtx::addData(Name name, + MemoryIdxT*, + std::optional<ExprT>, + std::vector<char>&& data, + Index pos) { + auto d = std::make_unique<DataSegment>(); + if (name) { + if (wasm.getDataSegmentOrNull(name)) { + // TODO: if the existing segment is not explicitly named, fix its name + // and continue. + return in.err(pos, "repeated data segment name"); + } + d->setExplicitName(name); + } else { + name = std::to_string(dataCounter++); + name = Names::getValidDataSegmentName(wasm, name); + d->name = name; + } + d->data = std::move(data); + dataDefs.push_back({name, pos, Index(wasm.dataSegments.size())}); + wasm.addDataSegment(std::move(d)); + return Ok{}; +} + +} // namespace wasm::WATParser |