diff --git a/src/parser/contexts.h b/src/parser/contexts.h index c1ccefe53da..507a543424b 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -589,6 +589,7 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx { std::vector tableDefs; std::vector memoryDefs; std::vector globalDefs; + std::vector startDefs; std::vector elemDefs; std::vector dataDefs; std::vector tagDefs; @@ -715,6 +716,14 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx { std::optional, Index pos); + Result<> addStart(FuncIdxT, Index pos) { + if (!startDefs.empty()) { + return Err{"unexpected extra 'start' function"}; + } + startDefs.push_back({{}, pos, 0}); + return Ok{}; + } + Result<> addElem(Name, TableIdxT*, std::optional, ElemListT&&, Index); Result<> addDeclareElem(Name, ElemListT&&, Index) { return Ok{}; } @@ -1325,6 +1334,11 @@ struct ParseDefsCtx : TypeParserCtx { std::optional exp, Index); + Result<> addStart(Name name, Index pos) { + wasm.start = name; + return Ok{}; + } + Result<> addImplicitElems(Type type, std::vector&& elems); Result<> addDeclareElem(Name, std::vector&&, Index) { diff --git a/src/parser/parsers.h b/src/parser/parsers.h index c7b9168b11b..d6264544173 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -202,6 +202,7 @@ template MaybeResult<> table(Ctx&); template MaybeResult<> memory(Ctx&); template MaybeResult<> global(Ctx&); template MaybeResult<> export_(Ctx&); +template MaybeResult<> start(Ctx&); template MaybeResult maybeElemexpr(Ctx&); template Result elemlist(Ctx&, bool); template MaybeResult<> elem(Ctx&); @@ -2648,6 +2649,23 @@ template MaybeResult<> export_(Ctx& ctx) { return Ok{}; } +// start ::= '(' 'start' funcidx ')' +template MaybeResult<> start(Ctx& ctx) { + auto pos = ctx.in.getPos(); + if (!ctx.in.takeSExprStart("start"sv)) { + return {}; + } + auto func = funcidx(ctx); + CHECK_ERR(func); + + CHECK_ERR(ctx.addStart(*func, pos)); + + if (!ctx.in.takeRParen()) { + return ctx.in.err("expected end of start declaration"); + } + return Ok{}; +} + // elemexpr ::= '(' 'item' expr ')' | '(' instr ')' template MaybeResult maybeElemexpr(Ctx& ctx) { @@ -2896,6 +2914,10 @@ template MaybeResult<> modulefield(Ctx& ctx) { CHECK_ERR(res); return Ok{}; } + if (auto res = start(ctx)) { + CHECK_ERR(res); + return Ok{}; + } if (auto res = elem(ctx)) { CHECK_ERR(res); return Ok{}; diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index a9ee2a18923..f247dbf48a4 100644 --- a/src/parser/wat-parser.cpp +++ b/src/parser/wat-parser.cpp @@ -171,6 +171,7 @@ Result<> parseModule(Module& wasm, std::string_view input) { *typeIndices); CHECK_ERR(parseDefs(ctx, decls.tableDefs, table)); CHECK_ERR(parseDefs(ctx, decls.globalDefs, global)); + CHECK_ERR(parseDefs(ctx, decls.startDefs, start)); CHECK_ERR(parseDefs(ctx, decls.elemDefs, elem)); CHECK_ERR(parseDefs(ctx, decls.dataDefs, data)); diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 68046893533..4e4c3639c26 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -432,11 +432,15 @@ (export "exported-global" (global $g1)) (export "exported-tag" (tag 0)) + ;; start function + ;; CHECK: (export "exported-tag" (tag $imported)) + + ;; CHECK: (start $return-none) + (start $return-none) + ;; functions (func) - ;; CHECK: (export "exported-tag" (tag $imported)) - ;; CHECK: (func $2 (type $void) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: )