blob: 17b38948857eb0633d51fb85e53546a879b0d9db [file] [log] [blame] [edit]
/*
* 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>,
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