blob: c124689d3341dc807af1bb609b0cc0aa7807b711 [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(Lexer& 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::vector<Annotation>&& annotations,
Index pos) {
CHECK_ERR(checkImport(pos, 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()), std::move(annotations)});
return Ok{};
}
Result<Table*> ParseDeclsCtx::addTableDecl(Index pos,
Name name,
ImportNames* importNames,
TableType type) {
auto t = std::make_unique<Table>();
t->addressType = type.addressType;
t->initial = type.limits.initial;
t->max = type.limits.max ? *type.limits.max : Table::kUnlimitedSize;
if (name.is()) {
if (wasm.getTableOrNull(name)) {
// TODO: if the existing table is not explicitly named, fix its name and
// continue.
return in.err(pos, "repeated table name");
}
t->setExplicitName(name);
} else {
name = (importNames ? "timport$" : "") + std::to_string(tableCounter++);
name = Names::getValidTableName(wasm, name);
t->name = name;
}
applyImportNames(*t, importNames);
return wasm.addTable(std::move(t));
}
Result<> ParseDeclsCtx::addTable(Name name,
const std::vector<Name>& exports,
ImportNames* import,
TableType type,
Index pos) {
CHECK_ERR(checkImport(pos, import));
auto t = addTableDecl(pos, name, import, type);
CHECK_ERR(t);
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Table));
// TODO: table annotations
tableDefs.push_back({name, pos, Index(tableDefs.size()), {}});
return Ok{};
}
Result<> ParseDeclsCtx::addImplicitElems(TypeT, ElemListT&& elems) {
auto& table = *wasm.tables.back();
auto e = std::make_unique<ElementSegment>();
e->table = table.name;
e->offset = Builder(wasm).makeConstPtr(0, Type::i32);
e->name = Names::getValidElementSegmentName(wasm, "implicit-elem");
wasm.addElementSegment(std::move(e));
// Record the index mapping so we can find this segment again to set its type
// and elements in later phases.
Index tableIndex = wasm.tables.size() - 1;
Index elemIndex = wasm.elementSegments.size() - 1;
implicitElemIndices[tableIndex] = elemIndex;
return Ok{};
}
Result<Memory*> ParseDeclsCtx::addMemoryDecl(Index pos,
Name name,
ImportNames* importNames,
MemType type) {
auto m = std::make_unique<Memory>();
m->addressType = type.addressType;
m->initial = type.limits.initial;
m->max = type.limits.max ? *type.limits.max : Memory::kUnlimitedSize;
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) {
CHECK_ERR(checkImport(pos, import));
auto m = addMemoryDecl(pos, name, import, type);
CHECK_ERR(m);
CHECK_ERR(addExports(in, wasm, *m, exports, ExternalKind::Memory));
// TODO: memory annotations
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.addressType);
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$" : "global$") + 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) {
CHECK_ERR(checkImport(pos, import));
auto g = addGlobalDecl(pos, name, import);
CHECK_ERR(g);
CHECK_ERR(addExports(in, wasm, *g, exports, ExternalKind::Global));
// TODO: global annotations
globalDefs.push_back({name, pos, Index(globalDefs.size()), {}});
return Ok{};
}
Result<> ParseDeclsCtx::addElem(
Name name, TableIdxT*, std::optional<ExprT>, ElemListT&&, Index pos) {
auto e = std::make_unique<ElementSegment>();
if (name) {
if (wasm.getElementSegmentOrNull(name)) {
// TDOO: if the existing segment is not explicitly named, fix its name and
// continue.
return in.err(pos, "repeated element segment name");
}
e->setExplicitName(name);
} else {
name = std::to_string(elemCounter++);
name = Names::getValidElementSegmentName(wasm, name);
e->name = name;
}
// TODO: element segment annotations
elemDefs.push_back({name, pos, Index(wasm.elementSegments.size()), {}});
wasm.addElementSegment(std::move(e));
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);
// TODO: data segment annotations
dataDefs.push_back({name, pos, Index(wasm.dataSegments.size()), {}});
wasm.addDataSegment(std::move(d));
return Ok{};
}
Result<Tag*>
ParseDeclsCtx::addTagDecl(Index pos, Name name, ImportNames* importNames) {
auto t = std::make_unique<Tag>();
if (name) {
if (wasm.getTagOrNull(name)) {
// TODO: if the existing tag is not explicitly named, fix its name and
// continue.
return in.err(pos, "repeated tag name");
}
t->setExplicitName(name);
} else {
name = (importNames ? "eimport$" : "tag$") + std::to_string(tagCounter++);
name = Names::getValidTagName(wasm, name);
t->name = name;
}
applyImportNames(*t, importNames);
return wasm.addTag(std::move(t));
}
Result<> ParseDeclsCtx::addTag(Name name,
const std::vector<Name>& exports,
ImportNames* import,
TypeUseT type,
Index pos) {
CHECK_ERR(checkImport(pos, import));
auto t = addTagDecl(pos, name, import);
CHECK_ERR(t);
CHECK_ERR(addExports(in, wasm, *t, exports, ExternalKind::Tag));
// TODO: tag annotations
tagDefs.push_back({name, pos, Index(tagDefs.size()), {}});
return Ok{};
}
} // namespace wasm::WATParser