diff options
-rwxr-xr-x | scripts/gen-s-parser.py | 1 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 14 | ||||
-rw-r--r-- | src/passes/Print.cpp | 6 | ||||
-rw-r--r-- | src/wasm-binary.h | 1 | ||||
-rw-r--r-- | src/wasm-builder.h | 5 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 1 | ||||
-rw-r--r-- | src/wasm.h | 5 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 7 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 8 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | test/lit/ref-cast-nop.wast | 18 |
11 files changed, 63 insertions, 9 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 29ce83820..557696046 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -573,6 +573,7 @@ instructions = [ ("ref.test_static", "makeRefTestStatic(s)"), ("ref.cast", "makeRefCast(s)"), ("ref.cast_static", "makeRefCastStatic(s)"), + ("ref.cast_nop_static", "makeRefCastNopStatic(s)"), ("br_on_null", "makeBrOn(s, BrOnNull)"), ("br_on_non_null", "makeBrOn(s, BrOnNonNull)"), ("br_on_cast", "makeBrOn(s, BrOnCast)"), diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index d9505bcdd..411196986 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -3027,9 +3027,17 @@ switch (op[0]) { case '\0': if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); } goto parse_error; - case '_': - if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } - goto parse_error; + case '_': { + switch (op[9]) { + case 'n': + if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); } + goto parse_error; + case 's': + if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 9a4235cbf..ce70f50fd 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1984,7 +1984,11 @@ struct PrintExpressionContents if (curr->rtt) { printMedium(o, "ref.cast"); } else { - printMedium(o, "ref.cast_static "); + if (curr->safety == RefCast::Unsafe) { + printMedium(o, "ref.cast_nop_static "); + } else { + printMedium(o, "ref.cast_static "); + } printHeapType(o, curr->intendedType, wasm); } } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 12deeacab..58dcd2224 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1112,6 +1112,7 @@ enum ASTNodes { RefCastStatic = 0x45, BrOnCastStatic = 0x46, BrOnCastStaticFail = 0x47, + RefCastNopStatic = 0x48, RefIsFunc = 0x50, RefIsData = 0x51, RefIsI31 = 0x52, diff --git a/src/wasm-builder.h b/src/wasm-builder.h index de26886a4..86de1f7db 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -810,10 +810,13 @@ public: ret->finalize(); return ret; } - RefCast* makeRefCast(Expression* ref, HeapType intendedType) { + + RefCast* + makeRefCast(Expression* ref, HeapType intendedType, RefCast::Safety safety) { auto* ret = wasm.allocator.alloc<RefCast>(); ret->ref = ref; ret->intendedType = intendedType; + ret->safety = safety; ret->finalize(); return ret; } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index d6f3b2f4e..61383f084 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -282,6 +282,7 @@ private: Expression* makeRefTestStatic(Element& s); Expression* makeRefCast(Element& s); Expression* makeRefCastStatic(Element& s); + Expression* makeRefCastNopStatic(Element& s); Expression* makeBrOn(Element& s, BrOnOp op); Expression* makeBrOnStatic(Element& s, BrOnOp op); Expression* makeRttCanon(Element& s); diff --git a/src/wasm.h b/src/wasm.h index 3b736fcbc..b8e3d6704 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1457,6 +1457,11 @@ public: Expression* rtt = nullptr; HeapType intendedType; + // Support the unsafe `ref.cast_nop_static` to enable precise cast overhead + // measurements. + enum Safety { Safe, Unsafe }; + Safety safety; + void finalize(); // Returns the type we intend to cast to. diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 60a4bad77..9cd7e79a7 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -6712,10 +6712,13 @@ bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { auto* ref = popNonVoidExpression(); out = Builder(wasm).makeRefCast(ref, rtt); return true; - } else if (code == BinaryConsts::RefCastStatic) { + } else if (code == BinaryConsts::RefCastStatic || + code == BinaryConsts::RefCastNopStatic) { auto intendedType = getIndexedHeapType(); auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeRefCast(ref, intendedType); + auto safety = + code == BinaryConsts::RefCastNopStatic ? RefCast::Unsafe : RefCast::Safe; + out = Builder(wasm).makeRefCast(ref, intendedType, safety); return true; } return false; diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 02da4f909..8680ff8cc 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2702,7 +2702,13 @@ Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { Expression* SExpressionWasmBuilder::makeRefCastStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, heapType); + return Builder(wasm).makeRefCast(ref, heapType, RefCast::Safe); +} + +Expression* SExpressionWasmBuilder::makeRefCastNopStatic(Element& s) { + auto heapType = parseHeapType(*s[1]); + auto* ref = parseExpression(*s[2]); + return Builder(wasm).makeRefCast(ref, heapType, RefCast::Unsafe); } Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 8afeb6779..8588a049f 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2051,7 +2051,11 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) { if (curr->rtt) { o << U32LEB(BinaryConsts::RefCast); } else { - o << U32LEB(BinaryConsts::RefCastStatic); + if (curr->safety == RefCast::Unsafe) { + o << U32LEB(BinaryConsts::RefCastNopStatic); + } else { + o << U32LEB(BinaryConsts::RefCastStatic); + } parent.writeIndexedHeapType(curr->intendedType); } } diff --git a/test/lit/ref-cast-nop.wast b/test/lit/ref-cast-nop.wast new file mode 100644 index 000000000..6e49508d5 --- /dev/null +++ b/test/lit/ref-cast-nop.wast @@ -0,0 +1,18 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; RUN: wasm-opt -all %s -S --roundtrip -o - | filecheck %s + +(module + ;; CHECK: (type $struct (struct (field i32))) + (type $struct (struct i32)) + ;; CHECK: (func $ref.cast_nop_static (param $x (ref any)) (result (ref $struct)) + ;; CHECK-NEXT: (ref.cast_nop_static $struct + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $ref.cast_nop_static (param $x (ref any)) (result (ref $struct)) + (ref.cast_nop_static $struct + (local.get $x) + ) + ) +) |