diff options
-rw-r--r-- | src/parser/contexts.h | 7 | ||||
-rw-r--r-- | src/parser/parsers.h | 10 | ||||
-rw-r--r-- | src/wasm-ir-builder.h | 3 | ||||
-rw-r--r-- | src/wasm/wasm-ir-builder.cpp | 25 | ||||
-rw-r--r-- | test/lit/wat-kitchen-sink.wast | 106 |
5 files changed, 129 insertions, 22 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h index f6dd92063..192442c84 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -393,6 +393,9 @@ struct NullInstrParserCtx { Result<> makeRefIsNull(Index) { return Ok{}; } Result<> makeRefFunc(Index, FuncIdxT) { return Ok{}; } Result<> makeRefEq(Index) { return Ok{}; } + template<typename HeapTypeT> Result<> makeCallRef(Index, HeapTypeT, bool) { + return Ok{}; + } Result<> makeRefI31(Index) { return Ok{}; } Result<> makeI31Get(Index, bool) { return Ok{}; } template<typename TypeT> Result<> makeRefTest(Index, TypeT) { return Ok{}; } @@ -1285,6 +1288,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { Result<> makeRefEq(Index pos) { return withLoc(pos, irBuilder.makeRefEq()); } + Result<> makeCallRef(Index pos, HeapType type, bool isReturn) { + return withLoc(pos, irBuilder.makeCallRef(type, isReturn)); + } + Result<> makeRefI31(Index pos) { return withLoc(pos, irBuilder.makeRefI31()); } diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 2d90a7d27..41e625657 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -1291,7 +1291,9 @@ template<typename Ctx> Result<> makeTupleExtract(Ctx& ctx, Index pos) { template<typename Ctx> Result<> makeCallRef(Ctx& ctx, Index pos, bool isReturn) { - return ctx.in.err("unimplemented instruction"); + auto type = typeidx(ctx); + CHECK_ERR(type); + return ctx.makeCallRef(pos, *type, isReturn); } template<typename Ctx> Result<> makeRefI31(Ctx& ctx, Index pos) { @@ -1374,11 +1376,7 @@ template<typename Ctx> Result<> makeArrayNewData(Ctx& ctx, Index pos) { } template<typename Ctx> Result<> makeArrayNewElem(Ctx& ctx, Index pos) { - auto type = typeidx(ctx); - CHECK_ERR(type); - auto data = dataidx(ctx); - CHECK_ERR(data); - return ctx.makeArrayNewElem(pos, *type, *data); + return ctx.in.err("unimplemented instruction"); } template<typename Ctx> Result<> makeArrayNewFixed(Ctx& ctx, Index pos) { diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 4b6cacae9..e02d623f8 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -148,7 +148,7 @@ public: // [[nodiscard]] Result<> makeTupleExtract(); [[nodiscard]] Result<> makeRefI31(); [[nodiscard]] Result<> makeI31Get(bool signed_); - // [[nodiscard]] Result<> makeCallRef(); + [[nodiscard]] Result<> makeCallRef(HeapType type, bool isReturn); [[nodiscard]] Result<> makeRefTest(Type type); [[nodiscard]] Result<> makeRefCast(Type type); [[nodiscard]] Result<> @@ -197,6 +197,7 @@ public: [[nodiscard]] Result<> visitSwitch(Switch*, std::optional<Index> defaultLabel = std::nullopt); [[nodiscard]] Result<> visitCall(Call*); + [[nodiscard]] Result<> visitCallRef(CallRef*); private: Module& wasm; diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 9b2a944dd..433145d13 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -349,6 +349,18 @@ Result<> IRBuilder::visitCall(Call* curr) { return Ok{}; } +Result<> IRBuilder::visitCallRef(CallRef* curr) { + auto target = pop(); + CHECK_ERR(target); + curr->target = *target; + for (size_t i = 0, numArgs = curr->operands.size(); i < numArgs; ++i) { + auto arg = pop(); + CHECK_ERR(arg); + curr->operands[numArgs - 1 - i] = *arg; + } + return Ok{}; +} + Result<> IRBuilder::visitFunctionStart(Function* func) { if (!scopeStack.empty()) { return Err{"unexpected start of function"}; @@ -923,7 +935,18 @@ Result<> IRBuilder::makeI31Get(bool signed_) { return Ok{}; } -// Result<> IRBuilder::makeCallRef() {} +Result<> IRBuilder::makeCallRef(HeapType type, bool isReturn) { + CallRef curr(wasm.allocator); + if (!type.isSignature()) { + return Err{"expected function type"}; + } + auto sig = type.getSignature(); + curr.operands.resize(type.getSignature().params.size()); + CHECK_ERR(visitCallRef(&curr)); + CHECK_ERR(validateTypeAnnotation(type, curr.target)); + push(builder.makeCallRef(curr.target, curr.operands, sig.results, isReturn)); + return Ok{}; +} Result<> IRBuilder::makeRefTest(Type type) { RefTest curr; diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 751b9f5ef..fc2bee18d 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -25,13 +25,15 @@ ;; CHECK: (type $8 (func (param anyref))) + ;; CHECK: (type $many (sub (func (param i32 i64 f32 f64) (result anyref (ref func))))) + ;; CHECK: (type $a0 (array i32)) - ;; CHECK: (type $10 (func (param i32))) + ;; CHECK: (type $11 (func (param i32))) - ;; CHECK: (type $11 (func (param i32 i32 i32))) + ;; CHECK: (type $12 (func (param i32 i32 i32))) - ;; CHECK: (type $12 (func (param v128 i32) (result v128))) + ;; CHECK: (type $13 (func (param v128 i32) (result v128))) ;; CHECK: (rec ;; CHECK-NEXT: (type $s0 (struct )) @@ -46,9 +48,7 @@ ;; CHECK: (type $packed-i16 (array (mut i16))) - ;; CHECK: (type $17 (func (param i32 i64) (result f32))) - - ;; CHECK: (type $many (sub (func (param i32 i64 f32 f64) (result anyref (ref func))))) + ;; CHECK: (type $18 (func (param i32 i64) (result f32))) ;; CHECK: (type $19 (func (param i32 i32))) @@ -237,11 +237,11 @@ ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - ;; CHECK: (func $f1 (type $10) (param $0 i32) + ;; CHECK: (func $f1 (type $11) (param $0 i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $f1 (param i32)) - ;; CHECK: (func $f2 (type $10) (param $x i32) + ;; CHECK: (func $f2 (type $11) (param $x i32) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $f2 (param $x i32)) @@ -1759,7 +1759,7 @@ drop ) - ;; CHECK: (func $select (type $11) (param $0 i32) (param $1 i32) (param $2 i32) + ;; CHECK: (func $select (type $12) (param $0 i32) (param $1 i32) (param $2 i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $0) @@ -2051,7 +2051,7 @@ i32x4.extract_lane 3 ) - ;; CHECK: (func $simd-replace (type $12) (param $0 v128) (param $1 i32) (result v128) + ;; CHECK: (func $simd-replace (type $13) (param $0 v128) (param $1 i32) (result v128) ;; CHECK-NEXT: (i32x4.replace_lane 2 ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -2089,7 +2089,7 @@ v128.bitselect ) - ;; CHECK: (func $simd-shift (type $12) (param $0 v128) (param $1 i32) (result v128) + ;; CHECK: (func $simd-shift (type $13) (param $0 v128) (param $1 i32) (result v128) ;; CHECK-NEXT: (i8x16.shl ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -2144,7 +2144,7 @@ v128.store64_lane 3 align=4 0 ) - ;; CHECK: (func $memory-init (type $11) (param $0 i32) (param $1 i32) (param $2 i32) + ;; CHECK: (func $memory-init (type $12) (param $0 i32) (param $1 i32) (param $2 i32) ;; CHECK-NEXT: (memory.init $mem-i32 $passive ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -2379,6 +2379,84 @@ drop ) + ;; CHECK: (func $call-ref (type $void) + ;; CHECK-NEXT: (local $0 (ref null $void)) + ;; CHECK-NEXT: (local $1 (ref null $ret2)) + ;; CHECK-NEXT: (local $2 (ref null $many)) + ;; CHECK-NEXT: (local $scratch (i32 i32)) + ;; CHECK-NEXT: (local $scratch_4 i32) + ;; CHECK-NEXT: (local $scratch_5 (anyref (ref func))) + ;; CHECK-NEXT: (local $scratch_6 anyref) + ;; CHECK-NEXT: (call_ref $void + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $scratch_4 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $scratch + ;; CHECK-NEXT: (call_ref $ret2 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (local.get $scratch) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (tuple.extract 1 + ;; CHECK-NEXT: (local.get $scratch) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (local.set $scratch_6 + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (local.set $scratch_5 + ;; CHECK-NEXT: (call_ref $many + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: (f32.const 2) + ;; CHECK-NEXT: (f64.const 3) + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (tuple.extract 0 + ;; CHECK-NEXT: (local.get $scratch_5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (tuple.extract 1 + ;; CHECK-NEXT: (local.get $scratch_5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_6) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-ref + (local (ref null $void) (ref null $ret2) (ref null $many)) + local.get 0 + call_ref $void + local.get 1 + call_ref $ret2 + drop + drop + i32.const 0 + i64.const 1 + f32.const 2 + f64.const 3 + local.get 2 + call_ref $many + drop + drop + ) + ;; CHECK: (func $ref-test (type $8) (param $0 anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.test i31ref @@ -2757,7 +2835,7 @@ drop ) - ;; CHECK: (func $call (type $17) (param $0 i32) (param $1 i64) (result f32) + ;; CHECK: (func $call (type $18) (param $0 i32) (param $1 i64) (result f32) ;; CHECK-NEXT: (call $call ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -2769,7 +2847,7 @@ call $call ) - ;; CHECK: (func $return_call (type $17) (param $0 i32) (param $1 i64) (result f32) + ;; CHECK: (func $return_call (type $18) (param $0 i32) (param $1 i64) (result f32) ;; CHECK-NEXT: (return_call $return_call ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) |