summaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/contexts.h5
-rw-r--r--src/parser/lexer.cpp4
-rw-r--r--src/parser/parsers.h22
-rw-r--r--src/parser/wast-parser.cpp32
-rw-r--r--src/parser/wat-parser.cpp8
-rw-r--r--src/parser/wat-parser.h24
6 files changed, 52 insertions, 43 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index 5ad0c16de..bce051a93 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -1665,7 +1665,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return Ok{};
}
- Result<> addExport(Index, Name value, Name name, ExternalKind kind) {
+ Result<> addExport(Index pos, Name value, Name name, ExternalKind kind) {
+ if (wasm.getExportOrNull(name)) {
+ return in.err(pos, "duplicate export");
+ }
wasm.addExport(builder.makeExport(name, value, kind));
return Ok{};
}
diff --git a/src/parser/lexer.cpp b/src/parser/lexer.cpp
index fd0a262b8..bb6428e87 100644
--- a/src/parser/lexer.cpp
+++ b/src/parser/lexer.cpp
@@ -23,6 +23,7 @@
#include <variant>
#include "lexer.h"
+#include "support/bits.h"
#include "support/string.h"
using namespace std::string_view_literals;
@@ -1005,6 +1006,9 @@ std::optional<uint32_t> Lexer::takeAlign() {
}
Lexer subLexer(result->span.substr(6));
if (auto o = subLexer.takeU32()) {
+ if (Bits::popCount(*o) != 1) {
+ return std::nullopt;
+ }
pos += result->span.size();
advance();
return o;
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 88600fec3..5900deb27 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -30,7 +30,8 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::RefTypeT> reftype(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx&);
template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx&);
-template<typename Ctx> MaybeResult<typename Ctx::ParamsT> params(Ctx&);
+template<typename Ctx>
+MaybeResult<typename Ctx::ParamsT> params(Ctx&, bool allowNames = true);
template<typename Ctx> MaybeResult<typename Ctx::ResultsT> results(Ctx&);
template<typename Ctx> MaybeResult<typename Ctx::SignatureT> functype(Ctx&);
template<typename Ctx> Result<typename Ctx::FieldT> storagetype(Ctx&);
@@ -325,7 +326,8 @@ MaybeResult<typename Ctx::LabelIdxT> maybeLabelidx(Ctx&,
template<typename Ctx>
Result<typename Ctx::LabelIdxT> labelidx(Ctx&, bool inDelegate = false);
template<typename Ctx> Result<typename Ctx::TagIdxT> tagidx(Ctx&);
-template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx&);
+template<typename Ctx>
+Result<typename Ctx::TypeUseT> typeuse(Ctx&, bool allowNames = true);
MaybeResult<ImportNames> inlineImport(Lexer&);
Result<std::vector<Name>> inlineExports(Lexer&);
template<typename Ctx> Result<> strtype(Ctx&);
@@ -561,13 +563,18 @@ template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) {
// param ::= '(' 'param id? t:valtype ')' => [t]
// | '(' 'param t*:valtype* ')' => [t*]
// params ::= param*
-template<typename Ctx> MaybeResult<typename Ctx::ParamsT> params(Ctx& ctx) {
+template<typename Ctx>
+MaybeResult<typename Ctx::ParamsT> params(Ctx& ctx, bool allowNames) {
bool hasAny = false;
auto res = ctx.makeParams();
while (ctx.in.takeSExprStart("param"sv)) {
hasAny = true;
+ auto pos = ctx.in.getPos();
if (auto id = ctx.in.takeID()) {
// Single named param
+ if (!allowNames) {
+ return ctx.in.err(pos, "unexpected named parameter");
+ }
auto type = valtype(ctx);
CHECK_ERR(type);
if (!ctx.in.takeRParen()) {
@@ -1065,7 +1072,7 @@ template<typename Ctx> Result<typename Ctx::BlockTypeT> blocktype(Ctx& ctx) {
// We either had no results or multiple results. Reset and parse again as a
// type use.
ctx.in = initialLexer;
- auto use = typeuse(ctx);
+ auto use = typeuse(ctx, false);
CHECK_ERR(use);
auto type = ctx.getBlockTypeFromTypeUse(pos, *use);
@@ -1935,7 +1942,7 @@ Result<> makeCallIndirect(Ctx& ctx,
bool isReturn) {
auto table = maybeTableidx(ctx);
CHECK_ERR(table);
- auto type = typeuse(ctx);
+ auto type = typeuse(ctx, false);
CHECK_ERR(type);
return ctx.makeCallIndirect(
pos, annotations, table.getPtr(), *type, isReturn);
@@ -2669,7 +2676,8 @@ template<typename Ctx> Result<typename Ctx::TagIdxT> tagidx(Ctx& ctx) {
// (if typedefs[x] = [t1*] -> [t2*])
// | ((t1,IDs):param)* (t2:result)* => x, IDs
// (if x is minimum s.t. typedefs[x] = [t1*] -> [t2*])
-template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx& ctx) {
+template<typename Ctx>
+Result<typename Ctx::TypeUseT> typeuse(Ctx& ctx, bool allowNames) {
auto pos = ctx.in.getPos();
std::optional<typename Ctx::HeapTypeT> type;
if (ctx.in.takeSExprStart("type"sv)) {
@@ -2683,7 +2691,7 @@ template<typename Ctx> Result<typename Ctx::TypeUseT> typeuse(Ctx& ctx) {
type = *x;
}
- auto namedParams = params(ctx);
+ auto namedParams = params(ctx, allowNames);
CHECK_ERR(namedParams);
auto resultTypes = results(ctx);
diff --git a/src/parser/wast-parser.cpp b/src/parser/wast-parser.cpp
index fb0dce932..87060b9fc 100644
--- a/src/parser/wast-parser.cpp
+++ b/src/parser/wast-parser.cpp
@@ -41,8 +41,7 @@ Result<Literals> consts(Lexer& in) {
MaybeResult<Action> action(Lexer& in) {
if (in.takeSExprStart("invoke"sv)) {
- // TODO: Do we need to use this optional id?
- in.takeID();
+ auto id = in.takeID();
auto name = in.takeName();
if (!name) {
return in.err("expected export name");
@@ -52,12 +51,11 @@ MaybeResult<Action> action(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of invoke action");
}
- return InvokeAction{*name, *args};
+ return InvokeAction{id, *name, *args};
}
if (in.takeSExprStart("get"sv)) {
- // TODO: Do we need to use this optional id?
- in.takeID();
+ auto id = in.takeID();
auto name = in.takeName();
if (!name) {
return in.err("expected export name");
@@ -65,7 +63,7 @@ MaybeResult<Action> action(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of get action");
}
- return GetAction{*name};
+ return GetAction{id, *name};
}
return {};
@@ -236,7 +234,7 @@ MaybeResult<AssertReturn> assertReturn(Lexer& in) {
}
// (assert_exception action)
-MaybeResult<AssertException> assertException(Lexer& in) {
+MaybeResult<AssertAction> assertException(Lexer& in) {
if (!in.takeSExprStart("assert_exception"sv)) {
return {};
}
@@ -245,7 +243,7 @@ MaybeResult<AssertException> assertException(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of assert_exception");
}
- return AssertException{*a};
+ return AssertAction{ActionAssertionType::Exception, *a};
}
// (assert_exhaustion action msg)
@@ -266,7 +264,7 @@ MaybeResult<AssertAction> assertAction(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of assertion");
}
- return AssertAction{type, *a, *msg};
+ return AssertAction{type, *a};
}
// (assert_malformed module msg)
@@ -293,7 +291,7 @@ MaybeResult<AssertModule> assertModule(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of assertion");
}
- return AssertModule{type, *mod, *msg};
+ return AssertModule{type, *mod};
}
// (assert_trap action msg)
@@ -312,7 +310,7 @@ MaybeResult<Assertion> assertTrap(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of assertion");
}
- return Assertion{AssertAction{ActionAssertionType::Trap, *a, *msg}};
+ return Assertion{AssertAction{ActionAssertionType::Trap, *a}};
}
auto mod = wastModule(in);
if (mod.getErr()) {
@@ -325,7 +323,7 @@ MaybeResult<Assertion> assertTrap(Lexer& in) {
if (!in.takeRParen()) {
return in.err("expected end of assertion");
}
- return Assertion{AssertModule{ModuleAssertionType::Trap, *mod, *msg}};
+ return Assertion{AssertModule{ModuleAssertionType::Trap, *mod}};
}
MaybeResult<Assertion> assertion(Lexer& in) {
@@ -391,24 +389,30 @@ Result<WASTCommand> command(Lexer& in) {
return *mod;
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
Result<WASTScript> wast(Lexer& in) {
WASTScript cmds;
while (!in.empty()) {
+ size_t line = in.position().line;
auto cmd = command(in);
if (cmd.getErr() && cmds.empty()) {
// The entire script might be a single module comprising a sequence of
// module fields with a top-level `(module ...)`.
auto wasm = std::make_shared<Module>();
CHECK_ERR(parseModule(*wasm, in.buffer));
- cmds.emplace_back(std::move(wasm));
+ cmds.push_back({WASTModule{std::move(wasm)}, line});
return cmds;
}
CHECK_ERR(cmd);
- cmds.emplace_back(std::move(*cmd));
+ cmds.push_back(ScriptEntry{std::move(*cmd), line});
}
return cmds;
}
+#pragma GCC diagnostic pop
+
} // anonymous namespace
Result<WASTScript> parseScript(std::string_view in) {
diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp
index 85ef1e80f..4763c69ec 100644
--- a/src/parser/wat-parser.cpp
+++ b/src/parser/wat-parser.cpp
@@ -237,14 +237,6 @@ Result<> parseModule(Module& wasm, Lexer& lexer) {
return doParseModule(wasm, lexer, true);
}
-Result<Expression*> parseExpression(Module& wasm, Lexer& lexer) {
- ParseDefsCtx ctx(lexer, wasm, {}, {}, {}, {}, {});
- auto e = expr(ctx);
- CHECK_ERR(e);
- lexer = ctx.in;
- return *e;
-}
-
Result<Literal> parseConst(Lexer& lexer) {
Module wasm;
ParseDefsCtx ctx(lexer, wasm, {}, {}, {}, {}, {});
diff --git a/src/parser/wat-parser.h b/src/parser/wat-parser.h
index 7fe6abfdd..041ba1d58 100644
--- a/src/parser/wat-parser.h
+++ b/src/parser/wat-parser.h
@@ -34,14 +34,14 @@ Result<> parseModule(Module& wasm, Lexer& lexer);
Result<Literal> parseConst(Lexer& lexer);
-Result<Expression*> parseExpression(Module& wasm, Lexer& lexer);
-
struct InvokeAction {
+ std::optional<Name> base;
Name name;
Literals args;
};
struct GetAction {
+ std::optional<Name> base;
Name name;
};
@@ -68,19 +68,14 @@ using ExpectedResults = std::vector<ExpectedResult>;
struct AssertReturn {
Action action;
- ExpectedResults results;
-};
-
-struct AssertException {
- Action action;
+ ExpectedResults expected;
};
-enum class ActionAssertionType { Trap, Exhaustion };
+enum class ActionAssertionType { Trap, Exhaustion, Exception };
struct AssertAction {
ActionAssertionType type;
Action action;
- std::string msg;
};
enum class QuotedModuleType { Text, Binary };
@@ -97,11 +92,9 @@ enum class ModuleAssertionType { Trap, Malformed, Invalid, Unlinkable };
struct AssertModule {
ModuleAssertionType type;
WASTModule wasm;
- std::string msg;
};
-using Assertion =
- std::variant<AssertReturn, AssertException, AssertAction, AssertModule>;
+using Assertion = std::variant<AssertReturn, AssertAction, AssertModule>;
struct Register {
Name name;
@@ -109,7 +102,12 @@ struct Register {
using WASTCommand = std::variant<WASTModule, Register, Action, Assertion>;
-using WASTScript = std::vector<WASTCommand>;
+struct ScriptEntry {
+ WASTCommand cmd;
+ size_t line;
+};
+
+using WASTScript = std::vector<ScriptEntry>;
Result<WASTScript> parseScript(std::string_view in);