Skip to content

Commit 1940c68

Browse files
tlivelyradekdoulik
authored andcommitted
[Parser] Parse explicit exports (WebAssembly#6179)
1 parent 009851f commit 1940c68

File tree

4 files changed

+93
-3
lines changed

4 files changed

+93
-3
lines changed

src/parser/contexts.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,9 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
548548
std::vector<DefPos> dataDefs;
549549
std::vector<DefPos> tagDefs;
550550

551+
// Positions of export definitions.
552+
std::vector<Index> exportDefs;
553+
551554
// Positions of typeuses that might implicitly define new types.
552555
std::vector<Index> implicitTypeDefs;
553556

@@ -684,6 +687,11 @@ struct ParseDeclsCtx : NullTypeParserCtx, NullInstrParserCtx {
684687
ImportNames* import,
685688
TypeUseT type,
686689
Index pos);
690+
691+
Result<> addExport(Index pos, Ok, Name, ExternalKind) {
692+
exportDefs.push_back(pos);
693+
return Ok{};
694+
}
687695
};
688696

689697
// Phase 2: Parse type definitions into a TypeBuilder.
@@ -1265,6 +1273,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
12651273
Result<>
12661274
addData(Name, Name* mem, std::optional<ExprT> offset, DataStringT, Index pos);
12671275

1276+
Result<> addExport(Index, Name value, Name name, ExternalKind kind) {
1277+
wasm.addExport(builder.makeExport(name, value, kind));
1278+
return Ok{};
1279+
}
1280+
12681281
Result<Index> addScratchLocal(Index pos, Type type) {
12691282
if (!func) {
12701283
return in.err(pos,

src/parser/parsers.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ template<typename Ctx> MaybeResult<> func(Ctx&);
194194
template<typename Ctx> MaybeResult<> table(Ctx&);
195195
template<typename Ctx> MaybeResult<> memory(Ctx&);
196196
template<typename Ctx> MaybeResult<> global(Ctx&);
197+
template<typename Ctx> MaybeResult<> export_(Ctx&);
197198
template<typename Ctx> MaybeResult<typename Ctx::ExprT> maybeElemexpr(Ctx&);
198199
template<typename Ctx> Result<typename Ctx::ElemListT> elemlist(Ctx&, bool);
199200
template<typename Ctx> MaybeResult<> elem(Ctx&);
@@ -2371,6 +2372,56 @@ template<typename Ctx> MaybeResult<> global(Ctx& ctx) {
23712372
return Ok{};
23722373
}
23732374

2375+
// export ::= '(' 'export' nm:name exportdesc ')'
2376+
// exportdesc ::= '(' 'func' x:funcidx ')'
2377+
// | '(' 'table' x:tableidx ')'
2378+
// | '(' 'memory' x:memidx ')'
2379+
// | '(' 'global' x:globalidx ')'
2380+
// | '(' 'tag' x:tagidx ')'
2381+
template<typename Ctx> MaybeResult<> export_(Ctx& ctx) {
2382+
auto pos = ctx.in.getPos();
2383+
if (!ctx.in.takeSExprStart("export"sv)) {
2384+
return {};
2385+
}
2386+
2387+
auto name = ctx.in.takeName();
2388+
if (!name) {
2389+
return ctx.in.err("expected export name");
2390+
}
2391+
2392+
if (ctx.in.takeSExprStart("func"sv)) {
2393+
auto idx = funcidx(ctx);
2394+
CHECK_ERR(idx);
2395+
CHECK_ERR(ctx.addExport(pos, *idx, *name, ExternalKind::Function));
2396+
} else if (ctx.in.takeSExprStart("table"sv)) {
2397+
auto idx = tableidx(ctx);
2398+
CHECK_ERR(idx);
2399+
CHECK_ERR(ctx.addExport(pos, *idx, *name, ExternalKind::Table));
2400+
} else if (ctx.in.takeSExprStart("memory"sv)) {
2401+
auto idx = memidx(ctx);
2402+
CHECK_ERR(idx);
2403+
CHECK_ERR(ctx.addExport(pos, *idx, *name, ExternalKind::Memory));
2404+
} else if (ctx.in.takeSExprStart("global"sv)) {
2405+
auto idx = globalidx(ctx);
2406+
CHECK_ERR(idx);
2407+
CHECK_ERR(ctx.addExport(pos, *idx, *name, ExternalKind::Global));
2408+
} else if (ctx.in.takeSExprStart("tag"sv)) {
2409+
auto idx = tagidx(ctx);
2410+
CHECK_ERR(idx);
2411+
CHECK_ERR(ctx.addExport(pos, *idx, *name, ExternalKind::Tag));
2412+
} else {
2413+
return ctx.in.err("expected export description");
2414+
}
2415+
2416+
if (!ctx.in.takeRParen()) {
2417+
return ctx.in.err("expected end of export description");
2418+
}
2419+
if (!ctx.in.takeRParen()) {
2420+
return ctx.in.err("expected end of export");
2421+
}
2422+
return Ok{};
2423+
}
2424+
23742425
// elemexpr ::= '(' 'item' expr ')' | '(' instr ')'
23752426
template<typename Ctx>
23762427
MaybeResult<typename Ctx::ExprT> maybeElemexpr(Ctx& ctx) {
@@ -2611,6 +2662,10 @@ template<typename Ctx> MaybeResult<> modulefield(Ctx& ctx) {
26112662
CHECK_ERR(res);
26122663
return Ok{};
26132664
}
2665+
if (auto res = export_(ctx)) {
2666+
CHECK_ERR(res);
2667+
return Ok{};
2668+
}
26142669
if (auto res = elem(ctx)) {
26152670
CHECK_ERR(res);
26162671
return Ok{};

src/parser/wat-parser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,16 @@ Result<> parseModule(Module& wasm, std::string_view input) {
178178
CHECK_ERR(parsed);
179179
assert(parsed);
180180
}
181+
182+
// Parse exports.
183+
// TODO: It would be more technically correct to interleave these properly
184+
// with the implicit inline exports in other module field definitions.
185+
for (auto pos : decls.exportDefs) {
186+
WithPosition with(ctx, pos);
187+
auto parsed = export_(ctx);
188+
CHECK_ERR(parsed);
189+
assert(parsed);
190+
}
181191
}
182192

183193
return Ok{};

test/lit/wat-kitchen-sink.wast

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,7 @@
354354
;; CHECK: (tag $tag-pair (param i32 i64))
355355
(tag $tag-pair (param i32 i64))
356356

357-
;; functions
358-
(func)
359-
357+
;; explicit exports
360358
;; CHECK: (export "g1" (global $g1))
361359

362360
;; CHECK: (export "g1.1" (global $g1))
@@ -377,6 +375,20 @@
377375

378376
;; CHECK: (export "t0.1" (tag $imported))
379377

378+
;; CHECK: (export "exported-func" (func $fimport$0))
379+
(export "exported-func" (func 0))
380+
;; CHECK: (export "exported-table" (table $timport$0))
381+
(export "exported-table" (table 0))
382+
;; CHECK: (export "exported-memory" (memory $mimport$0))
383+
(export "exported-memory" (memory 0))
384+
;; CHECK: (export "exported-global" (global $g1))
385+
(export "exported-global" (global 0))
386+
;; CHECK: (export "exported-tag" (tag $imported))
387+
(export "exported-tag" (tag 0))
388+
389+
;; functions
390+
(func)
391+
380392
;; CHECK: (func $1 (type $void)
381393
;; CHECK-NEXT: (nop)
382394
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)