From f7afcdd0759041bad2869a8e316932aa05983817 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 7 Dec 2023 12:55:39 -0800 Subject: [PATCH] [Parser] Parse table operations Including table.get, table.set, table.size, table.grow, table.fill, and table.copy. --- src/parser/contexts.h | 44 +++++++++ src/parser/parsers.h | 29 ++++-- src/wasm-ir-builder.h | 12 +-- src/wasm.h | 2 + src/wasm/wasm-ir-builder.cpp | 42 ++++++++- test/lit/wat-kitchen-sink.wast | 167 ++++++++++++++++++++++++++++++++- 6 files changed, 279 insertions(+), 17 deletions(-) diff --git a/src/parser/contexts.h b/src/parser/contexts.h index 396b115bfeb..7ce5bbf96cd 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -411,6 +411,12 @@ struct NullInstrParserCtx { Result<> makeRefIsNull(Index) { return Ok{}; } Result<> makeRefFunc(Index, FuncIdxT) { return Ok{}; } Result<> makeRefEq(Index) { return Ok{}; } + Result<> makeTableGet(Index, TableIdxT*) { return Ok{}; } + Result<> makeTableSet(Index, TableIdxT*) { return Ok{}; } + Result<> makeTableSize(Index, TableIdxT*) { return Ok{}; } + Result<> makeTableGrow(Index, TableIdxT*) { return Ok{}; } + Result<> makeTableFill(Index, TableIdxT*) { return Ok{}; } + Result<> makeTableCopy(Index, TableIdxT*, TableIdxT*) { return Ok{}; } Result<> makeThrow(Index, TagIdxT) { return Ok{}; } template Result<> makeCallRef(Index, HeapTypeT, bool) { return Ok{}; @@ -1524,6 +1530,44 @@ struct ParseDefsCtx : TypeParserCtx { Result<> makeRefEq(Index pos) { return withLoc(pos, irBuilder.makeRefEq()); } + Result<> makeTableGet(Index pos, Name* table) { + auto t = getTable(pos, table); + CHECK_ERR(t); + return withLoc(pos, irBuilder.makeTableGet(*t)); + } + + Result<> makeTableSet(Index pos, Name* table) { + auto t = getTable(pos, table); + CHECK_ERR(t); + return withLoc(pos, irBuilder.makeTableSet(*t)); + } + + Result<> makeTableSize(Index pos, Name* table) { + auto t = getTable(pos, table); + CHECK_ERR(t); + return withLoc(pos, irBuilder.makeTableSize(*t)); + } + + Result<> makeTableGrow(Index pos, Name* table) { + auto t = getTable(pos, table); + CHECK_ERR(t); + return withLoc(pos, irBuilder.makeTableGrow(*t)); + } + + Result<> makeTableFill(Index pos, Name* table) { + auto t = getTable(pos, table); + CHECK_ERR(t); + return withLoc(pos, irBuilder.makeTableFill(*t)); + } + + Result<> makeTableCopy(Index pos, Name* destTable, Name* srcTable) { + auto dest = getTable(pos, destTable); + CHECK_ERR(dest); + auto src = getTable(pos, srcTable); + CHECK_ERR(src); + return withLoc(pos, irBuilder.makeTableCopy(*dest, *src)); + } + Result<> makeThrow(Index pos, Name tag) { return withLoc(pos, irBuilder.makeThrow(tag)); } diff --git a/src/parser/parsers.h b/src/parser/parsers.h index fdcfd6d0f55..19dc8736d45 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -1432,27 +1432,44 @@ template Result<> makeRefEq(Ctx& ctx, Index pos) { } template Result<> makeTableGet(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto table = maybeTableidx(ctx); + CHECK_ERR(table); + return ctx.makeTableGet(pos, table.getPtr()); } template Result<> makeTableSet(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto table = maybeTableidx(ctx); + CHECK_ERR(table); + return ctx.makeTableSet(pos, table.getPtr()); } template Result<> makeTableSize(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto table = maybeTableidx(ctx); + CHECK_ERR(table); + return ctx.makeTableSize(pos, table.getPtr()); } template Result<> makeTableGrow(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto table = maybeTableidx(ctx); + CHECK_ERR(table); + return ctx.makeTableGrow(pos, table.getPtr()); } template Result<> makeTableFill(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto table = maybeTableidx(ctx); + CHECK_ERR(table); + return ctx.makeTableFill(pos, table.getPtr()); } template Result<> makeTableCopy(Ctx& ctx, Index pos) { - return ctx.in.err("unimplemented instruction"); + auto destTable = maybeTableidx(ctx); + CHECK_ERR(destTable); + auto srcTable = maybeTableidx(ctx); + CHECK_ERR(srcTable); + if (destTable && !srcTable) { + return ctx.in.err("expected table index or identifier"); + } + return ctx.makeTableCopy(pos, destTable.getPtr(), srcTable.getPtr()); } template Result<> makeThrow(Ctx& ctx, Index pos) { diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 96d0c44a17e..ab633b9fac5 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -148,12 +148,12 @@ class IRBuilder : public UnifiedExpressionVisitor> { [[nodiscard]] Result<> makeRefIsNull(); [[nodiscard]] Result<> makeRefFunc(Name func); [[nodiscard]] Result<> makeRefEq(); - // [[nodiscard]] Result<> makeTableGet(); - // [[nodiscard]] Result<> makeTableSet(); - // [[nodiscard]] Result<> makeTableSize(); - // [[nodiscard]] Result<> makeTableGrow(); - // [[nodiscard]] Result<> makeTableFill(); - // [[nodiscard]] Result<> makeTableCopy(); + [[nodiscard]] Result<> makeTableGet(Name table); + [[nodiscard]] Result<> makeTableSet(Name table); + [[nodiscard]] Result<> makeTableSize(Name table); + [[nodiscard]] Result<> makeTableGrow(Name table); + [[nodiscard]] Result<> makeTableFill(Name table); + [[nodiscard]] Result<> makeTableCopy(Name destTable, Name srcTable); [[nodiscard]] Result<> makeTry(Name label, Type type); [[nodiscard]] Result<> makeThrow(Name tag); // [[nodiscard]] Result<> makeRethrow(); diff --git a/src/wasm.h b/src/wasm.h index 24138c99d49..7da80d89647 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1380,6 +1380,7 @@ class RefEq : public SpecificExpression { class TableGet : public SpecificExpression { public: + TableGet() = default; TableGet(MixedArena& allocator) {} Name table; @@ -1391,6 +1392,7 @@ class TableGet : public SpecificExpression { class TableSet : public SpecificExpression { public: + TableSet() = default; TableSet(MixedArena& allocator) {} Name table; diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index be2bb440416..a95329f7d85 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -1159,13 +1159,47 @@ Result<> IRBuilder::makeRefEq() { return Ok{}; } -// Result<> IRBuilder::makeTableGet() {} +Result<> IRBuilder::makeTableGet(Name table) { + TableGet curr; + CHECK_ERR(visitTableGet(&curr)); + auto type = wasm.getTable(table)->type; + push(builder.makeTableGet(table, curr.index, type)); + return Ok{}; +} + +Result<> IRBuilder::makeTableSet(Name table) { + TableSet curr; + CHECK_ERR(visitTableSet(&curr)); + push(builder.makeTableSet(table, curr.index, curr.value)); + return Ok{}; +} + +Result<> IRBuilder::makeTableSize(Name table) { + push(builder.makeTableSize(table)); + return Ok{}; +} -// Result<> IRBuilder::makeTableSet() {} +Result<> IRBuilder::makeTableGrow(Name table) { + TableGrow curr; + CHECK_ERR(visitTableGrow(&curr)); + push(builder.makeTableGrow(table, curr.value, curr.delta)); + return Ok{}; +} -// Result<> IRBuilder::makeTableSize() {} +Result<> IRBuilder::makeTableFill(Name table) { + TableFill curr; + CHECK_ERR(visitTableFill(&curr)); + push(builder.makeTableFill(table, curr.dest, curr.value, curr.size)); + return Ok{}; +} -// Result<> IRBuilder::makeTableGrow() {} +Result<> IRBuilder::makeTableCopy(Name destTable, Name srcTable) { + TableCopy curr; + CHECK_ERR(visitTableCopy(&curr)); + push(builder.makeTableCopy( + curr.dest, curr.source, curr.size, destTable, srcTable)); + return Ok{}; +} Result<> IRBuilder::makeTry(Name label, Type type) { auto* tryy = wasm.allocator.alloc(); diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 54449b9b3fa..208e4a7a719 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -292,7 +292,7 @@ ;; tags (tag) - ;; CHECK: (elem declare func $ref-func) + ;; CHECK: (elem declare func $ref-func $table-fill $table-grow $table-set) ;; CHECK: (tag $1) @@ -2957,6 +2957,171 @@ ref.eq ) + ;; CHECK: (func $table-get (type $void) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.get $timport$0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.get $funcs + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.get $table-any + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-get + i32.const 0 + table.get + drop + i32.const 1 + table.get 1 + drop + i32.const 2 + table.get $table-any + drop + ) + + ;; CHECK: (func $table-set (type $void) + ;; CHECK-NEXT: (table.set $timport$0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (ref.null nofunc) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (table.set $funcs + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (ref.func $table-set) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (table.set $table-any + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-set + i32.const 0 + ref.null func + table.set + i32.const 1 + ref.func $table-set + table.set 1 + i32.const 2 + ref.null any + table.set $table-any + ) + + ;; CHECK: (func $table-size (type $void) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.size $timport$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.size $funcs) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.size $table-any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-size + table.size + drop + table.size 1 + drop + table.size $table-any + drop + ) + + ;; CHECK: (func $table-grow (type $void) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.grow $timport$0 + ;; CHECK-NEXT: (ref.null nofunc) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.grow $funcs + ;; CHECK-NEXT: (ref.func $table-grow) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (table.grow $table-any + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-grow + ref.null func + i32.const 0 + table.grow + drop + ref.func $table-grow + i32.const 1 + table.grow 1 + drop + ref.null any + i32.const 2 + table.grow $table-any + drop + ) + + ;; CHECK: (func $table-fill (type $void) + ;; CHECK-NEXT: (table.fill $timport$0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (ref.null nofunc) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (table.fill $funcs + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (ref.func $table-fill) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (table.fill $table-any + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-fill + i32.const 0 + ref.null func + i32.const 1 + table.fill + i32.const 2 + ref.func $table-fill + i32.const 3 + table.fill 1 + i32.const 4 + ref.null any + i32.const 5 + table.fill $table-any + ) + + ;; CHECK: (func $table-copy (type $void) + ;; CHECK-NEXT: (table.copy $timport$0 $timport$0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (table.copy $funcs $funcs + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $table-copy + i32.const 0 + i32.const 1 + i32.const 2 + table.copy + i32.const 3 + i32.const 4 + i32.const 5 + table.copy 1 $funcs + ) + ;; CHECK: (func $i31-new (type $34) (param $0 i32) (result i31ref) ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (local.get $0)