From 1e127e071e544319a674b4eee3bbfa583ec5f6cf Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 9 May 2024 17:07:45 -0700 Subject: [PATCH 1/7] Remove stringview types and instructions The stringview types from the stringref proposal have three irregularities that break common invariants and require pervasive special casing to handle properly: they are supertypes of `none` but not subtypes of `any`, they cannot be the targets of casts, and they cannot be used to construct nullable references. At the same time, the stringref proposal has been superseded by the imported strings proposal, which does not have these irregularities. The cost of maintaing and improving our support for stringview types is no longer worth the benefit of supporting them. Simplify the code base by entirely removing the stringview types and related instructions that do not have analogues in the imported strings proposal and do not make sense in the absense of stringviews. Three remaining instructions, `stringview_wtf16.get_codeunit`, `stringview_wtf16.slice`, and `stringview_wtf16.length` take stringview operands in the stringref proposal but cannot be removed because they lower to operations from the imported strings proposal. These instructions are changed to take stringref operands in Binaryen IR, and to allow a graceful upgrade path for users of these instructions, the text parser still accepts but ignores `string.as_wtf16`, which is the instruction used to convert stringrefs to stringviews. No attempt is made to fix up the binary output to include the `string.as_wtf16` instructions that the stringref proposal requires, so binaryen no longer emits valid string code unless `--string-lowering` is used to target the imported strings proposal instead. This should not be a problem because users should universally be using imported strings over stringref. Future PRs will further align binaryen with the imported strings proposal instead of the stringref proposal, for example by making `string` a subtype of `extern` instead of a subtype of `any` and by removing additional instructions that do not have analogues in the imported strings proposal. --- scripts/gen-s-parser.py | 15 +- src/binaryen-c.cpp | 225 +----------------- src/binaryen-c.h | 81 ------- src/gen-s-parser.inc | 202 +++------------- src/ir/ReFinalize.cpp | 10 - src/ir/child-typer.h | 41 +--- src/ir/cost.h | 13 - src/ir/effects.h | 31 --- src/ir/possible-contents.cpp | 20 -- src/ir/subtype-exprs.h | 5 - src/ir/type-updating.cpp | 9 - src/js/binaryen.js-post.js | 37 --- src/parser/contexts.h | 48 +--- src/parser/parsers.h | 84 +------ src/passes/Print.cpp | 50 +--- src/passes/StringLowering.cpp | 40 +--- src/passes/TypeGeneralizing.cpp | 7 - src/tools/fuzzing/fuzzing.cpp | 34 +-- src/tools/fuzzing/heap-types.cpp | 13 - src/tools/wasm-ctor-eval.cpp | 8 - src/wasm-binary.h | 26 +- src/wasm-builder.h | 46 +--- src/wasm-delegations-fields.def | 27 --- src/wasm-delegations.def | 5 - src/wasm-interpreter.h | 39 +-- src/wasm-ir-builder.h | 5 +- src/wasm-s-parser.h | 8 +- src/wasm-type.h | 3 - src/wasm.h | 87 ------- src/wasm/literal.cpp | 10 - src/wasm/wasm-binary.cpp | 127 +--------- src/wasm/wasm-ir-builder.cpp | 40 +--- src/wasm/wasm-s-parser.cpp | 47 +--- src/wasm/wasm-stack.cpp | 78 +----- src/wasm/wasm-type.cpp | 115 +++------ src/wasm/wasm-validator.cpp | 34 --- src/wasm/wasm.cpp | 53 ----- src/wasm2js.h | 20 -- test/binaryen.js/kitchen-sink.js | 3 - test/binaryen.js/kitchen-sink.js.txt | 32 +-- test/example/c-api-kitchen-sink.c | 100 +------- test/example/c-api-kitchen-sink.txt | 91 +------ test/gtest/type-builder.cpp | 86 +------ test/lit/ctor-eval/string_view.wast | 32 --- test/lit/exec/strings.wast | 31 +-- test/lit/passes/j2cl-inline.wast | 13 +- test/lit/passes/precompute-strings.wast | 40 +--- test/lit/passes/roundtrip.wast | 66 ----- test/lit/passes/simplify-locals-strings.wast | 66 ----- .../passes/string-lowering-instructions.wast | 134 +++-------- test/lit/string.as_wtf16.wast | 43 ++++ test/lit/strings.wast | 195 ++------------- test/lit/wat-kitchen-sink.wast | 178 ++------------ 53 files changed, 275 insertions(+), 2578 deletions(-) delete mode 100644 test/lit/ctor-eval/string_view.wast create mode 100644 test/lit/string.as_wtf16.wast diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 3f632c00432..ed2ef72c36e 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -620,6 +620,7 @@ ("string.measure_utf8", "makeStringMeasure(s, StringMeasureUTF8)"), ("string.measure_wtf8", "makeStringMeasure(s, StringMeasureWTF8)"), ("string.measure_wtf16", "makeStringMeasure(s, StringMeasureWTF16)"), + ("stringview_wtf16.length", "makeStringMeasure(s, StringMeasureWTF16)"), ("string.is_usv_sequence", "makeStringMeasure(s, StringMeasureIsUSV)"), ("string.hash", "makeStringMeasure(s, StringMeasureHash)"), ("string.encode_utf8", "makeStringEncode(s, StringEncodeUTF8)"), @@ -633,18 +634,10 @@ ("string.concat", "makeStringConcat(s)"), ("string.eq", "makeStringEq(s, StringEqEqual)"), ("string.compare", "makeStringEq(s, StringEqCompare)"), - ("string.as_wtf8", "makeStringAs(s, StringAsWTF8)"), - ("string.as_wtf16", "makeStringAs(s, StringAsWTF16)"), - ("string.as_iter", "makeStringAs(s, StringAsIter)"), - ("stringview_wtf8.advance", "makeStringWTF8Advance(s)"), ("stringview_wtf16.get_codeunit", "makeStringWTF16Get(s)"), - ("stringview_iter.next", "makeStringIterNext(s)"), - ("stringview_iter.advance", "makeStringIterMove(s, StringIterMoveAdvance)"), - ("stringview_iter.rewind", "makeStringIterMove(s, StringIterMoveRewind)"), - ("stringview_wtf8.slice", "makeStringSliceWTF(s, StringSliceWTF8)"), - ("stringview_wtf16.slice", "makeStringSliceWTF(s, StringSliceWTF16)"), - ("stringview_iter.slice", "makeStringSliceIter(s)"), - ("stringview_wtf16.length", "makeStringMeasure(s, StringMeasureWTF16View)"), + ("stringview_wtf16.slice", "makeStringSliceWTF(s)"), + # Ignored in input + ("string.as_wtf16", "ignore(s)"), ] diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 1c9a5be0e76..a9a21bc1468 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -93,9 +93,6 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { case HeapType::exn: WASM_UNREACHABLE("invalid type"); case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: WASM_UNREACHABLE("TODO: string literals"); case HeapType::none: case HeapType::noext: @@ -150,9 +147,6 @@ Literal fromBinaryenLiteral(BinaryenLiteral x) { case HeapType::exn: WASM_UNREACHABLE("invalid type"); case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: WASM_UNREACHABLE("TODO: string literals"); case HeapType::none: case HeapType::noext: @@ -218,15 +212,6 @@ BinaryenType BinaryenTypeArrayref(void) { BinaryenType BinaryenTypeStringref() { return Type(HeapType::string, Nullable).getID(); } -BinaryenType BinaryenTypeStringviewWTF8() { - return Type(HeapType::stringview_wtf8, Nullable).getID(); -} -BinaryenType BinaryenTypeStringviewWTF16() { - return Type(HeapType::stringview_wtf16, Nullable).getID(); -} -BinaryenType BinaryenTypeStringviewIter() { - return Type(HeapType::stringview_iter, Nullable).getID(); -} BinaryenType BinaryenTypeNullref() { return Type(HeapType::none, Nullable).getID(); } @@ -303,18 +288,6 @@ BinaryenHeapType BinaryenHeapTypeArray() { BinaryenHeapType BinaryenHeapTypeString() { return static_cast(HeapType::BasicHeapType::string); } -BinaryenHeapType BinaryenHeapTypeStringviewWTF8() { - return static_cast( - HeapType::BasicHeapType::stringview_wtf8); -} -BinaryenHeapType BinaryenHeapTypeStringviewWTF16() { - return static_cast( - HeapType::BasicHeapType::stringview_wtf16); -} -BinaryenHeapType BinaryenHeapTypeStringviewIter() { - return static_cast( - HeapType::BasicHeapType::stringview_iter); -} BinaryenHeapType BinaryenHeapTypeNone() { return static_cast(HeapType::BasicHeapType::none); } @@ -1063,9 +1036,6 @@ BinaryenOp BinaryenStringMeasureUTF8(void) { return StringMeasureUTF8; } BinaryenOp BinaryenStringMeasureWTF8(void) { return StringMeasureWTF8; } BinaryenOp BinaryenStringMeasureWTF16(void) { return StringMeasureWTF16; } BinaryenOp BinaryenStringMeasureIsUSV(void) { return StringMeasureIsUSV; } -BinaryenOp BinaryenStringMeasureWTF16View(void) { - return StringMeasureWTF16View; -} BinaryenOp BinaryenStringEncodeUTF8(void) { return StringEncodeUTF8; } BinaryenOp BinaryenStringEncodeLossyUTF8(void) { return StringEncodeLossyUTF8; } BinaryenOp BinaryenStringEncodeWTF8(void) { return StringEncodeWTF8; } @@ -1078,13 +1048,6 @@ BinaryenOp BinaryenStringEncodeWTF8Array(void) { return StringEncodeWTF8Array; } BinaryenOp BinaryenStringEncodeWTF16Array(void) { return StringEncodeWTF16Array; } -BinaryenOp BinaryenStringAsWTF8(void) { return StringAsWTF8; } -BinaryenOp BinaryenStringAsWTF16(void) { return StringAsWTF16; } -BinaryenOp BinaryenStringAsIter(void) { return StringAsIter; } -BinaryenOp BinaryenStringIterMoveAdvance(void) { return StringIterMoveAdvance; } -BinaryenOp BinaryenStringIterMoveRewind(void) { return StringIterMoveRewind; } -BinaryenOp BinaryenStringSliceWTF8(void) { return StringSliceWTF8; } -BinaryenOp BinaryenStringSliceWTF16(void) { return StringSliceWTF16; } BinaryenOp BinaryenStringEqEqual(void) { return StringEqEqual; } BinaryenOp BinaryenStringEqCompare(void) { return StringEqCompare; } @@ -1942,21 +1905,6 @@ BinaryenExpressionRef BinaryenStringEq(BinaryenModuleRef module, Builder(*(Module*)module) .makeStringEq(StringEqOp(op), (Expression*)left, (Expression*)right)); } -BinaryenExpressionRef BinaryenStringAs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef ref) { - return static_cast( - Builder(*(Module*)module).makeStringAs(StringAsOp(op), (Expression*)ref)); -} -BinaryenExpressionRef BinaryenStringWTF8Advance(BinaryenModuleRef module, - BinaryenExpressionRef ref, - BinaryenExpressionRef pos, - BinaryenExpressionRef bytes) { - return static_cast(Builder(*(Module*)module) - .makeStringWTF8Advance((Expression*)ref, - (Expression*)pos, - (Expression*)bytes)); -} BinaryenExpressionRef BinaryenStringWTF16Get(BinaryenModuleRef module, BinaryenExpressionRef ref, BinaryenExpressionRef pos) { @@ -1964,38 +1912,15 @@ BinaryenExpressionRef BinaryenStringWTF16Get(BinaryenModuleRef module, Builder(*(Module*)module) .makeStringWTF16Get((Expression*)ref, (Expression*)pos)); } -BinaryenExpressionRef BinaryenStringIterNext(BinaryenModuleRef module, - BinaryenExpressionRef ref) { - return static_cast( - Builder(*(Module*)module).makeStringIterNext((Expression*)ref)); -} -BinaryenExpressionRef BinaryenStringIterMove(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef ref, - BinaryenExpressionRef num) { - return static_cast(Builder(*(Module*)module) - .makeStringIterMove(StringIterMoveOp(op), - (Expression*)ref, - (Expression*)num)); -} BinaryenExpressionRef BinaryenStringSliceWTF(BinaryenModuleRef module, - BinaryenOp op, BinaryenExpressionRef ref, BinaryenExpressionRef start, BinaryenExpressionRef end) { return static_cast(Builder(*(Module*)module) - .makeStringSliceWTF(StringSliceWTFOp(op), - (Expression*)ref, + .makeStringSliceWTF((Expression*)ref, (Expression*)start, (Expression*)end)); } -BinaryenExpressionRef BinaryenStringSliceIter(BinaryenModuleRef module, - BinaryenExpressionRef ref, - BinaryenExpressionRef num) { - return static_cast( - Builder(*(Module*)module) - .makeStringSliceIter((Expression*)ref, (Expression*)num)); -} // Expression utility @@ -4720,69 +4645,6 @@ void BinaryenStringEqSetRight(BinaryenExpressionRef expr, assert(rightExpr); static_cast(expression)->right = (Expression*)rightExpr; } -// StringAs -BinaryenOp BinaryenStringAsGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; -} -void BinaryenStringAsSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = StringAsOp(op); -} -BinaryenExpressionRef BinaryenStringAsGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ref; -} -void BinaryenStringAsSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(refExpr); - static_cast(expression)->ref = (Expression*)refExpr; -} -// StringWTF8Advance -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ref; -} -void BinaryenStringWTF8AdvanceSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(refExpr); - static_cast(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetPos(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->pos; -} -void BinaryenStringWTF8AdvanceSetPos(BinaryenExpressionRef expr, - BinaryenExpressionRef posExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(posExpr); - static_cast(expression)->pos = (Expression*)posExpr; -} -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetBytes(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->bytes; -} -void BinaryenStringWTF8AdvanceSetBytes(BinaryenExpressionRef expr, - BinaryenExpressionRef bytesExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(bytesExpr); - static_cast(expression)->bytes = (Expression*)bytesExpr; -} // StringWTF16Get BinaryenExpressionRef BinaryenStringWTF16GetGetRef(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; @@ -4808,65 +4670,7 @@ void BinaryenStringWTF16GetSetPos(BinaryenExpressionRef expr, assert(posExpr); static_cast(expression)->pos = (Expression*)posExpr; } -// StringIterNext -BinaryenExpressionRef BinaryenStringIterNextGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ref; -} -void BinaryenStringIterNextSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(refExpr); - static_cast(expression)->ref = (Expression*)refExpr; -} -// StringIterMove -BinaryenOp BinaryenStringIterMoveGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; -} -void BinaryenStringIterMoveSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = StringIterMoveOp(op); -} -BinaryenExpressionRef BinaryenStringIterMoveGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ref; -} -void BinaryenStringIterMoveSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(refExpr); - static_cast(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef BinaryenStringIterMoveGetNum(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->num; -} -void BinaryenStringIterMoveSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(numExpr); - static_cast(expression)->num = (Expression*)numExpr; -} // StringSliceWTF -BinaryenOp BinaryenStringSliceWTFGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; -} -void BinaryenStringSliceWTFSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = StringSliceWTFOp(op); -} BinaryenExpressionRef BinaryenStringSliceWTFGetRef(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); @@ -4904,33 +4708,6 @@ void BinaryenStringSliceWTFSetEnd(BinaryenExpressionRef expr, assert(endExpr); static_cast(expression)->end = (Expression*)endExpr; } -// StringSliceIter -BinaryenExpressionRef -BinaryenStringSliceIterGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ref; -} -void BinaryenStringSliceIterSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(refExpr); - static_cast(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef -BinaryenStringSliceIterGetNum(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->num; -} -void BinaryenStringSliceIterSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(numExpr); - static_cast(expression)->num = (Expression*)numExpr; -} // Functions diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 595086d6a25..f01b4c3be56 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -107,9 +107,6 @@ BINARYEN_API BinaryenType BinaryenTypeI31ref(void); BINARYEN_API BinaryenType BinaryenTypeStructref(void); BINARYEN_API BinaryenType BinaryenTypeArrayref(void); BINARYEN_API BinaryenType BinaryenTypeStringref(void); -BINARYEN_API BinaryenType BinaryenTypeStringviewWTF8(void); -BINARYEN_API BinaryenType BinaryenTypeStringviewWTF16(void); -BINARYEN_API BinaryenType BinaryenTypeStringviewIter(void); BINARYEN_API BinaryenType BinaryenTypeNullref(void); BINARYEN_API BinaryenType BinaryenTypeNullExternref(void); BINARYEN_API BinaryenType BinaryenTypeNullFuncref(void); @@ -149,9 +146,6 @@ BINARYEN_API BinaryenHeapType BinaryenHeapTypeI31(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeStruct(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeArray(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeString(void); -BINARYEN_API BinaryenHeapType BinaryenHeapTypeStringviewWTF8(void); -BINARYEN_API BinaryenHeapType BinaryenHeapTypeStringviewWTF16(void); -BINARYEN_API BinaryenHeapType BinaryenHeapTypeStringviewIter(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeNone(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeNoext(void); BINARYEN_API BinaryenHeapType BinaryenHeapTypeNofunc(void); @@ -701,7 +695,6 @@ BINARYEN_API BinaryenOp BinaryenStringMeasureUTF8(void); BINARYEN_API BinaryenOp BinaryenStringMeasureWTF8(void); BINARYEN_API BinaryenOp BinaryenStringMeasureWTF16(void); BINARYEN_API BinaryenOp BinaryenStringMeasureIsUSV(void); -BINARYEN_API BinaryenOp BinaryenStringMeasureWTF16View(void); BINARYEN_API BinaryenOp BinaryenStringEncodeUTF8(void); BINARYEN_API BinaryenOp BinaryenStringEncodeLossyUTF8(void); BINARYEN_API BinaryenOp BinaryenStringEncodeWTF8(void); @@ -710,13 +703,6 @@ BINARYEN_API BinaryenOp BinaryenStringEncodeUTF8Array(void); BINARYEN_API BinaryenOp BinaryenStringEncodeLossyUTF8Array(void); BINARYEN_API BinaryenOp BinaryenStringEncodeWTF8Array(void); BINARYEN_API BinaryenOp BinaryenStringEncodeWTF16Array(void); -BINARYEN_API BinaryenOp BinaryenStringAsWTF8(void); -BINARYEN_API BinaryenOp BinaryenStringAsWTF16(void); -BINARYEN_API BinaryenOp BinaryenStringAsIter(void); -BINARYEN_API BinaryenOp BinaryenStringIterMoveAdvance(void); -BINARYEN_API BinaryenOp BinaryenStringIterMoveRewind(void); -BINARYEN_API BinaryenOp BinaryenStringSliceWTF8(void); -BINARYEN_API BinaryenOp BinaryenStringSliceWTF16(void); BINARYEN_API BinaryenOp BinaryenStringEqEqual(void); BINARYEN_API BinaryenOp BinaryenStringEqCompare(void); @@ -1130,9 +1116,6 @@ BinaryenStringEq(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef left, BinaryenExpressionRef right); -BINARYEN_API BinaryenExpressionRef BinaryenStringAs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef ref); BINARYEN_API BinaryenExpressionRef BinaryenStringWTF8Advance(BinaryenModuleRef module, BinaryenExpressionRef ref, @@ -1151,7 +1134,6 @@ BinaryenStringIterMove(BinaryenModuleRef module, BinaryenExpressionRef num); BINARYEN_API BinaryenExpressionRef BinaryenStringSliceWTF(BinaryenModuleRef module, - BinaryenOp op, BinaryenExpressionRef ref, BinaryenExpressionRef start, BinaryenExpressionRef end); @@ -2619,34 +2601,6 @@ BinaryenStringEqGetRight(BinaryenExpressionRef expr); BINARYEN_API void BinaryenStringEqSetRight(BinaryenExpressionRef expr, BinaryenExpressionRef rightExpr); -// StringAs - -BINARYEN_API BinaryenOp BinaryenStringAsGetOp(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringAsSetOp(BinaryenExpressionRef expr, - BinaryenOp op); -BINARYEN_API BinaryenExpressionRef -BinaryenStringAsGetRef(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringAsSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr); - -// StringWTF8Advance - -BINARYEN_API BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetRef(BinaryenExpressionRef expr); -BINARYEN_API void -BinaryenStringWTF8AdvanceSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr); -BINARYEN_API BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetPos(BinaryenExpressionRef expr); -BINARYEN_API void -BinaryenStringWTF8AdvanceSetPos(BinaryenExpressionRef expr, - BinaryenExpressionRef posExpr); -BINARYEN_API BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetBytes(BinaryenExpressionRef expr); -BINARYEN_API void -BinaryenStringWTF8AdvanceSetBytes(BinaryenExpressionRef expr, - BinaryenExpressionRef bytesExpr); - // StringWTF16Get BINARYEN_API BinaryenExpressionRef @@ -2658,32 +2612,8 @@ BinaryenStringWTF16GetGetPos(BinaryenExpressionRef expr); BINARYEN_API void BinaryenStringWTF16GetSetPos(BinaryenExpressionRef expr, BinaryenExpressionRef posExpr); -// StringIterNext - -BINARYEN_API BinaryenExpressionRef -BinaryenStringIterNextGetRef(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringIterNextSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr); - -// StringIterMove - -BINARYEN_API BinaryenOp BinaryenStringIterMoveGetOp(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringIterMoveSetOp(BinaryenExpressionRef expr, - BinaryenOp op); -BINARYEN_API BinaryenExpressionRef -BinaryenStringIterMoveGetRef(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringIterMoveSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr); -BINARYEN_API BinaryenExpressionRef -BinaryenStringIterMoveGetNum(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringIterMoveSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr); - // StringSliceWTF -BINARYEN_API BinaryenOp BinaryenStringSliceWTFGetOp(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringSliceWTFSetOp(BinaryenExpressionRef expr, - BinaryenOp op); BINARYEN_API BinaryenExpressionRef BinaryenStringSliceWTFGetRef(BinaryenExpressionRef expr); BINARYEN_API void BinaryenStringSliceWTFSetRef(BinaryenExpressionRef expr, @@ -2698,17 +2628,6 @@ BinaryenStringSliceWTFGetEnd(BinaryenExpressionRef expr); BINARYEN_API void BinaryenStringSliceWTFSetEnd(BinaryenExpressionRef expr, BinaryenExpressionRef endExpr); -// StringSliceIter - -BINARYEN_API BinaryenExpressionRef -BinaryenStringSliceIterGetRef(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringSliceIterSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr); -BINARYEN_API BinaryenExpressionRef -BinaryenStringSliceIterGetNum(BinaryenExpressionRef expr); -BINARYEN_API void BinaryenStringSliceIterSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr); - // Functions BINARYEN_REF(Function); diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 939031020a7..b76a26ea130 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -3072,25 +3072,9 @@ switch (buf[0]) { switch (buf[6]) { case '.': { switch (buf[7]) { - case 'a': { - switch (buf[10]) { - case 'i': - if (op == "string.as_iter"sv) { return makeStringAs(s, StringAsIter); } - goto parse_error; - case 'w': { - switch (buf[13]) { - case '1': - if (op == "string.as_wtf16"sv) { return makeStringAs(s, StringAsWTF16); } - goto parse_error; - case '8': - if (op == "string.as_wtf8"sv) { return makeStringAs(s, StringAsWTF8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } + case 'a': + if (op == "string.as_wtf16"sv) { return ignore(s); } + goto parse_error; case 'c': { switch (buf[9]) { case 'm': @@ -3274,54 +3258,16 @@ switch (buf[0]) { } } case 'v': { - switch (buf[11]) { - case 'i': { - switch (buf[16]) { - case 'a': - if (op == "stringview_iter.advance"sv) { return makeStringIterMove(s, StringIterMoveAdvance); } - goto parse_error; - case 'n': - if (op == "stringview_iter.next"sv) { return makeStringIterNext(s); } - goto parse_error; - case 'r': - if (op == "stringview_iter.rewind"sv) { return makeStringIterMove(s, StringIterMoveRewind); } - goto parse_error; - case 's': - if (op == "stringview_iter.slice"sv) { return makeStringSliceIter(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'w': { - switch (buf[14]) { - case '1': { - switch (buf[17]) { - case 'g': - if (op == "stringview_wtf16.get_codeunit"sv) { return makeStringWTF16Get(s); } - goto parse_error; - case 'l': - if (op == "stringview_wtf16.length"sv) { return makeStringMeasure(s, StringMeasureWTF16View); } - goto parse_error; - case 's': - if (op == "stringview_wtf16.slice"sv) { return makeStringSliceWTF(s, StringSliceWTF16); } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (buf[16]) { - case 'a': - if (op == "stringview_wtf8.advance"sv) { return makeStringWTF8Advance(s); } - goto parse_error; - case 's': - if (op == "stringview_wtf8.slice"sv) { return makeStringSliceWTF(s, StringSliceWTF8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } + switch (buf[17]) { + case 'g': + if (op == "stringview_wtf16.get_codeunit"sv) { return makeStringWTF16Get(s); } + goto parse_error; + case 'l': + if (op == "stringview_wtf16.length"sv) { return makeStringMeasure(s, StringMeasureWTF16); } + goto parse_error; + case 's': + if (op == "stringview_wtf16.slice"sv) { return makeStringSliceWTF(s); } + goto parse_error; default: goto parse_error; } } @@ -8221,34 +8167,12 @@ switch (buf[0]) { switch (buf[6]) { case '.': { switch (buf[7]) { - case 'a': { - switch (buf[10]) { - case 'i': - if (op == "string.as_iter"sv) { - CHECK_ERR(makeStringAs(ctx, pos, annotations, StringAsIter)); - return Ok{}; - } - goto parse_error; - case 'w': { - switch (buf[13]) { - case '1': - if (op == "string.as_wtf16"sv) { - CHECK_ERR(makeStringAs(ctx, pos, annotations, StringAsWTF16)); - return Ok{}; - } - goto parse_error; - case '8': - if (op == "string.as_wtf8"sv) { - CHECK_ERR(makeStringAs(ctx, pos, annotations, StringAsWTF8)); - return Ok{}; - } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; + case 'a': + if (op == "string.as_wtf16"sv) { + CHECK_ERR(ignore(ctx, pos, annotations)); + return Ok{}; } - } + goto parse_error; case 'c': { switch (buf[9]) { case 'm': @@ -8516,81 +8440,25 @@ switch (buf[0]) { } } case 'v': { - switch (buf[11]) { - case 'i': { - switch (buf[16]) { - case 'a': - if (op == "stringview_iter.advance"sv) { - CHECK_ERR(makeStringIterMove(ctx, pos, annotations, StringIterMoveAdvance)); - return Ok{}; - } - goto parse_error; - case 'n': - if (op == "stringview_iter.next"sv) { - CHECK_ERR(makeStringIterNext(ctx, pos, annotations)); - return Ok{}; - } - goto parse_error; - case 'r': - if (op == "stringview_iter.rewind"sv) { - CHECK_ERR(makeStringIterMove(ctx, pos, annotations, StringIterMoveRewind)); - return Ok{}; - } - goto parse_error; - case 's': - if (op == "stringview_iter.slice"sv) { - CHECK_ERR(makeStringSliceIter(ctx, pos, annotations)); - return Ok{}; - } - goto parse_error; - default: goto parse_error; + switch (buf[17]) { + case 'g': + if (op == "stringview_wtf16.get_codeunit"sv) { + CHECK_ERR(makeStringWTF16Get(ctx, pos, annotations)); + return Ok{}; } - } - case 'w': { - switch (buf[14]) { - case '1': { - switch (buf[17]) { - case 'g': - if (op == "stringview_wtf16.get_codeunit"sv) { - CHECK_ERR(makeStringWTF16Get(ctx, pos, annotations)); - return Ok{}; - } - goto parse_error; - case 'l': - if (op == "stringview_wtf16.length"sv) { - CHECK_ERR(makeStringMeasure(ctx, pos, annotations, StringMeasureWTF16View)); - return Ok{}; - } - goto parse_error; - case 's': - if (op == "stringview_wtf16.slice"sv) { - CHECK_ERR(makeStringSliceWTF(ctx, pos, annotations, StringSliceWTF16)); - return Ok{}; - } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (buf[16]) { - case 'a': - if (op == "stringview_wtf8.advance"sv) { - CHECK_ERR(makeStringWTF8Advance(ctx, pos, annotations)); - return Ok{}; - } - goto parse_error; - case 's': - if (op == "stringview_wtf8.slice"sv) { - CHECK_ERR(makeStringSliceWTF(ctx, pos, annotations, StringSliceWTF8)); - return Ok{}; - } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; + goto parse_error; + case 'l': + if (op == "stringview_wtf16.length"sv) { + CHECK_ERR(makeStringMeasure(ctx, pos, annotations, StringMeasureWTF16)); + return Ok{}; } - } + goto parse_error; + case 's': + if (op == "stringview_wtf16.slice"sv) { + CHECK_ERR(makeStringSliceWTF(ctx, pos, annotations)); + return Ok{}; + } + goto parse_error; default: goto parse_error; } } diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index c8f83f1ba90..8fae5d0731a 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -170,18 +170,8 @@ void ReFinalize::visitStringMeasure(StringMeasure* curr) { curr->finalize(); } void ReFinalize::visitStringEncode(StringEncode* curr) { curr->finalize(); } void ReFinalize::visitStringConcat(StringConcat* curr) { curr->finalize(); } void ReFinalize::visitStringEq(StringEq* curr) { curr->finalize(); } -void ReFinalize::visitStringAs(StringAs* curr) { curr->finalize(); } -void ReFinalize::visitStringWTF8Advance(StringWTF8Advance* curr) { - curr->finalize(); -} void ReFinalize::visitStringWTF16Get(StringWTF16Get* curr) { curr->finalize(); } -void ReFinalize::visitStringIterNext(StringIterNext* curr) { curr->finalize(); } -void ReFinalize::visitStringIterMove(StringIterMove* curr) { curr->finalize(); } void ReFinalize::visitStringSliceWTF(StringSliceWTF* curr) { curr->finalize(); } -void ReFinalize::visitStringSliceIter(StringSliceIter* curr) { - curr->finalize(); -} - void ReFinalize::visitContNew(ContNew* curr) { curr->finalize(); } void ReFinalize::visitContBind(ContBind* curr) { curr->finalize(); } void ReFinalize::visitResume(Resume* curr) { curr->finalize(); } diff --git a/src/ir/child-typer.h b/src/ir/child-typer.h index 94ef11d777e..e015f3db88f 100644 --- a/src/ir/child-typer.h +++ b/src/ir/child-typer.h @@ -991,11 +991,7 @@ template struct ChildTyper : OverriddenVisitor { void visitStringConst(StringConst* curr) {} void visitStringMeasure(StringMeasure* curr) { - if (curr->op == StringMeasureWTF16View) { - note(&curr->ref, Type(HeapType::stringview_wtf16, Nullable)); - } else { - note(&curr->ref, Type(HeapType::string, Nullable)); - } + note(&curr->ref, Type(HeapType::string, Nullable)); } void visitStringEncode(StringEncode* curr, @@ -1035,48 +1031,17 @@ template struct ChildTyper : OverriddenVisitor { note(&curr->right, stringref); } - void visitStringAs(StringAs* curr) { - note(&curr->ref, Type(HeapType::string, Nullable)); - } - - void visitStringWTF8Advance(StringWTF8Advance* curr) { - note(&curr->ref, Type(HeapType::stringview_wtf8, Nullable)); - note(&curr->pos, Type::i32); - note(&curr->bytes, Type::i32); - } - void visitStringWTF16Get(StringWTF16Get* curr) { - note(&curr->ref, Type(HeapType::stringview_wtf16, Nullable)); + note(&curr->ref, Type(HeapType::string, Nullable)); note(&curr->pos, Type::i32); } - void visitStringIterNext(StringIterNext* curr) { - note(&curr->ref, Type(HeapType::stringview_iter, Nullable)); - } - - void visitStringIterMove(StringIterMove* curr) { - note(&curr->ref, Type(HeapType::stringview_iter, Nullable)); - note(&curr->num, Type::i32); - } - void visitStringSliceWTF(StringSliceWTF* curr) { - switch (curr->op) { - case StringSliceWTF8: - note(&curr->ref, Type(HeapType::stringview_wtf8, Nullable)); - break; - case StringSliceWTF16: - note(&curr->ref, Type(HeapType::stringview_wtf16, Nullable)); - break; - } + note(&curr->ref, Type(HeapType::string, Nullable)); note(&curr->start, Type::i32); note(&curr->end, Type::i32); } - void visitStringSliceIter(StringSliceIter* curr) { - note(&curr->ref, Type(HeapType::stringview_iter, Nullable)); - note(&curr->num, Type::i32); - } - void visitContBind(ContBind* curr) { auto paramsBefore = curr->contTypeBefore.getContinuation().type.getSignature().params; diff --git a/src/ir/cost.h b/src/ir/cost.h index edb39546d82..8af68dbf1a1 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -706,25 +706,12 @@ struct CostAnalyzer : public OverriddenVisitor { // "3" is chosen since strings might or might not be interned in the engine. return 3 + visit(curr->left) + visit(curr->right); } - CostType visitStringAs(StringAs* curr) { return 4 + visit(curr->ref); } - CostType visitStringWTF8Advance(StringWTF8Advance* curr) { - return 4 + visit(curr->ref) + visit(curr->pos) + visit(curr->bytes); - } CostType visitStringWTF16Get(StringWTF16Get* curr) { return 1 + visit(curr->ref) + visit(curr->pos); } - CostType visitStringIterNext(StringIterNext* curr) { - return 2 + visit(curr->ref); - } - CostType visitStringIterMove(StringIterMove* curr) { - return 4 + visit(curr->ref) + visit(curr->num); - } CostType visitStringSliceWTF(StringSliceWTF* curr) { return 8 + visit(curr->ref) + visit(curr->start) + visit(curr->end); } - CostType visitStringSliceIter(StringSliceIter* curr) { - return 8 + visit(curr->ref) + visit(curr->num); - } CostType visitContBind(ContBind* curr) { // Inspired by struct.new: The only cost of cont.bind is that it may need to diff --git a/src/ir/effects.h b/src/ir/effects.h index ef9aceb37cd..e4078eb1c62 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -997,45 +997,14 @@ class EffectAnalyzer { } } } - void visitStringAs(StringAs* curr) { - // traps when ref is null. - parent.implicitTrap = true; - } - void visitStringWTF8Advance(StringWTF8Advance* curr) { - // traps when ref is null. - parent.implicitTrap = true; - } void visitStringWTF16Get(StringWTF16Get* curr) { // traps when ref is null. parent.implicitTrap = true; } - void visitStringIterNext(StringIterNext* curr) { - // traps when ref is null. - parent.implicitTrap = true; - // modifies state in the iterator. we model that as accessing heap memory - // in an array atm TODO consider adding a new effect type for this (we - // added one for arrays because struct/array operations often interleave, - // say with vtable accesses, but it's not clear adding overhead to this - // class is worth it for string iters) - parent.readsArray = true; - parent.writesArray = true; - } - void visitStringIterMove(StringIterMove* curr) { - // traps when ref is null. - parent.implicitTrap = true; - // see StringIterNext. - parent.readsArray = true; - parent.writesArray = true; - } void visitStringSliceWTF(StringSliceWTF* curr) { // traps when ref is null. parent.implicitTrap = true; } - void visitStringSliceIter(StringSliceIter* curr) { - // traps when ref is null. - parent.implicitTrap = true; - } - void visitContBind(ContBind* curr) { // traps when curr->cont is null ref. parent.implicitTrap = true; diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index c44cd7ce1c3..ac320c4192a 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -1084,34 +1084,14 @@ struct InfoCollector // TODO: optimize when possible addRoot(curr); } - void visitStringAs(StringAs* curr) { - // TODO: optimize when possible - addRoot(curr); - } - void visitStringWTF8Advance(StringWTF8Advance* curr) { - // TODO: optimize when possible - addRoot(curr); - } void visitStringWTF16Get(StringWTF16Get* curr) { // TODO: optimize when possible addRoot(curr); } - void visitStringIterNext(StringIterNext* curr) { - // TODO: optimize when possible - addRoot(curr); - } - void visitStringIterMove(StringIterMove* curr) { - // TODO: optimize when possible - addRoot(curr); - } void visitStringSliceWTF(StringSliceWTF* curr) { // TODO: optimize when possible addRoot(curr); } - void visitStringSliceIter(StringSliceIter* curr) { - // TODO: optimize when possible - addRoot(curr); - } // TODO: Model which throws can go to which catches. For now, anything thrown // is sent to the location of that tag, and any catch of that tag can diff --git a/src/ir/subtype-exprs.h b/src/ir/subtype-exprs.h index 1457e1ef509..f563cce1453 100644 --- a/src/ir/subtype-exprs.h +++ b/src/ir/subtype-exprs.h @@ -383,13 +383,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor { void visitStringEncode(StringEncode* curr) {} void visitStringConcat(StringConcat* curr) {} void visitStringEq(StringEq* curr) {} - void visitStringAs(StringAs* curr) {} - void visitStringWTF8Advance(StringWTF8Advance* curr) {} void visitStringWTF16Get(StringWTF16Get* curr) {} - void visitStringIterNext(StringIterNext* curr) {} - void visitStringIterMove(StringIterMove* curr) {} void visitStringSliceWTF(StringSliceWTF* curr) {} - void visitStringSliceIter(StringSliceIter* curr) {} void visitContBind(ContBind* curr) { WASM_UNREACHABLE("not implemented"); } void visitContNew(ContNew* curr) { WASM_UNREACHABLE("not implemented"); } diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp index 0144b933060..12a8c7c3621 100644 --- a/src/ir/type-updating.cpp +++ b/src/ir/type-updating.cpp @@ -304,15 +304,6 @@ namespace TypeUpdating { bool canHandleAsLocal(Type type) { // TODO: Inline this into its callers. - if (type.isRef()) { - // V8 does not accept nullable string views, and so we must avoid putting - // them in locals (as even a non-nullable one may end up nullable if we see - // situations that require fixing in handleNonDefaultableLocals). - auto heapType = type.getHeapType(); - return heapType != HeapType::stringview_wtf8 && - heapType != HeapType::stringview_wtf16 && - heapType != HeapType::stringview_iter; - } return type.isConcrete(); } diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index dfde2d7effe..86a6e8df9e9 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -40,9 +40,6 @@ function initializeConstants() { ['i31ref', 'I31ref'], ['structref', 'Structref'], ['stringref', 'Stringref'], - ['stringview_wtf8', 'StringviewWTF8'], - ['stringview_wtf16', 'StringviewWTF16'], - ['stringview_iter', 'StringviewIter'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] ].forEach(entry => { @@ -127,13 +124,8 @@ function initializeConstants() { 'StringEncode', 'StringConcat', 'StringEq', - 'StringAs', - 'StringWTF8Advance', 'StringWTF16Get', - 'StringIterNext', - 'StringIterMove', 'StringSliceWTF', - 'StringSliceIter' ].forEach(name => { Module['ExpressionIds'][name] = Module[name + 'Id'] = Module['_Binaryen' + name + 'Id'](); }); @@ -589,7 +581,6 @@ function initializeConstants() { 'StringMeasureWTF8', 'StringMeasureWTF16', 'StringMeasureIsUSV', - 'StringMeasureWTF16View', 'StringEncodeUTF8', 'StringEncodeLossyUTF8', 'StringEncodeWTF8', @@ -598,13 +589,6 @@ function initializeConstants() { 'StringEncodeLossyUTF8Array', 'StringEncodeWTF8Array', 'StringEncodeWTF16Array', - 'StringAsWTF8', - 'StringAsWTF16', - 'StringAsIter', - 'StringIterMoveAdvance', - 'StringIterMoveRewind', - 'StringSliceWTF8', - 'StringSliceWTF16', 'StringEqEqual', 'StringEqCompare' ].forEach(name => { @@ -2338,24 +2322,6 @@ function wrapModule(module, self = {}) { } }; - self['stringview_wtf8'] = { - 'pop'() { - return Module['_BinaryenPop'](module, Module['stringview_wtf8']); - } - }; - - self['stringview_wtf16'] = { - 'pop'() { - return Module['_BinaryenPop'](module, Module['stringview_wtf16']); - } - }; - - self['stringview_iter'] = { - 'pop'() { - return Module['_BinaryenPop'](module, Module['stringview_iter']); - } - }; - self['ref'] = { 'null'(type) { return Module['_BinaryenRefNull'](module, type); @@ -2436,9 +2402,6 @@ function wrapModule(module, self = {}) { // TODO: struct.* // TODO: array.* // TODO: string.* - // TODO: stringview_wtf8.* - // TODO: stringview_wtf16.* - // TODO: stringview_iter.* // 'Module' operations self['addFunction'] = function(name, params, results, varTypes, body) { diff --git a/src/parser/contexts.h b/src/parser/contexts.h index 3e42d0d6b6c..a1730234ef9 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -217,9 +217,6 @@ template struct TypeParserCtx { HeapTypeT makeArrayType() { return HeapType::array; } HeapTypeT makeExnType() { return HeapType::exn; } HeapTypeT makeStringType() { return HeapType::string; } - HeapTypeT makeStringViewWTF8Type() { return HeapType::stringview_wtf8; } - HeapTypeT makeStringViewWTF16Type() { return HeapType::stringview_wtf16; } - HeapTypeT makeStringViewIterType() { return HeapType::stringview_iter; } HeapTypeT makeContType() { return HeapType::cont; } HeapTypeT makeNoneType() { return HeapType::none; } HeapTypeT makeNoextType() { return HeapType::noext; } @@ -799,9 +796,6 @@ struct NullInstrParserCtx { Result<> makeStringEq(Index, const std::vector&, StringEqOp) { return Ok{}; } - Result<> makeStringAs(Index, const std::vector&, StringAsOp) { - return Ok{}; - } Result<> makeStringWTF8Advance(Index, const std::vector&) { return Ok{}; } @@ -811,15 +805,7 @@ struct NullInstrParserCtx { Result<> makeStringIterNext(Index, const std::vector&) { return Ok{}; } - Result<> - makeStringIterMove(Index, const std::vector&, StringIterMoveOp) { - return Ok{}; - } - Result<> - makeStringSliceWTF(Index, const std::vector&, StringSliceWTFOp) { - return Ok{}; - } - Result<> makeStringSliceIter(Index, const std::vector&) { + Result<> makeStringSliceWTF(Index, const std::vector&) { return Ok{}; } template @@ -2556,42 +2542,14 @@ struct ParseDefsCtx : TypeParserCtx { return withLoc(pos, irBuilder.makeStringEq(op)); } - Result<> makeStringAs(Index pos, - const std::vector& annotations, - StringAsOp op) { - return withLoc(pos, irBuilder.makeStringAs(op)); - } - - Result<> makeStringWTF8Advance(Index pos, - const std::vector& annotations) { - return withLoc(pos, irBuilder.makeStringWTF8Advance()); - } - Result<> makeStringWTF16Get(Index pos, const std::vector& annotations) { return withLoc(pos, irBuilder.makeStringWTF16Get()); } - Result<> makeStringIterNext(Index pos, - const std::vector& annotations) { - return withLoc(pos, irBuilder.makeStringIterNext()); - } - - Result<> makeStringIterMove(Index pos, - const std::vector& annotations, - StringIterMoveOp op) { - return withLoc(pos, irBuilder.makeStringIterMove(op)); - } - Result<> makeStringSliceWTF(Index pos, - const std::vector& annotations, - StringSliceWTFOp op) { - return withLoc(pos, irBuilder.makeStringSliceWTF(op)); - } - - Result<> makeStringSliceIter(Index pos, - const std::vector& annotations) { - return withLoc(pos, irBuilder.makeStringSliceIter()); + const std::vector& annotations) { + return withLoc(pos, irBuilder.makeStringSliceWTF()); } Result<> makeContBind(Index pos, diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 30a82882262..60d3f039197 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -285,26 +285,9 @@ Result<> makeStringConcat(Ctx&, Index, const std::vector&); template Result<> makeStringEq(Ctx&, Index, const std::vector&, StringEqOp); template -Result<> -makeStringAs(Ctx&, Index, const std::vector&, StringAsOp op); -template -Result<> makeStringWTF8Advance(Ctx&, Index, const std::vector&); -template Result<> makeStringWTF16Get(Ctx&, Index, const std::vector&); template -Result<> makeStringIterNext(Ctx&, Index, const std::vector&); -template -Result<> makeStringIterMove(Ctx&, - Index, - const std::vector&, - StringIterMoveOp op); -template -Result<> makeStringSliceWTF(Ctx&, - Index, - const std::vector&, - StringSliceWTFOp op); -template -Result<> makeStringSliceIter(Ctx&, Index, const std::vector&); +Result<> makeStringSliceWTF(Ctx&, Index, const std::vector&); template Result<> makeContBind(Ctx&, Index, const std::vector&); template @@ -314,6 +297,11 @@ Result<> makeResume(Ctx&, Index, const std::vector&); template Result<> makeSuspend(Ctx&, Index, const std::vector&); +template +Result<> ignore(Ctx&, Index, const std::vector&) { + return Ok{}; +} + // Modules template MaybeResult maybeTypeidx(Ctx& ctx); template Result typeidx(Ctx&); @@ -421,15 +409,6 @@ template Result heaptype(Ctx& ctx) { if (ctx.in.takeKeyword("string"sv)) { return ctx.makeStringType(); } - if (ctx.in.takeKeyword("stringview_wtf8"sv)) { - return ctx.makeStringViewWTF8Type(); - } - if (ctx.in.takeKeyword("stringview_wtf16"sv)) { - return ctx.makeStringViewWTF16Type(); - } - if (ctx.in.takeKeyword("stringview_iter"sv)) { - return ctx.makeStringViewIterType(); - } if (ctx.in.takeKeyword("cont"sv)) { return ctx.makeContType(); } @@ -489,15 +468,6 @@ template MaybeResult reftype(Ctx& ctx) { if (ctx.in.takeKeyword("stringref"sv)) { return ctx.makeRefType(ctx.makeStringType(), Nullable); } - if (ctx.in.takeKeyword("stringview_wtf8"sv)) { - return ctx.makeRefType(ctx.makeStringViewWTF8Type(), Nullable); - } - if (ctx.in.takeKeyword("stringview_wtf16"sv)) { - return ctx.makeRefType(ctx.makeStringViewWTF16Type(), Nullable); - } - if (ctx.in.takeKeyword("stringview_iter"sv)) { - return ctx.makeRefType(ctx.makeStringViewIterType(), Nullable); - } if (ctx.in.takeKeyword("contref"sv)) { return ctx.makeRefType(ctx.makeContType(), Nullable); } @@ -2435,21 +2405,6 @@ Result<> makeStringEq(Ctx& ctx, return ctx.makeStringEq(pos, annotations, op); } -template -Result<> makeStringAs(Ctx& ctx, - Index pos, - const std::vector& annotations, - StringAsOp op) { - return ctx.makeStringAs(pos, annotations, op); -} - -template -Result<> makeStringWTF8Advance(Ctx& ctx, - Index pos, - const std::vector& annotations) { - return ctx.makeStringWTF8Advance(pos, annotations); -} - template Result<> makeStringWTF16Get(Ctx& ctx, Index pos, @@ -2457,34 +2412,11 @@ Result<> makeStringWTF16Get(Ctx& ctx, return ctx.makeStringWTF16Get(pos, annotations); } -template -Result<> makeStringIterNext(Ctx& ctx, - Index pos, - const std::vector& annotations) { - return ctx.makeStringIterNext(pos, annotations); -} - -template -Result<> makeStringIterMove(Ctx& ctx, - Index pos, - const std::vector& annotations, - StringIterMoveOp op) { - return ctx.makeStringIterMove(pos, annotations, op); -} - template Result<> makeStringSliceWTF(Ctx& ctx, Index pos, - const std::vector& annotations, - StringSliceWTFOp op) { - return ctx.makeStringSliceWTF(pos, annotations, op); -} - -template -Result<> makeStringSliceIter(Ctx& ctx, - Index pos, - const std::vector& annotations) { - return ctx.makeStringSliceIter(pos, annotations); + const std::vector& annotations) { + return ctx.makeStringSliceWTF(pos, annotations); } // contbind ::= 'cont.bind' typeidx typeidx diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 02eaea21c5d..5a00e05f789 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2294,9 +2294,6 @@ struct PrintExpressionContents case StringMeasureIsUSV: printMedium(o, "string.is_usv_sequence"); break; - case StringMeasureWTF16View: - printMedium(o, "stringview_wtf16.length"); - break; case StringMeasureHash: printMedium(o, "string.hash"); break; @@ -2349,56 +2346,11 @@ struct PrintExpressionContents WASM_UNREACHABLE("invalid string.eq*"); } } - void visitStringAs(StringAs* curr) { - switch (curr->op) { - case StringAsWTF8: - printMedium(o, "string.as_wtf8"); - break; - case StringAsWTF16: - printMedium(o, "string.as_wtf16"); - break; - case StringAsIter: - printMedium(o, "string.as_iter"); - break; - default: - WASM_UNREACHABLE("invalid string.as*"); - } - } - void visitStringWTF8Advance(StringWTF8Advance* curr) { - printMedium(o, "stringview_wtf8.advance"); - } void visitStringWTF16Get(StringWTF16Get* curr) { printMedium(o, "stringview_wtf16.get_codeunit"); } - void visitStringIterNext(StringIterNext* curr) { - printMedium(o, "stringview_iter.next"); - } - void visitStringIterMove(StringIterMove* curr) { - switch (curr->op) { - case StringIterMoveAdvance: - printMedium(o, "stringview_iter.advance"); - break; - case StringIterMoveRewind: - printMedium(o, "stringview_iter.rewind"); - break; - default: - WASM_UNREACHABLE("invalid string.move*"); - } - } void visitStringSliceWTF(StringSliceWTF* curr) { - switch (curr->op) { - case StringSliceWTF8: - printMedium(o, "stringview_wtf8.slice"); - break; - case StringSliceWTF16: - printMedium(o, "stringview_wtf16.slice"); - break; - default: - WASM_UNREACHABLE("invalid string.slice*"); - } - } - void visitStringSliceIter(StringSliceIter* curr) { - printMedium(o, "stringview_iter.slice"); + printMedium(o, "stringview_wtf16.slice"); } void visitContBind(ContBind* curr) { printMedium(o, "cont.bind "); diff --git a/src/passes/StringLowering.cpp b/src/passes/StringLowering.cpp index 5b5a5b551f3..27f4e9c070e 100644 --- a/src/passes/StringLowering.cpp +++ b/src/passes/StringLowering.cpp @@ -269,12 +269,8 @@ struct StringLowering : public StringGathering { void updateTypes(Module* module) { TypeMapper::TypeUpdates updates; - // There is no difference between strings and views with imported strings: - // they are all just JS strings, so they all turn into externref. + // Strings turn into externref. updates[HeapType::string] = HeapType::ext; - updates[HeapType::stringview_wtf8] = HeapType::ext; - updates[HeapType::stringview_wtf16] = HeapType::ext; - updates[HeapType::stringview_iter] = HeapType::ext; // The module may have its own array16 type inside a big rec group, but // imported strings expects that type in its own rec group as part of the @@ -397,18 +393,6 @@ struct StringLowering : public StringGathering { lowering.concatImport, {curr->left, curr->right}, lowering.nnExt)); } - void visitStringAs(StringAs* curr) { - // There is no difference between strings and views with imported - // strings: they are all just JS strings, so no conversion is needed. - // However, we must keep the same nullability: the output of StringAs - // must be non-nullable. - auto* ref = curr->ref; - if (ref->type.isNullable()) { - ref = Builder(*getModule()).makeRefAs(RefAsNonNull, ref); - } - replaceCurrent(ref); - } - void visitStringEncode(StringEncode* curr) { Builder builder(*getModule()); switch (curr->op) { @@ -440,14 +424,8 @@ struct StringLowering : public StringGathering { void visitStringMeasure(StringMeasure* curr) { Builder builder(*getModule()); - switch (curr->op) { - case StringMeasureWTF16View: - replaceCurrent( - builder.makeCall(lowering.lengthImport, {curr->ref}, Type::i32)); - return; - default: - WASM_UNREACHABLE("invalid string.measure*"); - } + replaceCurrent( + builder.makeCall(lowering.lengthImport, {curr->ref}, Type::i32)); } void visitStringWTF16Get(StringWTF16Get* curr) { @@ -458,15 +436,9 @@ struct StringLowering : public StringGathering { void visitStringSliceWTF(StringSliceWTF* curr) { Builder builder(*getModule()); - switch (curr->op) { - case StringSliceWTF16: - replaceCurrent(builder.makeCall(lowering.substringImport, - {curr->ref, curr->start, curr->end}, - lowering.nnExt)); - return; - default: - WASM_UNREACHABLE("TODO: all string.slice*"); - } + replaceCurrent(builder.makeCall(lowering.substringImport, + {curr->ref, curr->start, curr->end}, + lowering.nnExt)); } }; diff --git a/src/passes/TypeGeneralizing.cpp b/src/passes/TypeGeneralizing.cpp index 26a0f1eab9b..81dd0a39ea3 100644 --- a/src/passes/TypeGeneralizing.cpp +++ b/src/passes/TypeGeneralizing.cpp @@ -865,15 +865,8 @@ struct TransferFn : OverriddenVisitor { void visitStringEncode(StringEncode* curr) { WASM_UNREACHABLE("TODO"); } void visitStringConcat(StringConcat* curr) { WASM_UNREACHABLE("TODO"); } void visitStringEq(StringEq* curr) { WASM_UNREACHABLE("TODO"); } - void visitStringAs(StringAs* curr) { WASM_UNREACHABLE("TODO"); } - void visitStringWTF8Advance(StringWTF8Advance* curr) { - WASM_UNREACHABLE("TODO"); - } void visitStringWTF16Get(StringWTF16Get* curr) { WASM_UNREACHABLE("TODO"); } - void visitStringIterNext(StringIterNext* curr) { WASM_UNREACHABLE("TODO"); } - void visitStringIterMove(StringIterMove* curr) { WASM_UNREACHABLE("TODO"); } void visitStringSliceWTF(StringSliceWTF* curr) { WASM_UNREACHABLE("TODO"); } - void visitStringSliceIter(StringSliceIter* curr) { WASM_UNREACHABLE("TODO"); } void visitContBind(ContBind* curr) { WASM_UNREACHABLE("TODO"); } void visitContNew(ContNew* curr) { WASM_UNREACHABLE("TODO"); } diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 3378d0745f7..5de10c0d1ba 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -29,13 +29,6 @@ namespace wasm { namespace { -bool canBeNullable(HeapType type) { - // V8 does not accept nullable string views. - return type != HeapType::stringview_wtf8 && - type != HeapType::stringview_wtf16 && - type != HeapType::stringview_iter; -} - } // anonymous namespace TranslateToFuzzReader::TranslateToFuzzReader(Module& wasm, @@ -2654,16 +2647,6 @@ Expression* TranslateToFuzzReader::makeBasicRef(Type type) { } WASM_UNREACHABLE("bad switch"); } - case HeapType::stringview_wtf16: - // We fully support wtf16 strings. - return builder.makeStringAs(StringAsWTF16, - makeTrappingRefUse(HeapType::string)); - case HeapType::stringview_wtf8: - case HeapType::stringview_iter: - // We do not have interpreter support for wtf8 and iter, so emit something - // that does not return, with a block that casts to the type the parent - // expects. - return builder.makeBlock({_makeunreachable()}, type); case HeapType::none: case HeapType::noext: case HeapType::nofunc: @@ -2719,9 +2702,6 @@ Expression* TranslateToFuzzReader::makeCompoundRef(Type type) { if (funcContext && !funcContext->typeLocals[type].empty()) { return makeLocalGet(type); } - if (!canBeNullable(heapType)) { - return makeConst(type); - } return builder.makeRefAs(RefAsNonNull, builder.makeRefNull(heapType)); } @@ -2834,11 +2814,10 @@ Expression* TranslateToFuzzReader::makeStringConcat() { } Expression* TranslateToFuzzReader::makeStringSlice() { - // StringViews cannot be non-nullable. - auto* ref = make(Type(HeapType::stringview_wtf16, NonNullable)); + auto* ref = make(Type(HeapType::string, getNullability())); auto* start = make(Type::i32); auto* end = make(Type::i32); - return builder.makeStringSliceWTF(StringSliceWTF16, ref, start, end); + return builder.makeStringSliceWTF(ref, start, end); } Expression* TranslateToFuzzReader::makeStringEq(Type type) { @@ -2866,8 +2845,7 @@ Expression* TranslateToFuzzReader::makeStringMeasure(Type type) { Expression* TranslateToFuzzReader::makeStringGet(Type type) { assert(type == Type::i32); - // StringViews cannot be non-nullable. - auto* ref = make(Type(HeapType::stringview_wtf16, NonNullable)); + auto* ref = make(Type(HeapType::string, getNullability())); auto* pos = make(Type::i32); return builder.makeStringWTF16Get(ref, pos); } @@ -4277,12 +4255,6 @@ HeapType TranslateToFuzzReader::getSubType(HeapType type) { return HeapType::exn; case HeapType::string: return HeapType::string; - case HeapType::stringview_wtf8: - return HeapType::stringview_wtf8; - case HeapType::stringview_wtf16: - return HeapType::stringview_wtf16; - case HeapType::stringview_iter: - return HeapType::stringview_iter; case HeapType::none: case HeapType::noext: case HeapType::nofunc: diff --git a/src/tools/fuzzing/heap-types.cpp b/src/tools/fuzzing/heap-types.cpp index 3d0d29153ba..08b4c445310 100644 --- a/src/tools/fuzzing/heap-types.cpp +++ b/src/tools/fuzzing/heap-types.cpp @@ -395,9 +395,6 @@ struct HeapTypeGeneratorImpl { case HeapType::ext: case HeapType::exn: case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: case HeapType::none: case HeapType::noext: case HeapType::nofunc: @@ -460,17 +457,7 @@ struct HeapTypeGeneratorImpl { case HeapType::string: candidates.push_back(HeapType::any); break; - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - break; case HeapType::none: - if (features.hasStrings() && rand.oneIn(10)) { - candidates.push_back(HeapType::stringview_wtf8); - candidates.push_back(HeapType::stringview_wtf16); - candidates.push_back(HeapType::stringview_iter); - break; - } return pickSubAny(); case HeapType::nofunc: return pickSubFunc(); diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index d3f7980848d..c025764e717 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -93,14 +93,6 @@ class EvallingModuleRunner : public ModuleRunnerBase { // serialize them.) throw FailToEvalException("table.set: TODO"); } - - Flow visitStringAs(StringAs* curr) { - // TODO: It is not clear how we can handle string.as, since it can lead to - // us needing string_views in globals, but string.as is not a constant - // instruction, so we cannot generate such globals atm. Perhaps we - // could generate them in the start function? - throw FailToEvalException("string.as: TODO"); - } }; // Build an artificial `env` module based on a module's imports, so that the diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 9610aed9fec..ce8f1dbbaf2 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -369,10 +369,7 @@ enum EncodedType { exnref = -0x17, // 0x69 nullexnref = -0xc, // 0x74 // string reference types - stringref = -0x19, // 0x67 - stringview_wtf8 = -0x1a, // 0x66 - stringview_wtf16 = -0x1e, // 0x62 - stringview_iter = -0x1f, // 0x61 + stringref = -0x19, // 0x67 // type forms Func = -0x20, // 0x60 Cont = -0x23, // 0x5d @@ -402,12 +399,6 @@ enum EncodedHeapType { struct_ = -0x15, // 0x6b array = -0x16, // 0x6a string = -0x19, // 0x67 - // stringview/iter constants are identical to type, and cannot be duplicated - // here as that would be a compiler error, so add _heap suffixes. See - // https://github.com/WebAssembly/stringref/issues/12 - stringview_wtf8_heap = -0x1a, // 0x66 - stringview_wtf16_heap = -0x1e, // 0x62 - stringview_iter_heap = -0x1f, // 0x61 }; namespace CustomSections { @@ -1146,18 +1137,8 @@ enum ASTNodes { StringEncodeLossyUTF8 = 0x8d, StringEncodeWTF8 = 0x8e, StringNewUTF8Try = 0x8f, - StringAsWTF8 = 0x90, - StringViewWTF8Advance = 0x91, - StringViewWTF8Slice = 0x93, - StringAsWTF16 = 0x98, - StringViewWTF16Length = 0x99, StringViewWTF16GetCodePoint = 0x9a, StringViewWTF16Slice = 0x9c, - StringAsIter = 0xa0, - StringViewIterNext = 0xa1, - StringViewIterAdvance = 0xa2, - StringViewIterRewind = 0xa3, - StringViewIterSlice = 0xa4, StringCompare = 0xa8, StringFromCodePoint = 0xa9, StringHash = 0xaa, @@ -1782,13 +1763,8 @@ class WasmBinaryReader { bool maybeVisitStringEncode(Expression*& out, uint32_t code); bool maybeVisitStringConcat(Expression*& out, uint32_t code); bool maybeVisitStringEq(Expression*& out, uint32_t code); - bool maybeVisitStringAs(Expression*& out, uint32_t code); - bool maybeVisitStringWTF8Advance(Expression*& out, uint32_t code); bool maybeVisitStringWTF16Get(Expression*& out, uint32_t code); - bool maybeVisitStringIterNext(Expression*& out, uint32_t code); - bool maybeVisitStringIterMove(Expression*& out, uint32_t code); bool maybeVisitStringSliceWTF(Expression*& out, uint32_t code); - bool maybeVisitStringSliceIter(Expression*& out, uint32_t code); void visitSelect(Select* curr, uint8_t code); void visitReturn(Return* curr); void visitMemorySize(MemorySize* curr); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index fbc680d17bd..e476e7b9fac 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1151,22 +1151,6 @@ class Builder { ret->finalize(); return ret; } - StringAs* makeStringAs(StringAsOp op, Expression* ref) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->ref = ref; - ret->finalize(); - return ret; - } - StringWTF8Advance* - makeStringWTF8Advance(Expression* ref, Expression* pos, Expression* bytes) { - auto* ret = wasm.allocator.alloc(); - ret->ref = ref; - ret->pos = pos; - ret->bytes = bytes; - ret->finalize(); - return ret; - } StringWTF16Get* makeStringWTF16Get(Expression* ref, Expression* pos) { auto* ret = wasm.allocator.alloc(); ret->ref = ref; @@ -1174,41 +1158,15 @@ class Builder { ret->finalize(); return ret; } - StringIterNext* makeStringIterNext(Expression* ref) { - auto* ret = wasm.allocator.alloc(); - ret->ref = ref; - ret->finalize(); - return ret; - } - StringIterMove* - makeStringIterMove(StringIterMoveOp op, Expression* ref, Expression* num) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->ref = ref; - ret->num = num; - ret->finalize(); - return ret; - } - StringSliceWTF* makeStringSliceWTF(StringSliceWTFOp op, - Expression* ref, - Expression* start, - Expression* end) { + StringSliceWTF* + makeStringSliceWTF(Expression* ref, Expression* start, Expression* end) { auto* ret = wasm.allocator.alloc(); - ret->op = op; ret->ref = ref; ret->start = start; ret->end = end; ret->finalize(); return ret; } - StringSliceIter* makeStringSliceIter(Expression* ref, Expression* num) { - auto* ret = wasm.allocator.alloc(); - ret->ref = ref; - ret->num = num; - ret->finalize(); - return ret; - } - ContBind* makeContBind(HeapType contTypeBefore, HeapType contTypeAfter, const std::vector& operands, diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index b5eebfc2b46..b9d71608c7f 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -750,44 +750,17 @@ DELEGATE_FIELD_CHILD(StringEq, right) DELEGATE_FIELD_CHILD(StringEq, left) DELEGATE_FIELD_CASE_END(StringEq) -DELEGATE_FIELD_CASE_START(StringAs) -DELEGATE_FIELD_INT(StringAs, op) -DELEGATE_FIELD_CHILD(StringAs, ref) -DELEGATE_FIELD_CASE_END(StringAs) - -DELEGATE_FIELD_CASE_START(StringWTF8Advance) -DELEGATE_FIELD_CHILD(StringWTF8Advance, bytes) -DELEGATE_FIELD_CHILD(StringWTF8Advance, pos) -DELEGATE_FIELD_CHILD(StringWTF8Advance, ref) -DELEGATE_FIELD_CASE_END(StringWTF8Advance) - DELEGATE_FIELD_CASE_START(StringWTF16Get) DELEGATE_FIELD_CHILD(StringWTF16Get, pos) DELEGATE_FIELD_CHILD(StringWTF16Get, ref) DELEGATE_FIELD_CASE_END(StringWTF16Get) -DELEGATE_FIELD_CASE_START(StringIterNext) -DELEGATE_FIELD_CHILD(StringIterNext, ref) -DELEGATE_FIELD_CASE_END(StringIterNext) - -DELEGATE_FIELD_CASE_START(StringIterMove) -DELEGATE_FIELD_INT(StringIterMove, op) -DELEGATE_FIELD_CHILD(StringIterMove, num) -DELEGATE_FIELD_CHILD(StringIterMove, ref) -DELEGATE_FIELD_CASE_END(StringIterMove) - DELEGATE_FIELD_CASE_START(StringSliceWTF) -DELEGATE_FIELD_INT(StringSliceWTF, op) DELEGATE_FIELD_CHILD(StringSliceWTF, end) DELEGATE_FIELD_CHILD(StringSliceWTF, start) DELEGATE_FIELD_CHILD(StringSliceWTF, ref) DELEGATE_FIELD_CASE_END(StringSliceWTF) -DELEGATE_FIELD_CASE_START(StringSliceIter) -DELEGATE_FIELD_CHILD(StringSliceIter, num) -DELEGATE_FIELD_CHILD(StringSliceIter, ref) -DELEGATE_FIELD_CASE_END(StringSliceIter) - DELEGATE_FIELD_CASE_START(ContBind) DELEGATE_FIELD_CHILD(ContBind, cont) DELEGATE_FIELD_CHILD_VECTOR(ContBind, operands) diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def index ca07356b9f5..ea801ab9bb3 100644 --- a/src/wasm-delegations.def +++ b/src/wasm-delegations.def @@ -98,13 +98,8 @@ DELEGATE(StringMeasure); DELEGATE(StringEncode); DELEGATE(StringConcat); DELEGATE(StringEq); -DELEGATE(StringAs); -DELEGATE(StringWTF8Advance); DELEGATE(StringWTF16Get); -DELEGATE(StringIterNext); -DELEGATE(StringIterMove); DELEGATE(StringSliceWTF); -DELEGATE(StringSliceIter); DELEGATE(ContBind); DELEGATE(ContNew); DELEGATE(Resume); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index ec1ba77077a..bd7d78a6ed4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1919,7 +1919,7 @@ class ExpressionRunner : public OverriddenVisitor { Flow visitStringMeasure(StringMeasure* curr) { // For now we only support JS-style strings. - if (curr->op != StringMeasureWTF16View && curr->op != StringMeasureWTF16) { + if (curr->op != StringMeasureWTF16) { return Flow(NONCONSTANT_FLOW); } @@ -2076,29 +2076,6 @@ class ExpressionRunner : public OverriddenVisitor { } return Literal(result); } - Flow visitStringAs(StringAs* curr) { - // For now we only support JS-style strings. - if (curr->op != StringAsWTF16) { - return Flow(NONCONSTANT_FLOW); - } - - Flow flow = visit(curr->ref); - if (flow.breaking()) { - return flow; - } - auto value = flow.getSingleValue(); - auto data = value.getGCData(); - if (!data) { - trap("null ref"); - } - - // A JS-style string can be viewed simply as the underlying data. All we - // need to do is fix up the type. - return Literal(data, curr->type.getHeapType()); - } - Flow visitStringWTF8Advance(StringWTF8Advance* curr) { - return Flow(NONCONSTANT_FLOW); - } Flow visitStringWTF16Get(StringWTF16Get* curr) { NOTE_ENTER("StringWTF16Get"); Flow ref = visit(curr->ref); @@ -2122,18 +2099,7 @@ class ExpressionRunner : public OverriddenVisitor { return Literal(values[i].geti32()); } - Flow visitStringIterNext(StringIterNext* curr) { - return Flow(NONCONSTANT_FLOW); - } - Flow visitStringIterMove(StringIterMove* curr) { - return Flow(NONCONSTANT_FLOW); - } Flow visitStringSliceWTF(StringSliceWTF* curr) { - // For now we only support JS-style strings. - if (curr->op != StringSliceWTF16) { - return Flow(NONCONSTANT_FLOW); - } - Flow ref = visit(curr->ref); if (ref.breaking()) { return ref; @@ -2167,9 +2133,6 @@ class ExpressionRunner : public OverriddenVisitor { } return makeGCData(contents, curr->type); } - Flow visitStringSliceIter(StringSliceIter* curr) { - return Flow(NONCONSTANT_FLOW); - } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 3c4a52bea91..5740829a651 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -212,13 +212,10 @@ class IRBuilder : public UnifiedExpressionVisitor> { [[nodiscard]] Result<> makeStringEncode(StringEncodeOp op, Name mem); [[nodiscard]] Result<> makeStringConcat(); [[nodiscard]] Result<> makeStringEq(StringEqOp op); - [[nodiscard]] Result<> makeStringAs(StringAsOp op); [[nodiscard]] Result<> makeStringWTF8Advance(); [[nodiscard]] Result<> makeStringWTF16Get(); [[nodiscard]] Result<> makeStringIterNext(); - [[nodiscard]] Result<> makeStringIterMove(StringIterMoveOp op); - [[nodiscard]] Result<> makeStringSliceWTF(StringSliceWTFOp op); - [[nodiscard]] Result<> makeStringSliceIter(); + [[nodiscard]] Result<> makeStringSliceWTF(); [[nodiscard]] Result<> makeContBind(HeapType contTypeBefore, HeapType contTypeAfter); [[nodiscard]] Result<> makeContNew(HeapType ct); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 7b8faa16ba8..cfd21661df3 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -321,18 +321,16 @@ class SExpressionWasmBuilder { Expression* makeStringEncode(Element& s, StringEncodeOp op); Expression* makeStringConcat(Element& s); Expression* makeStringEq(Element& s, StringEqOp op); - Expression* makeStringAs(Element& s, StringAsOp op); Expression* makeStringWTF8Advance(Element& s); Expression* makeStringWTF16Get(Element& s); - Expression* makeStringIterNext(Element& s); - Expression* makeStringIterMove(Element& s, StringIterMoveOp op); - Expression* makeStringSliceWTF(Element& s, StringSliceWTFOp op); - Expression* makeStringSliceIter(Element& s); + Expression* makeStringSliceWTF(Element& s); Expression* makeContBind(Element& s); Expression* makeContNew(Element& s); Expression* makeResume(Element& s); Expression* makeSuspend(Element& s); + Expression* ignore(Element& s) { WASM_UNREACHABLE("unsupported"); } + // Helper functions Type parseBlockType(Element& s, Index& i); Index parseMemoryLimits(Element& s, Index i, std::unique_ptr& memory); diff --git a/src/wasm-type.h b/src/wasm-type.h index b18eaa6db12..6422d09ad0d 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -329,9 +329,6 @@ class HeapType { array, exn, string, - stringview_wtf8, - stringview_wtf16, - stringview_iter, none, noext, nofunc, diff --git a/src/wasm.h b/src/wasm.h index 2f3f09ad596..ea63d59def5 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -592,7 +592,6 @@ enum StringMeasureOp { StringMeasureWTF8, StringMeasureWTF16, StringMeasureIsUSV, - StringMeasureWTF16View, StringMeasureHash, }; @@ -612,22 +611,6 @@ enum StringEqOp { StringEqCompare, }; -enum StringAsOp { - StringAsWTF8, - StringAsWTF16, - StringAsIter, -}; - -enum StringIterMoveOp { - StringIterMoveAdvance, - StringIterMoveRewind, -}; - -enum StringSliceWTFOp { - StringSliceWTF8, - StringSliceWTF16, -}; - // // Expressions // @@ -736,13 +719,8 @@ class Expression { StringEncodeId, StringConcatId, StringEqId, - StringAsId, - StringWTF8AdvanceId, StringWTF16GetId, - StringIterNextId, - StringIterMoveId, StringSliceWTFId, - StringSliceIterId, ContBindId, ContNewId, ResumeId, @@ -1912,31 +1890,6 @@ class StringEq : public SpecificExpression { void finalize(); }; -class StringAs : public SpecificExpression { -public: - StringAs() = default; - StringAs(MixedArena& allocator) {} - - StringAsOp op; - - Expression* ref; - - void finalize(); -}; - -class StringWTF8Advance - : public SpecificExpression { -public: - StringWTF8Advance() = default; - StringWTF8Advance(MixedArena& allocator) {} - - Expression* ref; - Expression* pos; - Expression* bytes; - - void finalize(); -}; - class StringWTF16Get : public SpecificExpression { public: StringWTF16Get() = default; @@ -1948,39 +1901,11 @@ class StringWTF16Get : public SpecificExpression { void finalize(); }; -class StringIterNext : public SpecificExpression { -public: - StringIterNext() = default; - StringIterNext(MixedArena& allocator) {} - - Expression* ref; - - void finalize(); -}; - -class StringIterMove : public SpecificExpression { -public: - StringIterMove() = default; - StringIterMove(MixedArena& allocator) {} - - // Whether the movement is to advance or reverse. - StringIterMoveOp op; - - Expression* ref; - - // How many codepoints to advance or reverse. - Expression* num; - - void finalize(); -}; - class StringSliceWTF : public SpecificExpression { public: StringSliceWTF() = default; StringSliceWTF(MixedArena& allocator) {} - StringSliceWTFOp op; - Expression* ref; Expression* start; Expression* end; @@ -1988,18 +1913,6 @@ class StringSliceWTF : public SpecificExpression { void finalize(); }; -class StringSliceIter - : public SpecificExpression { -public: - StringSliceIter() = default; - StringSliceIter(MixedArena& allocator) {} - - Expression* ref; - Expression* num; - - void finalize(); -}; - class ContBind : public SpecificExpression { public: ContBind(MixedArena& allocator) : operands(allocator) {} diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 48ade544774..2c61be12a18 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -149,9 +149,6 @@ Literal::Literal(const Literal& other) : type(other.type) { case HeapType::exn: WASM_UNREACHABLE("invalid type"); case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: WASM_UNREACHABLE("TODO: string literals"); } } @@ -662,10 +659,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { } break; } - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - WASM_UNREACHABLE("TODO: string literals"); } } else if (heapType.isSignature()) { o << "funcref(" << literal.getFunc() << ")"; @@ -2684,9 +2677,6 @@ Literal Literal::externalize() const { HeapType::ext); } case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: WASM_UNREACHABLE("TODO: string literals"); default: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index c1e506c8e02..cf05e1b7337 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1547,15 +1547,6 @@ void WasmBinaryWriter::writeType(Type type) { case HeapType::string: o << S32LEB(BinaryConsts::EncodedType::stringref); return; - case HeapType::stringview_wtf8: - o << S32LEB(BinaryConsts::EncodedType::stringview_wtf8); - return; - case HeapType::stringview_wtf16: - o << S32LEB(BinaryConsts::EncodedType::stringview_wtf16); - return; - case HeapType::stringview_iter: - o << S32LEB(BinaryConsts::EncodedType::stringview_iter); - return; case HeapType::none: o << S32LEB(BinaryConsts::EncodedType::nullref); return; @@ -1668,15 +1659,6 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { case HeapType::string: ret = BinaryConsts::EncodedHeapType::string; break; - case HeapType::stringview_wtf8: - ret = BinaryConsts::EncodedHeapType::stringview_wtf8_heap; - break; - case HeapType::stringview_wtf16: - ret = BinaryConsts::EncodedHeapType::stringview_wtf16_heap; - break; - case HeapType::stringview_iter: - ret = BinaryConsts::EncodedHeapType::stringview_iter_heap; - break; case HeapType::none: ret = BinaryConsts::EncodedHeapType::none; break; @@ -2051,15 +2033,6 @@ bool WasmBinaryReader::getBasicType(int32_t code, Type& out) { case BinaryConsts::EncodedType::stringref: out = Type(HeapType::string, Nullable); return true; - case BinaryConsts::EncodedType::stringview_wtf8: - out = Type(HeapType::stringview_wtf8, Nullable); - return true; - case BinaryConsts::EncodedType::stringview_wtf16: - out = Type(HeapType::stringview_wtf16, Nullable); - return true; - case BinaryConsts::EncodedType::stringview_iter: - out = Type(HeapType::stringview_iter, Nullable); - return true; case BinaryConsts::EncodedType::nullref: out = Type(HeapType::none, Nullable); return true; @@ -2112,15 +2085,6 @@ bool WasmBinaryReader::getBasicHeapType(int64_t code, HeapType& out) { case BinaryConsts::EncodedHeapType::string: out = HeapType::string; return true; - case BinaryConsts::EncodedHeapType::stringview_wtf8_heap: - out = HeapType::stringview_wtf8; - return true; - case BinaryConsts::EncodedHeapType::stringview_wtf16_heap: - out = HeapType::stringview_wtf16; - return true; - case BinaryConsts::EncodedHeapType::stringview_iter_heap: - out = HeapType::stringview_iter; - return true; case BinaryConsts::EncodedHeapType::none: out = HeapType::none; return true; @@ -4292,27 +4256,12 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { if (maybeVisitStringEq(curr, opcode)) { break; } - if (maybeVisitStringAs(curr, opcode)) { - break; - } - if (maybeVisitStringWTF8Advance(curr, opcode)) { - break; - } if (maybeVisitStringWTF16Get(curr, opcode)) { break; } - if (maybeVisitStringIterNext(curr, opcode)) { - break; - } - if (maybeVisitStringIterMove(curr, opcode)) { - break; - } if (maybeVisitStringSliceWTF(curr, opcode)) { break; } - if (maybeVisitStringSliceIter(curr, opcode)) { - break; - } if (opcode == BinaryConsts::ExternInternalize || opcode == BinaryConsts::ExternExternalize) { visitRefAs((curr = allocator.alloc())->cast(), opcode); @@ -7646,8 +7595,6 @@ bool WasmBinaryReader::maybeVisitStringMeasure(Expression*& out, op = StringMeasureWTF16; } else if (code == BinaryConsts::StringIsUSV) { op = StringMeasureIsUSV; - } else if (code == BinaryConsts::StringViewWTF16Length) { - op = StringMeasureWTF16View; } else if (code == BinaryConsts::StringHash) { op = StringMeasureHash; } else { @@ -7728,34 +7675,6 @@ bool WasmBinaryReader::maybeVisitStringEq(Expression*& out, uint32_t code) { return true; } -bool WasmBinaryReader::maybeVisitStringAs(Expression*& out, uint32_t code) { - StringAsOp op; - if (code == BinaryConsts::StringAsWTF8) { - op = StringAsWTF8; - } else if (code == BinaryConsts::StringAsWTF16) { - op = StringAsWTF16; - } else if (code == BinaryConsts::StringAsIter) { - op = StringAsIter; - } else { - return false; - } - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringAs(op, ref); - return true; -} - -bool WasmBinaryReader::maybeVisitStringWTF8Advance(Expression*& out, - uint32_t code) { - if (code != BinaryConsts::StringViewWTF8Advance) { - return false; - } - auto* bytes = popNonVoidExpression(); - auto* pos = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringWTF8Advance(ref, pos, bytes); - return true; -} - bool WasmBinaryReader::maybeVisitStringWTF16Get(Expression*& out, uint32_t code) { if (code != BinaryConsts::StringViewWTF16GetCodePoint) { @@ -7767,57 +7686,15 @@ bool WasmBinaryReader::maybeVisitStringWTF16Get(Expression*& out, return true; } -bool WasmBinaryReader::maybeVisitStringIterNext(Expression*& out, - uint32_t code) { - if (code != BinaryConsts::StringViewIterNext) { - return false; - } - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringIterNext(ref); - return true; -} - -bool WasmBinaryReader::maybeVisitStringIterMove(Expression*& out, - uint32_t code) { - StringIterMoveOp op; - if (code == BinaryConsts::StringViewIterAdvance) { - op = StringIterMoveAdvance; - } else if (code == BinaryConsts::StringViewIterRewind) { - op = StringIterMoveRewind; - } else { - return false; - } - auto* num = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringIterMove(op, ref, num); - return true; -} - bool WasmBinaryReader::maybeVisitStringSliceWTF(Expression*& out, uint32_t code) { - StringSliceWTFOp op; - if (code == BinaryConsts::StringViewWTF8Slice) { - op = StringSliceWTF8; - } else if (code == BinaryConsts::StringViewWTF16Slice) { - op = StringSliceWTF16; - } else { + if (code != BinaryConsts::StringViewWTF16Slice) { return false; } auto* end = popNonVoidExpression(); auto* start = popNonVoidExpression(); auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringSliceWTF(op, ref, start, end); - return true; -} - -bool WasmBinaryReader::maybeVisitStringSliceIter(Expression*& out, - uint32_t code) { - if (code != BinaryConsts::StringViewIterSlice) { - return false; - } - auto* num = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringSliceIter(ref, num); + out = Builder(wasm).makeStringSliceWTF(ref, start, end); return true; } diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 91e990180ea..24d61c198a7 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -1872,20 +1872,6 @@ Result<> IRBuilder::makeStringEq(StringEqOp op) { return Ok{}; } -Result<> IRBuilder::makeStringAs(StringAsOp op) { - StringAs curr; - CHECK_ERR(visitStringAs(&curr)); - push(builder.makeStringAs(op, curr.ref)); - return Ok{}; -} - -Result<> IRBuilder::makeStringWTF8Advance() { - StringWTF8Advance curr; - CHECK_ERR(visitStringWTF8Advance(&curr)); - push(builder.makeStringWTF8Advance(curr.ref, curr.pos, curr.bytes)); - return Ok{}; -} - Result<> IRBuilder::makeStringWTF16Get() { StringWTF16Get curr; CHECK_ERR(visitStringWTF16Get(&curr)); @@ -1893,32 +1879,10 @@ Result<> IRBuilder::makeStringWTF16Get() { return Ok{}; } -Result<> IRBuilder::makeStringIterNext() { - StringIterNext curr; - CHECK_ERR(visitStringIterNext(&curr)); - push(builder.makeStringIterNext(curr.ref)); - return Ok{}; -} - -Result<> IRBuilder::makeStringIterMove(StringIterMoveOp op) { - StringIterMove curr; - CHECK_ERR(visitStringIterMove(&curr)); - push(builder.makeStringIterMove(op, curr.ref, curr.num)); - return Ok{}; -} - -Result<> IRBuilder::makeStringSliceWTF(StringSliceWTFOp op) { +Result<> IRBuilder::makeStringSliceWTF() { StringSliceWTF curr; - curr.op = op; CHECK_ERR(visitStringSliceWTF(&curr)); - push(builder.makeStringSliceWTF(op, curr.ref, curr.start, curr.end)); - return Ok{}; -} - -Result<> IRBuilder::makeStringSliceIter() { - StringSliceIter curr; - CHECK_ERR(visitStringSliceIter(&curr)); - push(builder.makeStringSliceIter(curr.ref, curr.num)); + push(builder.makeStringSliceWTF(curr.ref, curr.start, curr.end)); return Ok{}; } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index bca94a7684f..cab0e98b5f7 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1285,15 +1285,6 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str, if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) { return Type(HeapType::string, Nullable); } - if (str.substr(0, 15) == "stringview_wtf8" && (prefix || str.size() == 15)) { - return Type(HeapType::stringview_wtf8, Nullable); - } - if (str.substr(0, 16) == "stringview_wtf16" && (prefix || str.size() == 16)) { - return Type(HeapType::stringview_wtf16, Nullable); - } - if (str.substr(0, 15) == "stringview_iter" && (prefix || str.size() == 15)) { - return Type(HeapType::stringview_iter, Nullable); - } if (str.substr(0, 7) == "nullref" && (prefix || str.size() == 7)) { return Type(HeapType::none, Nullable); } @@ -1348,15 +1339,6 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) { return HeapType::string; } - if (str.substr(0, 15) == "stringview_wtf8" && (prefix || str.size() == 15)) { - return HeapType::stringview_wtf8; - } - if (str.substr(0, 16) == "stringview_wtf16" && (prefix || str.size() == 16)) { - return HeapType::stringview_wtf16; - } - if (str.substr(0, 15) == "stringview_iter" && (prefix || str.size() == 15)) { - return HeapType::stringview_iter; - } if (str.substr(0, 4) == "none" && (prefix || str.size() == 4)) { return HeapType::none; } @@ -3383,39 +3365,14 @@ Expression* SExpressionWasmBuilder::makeStringEq(Element& s, StringEqOp op) { op, parseExpression(s[1]), parseExpression(s[2])); } -Expression* SExpressionWasmBuilder::makeStringAs(Element& s, StringAsOp op) { - return Builder(wasm).makeStringAs(op, parseExpression(s[1])); -} - -Expression* SExpressionWasmBuilder::makeStringWTF8Advance(Element& s) { - return Builder(wasm).makeStringWTF8Advance( - parseExpression(s[1]), parseExpression(s[2]), parseExpression(s[3])); -} - Expression* SExpressionWasmBuilder::makeStringWTF16Get(Element& s) { return Builder(wasm).makeStringWTF16Get(parseExpression(s[1]), parseExpression(s[2])); } -Expression* SExpressionWasmBuilder::makeStringIterNext(Element& s) { - return Builder(wasm).makeStringIterNext(parseExpression(s[1])); -} - -Expression* SExpressionWasmBuilder::makeStringIterMove(Element& s, - StringIterMoveOp op) { - return Builder(wasm).makeStringIterMove( - op, parseExpression(s[1]), parseExpression(s[2])); -} - -Expression* SExpressionWasmBuilder::makeStringSliceWTF(Element& s, - StringSliceWTFOp op) { +Expression* SExpressionWasmBuilder::makeStringSliceWTF(Element& s) { return Builder(wasm).makeStringSliceWTF( - op, parseExpression(s[1]), parseExpression(s[2]), parseExpression(s[3])); -} - -Expression* SExpressionWasmBuilder::makeStringSliceIter(Element& s) { - return Builder(wasm).makeStringSliceIter(parseExpression(s[1]), - parseExpression(s[2])); + parseExpression(s[1]), parseExpression(s[2]), parseExpression(s[3])); } // converts an s-expression string representing binary data into an output diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 53a25d52bed..020a9f66062 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2089,24 +2089,6 @@ void BinaryInstWriter::visitRefTest(RefTest* curr) { } void BinaryInstWriter::visitRefCast(RefCast* curr) { - // We allow ref.cast of string views, but V8 does not. Work around that by - // emitting a ref.as_non_null (or nothing). - auto type = curr->type; - if (type.isRef()) { - auto heapType = type.getHeapType(); - if (heapType == HeapType::stringview_wtf8 || - heapType == HeapType::stringview_wtf16 || - heapType == HeapType::stringview_iter) { - // We cannot cast string views to/from anything, so the input must also - // be a view. - assert(curr->ref->type.getHeapType() == heapType); - if (type.isNonNullable() && curr->ref->type.isNullable()) { - o << int8_t(BinaryConsts::RefAsNonNull); - } - return; - } - } - o << int8_t(BinaryConsts::GCPrefix); if (curr->type.isNullable()) { o << U32LEB(BinaryConsts::RefCastNull); @@ -2385,9 +2367,6 @@ void BinaryInstWriter::visitStringMeasure(StringMeasure* curr) { case StringMeasureIsUSV: o << U32LEB(BinaryConsts::StringIsUSV); break; - case StringMeasureWTF16View: - o << U32LEB(BinaryConsts::StringViewWTF16Length); - break; case StringMeasureHash: o << U32LEB(BinaryConsts::StringHash); break; @@ -2455,69 +2434,14 @@ void BinaryInstWriter::visitStringEq(StringEq* curr) { } } -void BinaryInstWriter::visitStringAs(StringAs* curr) { - o << int8_t(BinaryConsts::GCPrefix); - switch (curr->op) { - case StringAsWTF8: - o << U32LEB(BinaryConsts::StringAsWTF8); - break; - case StringAsWTF16: - o << U32LEB(BinaryConsts::StringAsWTF16); - break; - case StringAsIter: - o << U32LEB(BinaryConsts::StringAsIter); - break; - default: - WASM_UNREACHABLE("invalid string.as*"); - } -} - -void BinaryInstWriter::visitStringWTF8Advance(StringWTF8Advance* curr) { - o << int8_t(BinaryConsts::GCPrefix) - << U32LEB(BinaryConsts::StringViewWTF8Advance); -} - void BinaryInstWriter::visitStringWTF16Get(StringWTF16Get* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringViewWTF16GetCodePoint); } -void BinaryInstWriter::visitStringIterNext(StringIterNext* curr) { - o << int8_t(BinaryConsts::GCPrefix) - << U32LEB(BinaryConsts::StringViewIterNext); -} - -void BinaryInstWriter::visitStringIterMove(StringIterMove* curr) { - o << int8_t(BinaryConsts::GCPrefix); - switch (curr->op) { - case StringIterMoveAdvance: - o << U32LEB(BinaryConsts::StringViewIterAdvance); - break; - case StringIterMoveRewind: - o << U32LEB(BinaryConsts::StringViewIterRewind); - break; - default: - WASM_UNREACHABLE("invalid string.move*"); - } -} - void BinaryInstWriter::visitStringSliceWTF(StringSliceWTF* curr) { o << int8_t(BinaryConsts::GCPrefix); - switch (curr->op) { - case StringSliceWTF8: - o << U32LEB(BinaryConsts::StringViewWTF8Slice); - break; - case StringSliceWTF16: - o << U32LEB(BinaryConsts::StringViewWTF16Slice); - break; - default: - WASM_UNREACHABLE("invalid string.move*"); - } -} - -void BinaryInstWriter::visitStringSliceIter(StringSliceIter* curr) { - o << int8_t(BinaryConsts::GCPrefix) - << U32LEB(BinaryConsts::StringViewIterSlice); + o << U32LEB(BinaryConsts::StringViewWTF16Slice); } void BinaryInstWriter::visitContBind(ContBind* curr) { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 155d8556e5c..2eb5369d0a9 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -496,11 +496,6 @@ std::optional getBasicHeapTypeLUB(HeapType::BasicHeapType a, case HeapType::array: case HeapType::string: return {HeapType::any}; - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - // Only joinable with bottom or self, both already handled. - return std::nullopt; case HeapType::none: case HeapType::noext: case HeapType::nofunc: @@ -915,9 +910,6 @@ FeatureSet Type::getFeatures() const { feats |= FeatureSet::ReferenceTypes | FeatureSet::GC; return; case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: feats |= FeatureSet::ReferenceTypes | FeatureSet::Strings; return; case HeapType::none: @@ -1184,8 +1176,7 @@ bool HeapType::isFunction() const { bool HeapType::isData() const { if (isBasic()) { - return id == struct_ || id == array || id == string || - id == stringview_wtf16; + return id == struct_ || id == array || id == string; } else { return getHeapTypeInfo(*this)->isData(); } @@ -1240,9 +1231,6 @@ bool HeapType::isBottom() const { case array: case exn: case string: - case stringview_wtf8: - case stringview_wtf16: - case stringview_iter: return false; case none: case noext: @@ -1314,9 +1302,6 @@ std::optional HeapType::getSuperType() const { case exn: case noexn: case string: - case stringview_wtf8: - case stringview_wtf16: - case stringview_iter: return {}; case eq: return any; @@ -1377,9 +1362,6 @@ size_t HeapType::getDepth() const { case HeapType::struct_: case HeapType::array: case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: depth += 2; break; case HeapType::none: @@ -1411,9 +1393,6 @@ HeapType::BasicHeapType HeapType::getBottom() const { case struct_: case array: case string: - case stringview_wtf8: - case stringview_wtf16: - case stringview_iter: case none: return none; case noext: @@ -1440,14 +1419,6 @@ HeapType::BasicHeapType HeapType::getBottom() const { } HeapType::BasicHeapType HeapType::getTop() const { - if (*this == HeapType::stringview_wtf8 || - *this == HeapType::stringview_wtf16 || - *this == HeapType::stringview_iter) { - // These types are their own top types even though they share a bottom type - // `none` with the anyref hierarchy. This means that technically there are - // multiple top types for `none`, but `any` is the canonical one. - return getBasic(); - } switch (getBottom()) { case none: return any; @@ -1469,9 +1440,6 @@ HeapType::BasicHeapType HeapType::getTop() const { case array: case exn: case string: - case stringview_wtf8: - case stringview_wtf16: - case stringview_iter: break; } WASM_UNREACHABLE("unexpected type"); @@ -1766,9 +1734,6 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { case HeapType::array: return a == HeapType::none || a.isArray(); case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: return a == HeapType::none; case HeapType::none: case HeapType::noext: @@ -1881,47 +1846,39 @@ std::ostream& TypePrinter::print(Type type) { print(type.getTuple()); } else if (type.isRef()) { auto heapType = type.getHeapType(); - if (heapType.isBasic()) { + if (heapType.isBasic() && type.isNullable()) { // Print shorthands for certain basic heap types. - if (type.isNullable()) { - switch (heapType.getBasic()) { - case HeapType::ext: - return os << "externref"; - case HeapType::func: - return os << "funcref"; - case HeapType::cont: - return os << "contref"; - case HeapType::any: - return os << "anyref"; - case HeapType::eq: - return os << "eqref"; - case HeapType::i31: - return os << "i31ref"; - case HeapType::struct_: - return os << "structref"; - case HeapType::array: - return os << "arrayref"; - case HeapType::exn: - return os << "exnref"; - case HeapType::string: - return os << "stringref"; - case HeapType::stringview_wtf8: - return os << "stringview_wtf8"; - case HeapType::stringview_wtf16: - return os << "stringview_wtf16"; - case HeapType::stringview_iter: - return os << "stringview_iter"; - case HeapType::none: - return os << "nullref"; - case HeapType::noext: - return os << "nullexternref"; - case HeapType::nofunc: - return os << "nullfuncref"; - case HeapType::nocont: - return os << "nullcontref"; - case HeapType::noexn: - return os << "nullexnref"; - } + switch (heapType.getBasic()) { + case HeapType::ext: + return os << "externref"; + case HeapType::func: + return os << "funcref"; + case HeapType::cont: + return os << "contref"; + case HeapType::any: + return os << "anyref"; + case HeapType::eq: + return os << "eqref"; + case HeapType::i31: + return os << "i31ref"; + case HeapType::struct_: + return os << "structref"; + case HeapType::array: + return os << "arrayref"; + case HeapType::exn: + return os << "exnref"; + case HeapType::string: + return os << "stringref"; + case HeapType::none: + return os << "nullref"; + case HeapType::noext: + return os << "nullexternref"; + case HeapType::nofunc: + return os << "nullfuncref"; + case HeapType::nocont: + return os << "nullcontref"; + case HeapType::noexn: + return os << "nullexnref"; } } os << "(ref "; @@ -1959,12 +1916,6 @@ std::ostream& TypePrinter::print(HeapType type) { return os << "exn"; case HeapType::string: return os << "string"; - case HeapType::stringview_wtf8: - return os << "stringview_wtf8"; - case HeapType::stringview_wtf16: - return os << "stringview_wtf16"; - case HeapType::stringview_iter: - return os << "stringview_iter"; case HeapType::none: return os << "none"; case HeapType::noext: diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 8f3082b41e2..e9bee8e0816 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -478,13 +478,8 @@ struct FunctionValidator : public WalkerPass> { void visitStringEncode(StringEncode* curr); void visitStringConcat(StringConcat* curr); void visitStringEq(StringEq* curr); - void visitStringAs(StringAs* curr); - void visitStringWTF8Advance(StringWTF8Advance* curr); void visitStringWTF16Get(StringWTF16Get* curr); - void visitStringIterNext(StringIterNext* curr); - void visitStringIterMove(StringIterMove* curr); void visitStringSliceWTF(StringSliceWTF* curr); - void visitStringSliceIter(StringSliceIter* curr); void visitContBind(ContBind* curr); void visitContNew(ContNew* curr); void visitResume(Resume* curr); @@ -3316,34 +3311,11 @@ void FunctionValidator::visitStringEq(StringEq* curr) { "string operations require reference-types [--enable-strings]"); } -void FunctionValidator::visitStringAs(StringAs* curr) { - shouldBeTrue(!getModule() || getModule()->features.hasStrings(), - curr, - "string operations require reference-types [--enable-strings]"); -} - -void FunctionValidator::visitStringWTF8Advance(StringWTF8Advance* curr) { - shouldBeTrue(!getModule() || getModule()->features.hasStrings(), - curr, - "string operations require reference-types [--enable-strings]"); -} - void FunctionValidator::visitStringWTF16Get(StringWTF16Get* curr) { shouldBeTrue(!getModule() || getModule()->features.hasStrings(), curr, "string operations require reference-types [--enable-strings]"); } -void FunctionValidator::visitStringIterNext(StringIterNext* curr) { - shouldBeTrue(!getModule() || getModule()->features.hasStrings(), - curr, - "string operations require reference-types [--enable-strings]"); -} - -void FunctionValidator::visitStringIterMove(StringIterMove* curr) { - shouldBeTrue(!getModule() || getModule()->features.hasStrings(), - curr, - "string operations require reference-types [--enable-strings]"); -} void FunctionValidator::visitStringSliceWTF(StringSliceWTF* curr) { shouldBeTrue(!getModule() || getModule()->features.hasStrings(), @@ -3351,12 +3323,6 @@ void FunctionValidator::visitStringSliceWTF(StringSliceWTF* curr) { "string operations require reference-types [--enable-strings]"); } -void FunctionValidator::visitStringSliceIter(StringSliceIter* curr) { - shouldBeTrue(!getModule() || getModule()->features.hasStrings(), - curr, - "string operations require reference-types [--enable-strings]"); -} - void FunctionValidator::visitContBind(ContBind* curr) { // TODO implement actual type-checking shouldBeTrue( diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 9bc0f6e0b99..d1b48990438 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1293,35 +1293,6 @@ void StringEq::finalize() { } } -void StringAs::finalize() { - if (ref->type == Type::unreachable) { - type = Type::unreachable; - } else { - switch (op) { - case StringAsWTF8: - type = Type(HeapType::stringview_wtf8, NonNullable); - break; - case StringAsWTF16: - type = Type(HeapType::stringview_wtf16, NonNullable); - break; - case StringAsIter: - type = Type(HeapType::stringview_iter, NonNullable); - break; - default: - WASM_UNREACHABLE("bad string.as"); - } - } -} - -void StringWTF8Advance::finalize() { - if (ref->type == Type::unreachable || pos->type == Type::unreachable || - bytes->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - void StringWTF16Get::finalize() { if (ref->type == Type::unreachable || pos->type == Type::unreachable) { type = Type::unreachable; @@ -1330,22 +1301,6 @@ void StringWTF16Get::finalize() { } } -void StringIterNext::finalize() { - if (ref->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - -void StringIterMove::finalize() { - if (ref->type == Type::unreachable || num->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - void StringSliceWTF::finalize() { if (ref->type == Type::unreachable || start->type == Type::unreachable || end->type == Type::unreachable) { @@ -1355,14 +1310,6 @@ void StringSliceWTF::finalize() { } } -void StringSliceIter::finalize() { - if (ref->type == Type::unreachable || num->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type(HeapType::string, NonNullable); - } -} - void ContBind::finalize() { if (cont->type == Type::unreachable) { type = Type::unreachable; diff --git a/src/wasm2js.h b/src/wasm2js.h index 3ac4d2b4d67..7540bd71ac2 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2395,34 +2395,14 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitStringAs(StringAs* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitStringWTF8Advance(StringWTF8Advance* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitStringWTF16Get(StringWTF16Get* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitStringIterNext(StringIterNext* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitStringIterMove(StringIterMove* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitStringSliceWTF(StringSliceWTF* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitStringSliceIter(StringSliceIter* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitRefAs(RefAs* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 52975f8bc2a..2f46c1d0f8c 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -662,9 +662,6 @@ function test_core() { module.i31ref.pop(), module.structref.pop(), module.stringref.pop(), - module.stringview_wtf8.pop(), - module.stringview_wtf16.pop(), - module.stringview_iter.pop(), // Memory module.memory.size(), diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 2c54f1142a3..de84b8197ec 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -109,13 +109,13 @@ StringMeasure: 81 StringEncode: 82 StringConcat: 83 StringEq: 84 -StringAs: 85 -StringWTF8Advance: 86 -StringWTF16Get: 87 -StringIterNext: 88 -StringIterMove: 89 -StringSliceWTF: 90 -StringSliceIter: 91 +StringAs: undefined +StringWTF8Advance: undefined +StringWTF16Get: 85 +StringIterNext: undefined +StringIterMove: undefined +StringSliceWTF: 86 +StringSliceIter: undefined getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) @@ -2190,15 +2190,6 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} (drop (pop stringref) ) - (drop - (pop stringview_wtf8) - ) - (drop - (pop stringview_wtf16) - ) - (drop - (pop stringview_iter) - ) (drop (memory.size) ) @@ -4300,15 +4291,6 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} (drop (pop stringref) ) - (drop - (pop stringview_wtf8) - ) - (drop - (pop stringview_wtf16) - ) - (drop - (pop stringview_iter) - ) (drop (memory.size) ) diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 66cf43290f7..1b78ea1e763 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -283,24 +283,6 @@ void test_types() { BinaryenTypeExpand(stringref, &valueType); assert(valueType == stringref); - BinaryenType stringview_wtf8_ = BinaryenTypeStringviewWTF8(); - printf("BinaryenTypeStringviewWTF8: (ptr)\n"); - assert(BinaryenTypeArity(stringview_wtf8_) == 1); - BinaryenTypeExpand(stringview_wtf8_, &valueType); - assert(valueType == stringview_wtf8_); - - BinaryenType stringview_wtf16_ = BinaryenTypeStringviewWTF16(); - printf("BinaryenTypeStringviewWTF16: (ptr)\n"); - assert(BinaryenTypeArity(stringview_wtf16_) == 1); - BinaryenTypeExpand(stringview_wtf16_, &valueType); - assert(valueType == stringview_wtf16_); - - BinaryenType stringview_iter_ = BinaryenTypeStringviewIter(); - printf("BinaryenTypeStringviewIter: (ptr)\n"); - assert(BinaryenTypeArity(stringview_iter_) == 1); - BinaryenTypeExpand(stringview_iter_, &valueType); - assert(valueType == stringview_iter_); - BinaryenType nullref = BinaryenTypeNullref(); printf("BinaryenTypeNullref: (ptr)\n"); assert(BinaryenTypeArity(nullref) == 1); @@ -351,12 +333,6 @@ void test_types() { printf("BinaryenHeapTypeStruct: %zd\n", BinaryenHeapTypeStruct()); printf("BinaryenHeapTypeArray: %zd\n", BinaryenHeapTypeArray()); printf("BinaryenHeapTypeString: %zd\n", BinaryenHeapTypeString()); - printf("BinaryenHeapTypeStringviewWTF8: %zd\n", - BinaryenHeapTypeStringviewWTF8()); - printf("BinaryenHeapTypeStringviewWTF16: %zd\n", - BinaryenHeapTypeStringviewWTF16()); - printf("BinaryenHeapTypeStringviewIter: %zd\n", - BinaryenHeapTypeStringviewIter()); printf("BinaryenHeapTypeNone: %zd\n", BinaryenHeapTypeNone()); printf("BinaryenHeapTypeNoext: %zd\n", BinaryenHeapTypeNoext()); printf("BinaryenHeapTypeNofunc: %zd\n", BinaryenHeapTypeNofunc()); @@ -1287,13 +1263,6 @@ void test_core() { module, BinaryenStringMeasureIsUSV(), BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - BinaryenStringMeasure( - module, - BinaryenStringMeasureWTF16View(), - BinaryenStringAs( - module, - BinaryenStringAsWTF16(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref()))), BinaryenStringEncode( module, BinaryenStringEncodeUTF8(), @@ -1356,80 +1325,15 @@ void test_core() { BinaryenStringEqCompare(), BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref()), BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - BinaryenStringAs( - module, - BinaryenStringAsWTF8(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - BinaryenStringAs( - module, - BinaryenStringAsWTF16(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - BinaryenStringAs( - module, - BinaryenStringAsIter(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - BinaryenStringWTF8Advance( - module, - BinaryenStringAs( - module, - BinaryenStringAsWTF8(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 0), - makeInt32(module, 0)), BinaryenStringWTF16Get( module, - BinaryenStringAs( - module, - BinaryenStringAsWTF16(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 0)), - BinaryenStringIterNext( - module, - BinaryenStringAs( - module, - BinaryenStringAsIter(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref()))), - BinaryenStringIterMove( - module, - BinaryenStringIterMoveAdvance(), - BinaryenStringAs( - module, - BinaryenStringAsIter(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 1)), - BinaryenStringIterMove( - module, - BinaryenStringIterMoveRewind(), - BinaryenStringAs( - module, - BinaryenStringAsIter(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 1)), - BinaryenStringSliceWTF( - module, - BinaryenStringSliceWTF8(), - BinaryenStringAs( - module, - BinaryenStringAsWTF8(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 0), + BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref()), makeInt32(module, 0)), BinaryenStringSliceWTF( module, - BinaryenStringSliceWTF16(), - BinaryenStringAs( - module, - BinaryenStringAsWTF16(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), + BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref()), makeInt32(module, 0), makeInt32(module, 0)), - BinaryenStringSliceIter( - module, - BinaryenStringAs( - module, - BinaryenStringAsIter(), - BinaryenGlobalGet(module, "string-global", BinaryenTypeStringref())), - makeInt32(module, 0)), // Other BinaryenNop(module), BinaryenUnreachable(module), diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index fe784a453aa..e10c3b47b31 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -13,9 +13,6 @@ BinaryenTypeI31ref: (ptr) BinaryenTypeStructref: (ptr) BinaryenTypeArrayref: (ptr) BinaryenTypeStringref: (ptr) -BinaryenTypeStringviewWTF8: (ptr) -BinaryenTypeStringviewWTF16: (ptr) -BinaryenTypeStringviewIter: (ptr) BinaryenTypeNullref: (ptr) BinaryenTypeNullExternref: (ptr) BinaryenTypeNullFuncref: (ptr) @@ -31,12 +28,9 @@ BinaryenHeapTypeI31: 5 BinaryenHeapTypeStruct: 6 BinaryenHeapTypeArray: 7 BinaryenHeapTypeString: 9 -BinaryenHeapTypeStringviewWTF8: 10 -BinaryenHeapTypeStringviewWTF16: 11 -BinaryenHeapTypeStringviewIter: 12 -BinaryenHeapTypeNone: 13 -BinaryenHeapTypeNoext: 14 -BinaryenHeapTypeNofunc: 15 +BinaryenHeapTypeNone: 10 +BinaryenHeapTypeNoext: 11 +BinaryenHeapTypeNofunc: 12 BinaryenFeatureMVP: 0 BinaryenFeatureAtomics: 1 BinaryenFeatureBulkMemory: 16 @@ -2435,13 +2429,6 @@ BinaryenFeatureAll: 131071 (global.get $string-global) ) ) - (drop - (stringview_wtf16.length - (string.as_wtf16 - (global.get $string-global) - ) - ) - ) (drop (string.encode_utf8 (global.get $string-global) @@ -2512,84 +2499,16 @@ BinaryenFeatureAll: 131071 (global.get $string-global) ) ) - (drop - (string.as_wtf8 - (global.get $string-global) - ) - ) - (drop - (string.as_wtf16 - (global.get $string-global) - ) - ) - (drop - (string.as_iter - (global.get $string-global) - ) - ) - (drop - (stringview_wtf8.advance - (string.as_wtf8 - (global.get $string-global) - ) - (i32.const 0) - (i32.const 0) - ) - ) (drop (stringview_wtf16.get_codeunit - (string.as_wtf16 - (global.get $string-global) - ) - (i32.const 0) - ) - ) - (drop - (stringview_iter.next - (string.as_iter - (global.get $string-global) - ) - ) - ) - (drop - (stringview_iter.advance - (string.as_iter - (global.get $string-global) - ) - (i32.const 1) - ) - ) - (drop - (stringview_iter.rewind - (string.as_iter - (global.get $string-global) - ) - (i32.const 1) - ) - ) - (drop - (stringview_wtf8.slice - (string.as_wtf8 - (global.get $string-global) - ) - (i32.const 0) + (global.get $string-global) (i32.const 0) ) ) (drop (stringview_wtf16.slice - (string.as_wtf16 - (global.get $string-global) - ) - (i32.const 0) + (global.get $string-global) (i32.const 0) - ) - ) - (drop - (stringview_iter.slice - (string.as_iter - (global.get $string-global) - ) (i32.const 0) ) ) diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp index 3c97028a4dd..443a7ee66bb 100644 --- a/test/gtest/type-builder.cpp +++ b/test/gtest/type-builder.cpp @@ -528,9 +528,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { HeapType struct_ = HeapType::struct_; HeapType array = HeapType::array; HeapType string = HeapType::string; - HeapType stringview_wtf8 = HeapType::stringview_wtf8; - HeapType stringview_wtf16 = HeapType::stringview_wtf16; - HeapType stringview_iter = HeapType::stringview_iter; HeapType none = HeapType::none; HeapType noext = HeapType::noext; HeapType nofunc = HeapType::nofunc; @@ -553,29 +550,23 @@ TEST_F(TypeTest, TestHeapTypeRelations) { } else if (lub && *lub == b) { EXPECT_TRUE(HeapType::isSubType(a, b)); EXPECT_FALSE(HeapType::isSubType(b, a)); - // This would hold except for the case of stringview types and none, where - // stringview types are their own top types, but we return `any` as the - // top type of none. - // EXPECT_EQ(a.getTop(), b.getTop()); + EXPECT_EQ(a.getTop(), b.getTop()); EXPECT_EQ(a.getBottom(), b.getBottom()); } else if (lub && *lub == a) { EXPECT_FALSE(HeapType::isSubType(a, b)); EXPECT_TRUE(HeapType::isSubType(b, a)); - // EXPECT_EQ(a.getTop(), b.getTop()); + EXPECT_EQ(a.getTop(), b.getTop()); EXPECT_EQ(a.getBottom(), b.getBottom()); } else if (lub) { EXPECT_FALSE(HeapType::isSubType(a, b)); EXPECT_FALSE(HeapType::isSubType(b, a)); - // EXPECT_EQ(a.getTop(), b.getTop()); + EXPECT_EQ(a.getTop(), b.getTop()); EXPECT_EQ(a.getBottom(), b.getBottom()); } else { EXPECT_FALSE(HeapType::isSubType(a, b)); EXPECT_FALSE(HeapType::isSubType(b, a)); EXPECT_NE(a.getTop(), b.getTop()); - // This would hold except for stringview types, which share a bottom with - // the anyref hierarchy despite having no shared upper bound with its - // types. - // EXPECT_NE(a.getBottom(), b.getBottom()); + EXPECT_NE(a.getBottom(), b.getBottom()); } }; @@ -588,9 +579,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(ext, struct_, {}); assertLUB(ext, array, {}); assertLUB(ext, string, {}); - assertLUB(ext, stringview_wtf8, {}); - assertLUB(ext, stringview_wtf16, {}); - assertLUB(ext, stringview_iter, {}); assertLUB(ext, none, {}); assertLUB(ext, noext, ext); assertLUB(ext, nofunc, {}); @@ -607,9 +595,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(func, struct_, {}); assertLUB(func, array, {}); assertLUB(func, string, {}); - assertLUB(func, stringview_wtf8, {}); - assertLUB(func, stringview_wtf16, {}); - assertLUB(func, stringview_iter, {}); assertLUB(func, none, {}); assertLUB(func, noext, {}); assertLUB(func, nofunc, func); @@ -627,9 +612,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(cont, struct_, {}); assertLUB(cont, array, {}); assertLUB(cont, string, {}); - assertLUB(cont, stringview_wtf8, {}); - assertLUB(cont, stringview_wtf16, {}); - assertLUB(cont, stringview_iter, {}); assertLUB(cont, none, {}); assertLUB(cont, noext, {}); assertLUB(cont, nofunc, {}); @@ -646,9 +628,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(any, struct_, any); assertLUB(any, array, any); assertLUB(any, string, any); - assertLUB(any, stringview_wtf8, {}); - assertLUB(any, stringview_wtf16, {}); - assertLUB(any, stringview_iter, {}); assertLUB(any, none, any); assertLUB(any, noext, {}); assertLUB(any, nofunc, {}); @@ -664,9 +643,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(eq, struct_, eq); assertLUB(eq, array, eq); assertLUB(eq, string, any); - assertLUB(eq, stringview_wtf8, {}); - assertLUB(eq, stringview_wtf16, {}); - assertLUB(eq, stringview_iter, {}); assertLUB(eq, none, eq); assertLUB(eq, noext, {}); assertLUB(eq, nofunc, {}); @@ -681,9 +657,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(i31, struct_, eq); assertLUB(i31, array, eq); assertLUB(i31, string, any); - assertLUB(i31, stringview_wtf8, {}); - assertLUB(i31, stringview_wtf16, {}); - assertLUB(i31, stringview_iter, {}); assertLUB(i31, none, i31); assertLUB(i31, noext, {}); assertLUB(i31, nofunc, {}); @@ -697,9 +670,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(struct_, cont, {}); assertLUB(struct_, array, eq); assertLUB(struct_, string, any); - assertLUB(struct_, stringview_wtf8, {}); - assertLUB(struct_, stringview_wtf16, {}); - assertLUB(struct_, stringview_iter, {}); assertLUB(struct_, none, struct_); assertLUB(struct_, noext, {}); assertLUB(struct_, nofunc, {}); @@ -712,9 +682,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(array, array, array); assertLUB(array, cont, {}); assertLUB(array, string, any); - assertLUB(array, stringview_wtf8, {}); - assertLUB(array, stringview_wtf16, {}); - assertLUB(array, stringview_iter, {}); assertLUB(array, none, array); assertLUB(array, noext, {}); assertLUB(array, nofunc, {}); @@ -726,9 +693,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(string, string, string); assertLUB(string, cont, {}); - assertLUB(string, stringview_wtf8, {}); - assertLUB(string, stringview_wtf16, {}); - assertLUB(string, stringview_iter, {}); assertLUB(string, none, string); assertLUB(string, noext, {}); assertLUB(string, nofunc, {}); @@ -738,39 +702,6 @@ TEST_F(TypeTest, TestHeapTypeRelations) { assertLUB(string, defStruct, any); assertLUB(string, defArray, any); - assertLUB(stringview_wtf8, stringview_wtf8, stringview_wtf8); - assertLUB(stringview_wtf8, stringview_wtf16, {}); - assertLUB(stringview_wtf8, stringview_iter, {}); - assertLUB(stringview_wtf8, none, stringview_wtf8); - assertLUB(stringview_wtf8, noext, {}); - assertLUB(stringview_wtf8, nofunc, {}); - assertLUB(stringview_wtf8, nocont, {}); - assertLUB(stringview_wtf8, defFunc, {}); - assertLUB(stringview_wtf8, defStruct, {}); - assertLUB(stringview_wtf8, defCont, {}); - assertLUB(stringview_wtf8, defArray, {}); - - assertLUB(stringview_wtf16, stringview_wtf16, stringview_wtf16); - assertLUB(stringview_wtf16, stringview_iter, {}); - assertLUB(stringview_wtf16, none, stringview_wtf16); - assertLUB(stringview_wtf16, noext, {}); - assertLUB(stringview_wtf16, nofunc, {}); - assertLUB(stringview_wtf16, nocont, {}); - assertLUB(stringview_wtf16, defFunc, {}); - assertLUB(stringview_wtf16, defStruct, {}); - assertLUB(stringview_wtf16, defCont, {}); - assertLUB(stringview_wtf16, defArray, {}); - - assertLUB(stringview_iter, stringview_iter, stringview_iter); - assertLUB(stringview_iter, none, stringview_iter); - assertLUB(stringview_iter, noext, {}); - assertLUB(stringview_iter, nofunc, {}); - assertLUB(stringview_iter, nocont, {}); - assertLUB(stringview_iter, defFunc, {}); - assertLUB(stringview_iter, defStruct, {}); - assertLUB(stringview_iter, defCont, {}); - assertLUB(stringview_iter, defArray, {}); - assertLUB(none, none, none); assertLUB(none, noext, {}); assertLUB(none, nofunc, {}); @@ -1113,9 +1044,6 @@ TEST_F(TypeTest, TestDepth) { EXPECT_EQ(HeapType(HeapType::i31).getDepth(), 2U); EXPECT_EQ(HeapType(HeapType::string).getDepth(), 2U); - EXPECT_EQ(HeapType(HeapType::stringview_wtf8).getDepth(), 2U); - EXPECT_EQ(HeapType(HeapType::stringview_wtf16).getDepth(), 2U); - EXPECT_EQ(HeapType(HeapType::stringview_iter).getDepth(), 2U); EXPECT_EQ(HeapType(HeapType::none).getDepth(), size_t(-1)); EXPECT_EQ(HeapType(HeapType::nofunc).getDepth(), size_t(-1)); @@ -1182,9 +1110,6 @@ TEST_F(TypeTest, TestSupertypes) { ASSERT_FALSE(HeapType(HeapType::struct_).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::array).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::string).getDeclaredSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_wtf8).getDeclaredSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_wtf16).getDeclaredSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_iter).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::none).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::noext).getDeclaredSuperType()); ASSERT_FALSE(HeapType(HeapType::nofunc).getDeclaredSuperType()); @@ -1200,9 +1125,6 @@ TEST_F(TypeTest, TestSupertypes) { ASSERT_EQ(HeapType(HeapType::struct_).getSuperType(), HeapType::eq); ASSERT_EQ(HeapType(HeapType::array).getSuperType(), HeapType::eq); ASSERT_FALSE(HeapType(HeapType::string).getSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_wtf8).getSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_wtf16).getSuperType()); - ASSERT_FALSE(HeapType(HeapType::stringview_iter).getSuperType()); ASSERT_FALSE(HeapType(HeapType::none).getSuperType()); ASSERT_FALSE(HeapType(HeapType::noext).getSuperType()); ASSERT_FALSE(HeapType(HeapType::nofunc).getSuperType()); diff --git a/test/lit/ctor-eval/string_view.wast b/test/lit/ctor-eval/string_view.wast deleted file mode 100644 index 5906e4f6027..00000000000 --- a/test/lit/ctor-eval/string_view.wast +++ /dev/null @@ -1,32 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-ctor-eval --ctors=test --kept-exports=test --quiet -all -S -o - | filecheck %s - -;; We cannot precompute string views atm. - -(module - ;; CHECK: (type $0 (func)) - - ;; CHECK: (export "test" (func $test)) - (export "test" (func $test)) - - ;; CHECK: (func $test (type $0) - ;; CHECK-NEXT: (local $temp-view (ref stringview_wtf16)) - ;; CHECK-NEXT: (local.set $temp-view - ;; CHECK-NEXT: (string.as_wtf16 - ;; CHECK-NEXT: (string.const "test") - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (local $temp-view (ref stringview_wtf16)) - ;; This code will remain: we cannot precompute a value that we store in a - ;; global, as string.as is not a constant instruction that can appear in a - ;; global. - (local.set $temp-view - (string.as_wtf16 - (string.const "test") - ) - ) - ) -) - diff --git a/test/lit/exec/strings.wast b/test/lit/exec/strings.wast index 0d5bb7dc4f2..ca77f9882d9 100644 --- a/test/lit/exec/strings.wast +++ b/test/lit/exec/strings.wast @@ -171,24 +171,11 @@ (func $get_codeunit (export "get_codeunit") (result i32) ;; Reads 'c' which is code 99. (stringview_wtf16.get_codeunit - (string.as_wtf16 - (string.const "abcdefg") - ) + (string.const "abcdefg") (i32.const 2) ) ) - ;; CHECK: [fuzz-exec] calling get_length - ;; CHECK-NEXT: [fuzz-exec] note result: get_length => 7 - (func $get_length (export "get_length") (result i32) - ;; This should return 7. - (stringview_wtf16.length - (string.as_wtf16 - (string.const "1234567") - ) - ) - ) - ;; CHECK: [fuzz-exec] calling encode ;; CHECK-NEXT: [LoggingExternalInterface logging 3] ;; CHECK-NEXT: [LoggingExternalInterface logging 0] @@ -280,9 +267,7 @@ (func $slice (export "slice") (result (ref string)) ;; Slicing [3:6] here should definitely output "def". (stringview_wtf16.slice - (string.as_wtf16 - (string.const "abcdefgh") - ) + (string.const "abcdefgh") (i32.const 3) (i32.const 6) ) @@ -293,9 +278,7 @@ (func $slice-big (export "slice-big") (result (ref string)) ;; Slicing [3:huge unsigned value] leads to slicing til the end: "defgh". (stringview_wtf16.slice - (string.as_wtf16 - (string.const "abcdefgh") - ) + (string.const "abcdefgh") (i32.const 3) (i32.const -1) ) @@ -400,9 +383,7 @@ (func $slice-unicode (export "slice-unicode") (result (ref string)) (stringview_wtf16.slice ;; abcd£fgh - (string.as_wtf16 - (string.const "abcd\C2\A3fgh") - ) + (string.const "abcd\C2\A3fgh") (i32.const 3) (i32.const 6) ) @@ -535,9 +516,6 @@ ;; CHECK: [fuzz-exec] calling get_codeunit ;; CHECK-NEXT: [fuzz-exec] note result: get_codeunit => 99 -;; CHECK: [fuzz-exec] calling get_length -;; CHECK-NEXT: [fuzz-exec] note result: get_length => 7 - ;; CHECK: [fuzz-exec] calling encode ;; CHECK-NEXT: [LoggingExternalInterface logging 3] ;; CHECK-NEXT: [LoggingExternalInterface logging 0] @@ -629,7 +607,6 @@ ;; CHECK-NEXT: [fuzz-exec] comparing eq.4 ;; CHECK-NEXT: [fuzz-exec] comparing eq.5 ;; CHECK-NEXT: [fuzz-exec] comparing get_codeunit -;; CHECK-NEXT: [fuzz-exec] comparing get_length ;; CHECK-NEXT: [fuzz-exec] comparing invalid_code_point ;; CHECK-NEXT: [fuzz-exec] comparing isolated_high_code_point ;; CHECK-NEXT: [fuzz-exec] comparing isolated_low_code_point diff --git a/test/lit/passes/j2cl-inline.wast b/test/lit/passes/j2cl-inline.wast index 9148b537833..88485f999dc 100644 --- a/test/lit/passes/j2cl-inline.wast +++ b/test/lit/passes/j2cl-inline.wast @@ -6,16 +6,23 @@ (module ;; A once function that has become empty + ;; CHECK: (type $0 (func)) + + ;; CHECK: (global $$class-initialized@Zoo (mut i32) (i32.const 0)) + + ;; CHECK: (func $clinit-trivial-1__@Foo (type $0) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) (func $clinit-trivial-1__@Foo ) ;; A once function that just calls another + ;; CHECK: (func $clinit-trivial-2__@Bar (type $0) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) (func $clinit-trivial-2__@Bar (call $clinit-trivial-1__@Foo) ) - ;; CHECK: (type $0 (func)) - - ;; CHECK: (global $$class-initialized@Zoo (mut i32) (i32.const 0)) (global $$class-initialized@Zoo (mut i32) (i32.const 0)) ;; Not hoisted but trivial. diff --git a/test/lit/passes/precompute-strings.wast b/test/lit/passes/precompute-strings.wast index a9d065fdcdb..9d4ec3a7a24 100644 --- a/test/lit/passes/precompute-strings.wast +++ b/test/lit/passes/precompute-strings.wast @@ -71,10 +71,8 @@ ;; CHECK-NEXT: (i32.const 7) ;; CHECK-NEXT: ) (func $length (result i32) - (stringview_wtf16.length - (string.as_wtf16 - (string.const "1234567") - ) + (string.measure_wtf16 + (string.const "1234567") ) ) @@ -82,11 +80,9 @@ ;; CHECK-NEXT: (i32.const 8) ;; CHECK-NEXT: ) (func $length-unicode (result i32) - (stringview_wtf16.length - (string.as_wtf16 - ;; $_£_€_𐍈 (the last character is encoded as a surrogate pair) - (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") - ) + (string.measure_wtf16 + ;; $_£_€_𐍈 (the last character is encoded as a surrogate pair) + (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") ) ) @@ -96,10 +92,8 @@ (func $get_codepoint (result i32) ;; Returns 95 ('_'). (stringview_wtf16.get_codeunit - (string.as_wtf16 - ;; $_£_€_𐍈 - (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") - ) + ;; $_£_€_𐍈 + (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") (i32.const 1) ) ) @@ -110,10 +104,8 @@ (func $get_codepoint-unicode (export "get_codepoint-unicode") (result i32) ;; Returns 8364 ('€') (stringview_wtf16.get_codeunit - (string.as_wtf16 - ;; $_£_€_𐍈 - (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") - ) + ;; $_£_€_𐍈 + (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") (i32.const 4) ) ) @@ -124,10 +116,8 @@ (func $get_codepoint-surrogate (export "get_codepoint-surrogate") (result i32) ;; Returns 0xd800 (the high surrogate in '𐍈') (stringview_wtf16.get_codeunit - (string.as_wtf16 - ;; $_£_€_𐍈 - (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") - ) + ;; $_£_€_𐍈 + (string.const "$_\C2\A3_\E2\82\AC_\F0\90\8D\88") (i32.const 6) ) ) @@ -217,9 +207,7 @@ (func $slice (export "slice") (result (ref string)) ;; Slicing [3:6] here should definitely output "def". (stringview_wtf16.slice - (string.as_wtf16 - (string.const "abcdefgh") - ) + (string.const "abcdefgh") (i32.const 3) (i32.const 6) ) @@ -231,9 +219,7 @@ (func $slice-unicode (export "slice-unicode") (result (ref string)) (stringview_wtf16.slice ;; abcd£fgh - (string.as_wtf16 - (string.const "abcd\C2\A3fgh") - ) + (string.const "abcd\C2\A3fgh") (i32.const 3) (i32.const 6) ) diff --git a/test/lit/passes/roundtrip.wast b/test/lit/passes/roundtrip.wast index 8fb69cb7dd2..59e303eafae 100644 --- a/test/lit/passes/roundtrip.wast +++ b/test/lit/passes/roundtrip.wast @@ -42,70 +42,4 @@ ) ) ) - - ;; CHECK: (func $string_view_casts (type $2) (param $x stringview_wtf8) (param $y stringview_wtf16) (param $z stringview_iter) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string_view_casts - ;; ref.cast of string views is not allowed in binaries: replace with - ;; ref.as_non_null, or remove if it is a no-op. - (param $x (ref null stringview_wtf8)) - (param $y (ref null stringview_wtf16)) - (param $z (ref null stringview_iter)) - ;; Here we still need a cast to non-null. - (drop - (ref.cast (ref stringview_wtf8) - (local.get $x) - ) - ) - (drop - (ref.cast (ref stringview_wtf16) - (local.get $y) - ) - ) - (drop - (ref.cast (ref stringview_iter) - (local.get $z) - ) - ) - ;; Here we do not need the cast. - (drop - (ref.cast (ref null stringview_wtf8) - (local.get $x) - ) - ) - (drop - (ref.cast (ref null stringview_wtf16) - (local.get $y) - ) - ) - (drop - (ref.cast (ref null stringview_iter) - (local.get $z) - ) - ) - ) ) diff --git a/test/lit/passes/simplify-locals-strings.wast b/test/lit/passes/simplify-locals-strings.wast index 890364a837d..d0387565203 100644 --- a/test/lit/passes/simplify-locals-strings.wast +++ b/test/lit/passes/simplify-locals-strings.wast @@ -540,70 +540,4 @@ (local.get $temp) ) ) - - ;; CHECK: (func $no-iteration-past-each-other (type $6) (param $iter stringview_iter) - ;; CHECK-NEXT: (local $i32 i32) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_iter.next - ;; CHECK-NEXT: (local.get $iter) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (stringview_iter.advance - ;; CHECK-NEXT: (local.get $iter) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_iter.next - ;; CHECK-NEXT: (local.get $iter) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (stringview_iter.rewind - ;; CHECK-NEXT: (local.get $iter) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-iteration-past-each-other - (param $iter stringview_iter) - (local $i32 i32) - ;; Iteration operations interact with each other, and can't be moved past - ;; each other. - (local.set $i32 - (stringview_iter.next - (local.get $iter) - ) - ) - (drop - (stringview_iter.advance - (local.get $iter) - (i32.const 3) - ) - ) - (drop - (local.get $i32) - ) - (local.set $i32 - (stringview_iter.next - (local.get $iter) - ) - ) - (drop - (stringview_iter.rewind - (local.get $iter) - (i32.const 4) - ) - ) - (drop - (local.get $i32) - ) - ) ) diff --git a/test/lit/passes/string-lowering-instructions.wast b/test/lit/passes/string-lowering-instructions.wast index 548586c4b71..44c004ea5f2 100644 --- a/test/lit/passes/string-lowering-instructions.wast +++ b/test/lit/passes/string-lowering-instructions.wast @@ -42,33 +42,29 @@ ;; CHECK: (type $13 (func (param externref) (result externref))) - ;; CHECK: (type $14 (func (param externref) (result externref))) + ;; CHECK: (type $14 (func (param externref) (result i32))) - ;; CHECK: (type $15 (func (param externref) (result i32))) + ;; CHECK: (type $15 (func (param externref externref) (result i32))) - ;; CHECK: (type $16 (func (param externref externref) (result i32))) + ;; CHECK: (type $16 (func (param externref (ref $0)) (result i32))) - ;; CHECK: (type $17 (func (param externref (ref $0)) (result i32))) + ;; CHECK: (type $17 (func (param externref externref) (result (ref extern)))) - ;; CHECK: (type $18 (func (param externref externref) (result (ref extern)))) + ;; CHECK: (type $18 (func (param (ref $0)))) - ;; CHECK: (type $19 (func (param (ref $0)))) + ;; CHECK: (type $19 (func (param (ref null $0) i32 i32) (result (ref extern)))) - ;; CHECK: (type $20 (func (param externref (ref extern) externref externref externref (ref extern)))) + ;; CHECK: (type $20 (func (param i32) (result (ref extern)))) - ;; CHECK: (type $21 (func (param (ref null $0) i32 i32) (result (ref extern)))) + ;; CHECK: (type $21 (func (param externref externref) (result (ref extern)))) - ;; CHECK: (type $22 (func (param i32) (result (ref extern)))) + ;; CHECK: (type $22 (func (param externref (ref null $0) i32) (result i32))) - ;; CHECK: (type $23 (func (param externref externref) (result (ref extern)))) + ;; CHECK: (type $23 (func (param externref) (result i32))) - ;; CHECK: (type $24 (func (param externref (ref null $0) i32) (result i32))) + ;; CHECK: (type $24 (func (param externref i32) (result i32))) - ;; CHECK: (type $25 (func (param externref) (result i32))) - - ;; CHECK: (type $26 (func (param externref i32) (result i32))) - - ;; CHECK: (type $27 (func (param externref i32 i32) (result (ref extern)))) + ;; CHECK: (type $25 (func (param externref i32 i32) (result (ref extern)))) ;; CHECK: (import "string.const" "0" (global $string.const_exported (ref extern))) @@ -78,23 +74,23 @@ (import "colliding" "name" (func $fromCodePoint)) - ;; CHECK: (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $21) (param (ref null $0) i32 i32) (result (ref extern)))) + ;; CHECK: (import "wasm:js-string" "fromCharCodeArray" (func $fromCharCodeArray (type $19) (param (ref null $0) i32 i32) (result (ref extern)))) - ;; CHECK: (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_19 (type $22) (param i32) (result (ref extern)))) + ;; CHECK: (import "wasm:js-string" "fromCodePoint" (func $fromCodePoint_18 (type $20) (param i32) (result (ref extern)))) - ;; CHECK: (import "wasm:js-string" "concat" (func $concat (type $23) (param externref externref) (result (ref extern)))) + ;; CHECK: (import "wasm:js-string" "concat" (func $concat (type $21) (param externref externref) (result (ref extern)))) - ;; CHECK: (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $24) (param externref (ref null $0) i32) (result i32))) + ;; CHECK: (import "wasm:js-string" "intoCharCodeArray" (func $intoCharCodeArray (type $22) (param externref (ref null $0) i32) (result i32))) ;; CHECK: (import "wasm:js-string" "equals" (func $equals (type $2) (param externref externref) (result i32))) ;; CHECK: (import "wasm:js-string" "compare" (func $compare (type $2) (param externref externref) (result i32))) - ;; CHECK: (import "wasm:js-string" "length" (func $length (type $25) (param externref) (result i32))) + ;; CHECK: (import "wasm:js-string" "length" (func $length (type $23) (param externref) (result i32))) - ;; CHECK: (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $26) (param externref i32) (result i32))) + ;; CHECK: (import "wasm:js-string" "charCodeAt" (func $charCodeAt (type $24) (param externref i32) (result i32))) - ;; CHECK: (import "wasm:js-string" "substring" (func $substring (type $27) (param externref i32 i32) (result (ref extern)))) + ;; CHECK: (import "wasm:js-string" "substring" (func $substring (type $25) (param externref i32 i32) (result (ref extern)))) ;; CHECK: (global $string externref (ref.null noextern)) (global $string stringref (ref.null string)) ;; Test we update global nulls. @@ -103,73 +99,7 @@ ;; CHECK: (export "export.2" (func $exported-string-receiver)) - ;; CHECK: (func $string.as (type $20) (param $a externref) (param $a_nn (ref extern)) (param $b externref) (param $c externref) (param $d externref) (param $nn_view (ref extern)) - ;; CHECK-NEXT: (local.set $b - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $c - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $nn_view - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $nn_view - ;; CHECK-NEXT: (local.get $a_nn) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.as - (param $a stringref) - (param $a_nn (ref string)) - (param $b stringview_wtf8) - (param $c stringview_wtf16) - (param $d stringview_iter) - (param $nn_view (ref stringview_wtf16)) - ;; These operations all vanish in the lowering, as they all become extref - ;; (JS strings). - (local.set $b - (string.as_wtf8 - (local.get $a) - ) - ) - (local.set $c - (string.as_wtf16 - (local.get $a) - ) - ) - (local.set $d - (string.as_iter - (local.get $a) - ) - ) - ;; The input is nullable, and string.as casts to non-null, so we will need - ;; to keep a cast here in order to validate. (We also add a cast in all the - ;; above as the inputs are nullable, but this is the only one that will - ;; fail to validate. Other opts can remove the above ones.) - (local.set $nn_view - (string.as_wtf16 - (local.get $a) - ) - ) - ;; The input is already non-nullable here, so no cast is needed. - (local.set $nn_view - (string.as_wtf16 - (local.get $a_nn) - ) - ) - ) - - ;; CHECK: (func $string.new.gc (type $19) (param $array16 (ref $0)) + ;; CHECK: (func $string.new.gc (type $18) (param $array16 (ref $0)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $fromCharCodeArray ;; CHECK-NEXT: (local.get $array16) @@ -189,7 +119,7 @@ ) ;; CHECK: (func $string.from_code_point (type $4) (result externref) - ;; CHECK-NEXT: (call $fromCodePoint_19 + ;; CHECK-NEXT: (call $fromCodePoint_18 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -199,7 +129,7 @@ ) ) - ;; CHECK: (func $string.concat (type $18) (param $0 externref) (param $1 externref) (result (ref extern)) + ;; CHECK: (func $string.concat (type $17) (param $0 externref) (param $1 externref) (result (ref extern)) ;; CHECK-NEXT: (call $concat ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -212,7 +142,7 @@ ) ) - ;; CHECK: (func $string.encode (type $17) (param $ref externref) (param $array16 (ref $0)) (result i32) + ;; CHECK: (func $string.encode (type $16) (param $ref externref) (param $array16 (ref $0)) (result i32) ;; CHECK-NEXT: (call $intoCharCodeArray ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $array16) @@ -227,7 +157,7 @@ ) ) - ;; CHECK: (func $string.eq (type $16) (param $a externref) (param $b externref) (result i32) + ;; CHECK: (func $string.eq (type $15) (param $a externref) (param $b externref) (result i32) ;; CHECK-NEXT: (call $equals ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: (local.get $b) @@ -240,7 +170,7 @@ ) ) - ;; CHECK: (func $string.compare (type $16) (param $a externref) (param $b externref) (result i32) + ;; CHECK: (func $string.compare (type $15) (param $a externref) (param $b externref) (result i32) ;; CHECK-NEXT: (call $compare ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: (local.get $b) @@ -253,38 +183,38 @@ ) ) - ;; CHECK: (func $string.length (type $15) (param $ref externref) (result i32) + ;; CHECK: (func $string.length (type $14) (param $ref externref) (result i32) ;; CHECK-NEXT: (call $length ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $string.length (param $ref stringview_wtf16) (result i32) - (stringview_wtf16.length + (func $string.length (param $ref stringref) (result i32) + (string.measure_wtf16 (local.get $ref) ) ) - ;; CHECK: (func $string.get_codeunit (type $15) (param $ref externref) (result i32) + ;; CHECK: (func $string.get_codeunit (type $14) (param $ref externref) (result i32) ;; CHECK-NEXT: (call $charCodeAt ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $string.get_codeunit (param $ref stringview_wtf16) (result i32) + (func $string.get_codeunit (param $ref stringref) (result i32) (stringview_wtf16.get_codeunit (local.get $ref) (i32.const 2) ) ) - ;; CHECK: (func $string.slice (type $14) (param $ref externref) (result externref) + ;; CHECK: (func $string.slice (type $13) (param $ref externref) (result externref) ;; CHECK-NEXT: (call $substring ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $string.slice (param $ref stringview_wtf16) (result stringref) + (func $string.slice (param $ref stringref) (result stringref) (stringview_wtf16.slice (local.get $ref) (i32.const 2) diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast new file mode 100644 index 00000000000..b009e47ed33 --- /dev/null +++ b/test/lit/string.as_wtf16.wast @@ -0,0 +1,43 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; Check that string.as_wtf16 is accepted by the parser but is not translated +;; into any IR. + +;; RUN: wasm-opt %s -all -S -o - | filecheck %s + +(module + ;; CHECK: (func $empty (type $1) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $empty + (string.as_wtf16) + ) + + ;; CHECK: (func $codeunit (type $0) (result i32) + ;; CHECK-NEXT: (stringview_wtf16.get_codeunit + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $codeunit (result i32) + (stringview_wtf16.get_codeunit + (string.as_wtf16 + (string.const "abc") + ) + (i32.const 0) + ) + ) + + ;; CHECK: (func $length (type $0) (result i32) + ;; CHECK-NEXT: (string.measure_wtf16 + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $length (result i32) + (stringview_wtf16.length + (string.as_wtf16 + (string.const "abc") + ) + ) + ) +) diff --git a/test/lit/strings.wast b/test/lit/strings.wast index 1166f13d0cf..59fc431e4dd 100644 --- a/test/lit/strings.wast +++ b/test/lit/strings.wast @@ -18,35 +18,31 @@ ;; CHECK: (type $1 (func (param stringref stringref))) - ;; CHECK: (type $2 (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter))) - ;; CHECK: (type $array (sub (array (mut i8)))) (type $array (sub (array (mut i8)))) ;; CHECK: (type $array16 (sub (array (mut i16)))) (type $array16 (sub (array (mut i16)))) - ;; CHECK: (type $5 (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter)))) - - ;; CHECK: (type $6 (func (param (ref string)))) + ;; CHECK: (type $4 (func (param stringref stringref (ref string)))) - ;; CHECK: (type $7 (func (param stringview_wtf16))) + ;; CHECK: (type $5 (func (param (ref string)))) - ;; CHECK: (type $8 (func (param (ref $array) (ref $array16)))) + ;; CHECK: (type $6 (func (param (ref $array) (ref $array16)))) - ;; CHECK: (type $9 (func (param stringref (ref $array) (ref $array16)))) + ;; CHECK: (type $7 (func (param stringref (ref $array) (ref $array16)))) - ;; CHECK: (type $10 (func)) + ;; CHECK: (type $8 (func)) - ;; CHECK: (type $11 (func (param (ref $array)))) + ;; CHECK: (type $9 (func (param (ref $array)))) - ;; CHECK: (type $12 (func (param stringref) (result i32))) + ;; CHECK: (type $10 (func (param stringref) (result i32))) ;; CHECK: (global $string-const stringref (string.const "string in a global \c2\a3_\e2\82\ac_\f0\90\8d\88 \01\00\t\t\n\n\r\r\"\"\'\'\\\\ ")) (global $string-const stringref (string.const "string in a global \C2\A3_\E2\82\AC_\F0\90\8D\88 \01\00\t\t\n\n\r\r\"\"\'\'\\\\ ")) ;; CHECK: (memory $0 10 10) - ;; CHECK: (func $string.new (type $5) (param $a stringref) (param $b stringview_wtf8) (param $c stringview_wtf16) (param $d stringview_iter) (param $e stringref) (param $f stringview_wtf8) (param $g stringview_wtf16) (param $h stringview_iter) (param $i (ref string)) (param $j (ref stringview_wtf8)) (param $k (ref stringview_wtf16)) (param $l (ref stringview_iter)) + ;; CHECK: (func $string.new (type $4) (param $a stringref) (param $b stringref) (param $c (ref string)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_wtf16 ;; CHECK-NEXT: (i32.const 7) @@ -74,17 +70,8 @@ ;; CHECK-NEXT: ) (func $string.new (param $a stringref) - (param $b stringview_wtf8) - (param $c stringview_wtf16) - (param $d stringview_iter) - (param $e (ref null string)) - (param $f (ref null stringview_wtf8)) - (param $g (ref null stringview_wtf16)) - (param $h (ref null stringview_iter)) - (param $i (ref string)) - (param $j (ref stringview_wtf8)) - (param $k (ref stringview_wtf16)) - (param $l (ref stringview_iter)) + (param $b (ref null string)) + (param $c (ref string)) (drop (string.new_wtf16 (i32.const 7) @@ -111,7 +98,7 @@ ) ) - ;; CHECK: (func $string.const (type $6) (param $param (ref string)) + ;; CHECK: (func $string.const (type $5) (param $param (ref string)) ;; CHECK-NEXT: (call $string.const ;; CHECK-NEXT: (string.const "foo") ;; CHECK-NEXT: ) @@ -313,184 +300,46 @@ ) ) - ;; CHECK: (func $string.as (type $2) (param $a stringref) (param $b stringview_wtf8) (param $c stringview_wtf16) (param $d stringview_iter) - ;; CHECK-NEXT: (local.set $b - ;; CHECK-NEXT: (string.as_wtf8 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $c - ;; CHECK-NEXT: (string.as_wtf16 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (string.as_iter - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.as - (param $a stringref) - (param $b stringview_wtf8) - (param $c stringview_wtf16) - (param $d stringview_iter) - (local.set $b ;; validate the output type - (string.as_wtf8 - (local.get $a) - ) - ) - (local.set $c - (string.as_wtf16 - (local.get $a) - ) - ) - (local.set $d - (string.as_iter - (local.get $a) - ) - ) - ) - - ;; CHECK: (func $stringview-access (type $2) (param $a stringref) (param $b stringview_wtf8) (param $c stringview_wtf16) (param $d stringview_iter) + ;; CHECK: (func $stringview-access (type $0) (param $a stringref) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_wtf8.advance - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (stringview_wtf16.get_codeunit - ;; CHECK-NEXT: (local.get $c) + ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_iter.next - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_iter.advance - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_iter.rewind - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $stringview-access (param $a stringref) - (param $b stringview_wtf8) - (param $c stringview_wtf16) - (param $d stringview_iter) (local $i32 i32) (local.set $i32 ;; validate the output type - (stringview_wtf8.advance - (local.get $b) - (i32.const 0) - (i32.const 1) - ) - ) - (local.set $i32 (stringview_wtf16.get_codeunit - (local.get $c) + (local.get $a) (i32.const 2) ) ) - (local.set $i32 - (stringview_iter.next - (local.get $d) - ) - ) - (local.set $i32 - (stringview_iter.advance - (local.get $d) - (i32.const 3) - ) - ) - (local.set $i32 - (stringview_iter.rewind - (local.get $d) - (i32.const 4) - ) - ) ) - ;; CHECK: (func $stringview-slice (type $2) (param $a stringref) (param $b stringview_wtf8) (param $c stringview_wtf16) (param $d stringview_iter) - ;; CHECK-NEXT: (local.set $a - ;; CHECK-NEXT: (stringview_wtf8.slice - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK: (func $stringview-slice (type $0) (param $a stringref) ;; CHECK-NEXT: (local.set $a ;; CHECK-NEXT: (stringview_wtf16.slice - ;; CHECK-NEXT: (local.get $c) + ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $a - ;; CHECK-NEXT: (stringview_iter.slice - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $stringview-slice (param $a stringref) - (param $b stringview_wtf8) - (param $c stringview_wtf16) - (param $d stringview_iter) (local.set $a ;; validate the output type - (stringview_wtf8.slice - (local.get $b) - (i32.const 0) - (i32.const 1) - ) - ) - (local.set $a (stringview_wtf16.slice - (local.get $c) + (local.get $a) (i32.const 2) (i32.const 3) ) ) - (local.set $a - (stringview_iter.slice - (local.get $d) - (i32.const 4) - ) - ) - ) - - ;; CHECK: (func $string.length (type $7) (param $ref stringview_wtf16) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (stringview_wtf16.length - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.length (param $ref stringview_wtf16) - (drop - (i32.eqz ;; validate the output is i32 - (stringview_wtf16.length - (local.get $ref) - ) - ) - ) ) - ;; CHECK: (func $string.new.gc (type $8) (param $array (ref $array)) (param $array16 (ref $array16)) + ;; CHECK: (func $string.new.gc (type $6) (param $array (ref $array)) (param $array16 (ref $array16)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_wtf16_array ;; CHECK-NEXT: (local.get $array16) @@ -551,7 +400,7 @@ ) ) - ;; CHECK: (func $string.encode.gc (type $9) (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16)) + ;; CHECK: (func $string.encode.gc (type $7) (param $ref stringref) (param $array (ref $array)) (param $array16 (ref $array16)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (string.encode_wtf16_array @@ -616,7 +465,7 @@ ) ) - ;; CHECK: (func $string.from_code_point (type $10) + ;; CHECK: (func $string.from_code_point (type $8) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.from_code_point ;; CHECK-NEXT: (i32.const 1) @@ -631,7 +480,7 @@ ) ) - ;; CHECK: (func $string.new_try (type $11) (param $array (ref $array)) + ;; CHECK: (func $string.new_try (type $9) (param $array (ref $array)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_utf8_try ;; CHECK-NEXT: (i32.const 1) @@ -662,7 +511,7 @@ ) ) - ;; CHECK: (func $string.hash (type $12) (param $ref stringref) (result i32) + ;; CHECK: (func $string.hash (type $10) (param $ref stringref) (result i32) ;; CHECK-NEXT: (string.hash ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index f778b6a63ea..68c881a6253 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -168,41 +168,23 @@ ;; CHECK: (type $77 (func (param stringref) (result i32))) - ;; CHECK: (type $78 (func (param stringview_wtf16) (result i32))) + ;; CHECK: (type $78 (func (param stringref (ref $packed-i8) i32) (result i32))) - ;; CHECK: (type $79 (func (param stringref (ref $packed-i8) i32) (result i32))) + ;; CHECK: (type $79 (func (param stringref stringref) (result (ref string)))) - ;; CHECK: (type $80 (func (param stringref stringref) (result (ref string)))) + ;; CHECK: (type $80 (func (param stringref i32) (result i32))) - ;; CHECK: (type $81 (func (param stringref) (result stringview_wtf8))) + ;; CHECK: (type $81 (func (param stringref i32 i32) (result (ref string)))) - ;; CHECK: (type $82 (func (param stringref) (result (ref stringview_wtf16)))) - - ;; CHECK: (type $83 (func (param stringref) (result stringview_iter))) - - ;; CHECK: (type $84 (func (param (ref stringview_wtf8) i32 i32) (result i32))) - - ;; CHECK: (type $85 (func (param stringview_wtf16 i32) (result i32))) - - ;; CHECK: (type $86 (func (param stringview_iter) (result i32))) - - ;; CHECK: (type $87 (func (param stringview_iter i32) (result i32))) - - ;; CHECK: (type $88 (func (param (ref stringview_iter) i32) (result i32))) - - ;; CHECK: (type $89 (func (param stringview_wtf8 stringview_wtf16 i32 i32))) - - ;; CHECK: (type $90 (func (param stringview_iter i32) (result (ref string)))) - - ;; CHECK: (type $91 (func (param (ref $simple-cont)))) + ;; CHECK: (type $82 (func (param (ref $simple-cont)))) ;; CHECK: (type $to-f32 (func (result f32))) ;; CHECK: (type $to-f32-cont (cont $to-f32)) - ;; CHECK: (type $94 (func (param (ref $simple)) (result (ref $simple-cont)))) + ;; CHECK: (type $85 (func (param (ref $simple)) (result (ref $simple-cont)))) - ;; CHECK: (type $95 (func (param (ref $cont-bind-before)) (result (ref $simple-cont)))) + ;; CHECK: (type $86 (func (param (ref $cont-bind-before)) (result (ref $simple-cont)))) ;; CHECK: (type $s2 (struct (field i32))) (type $s2 (struct i32)) @@ -256,7 +238,7 @@ (type $cont-bind-before-func (func (param i32) (param i64) (param i32) (param i64) (result f32))) (type $cont-bind-before (cont $cont-bind-before-func)) - ;; CHECK: (type $all-types (struct (field externref) (field (ref extern)) (field funcref) (field (ref func)) (field anyref) (field (ref any)) (field eqref) (field (ref eq)) (field i31ref) (field (ref i31)) (field structref) (field (ref struct)) (field arrayref) (field (ref array)) (field exnref) (field (ref exn)) (field stringref) (field (ref string)) (field stringview_wtf8) (field (ref stringview_wtf8)) (field stringview_wtf16) (field (ref stringview_wtf16)) (field stringview_iter) (field (ref stringview_iter)) (field contref) (field (ref cont)) (field nullref) (field (ref none)) (field nullexternref) (field (ref noextern)) (field nullfuncref) (field (ref nofunc)) (field nullexnref) (field (ref noexn)) (field nullcontref) (field (ref nocont)))) + ;; CHECK: (type $all-types (struct (field externref) (field (ref extern)) (field funcref) (field (ref func)) (field anyref) (field (ref any)) (field eqref) (field (ref eq)) (field i31ref) (field (ref i31)) (field structref) (field (ref struct)) (field arrayref) (field (ref array)) (field exnref) (field (ref exn)) (field stringref) (field (ref string)) (field contref) (field (ref cont)) (field nullref) (field (ref none)) (field nullexternref) (field (ref noextern)) (field nullfuncref) (field (ref nofunc)) (field nullexnref) (field (ref noexn)) (field nullcontref) (field (ref nocont)))) (type $all-types (struct externref (ref extern) funcref (ref func) anyref (ref any) @@ -266,9 +248,6 @@ arrayref (ref array) exnref (ref exn) stringref (ref string) - stringview_wtf8 (ref stringview_wtf8) - stringview_wtf16 (ref stringview_wtf16) - stringview_iter (ref stringview_iter) contref (ref cont) nullref (ref none) nullexternref (ref noextern) @@ -278,7 +257,7 @@ ;; imported memories (memory (export "mem") (export "mem2") (import "" "mem") 0) - ;; CHECK: (type $107 (func (param (ref $s0) (ref $s1) (ref $s2) (ref $s3) (ref $s4) (ref $s5) (ref $s6) (ref $s7) (ref $s8) (ref $a0) (ref $a1) (ref $a2) (ref $a3) (ref $subvoid) (ref $submany) (ref $all-types)))) + ;; CHECK: (type $98 (func (param (ref $s0) (ref $s1) (ref $s2) (ref $s3) (ref $s4) (ref $s5) (ref $s6) (ref $s7) (ref $s8) (ref $a0) (ref $a1) (ref $a2) (ref $a3) (ref $subvoid) (ref $submany) (ref $all-types)))) ;; CHECK: (import "" "mem" (memory $mimport$0 0)) @@ -4554,16 +4533,6 @@ string.hash ) - ;; CHECK: (func $stringview-length (type $78) (param $0 stringview_wtf16) (result i32) - ;; CHECK-NEXT: (stringview_wtf16.length - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $stringview-length (param stringview_wtf16) (result i32) - local.get 0 - stringview_wtf16.length - ) - ;; CHECK: (func $string-encode (type $29) (param $0 stringref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.encode_wtf8 @@ -4609,7 +4578,7 @@ drop ) - ;; CHECK: (func $string-encode-gc (type $79) (param $0 stringref) (param $1 (ref $packed-i8)) (param $2 i32) (result i32) + ;; CHECK: (func $string-encode-gc (type $78) (param $0 stringref) (param $1 (ref $packed-i8)) (param $2 i32) (result i32) ;; CHECK-NEXT: (string.encode_wtf8_array ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4623,7 +4592,7 @@ string.encode_wtf8_array ) - ;; CHECK: (func $string-concat (type $80) (param $0 stringref) (param $1 stringref) (result (ref string)) + ;; CHECK: (func $string-concat (type $79) (param $0 stringref) (param $1 stringref) (result (ref string)) ;; CHECK-NEXT: (string.concat ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) @@ -4659,135 +4628,30 @@ string.compare ) - ;; CHECK: (func $string-as-wtf8 (type $81) (param $0 stringref) (result stringview_wtf8) - ;; CHECK-NEXT: (string.as_wtf8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-as-wtf8 (param stringref) (result stringview_wtf8) - local.get 0 - string.as_wtf8 - ) - - ;; CHECK: (func $string-as-wtf16 (type $82) (param $0 stringref) (result (ref stringview_wtf16)) - ;; CHECK-NEXT: (string.as_wtf16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-as-wtf16 (param stringref) (result (ref stringview_wtf16)) - local.get 0 - string.as_wtf16 - ) - - ;; CHECK: (func $string-as-iter (type $83) (param $0 stringref) (result stringview_iter) - ;; CHECK-NEXT: (string.as_iter - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-as-iter (param stringref) (result stringview_iter) - local.get 0 - string.as_iter - ) - - ;; CHECK: (func $string-advance (type $84) (param $0 (ref stringview_wtf8)) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (stringview_wtf8.advance - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-advance (param (ref stringview_wtf8) i32 i32) (result i32) - local.get 0 - local.get 1 - local.get 2 - stringview_wtf8.advance - ) - - ;; CHECK: (func $string-get (type $85) (param $0 stringview_wtf16) (param $1 i32) (result i32) + ;; CHECK: (func $string-get (type $80) (param $0 stringref) (param $1 i32) (result i32) ;; CHECK-NEXT: (stringview_wtf16.get_codeunit ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $string-get (param stringview_wtf16 i32) (result i32) + (func $string-get (param stringref i32) (result i32) local.get 0 local.get 1 stringview_wtf16.get_codeunit ) - ;; CHECK: (func $string-iter-next (type $86) (param $0 stringview_iter) (result i32) - ;; CHECK-NEXT: (stringview_iter.next - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-iter-next (param stringview_iter) (result i32) - local.get 0 - stringview_iter.next - ) - - ;; CHECK: (func $string-iter-advance (type $87) (param $0 stringview_iter) (param $1 i32) (result i32) - ;; CHECK-NEXT: (stringview_iter.advance - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-iter-advance (param (ref null stringview_iter) i32) (result i32) - local.get 0 - local.get 1 - stringview_iter.advance - ) - - ;; CHECK: (func $string-iter-rewind (type $88) (param $0 (ref stringview_iter)) (param $1 i32) (result i32) - ;; CHECK-NEXT: (stringview_iter.rewind + ;; CHECK: (func $string-slice (type $81) (param $0 stringref) (param $1 i32) (param $2 i32) (result (ref string)) + ;; CHECK-NEXT: (stringview_wtf16.slice ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $string-iter-rewind (param (ref stringview_iter) i32) (result i32) - local.get 0 - local.get 1 - stringview_iter.rewind - ) - - ;; CHECK: (func $string-slice (type $89) (param $0 stringview_wtf8) (param $1 stringview_wtf16) (param $2 i32) (param $3 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (stringview_wtf8.slice - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (stringview_wtf16.slice - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-slice (param stringview_wtf8 stringview_wtf16 i32 i32) + (func $string-slice (param stringref i32 i32) (result (ref string)) local.get 0 - local.get 2 - local.get 3 - stringview_wtf8.slice - drop local.get 1 local.get 2 - local.get 3 stringview_wtf16.slice - drop - ) - - ;; CHECK: (func $string-iter-slice (type $90) (param $0 stringview_iter) (param $1 i32) (result (ref string)) - ;; CHECK-NEXT: (stringview_iter.slice - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string-iter-slice (param stringview_iter i32) (result (ref string)) - local.get 0 - local.get 1 - stringview_iter.slice ) ;; CHECK: (func $call (type $simple) (param $0 i32) (param $1 i64) (result f32) @@ -5077,7 +4941,7 @@ ) ) - ;; CHECK: (func $resume (type $91) (param $ct (ref $simple-cont)) + ;; CHECK: (func $resume (type $82) (param $ct (ref $simple-cont)) ;; CHECK-NEXT: (local $f f32) ;; CHECK-NEXT: (block $label ;; CHECK-NEXT: (drop @@ -5116,7 +4980,7 @@ br 0 ) - ;; CHECK: (func $contnew (type $94) (param $f (ref $simple)) (result (ref $simple-cont)) + ;; CHECK: (func $contnew (type $85) (param $f (ref $simple)) (result (ref $simple-cont)) ;; CHECK-NEXT: (cont.new $simple-cont ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) @@ -5126,7 +4990,7 @@ cont.new $simple-cont ) - ;; CHECK: (func $contbind (type $95) (param $c (ref $cont-bind-before)) (result (ref $simple-cont)) + ;; CHECK: (func $contbind (type $86) (param $c (ref $cont-bind-before)) (result (ref $simple-cont)) ;; CHECK-NEXT: (cont.bind $cont-bind-before $simple-cont ;; CHECK-NEXT: (i32.const 123) ;; CHECK-NEXT: (i64.const 123) @@ -5251,7 +5115,7 @@ drop ) - ;; CHECK: (func $use-types (type $107) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany)) (param $15 (ref $all-types)) + ;; CHECK: (func $use-types (type $98) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany)) (param $15 (ref $all-types)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $use-types From 0cde12629c229338189713ff19a035c992e60257 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Sat, 11 May 2024 22:35:16 -0700 Subject: [PATCH 2/7] Emit stringview conversions in binary writer So that we continue to produce valid stringref code. Parse the conversions as nops in the binary parser to preserve our ability to round-trip. Emitting the conversions requires using extra scratch locals, and between that and parsing the nop, there is quite a bit of code bloat when round-tripping, but stringref code should never be emitted in production use cases, so that's ok. --- src/parser/wat-parser.cpp | 5 ++- src/wasm-binary.h | 2 + src/wasm/wasm-binary.cpp | 18 +++++++++ src/wasm/wasm-stack.cpp | 37 ++++++++++++++++- test/lit/string.as_wtf16.wast | 76 +++++++++++++++++++++++++++++++++++ test/lit/strings.wast | 39 ------------------ 6 files changed, 135 insertions(+), 42 deletions(-) diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index 2bc222d6b8b..85ef1e80ffd 100644 --- a/src/parser/wat-parser.cpp +++ b/src/parser/wat-parser.cpp @@ -202,7 +202,10 @@ Result<> doParseModule(Module& wasm, Lexer& input, bool allowExtra) { CHECK_ERR(im); } if (!f->imported()) { - CHECK_ERR(ctx.irBuilder.visitEnd()); + auto end = ctx.irBuilder.visitEnd(); + if (auto* err = end.getErr()) { + return ctx.in.err(decls.funcDefs[i].pos, err->msg); + } } } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ce8f1dbbaf2..449c036995f 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1137,6 +1137,7 @@ enum ASTNodes { StringEncodeLossyUTF8 = 0x8d, StringEncodeWTF8 = 0x8e, StringNewUTF8Try = 0x8f, + StringAsWTF16 = 0x98, StringViewWTF16GetCodePoint = 0x9a, StringViewWTF16Slice = 0x9c, StringCompare = 0xa8, @@ -1758,6 +1759,7 @@ class WasmBinaryReader { bool maybeVisitArrayFill(Expression*& out, uint32_t code); bool maybeVisitArrayInit(Expression*& out, uint32_t code); bool maybeVisitStringNew(Expression*& out, uint32_t code); + bool maybeVisitStringAsWTF16(Expression*& out, uint32_t code); bool maybeVisitStringConst(Expression*& out, uint32_t code); bool maybeVisitStringMeasure(Expression*& out, uint32_t code); bool maybeVisitStringEncode(Expression*& out, uint32_t code); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index cf05e1b7337..0be6d570344 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -4241,6 +4241,9 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { if (maybeVisitStringNew(curr, opcode)) { break; } + if (maybeVisitStringAsWTF16(curr, opcode)) { + break; + } if (maybeVisitStringConst(curr, opcode)) { break; } @@ -7572,6 +7575,21 @@ bool WasmBinaryReader::maybeVisitStringNew(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryReader::maybeVisitStringAsWTF16(Expression*& out, + uint32_t code) { + if (code != BinaryConsts::StringAsWTF16) { + return false; + } + // Parse `string.as_wtf16` as a nop. We do not support this instruction in the + // IR, but parsing it as a nop will ensure that the subsequent + // `stringview_wtf16.get_codeunit` or `stringview_wtf16.slice` will still + // receive the string value. We need to at least accept this in the binary + // parser because we emit `string.as_wtf16` as part of the binary encoding of + // those other two instructions. + out = Builder(wasm).makeNop(); + return true; +} + bool WasmBinaryReader::maybeVisitStringConst(Expression*& out, uint32_t code) { if (code != BinaryConsts::StringConst) { return false; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 020a9f66062..b5afa2a5f9e 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2435,13 +2435,30 @@ void BinaryInstWriter::visitStringEq(StringEq* curr) { } void BinaryInstWriter::visitStringWTF16Get(StringWTF16Get* curr) { + // We need to convert the ref operand to a stringview, but it is under the pos + // operand. Put the i32 in a scratch local, emit the conversion, then get the + // i32 back onto the stack. + Index scratchPos = scratchLocals[Type::i32]; + o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchPos); + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringAsWTF16); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchPos); o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringViewWTF16GetCodePoint); } void BinaryInstWriter::visitStringSliceWTF(StringSliceWTF* curr) { - o << int8_t(BinaryConsts::GCPrefix); - o << U32LEB(BinaryConsts::StringViewWTF16Slice); + // We need to convert the ref operand to a stringview, but it is buried under + // the start and end operands. Put the i32s in scratch locals, emit the + // conversion, then get the i32s back onto the stack. + Index scratchStart = scratchLocals[Type::i32]; + Index scratchEnd = scratchStart + 1; + o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchEnd); + o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchStart); + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringAsWTF16); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchStart); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchEnd); + o << int8_t(BinaryConsts::GCPrefix) + << U32LEB(BinaryConsts::StringViewWTF16Slice); } void BinaryInstWriter::visitContBind(ContBind* curr) { @@ -2631,6 +2648,22 @@ InsertOrderedMap BinaryInstWriter::countScratchLocals() { count = std::max(count, 1u); } } + + void visitStringWTF16Get(StringWTF16Get* curr) { + if (curr->type == Type::unreachable) { + return; + } + auto& count = scratches[Type::i32]; + count = std::max(count, 1u); + } + + void visitStringSliceWTF(StringSliceWTF* curr) { + if (curr->type == Type::unreachable) { + return; + } + auto& count = scratches[Type::i32]; + count = std::max(count, 2u); + } }; ScratchLocalFinder finder(*this); diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast index b009e47ed33..5de33051535 100644 --- a/test/lit/string.as_wtf16.wast +++ b/test/lit/string.as_wtf16.wast @@ -4,11 +4,15 @@ ;; into any IR. ;; RUN: wasm-opt %s -all -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP (module ;; CHECK: (func $empty (type $1) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) + ;; RTRIP: (func $empty (type $1) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: ) (func $empty (string.as_wtf16) ) @@ -19,7 +23,26 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; RTRIP: (func $codeunit (type $0) (result i32) + ;; RTRIP-NEXT: (local $0 i32) + ;; RTRIP-NEXT: (local $1 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.get_codeunit + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $1 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.set $0 + ;; RTRIP-NEXT: (i32.const 0) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $0) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) (func $codeunit (result i32) + ;; This should parse ok with the conversion skipped. The roundtrip will + ;; include scratch locals. (stringview_wtf16.get_codeunit (string.as_wtf16 (string.const "abc") @@ -28,12 +51,65 @@ ) ) + ;; CHECK: (func $slice (type $2) (result stringref) + ;; CHECK-NEXT: (stringview_wtf16.slice + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $slice (type $2) (result stringref) + ;; RTRIP-NEXT: (local $0 i32) + ;; RTRIP-NEXT: (local $1 i32) + ;; RTRIP-NEXT: (local $2 i32) + ;; RTRIP-NEXT: (local $3 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.slice + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $3 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.set $0 + ;; RTRIP-NEXT: (block (result i32) + ;; RTRIP-NEXT: (local.set $2 + ;; RTRIP-NEXT: (i32.const 1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.set $1 + ;; RTRIP-NEXT: (i32.const 2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $3) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $0) + ;; RTRIP-NEXT: (local.get $1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + (func $slice (result stringref) + ;; This should parse ok with the conversion skipped. The roundtrip will + ;; include scratch locals. + (stringview_wtf16.slice + (string.as_wtf16 + (string.const "abc") + ) + (i32.const 1) + (i32.const 2) + ) + ) + ;; CHECK: (func $length (type $0) (result i32) ;; CHECK-NEXT: (string.measure_wtf16 ;; CHECK-NEXT: (string.const "abc") ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; RTRIP: (func $length (type $0) (result i32) + ;; RTRIP-NEXT: (string.measure_wtf16 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) (func $length (result i32) + ;; This should be parsed as string.measure_wtf16 instead. (stringview_wtf16.length (string.as_wtf16 (string.const "abc") diff --git a/test/lit/strings.wast b/test/lit/strings.wast index 59fc431e4dd..c06a3ead4c0 100644 --- a/test/lit/strings.wast +++ b/test/lit/strings.wast @@ -300,45 +300,6 @@ ) ) - ;; CHECK: (func $stringview-access (type $0) (param $a stringref) - ;; CHECK-NEXT: (local $i32 i32) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (stringview_wtf16.get_codeunit - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $stringview-access - (param $a stringref) - (local $i32 i32) - (local.set $i32 ;; validate the output type - (stringview_wtf16.get_codeunit - (local.get $a) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $stringview-slice (type $0) (param $a stringref) - ;; CHECK-NEXT: (local.set $a - ;; CHECK-NEXT: (stringview_wtf16.slice - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $stringview-slice - (param $a stringref) - (local.set $a ;; validate the output type - (stringview_wtf16.slice - (local.get $a) - (i32.const 2) - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $string.new.gc (type $6) (param $array (ref $array)) (param $array16 (ref $array16)) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (string.new_wtf16_array From 03ffb8e4432d94ebe5c2b0e2fe50f6ec57f0f38b Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 13 May 2024 14:52:59 -0700 Subject: [PATCH 3/7] address comments --- src/tools/fuzzing/fuzzing.cpp | 4 ++-- src/wasm/wasm-stack.cpp | 4 ++++ test/binaryen.js/kitchen-sink.js | 5 ----- test/binaryen.js/kitchen-sink.js.txt | 5 ----- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 5de10c0d1ba..d6f8e0f1203 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -2814,7 +2814,7 @@ Expression* TranslateToFuzzReader::makeStringConcat() { } Expression* TranslateToFuzzReader::makeStringSlice() { - auto* ref = make(Type(HeapType::string, getNullability())); + auto* ref = makeTrappingRefUse(HeapType::string); auto* start = make(Type::i32); auto* end = make(Type::i32); return builder.makeStringSliceWTF(ref, start, end); @@ -2845,7 +2845,7 @@ Expression* TranslateToFuzzReader::makeStringMeasure(Type type) { Expression* TranslateToFuzzReader::makeStringGet(Type type) { assert(type == Type::i32); - auto* ref = make(Type(HeapType::string, getNullability())); + auto* ref = makeTrappingRefUse(HeapType::string); auto* pos = make(Type::i32); return builder.makeStringWTF16Get(ref, pos); } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index b5afa2a5f9e..6978f4ca48b 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2653,6 +2653,8 @@ InsertOrderedMap BinaryInstWriter::countScratchLocals() { if (curr->type == Type::unreachable) { return; } + // Scratch local to hold the `pos` value while we emit a stringview + // conversion for the `ref` value. auto& count = scratches[Type::i32]; count = std::max(count, 1u); } @@ -2661,6 +2663,8 @@ InsertOrderedMap BinaryInstWriter::countScratchLocals() { if (curr->type == Type::unreachable) { return; } + // Scratch locals to hold the `start` and `end` values while we emit a + // stringview conversion for the `ref` value. auto& count = scratches[Type::i32]; count = std::max(count, 2u); } diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 2f46c1d0f8c..da281910f14 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -179,13 +179,8 @@ function test_ids() { console.log("StringEncode: " + binaryen.StringEncodeId); console.log("StringConcat: " + binaryen.StringConcatId); console.log("StringEq: " + binaryen.StringEqId); - console.log("StringAs: " + binaryen.StringAsId); - console.log("StringWTF8Advance: " + binaryen.StringWTF8AdvanceId); console.log("StringWTF16Get: " + binaryen.StringWTF16GetId); - console.log("StringIterNext: " + binaryen.StringIterNextId); - console.log("StringIterMove: " + binaryen.StringIterMoveId); console.log("StringSliceWTF: " + binaryen.StringSliceWTFId); - console.log("StringSliceIter: " + binaryen.StringSliceIterId); } function test_core() { diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index de84b8197ec..a3e88703e4f 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -109,13 +109,8 @@ StringMeasure: 81 StringEncode: 82 StringConcat: 83 StringEq: 84 -StringAs: undefined -StringWTF8Advance: undefined StringWTF16Get: 85 -StringIterNext: undefined -StringIterMove: undefined StringSliceWTF: 86 -StringSliceIter: undefined getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) From ed2621703a4daf58c70c3baaf5d54a625974535c Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 14 May 2024 16:39:13 -0700 Subject: [PATCH 4/7] optimize gets --- src/wasm-stack.h | 8 +- src/wasm/wasm-stack-opts.cpp | 26 ++- src/wasm/wasm-stack.cpp | 81 +++++++-- test/lit/string.as_wtf16.wast | 300 ++++++++++++++++++++++++++++++++-- 4 files changed, 391 insertions(+), 24 deletions(-) diff --git a/src/wasm-stack.h b/src/wasm-stack.h index fc38d07a482..e51e5eb9163 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -155,10 +155,15 @@ class BinaryInstWriter : public OverriddenVisitor { // Return the type and number of required scratch locals. InsertOrderedMap countScratchLocals(); - // local.get, local.tee, and glboal.get expressions that will be followed by + // local.get, local.tee, and global.get expressions that will be followed by // tuple.extracts. We can optimize these by getting only the local for the // extracted index. std::unordered_map extractedGets; + + // As an optimization, we do not need to use scratch locals for StringWTF16Get + // and StringSliceWTF if their non-string operands are already LocalGets. + // Record those LocalGets here. + std::unordered_set deferredGets; }; // Takes binaryen IR and converts it to something else (binary or stack IR) @@ -543,6 +548,7 @@ class StackIROptimizer { void removeAt(Index i); Index getNumConsumedValues(StackInst* inst); bool canRemoveSetGetPair(Index setIndex, Index getIndex); + std::unordered_set findStringViewDeferredGets(); }; // Generate and emit StackIR. diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index eac423fbd18..c6487f58f90 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -101,6 +101,12 @@ void StackIROptimizer::local2Stack() { // control flow. LocalGraph localGraph(func); localGraph.computeSetInfluences(); + // The binary writing of StringWTF16Get and StringSliceWTF is optimized to use + // fewer scratch locals when their operands are already LocalGets. To avoid + // interfering with that optimization, we have to avoid removing such + // LocalGets. + auto deferredGets = findStringViewDeferredGets(); + // We maintain a stack of relevant values. This contains: // * a null for each actual value that the value stack would have // * an index of each LocalSet that *could* be on the value @@ -163,7 +169,7 @@ void StackIROptimizer::local2Stack() { // optimized when they are visited in the binary writer and this // optimization would intefere with that one. if (auto* get = inst->origin->dynCast(); - get && inst->type.isSingle()) { + get && inst->type.isSingle() && !deferredGets.count(get)) { // Use another local to clarify what instIndex means in this scope. auto getIndex = instIndex; @@ -453,4 +459,22 @@ bool StackIROptimizer::canRemoveSetGetPair(Index setIndex, Index getIndex) { return true; } +std::unordered_set StackIROptimizer::findStringViewDeferredGets() { + std::unordered_set deferred; + auto note = [&](Expression* e) { + if (auto* get = e->dynCast()) { + deferred.insert(get); + } + }; + for (auto* inst : insts) { + if (auto* curr = inst->origin->dynCast()) { + note(curr->pos); + } else if (auto* curr = inst->origin->dynCast()) { + note(curr->start); + note(curr->end); + } + } + return deferred; +} + } // namespace wasm diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 6978f4ca48b..a817e529480 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -89,6 +89,11 @@ void BinaryInstWriter::visitCallIndirect(CallIndirect* curr) { } void BinaryInstWriter::visitLocalGet(LocalGet* curr) { + if (deferredGets.count(curr)) { + // This local.get will be emitted as part of the instruction that consumes + // it. + return; + } if (auto it = extractedGets.find(curr); it != extractedGets.end()) { // We have a tuple of locals to get, but we will only end up using one of // them, so we can just emit that one. @@ -2437,11 +2442,23 @@ void BinaryInstWriter::visitStringEq(StringEq* curr) { void BinaryInstWriter::visitStringWTF16Get(StringWTF16Get* curr) { // We need to convert the ref operand to a stringview, but it is under the pos // operand. Put the i32 in a scratch local, emit the conversion, then get the - // i32 back onto the stack. - Index scratchPos = scratchLocals[Type::i32]; - o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchPos); + // i32 back onto the stack. If `pos` is a local.get anyway, then we can skip + // the scratch local. + bool posDeferred = false; + Index posIndex; + if (auto* get = curr->pos->dynCast()) { + assert(deferredGets.count(get)); + posDeferred = true; + posIndex = mappedLocals[{get->index, 0}]; + } else { + posIndex = scratchLocals[Type::i32]; + } + + if (!posDeferred) { + o << int8_t(BinaryConsts::LocalSet) << U32LEB(posIndex); + } o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringAsWTF16); - o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchPos); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(posIndex); o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringViewWTF16GetCodePoint); } @@ -2449,14 +2466,37 @@ void BinaryInstWriter::visitStringWTF16Get(StringWTF16Get* curr) { void BinaryInstWriter::visitStringSliceWTF(StringSliceWTF* curr) { // We need to convert the ref operand to a stringview, but it is buried under // the start and end operands. Put the i32s in scratch locals, emit the - // conversion, then get the i32s back onto the stack. - Index scratchStart = scratchLocals[Type::i32]; - Index scratchEnd = scratchStart + 1; - o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchEnd); - o << int8_t(BinaryConsts::LocalSet) << U32LEB(scratchStart); + // conversion, then get the i32s back onto the stack. If either `start` or + // `end` is already a local.get, then we can skip its scratch local. + bool startDeferred = false, endDeferred = false; + Index startIndex, endIndex; + if (auto* get = curr->start->dynCast()) { + assert(deferredGets.count(get)); + startDeferred = true; + startIndex = mappedLocals[{get->index, 0}]; + } else { + startIndex = scratchLocals[Type::i32]; + } + if (auto* get = curr->end->dynCast()) { + assert(deferredGets.count(get)); + endDeferred = true; + endIndex = mappedLocals[{get->index, 0}]; + } else { + endIndex = scratchLocals[Type::i32]; + if (!startDeferred) { + ++endIndex; + } + } + + if (!endDeferred) { + o << int8_t(BinaryConsts::LocalSet) << U32LEB(endIndex); + } + if (!startDeferred) { + o << int8_t(BinaryConsts::LocalSet) << U32LEB(startIndex); + } o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringAsWTF16); - o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchStart); - o << int8_t(BinaryConsts::LocalGet) << U32LEB(scratchEnd); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(startIndex); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(endIndex); o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringViewWTF16Slice); } @@ -2653,6 +2693,12 @@ InsertOrderedMap BinaryInstWriter::countScratchLocals() { if (curr->type == Type::unreachable) { return; } + // If `pos` already a local.get, we can defer emitting that local.get + // instead of using a scratch local. + if (auto* get = curr->pos->dynCast()) { + parent.deferredGets.insert(get); + return; + } // Scratch local to hold the `pos` value while we emit a stringview // conversion for the `ref` value. auto& count = scratches[Type::i32]; @@ -2663,10 +2709,21 @@ InsertOrderedMap BinaryInstWriter::countScratchLocals() { if (curr->type == Type::unreachable) { return; } + // If `start` or `end` are already local.gets, we can defer emitting those + // gets instead of using scratch locals. + Index numScratches = 2; + if (auto* get = curr->start->dynCast()) { + parent.deferredGets.insert(get); + --numScratches; + } + if (auto* get = curr->end->dynCast()) { + parent.deferredGets.insert(get); + --numScratches; + } // Scratch locals to hold the `start` and `end` values while we emit a // stringview conversion for the `ref` value. auto& count = scratches[Type::i32]; - count = std::max(count, 2u); + count = std::max(count, numScratches); } }; diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast index 5de33051535..a793aea092b 100644 --- a/test/lit/string.as_wtf16.wast +++ b/test/lit/string.as_wtf16.wast @@ -4,26 +4,28 @@ ;; into any IR. ;; RUN: wasm-opt %s -all -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP +;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP +;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip --roundtrip -S -o - | filecheck %s --check-prefix=2TRIP (module - ;; CHECK: (func $empty (type $1) + ;; CHECK: (func $empty (type $2) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) - ;; RTRIP: (func $empty (type $1) - ;; RTRIP-NEXT: (nop) + ;; RTRIP: (func $empty (type $2) ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $empty (type $2) + ;; 2TRIP-NEXT: ) (func $empty (string.as_wtf16) ) - ;; CHECK: (func $codeunit (type $0) (result i32) + ;; CHECK: (func $codeunit (type $1) (result i32) ;; CHECK-NEXT: (stringview_wtf16.get_codeunit ;; CHECK-NEXT: (string.const "abc") ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; RTRIP: (func $codeunit (type $0) (result i32) + ;; RTRIP: (func $codeunit (type $1) (result i32) ;; RTRIP-NEXT: (local $0 i32) ;; RTRIP-NEXT: (local $1 (ref string)) ;; RTRIP-NEXT: (stringview_wtf16.get_codeunit @@ -40,6 +42,27 @@ ;; RTRIP-NEXT: (local.get $0) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $codeunit (type $1) (result i32) + ;; 2TRIP-NEXT: (local $0 i32) + ;; 2TRIP-NEXT: (local $1 (ref string)) + ;; 2TRIP-NEXT: (local $2 (ref string)) + ;; 2TRIP-NEXT: (local.set $1 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $0 + ;; 2TRIP-NEXT: (i32.const 0) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (local.get $1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $0) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) (func $codeunit (result i32) ;; This should parse ok with the conversion skipped. The roundtrip will ;; include scratch locals. @@ -51,14 +74,62 @@ ) ) - ;; CHECK: (func $slice (type $2) (result stringref) + ;; CHECK: (func $codeunit-get (type $1) (result i32) + ;; CHECK-NEXT: (local $pos i32) + ;; CHECK-NEXT: (stringview_wtf16.get_codeunit + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (local.get $pos) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $codeunit-get (type $1) (result i32) + ;; RTRIP-NEXT: (local $pos i32) + ;; RTRIP-NEXT: (local $1 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.get_codeunit + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $1 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $pos) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $codeunit-get (type $1) (result i32) + ;; 2TRIP-NEXT: (local $pos i32) + ;; 2TRIP-NEXT: (local $1 (ref string)) + ;; 2TRIP-NEXT: (local $2 (ref string)) + ;; 2TRIP-NEXT: (local.set $1 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (local.get $1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $pos) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) + (func $codeunit-get (result i32) + (local $pos i32) + ;; This will not use a scratch local for pos. + (stringview_wtf16.get_codeunit + (string.const "abc") + (local.get $pos) + ) + ) + + ;; CHECK: (func $slice (type $0) (result stringref) ;; CHECK-NEXT: (stringview_wtf16.slice ;; CHECK-NEXT: (string.const "abc") ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; RTRIP: (func $slice (type $2) (result stringref) + ;; RTRIP: (func $slice (type $0) (result stringref) ;; RTRIP-NEXT: (local $0 i32) ;; RTRIP-NEXT: (local $1 i32) ;; RTRIP-NEXT: (local $2 i32) @@ -86,6 +157,36 @@ ;; RTRIP-NEXT: (local.get $1) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $slice (type $0) (result stringref) + ;; 2TRIP-NEXT: (local $0 i32) + ;; 2TRIP-NEXT: (local $1 i32) + ;; 2TRIP-NEXT: (local $2 i32) + ;; 2TRIP-NEXT: (local $3 (ref string)) + ;; 2TRIP-NEXT: (local $4 (ref string)) + ;; 2TRIP-NEXT: (local.set $3 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (i32.const 1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $1 + ;; 2TRIP-NEXT: (i32.const 2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $0 + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.slice + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $4 + ;; 2TRIP-NEXT: (local.get $3) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $4) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $0) + ;; 2TRIP-NEXT: (local.get $1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) (func $slice (result stringref) ;; This should parse ok with the conversion skipped. The roundtrip will ;; include scratch locals. @@ -98,16 +199,195 @@ ) ) - ;; CHECK: (func $length (type $0) (result i32) + ;; CHECK: (func $slice-start-get (type $0) (result stringref) + ;; CHECK-NEXT: (local $start i32) + ;; CHECK-NEXT: (stringview_wtf16.slice + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (local.get $start) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $slice-start-get (type $0) (result stringref) + ;; RTRIP-NEXT: (local $start i32) + ;; RTRIP-NEXT: (local $1 i32) + ;; RTRIP-NEXT: (local $2 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.slice + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $2 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.set $1 + ;; RTRIP-NEXT: (i32.const 2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $start) + ;; RTRIP-NEXT: (local.get $1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $slice-start-get (type $0) (result stringref) + ;; 2TRIP-NEXT: (local $start i32) + ;; 2TRIP-NEXT: (local $1 i32) + ;; 2TRIP-NEXT: (local $2 (ref string)) + ;; 2TRIP-NEXT: (local $3 (ref string)) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $1 + ;; 2TRIP-NEXT: (i32.const 2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.slice + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $3 + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $3) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $start) + ;; 2TRIP-NEXT: (local.get $1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) + (func $slice-start-get (result stringref) + (local $start i32) + (stringview_wtf16.slice + (string.const "abc") + (local.get $start) + (i32.const 2) + ) + ) + + + ;; CHECK: (func $slice-end-get (type $0) (result stringref) + ;; CHECK-NEXT: (local $end i32) + ;; CHECK-NEXT: (stringview_wtf16.slice + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (local.get $end) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $slice-end-get (type $0) (result stringref) + ;; RTRIP-NEXT: (local $end i32) + ;; RTRIP-NEXT: (local $1 i32) + ;; RTRIP-NEXT: (local $2 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.slice + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $2 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.set $1 + ;; RTRIP-NEXT: (i32.const 1) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $1) + ;; RTRIP-NEXT: (local.get $end) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $slice-end-get (type $0) (result stringref) + ;; 2TRIP-NEXT: (local $end i32) + ;; 2TRIP-NEXT: (local $1 i32) + ;; 2TRIP-NEXT: (local $2 (ref string)) + ;; 2TRIP-NEXT: (local $3 (ref string)) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.set $1 + ;; 2TRIP-NEXT: (i32.const 1) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.slice + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $3 + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $3) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $1) + ;; 2TRIP-NEXT: (local.get $end) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) + (func $slice-end-get (result stringref) + (local $end i32) + (stringview_wtf16.slice + (string.const "abc") + (i32.const 1) + (local.get $end) + ) + ) + + ;; CHECK: (func $slice-both-get (type $0) (result stringref) + ;; CHECK-NEXT: (local $start i32) + ;; CHECK-NEXT: (local $end i32) + ;; CHECK-NEXT: (stringview_wtf16.slice + ;; CHECK-NEXT: (string.const "abc") + ;; CHECK-NEXT: (local.get $start) + ;; CHECK-NEXT: (local.get $end) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; RTRIP: (func $slice-both-get (type $0) (result stringref) + ;; RTRIP-NEXT: (local $start i32) + ;; RTRIP-NEXT: (local $end i32) + ;; RTRIP-NEXT: (local $2 (ref string)) + ;; RTRIP-NEXT: (stringview_wtf16.slice + ;; RTRIP-NEXT: (block (result (ref string)) + ;; RTRIP-NEXT: (local.set $2 + ;; RTRIP-NEXT: (string.const "abc") + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (nop) + ;; RTRIP-NEXT: (local.get $2) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (local.get $start) + ;; RTRIP-NEXT: (local.get $end) + ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $slice-both-get (type $0) (result stringref) + ;; 2TRIP-NEXT: (local $start i32) + ;; 2TRIP-NEXT: (local $end i32) + ;; 2TRIP-NEXT: (local $2 (ref string)) + ;; 2TRIP-NEXT: (local $3 (ref string)) + ;; 2TRIP-NEXT: (local.set $2 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (stringview_wtf16.slice + ;; 2TRIP-NEXT: (block (result (ref string)) + ;; 2TRIP-NEXT: (local.set $3 + ;; 2TRIP-NEXT: (local.get $2) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (nop) + ;; 2TRIP-NEXT: (local.get $3) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $start) + ;; 2TRIP-NEXT: (local.get $end) + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) + (func $slice-both-get (result stringref) + (local $start i32) + (local $end i32) + (stringview_wtf16.slice + (string.const "abc") + (local.get $start) + (local.get $end) + ) + ) + + ;; CHECK: (func $length (type $1) (result i32) ;; CHECK-NEXT: (string.measure_wtf16 ;; CHECK-NEXT: (string.const "abc") ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; RTRIP: (func $length (type $0) (result i32) + ;; RTRIP: (func $length (type $1) (result i32) ;; RTRIP-NEXT: (string.measure_wtf16 ;; RTRIP-NEXT: (string.const "abc") ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) + ;; 2TRIP: (func $length (type $1) (result i32) + ;; 2TRIP-NEXT: (string.measure_wtf16 + ;; 2TRIP-NEXT: (string.const "abc") + ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: ) (func $length (result i32) ;; This should be parsed as string.measure_wtf16 instead. (stringview_wtf16.length From 3705c4ffa4101f44b7ebaa262ca6f74d14722f00 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 14 May 2024 16:45:20 -0700 Subject: [PATCH 5/7] ignore string.as_wtf16 in binary --- src/wasm/wasm-binary.cpp | 12 +++-- test/lit/string.as_wtf16.wast | 84 ++++------------------------------- 2 files changed, 13 insertions(+), 83 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 0be6d570344..ed78b051e0c 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -7580,13 +7580,11 @@ bool WasmBinaryReader::maybeVisitStringAsWTF16(Expression*& out, if (code != BinaryConsts::StringAsWTF16) { return false; } - // Parse `string.as_wtf16` as a nop. We do not support this instruction in the - // IR, but parsing it as a nop will ensure that the subsequent - // `stringview_wtf16.get_codeunit` or `stringview_wtf16.slice` will still - // receive the string value. We need to at least accept this in the binary - // parser because we emit `string.as_wtf16` as part of the binary encoding of - // those other two instructions. - out = Builder(wasm).makeNop(); + // Accept but ignore `string.as_wtf16`, parsing the next expression in its + // place. We do not support this instruction in the IR, but we need to accept + // it in the parser because it is emitted as part of the instruction sequence + // for `stringview_wtf16.get_codeunit` and `stringview_wtf16.slice`. + readExpression(out); return true; } diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast index a793aea092b..14fc352f8c8 100644 --- a/test/lit/string.as_wtf16.wast +++ b/test/lit/string.as_wtf16.wast @@ -36,7 +36,6 @@ ;; RTRIP-NEXT: (local.set $0 ;; RTRIP-NEXT: (i32.const 0) ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) ;; RTRIP-NEXT: (local.get $1) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: (local.get $0) @@ -45,7 +44,6 @@ ;; 2TRIP: (func $codeunit (type $1) (result i32) ;; 2TRIP-NEXT: (local $0 i32) ;; 2TRIP-NEXT: (local $1 (ref string)) - ;; 2TRIP-NEXT: (local $2 (ref string)) ;; 2TRIP-NEXT: (local.set $1 ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: ) @@ -53,13 +51,7 @@ ;; 2TRIP-NEXT: (i32.const 0) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $1) ;; 2TRIP-NEXT: (local.get $0) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: ) @@ -83,33 +75,15 @@ ;; CHECK-NEXT: ) ;; RTRIP: (func $codeunit-get (type $1) (result i32) ;; RTRIP-NEXT: (local $pos i32) - ;; RTRIP-NEXT: (local $1 (ref string)) ;; RTRIP-NEXT: (stringview_wtf16.get_codeunit - ;; RTRIP-NEXT: (block (result (ref string)) - ;; RTRIP-NEXT: (local.set $1 - ;; RTRIP-NEXT: (string.const "abc") - ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) - ;; RTRIP-NEXT: (local.get $1) - ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (string.const "abc") ;; RTRIP-NEXT: (local.get $pos) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) ;; 2TRIP: (func $codeunit-get (type $1) (result i32) ;; 2TRIP-NEXT: (local $pos i32) - ;; 2TRIP-NEXT: (local $1 (ref string)) - ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local.set $1 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: (local.get $pos) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: ) @@ -150,7 +124,6 @@ ;; RTRIP-NEXT: (local.get $2) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) ;; RTRIP-NEXT: (local.get $3) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: (local.get $0) @@ -162,7 +135,6 @@ ;; 2TRIP-NEXT: (local $1 i32) ;; 2TRIP-NEXT: (local $2 i32) ;; 2TRIP-NEXT: (local $3 (ref string)) - ;; 2TRIP-NEXT: (local $4 (ref string)) ;; 2TRIP-NEXT: (local.set $3 ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: ) @@ -176,13 +148,7 @@ ;; 2TRIP-NEXT: (local.get $2) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $4 - ;; 2TRIP-NEXT: (local.get $3) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $4) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $3) ;; 2TRIP-NEXT: (local.get $0) ;; 2TRIP-NEXT: (local.get $1) ;; 2TRIP-NEXT: ) @@ -219,7 +185,6 @@ ;; RTRIP-NEXT: (local.set $1 ;; RTRIP-NEXT: (i32.const 2) ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) ;; RTRIP-NEXT: (local.get $2) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: (local.get $start) @@ -230,7 +195,6 @@ ;; 2TRIP-NEXT: (local $start i32) ;; 2TRIP-NEXT: (local $1 i32) ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local $3 (ref string)) ;; 2TRIP-NEXT: (local.set $2 ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: ) @@ -238,13 +202,7 @@ ;; 2TRIP-NEXT: (i32.const 2) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $3 - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $3) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $2) ;; 2TRIP-NEXT: (local.get $start) ;; 2TRIP-NEXT: (local.get $1) ;; 2TRIP-NEXT: ) @@ -279,7 +237,6 @@ ;; RTRIP-NEXT: (local.set $1 ;; RTRIP-NEXT: (i32.const 1) ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) ;; RTRIP-NEXT: (local.get $2) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: (local.get $1) @@ -290,7 +247,6 @@ ;; 2TRIP-NEXT: (local $end i32) ;; 2TRIP-NEXT: (local $1 i32) ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local $3 (ref string)) ;; 2TRIP-NEXT: (local.set $2 ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: ) @@ -298,13 +254,7 @@ ;; 2TRIP-NEXT: (i32.const 1) ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $3 - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $3) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (local.get $2) ;; 2TRIP-NEXT: (local.get $1) ;; 2TRIP-NEXT: (local.get $end) ;; 2TRIP-NEXT: ) @@ -330,15 +280,8 @@ ;; RTRIP: (func $slice-both-get (type $0) (result stringref) ;; RTRIP-NEXT: (local $start i32) ;; RTRIP-NEXT: (local $end i32) - ;; RTRIP-NEXT: (local $2 (ref string)) ;; RTRIP-NEXT: (stringview_wtf16.slice - ;; RTRIP-NEXT: (block (result (ref string)) - ;; RTRIP-NEXT: (local.set $2 - ;; RTRIP-NEXT: (string.const "abc") - ;; RTRIP-NEXT: ) - ;; RTRIP-NEXT: (nop) - ;; RTRIP-NEXT: (local.get $2) - ;; RTRIP-NEXT: ) + ;; RTRIP-NEXT: (string.const "abc") ;; RTRIP-NEXT: (local.get $start) ;; RTRIP-NEXT: (local.get $end) ;; RTRIP-NEXT: ) @@ -346,19 +289,8 @@ ;; 2TRIP: (func $slice-both-get (type $0) (result stringref) ;; 2TRIP-NEXT: (local $start i32) ;; 2TRIP-NEXT: (local $end i32) - ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local $3 (ref string)) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (block (result (ref string)) - ;; 2TRIP-NEXT: (local.set $3 - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (nop) - ;; 2TRIP-NEXT: (local.get $3) - ;; 2TRIP-NEXT: ) + ;; 2TRIP-NEXT: (string.const "abc") ;; 2TRIP-NEXT: (local.get $start) ;; 2TRIP-NEXT: (local.get $end) ;; 2TRIP-NEXT: ) From 4f0956669dc1da7dc8e75f6bae3d38b613605228 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 14 May 2024 17:31:09 -0700 Subject: [PATCH 6/7] fix --- src/wasm/wasm-stack-opts.cpp | 3 + test/lit/string.as_wtf16.wast | 186 +++++++++++++++++----------------- 2 files changed, 96 insertions(+), 93 deletions(-) diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index c6487f58f90..ae9fee3940a 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -467,6 +467,9 @@ std::unordered_set StackIROptimizer::findStringViewDeferredGets() { } }; for (auto* inst : insts) { + if (!inst) { + continue; + } if (auto* curr = inst->origin->dynCast()) { note(curr->pos); } else if (auto* curr = inst->origin->dynCast()) { diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast index 14fc352f8c8..6a550bdd92c 100644 --- a/test/lit/string.as_wtf16.wast +++ b/test/lit/string.as_wtf16.wast @@ -5,7 +5,7 @@ ;; RUN: wasm-opt %s -all -S -o - | filecheck %s ;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP -;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip --roundtrip -S -o - | filecheck %s --check-prefix=2TRIP +;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip --roundtrip -S -o - | filecheck %s --check-prefix=RRTRP (module ;; CHECK: (func $empty (type $2) @@ -13,8 +13,8 @@ ;; CHECK-NEXT: ) ;; RTRIP: (func $empty (type $2) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $empty (type $2) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $empty (type $2) + ;; RRTRP-NEXT: ) (func $empty (string.as_wtf16) ) @@ -41,20 +41,20 @@ ;; RTRIP-NEXT: (local.get $0) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $codeunit (type $1) (result i32) - ;; 2TRIP-NEXT: (local $0 i32) - ;; 2TRIP-NEXT: (local $1 (ref string)) - ;; 2TRIP-NEXT: (local.set $1 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $0 - ;; 2TRIP-NEXT: (i32.const 0) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: (local.get $0) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $codeunit (type $1) (result i32) + ;; RRTRP-NEXT: (local $0 i32) + ;; RRTRP-NEXT: (local $1 (ref string)) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $0 + ;; RRTRP-NEXT: (i32.const 0) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (stringview_wtf16.get_codeunit + ;; RRTRP-NEXT: (local.get $1) + ;; RRTRP-NEXT: (local.get $0) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $codeunit (result i32) ;; This should parse ok with the conversion skipped. The roundtrip will ;; include scratch locals. @@ -80,13 +80,13 @@ ;; RTRIP-NEXT: (local.get $pos) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $codeunit-get (type $1) (result i32) - ;; 2TRIP-NEXT: (local $pos i32) - ;; 2TRIP-NEXT: (stringview_wtf16.get_codeunit - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: (local.get $pos) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $codeunit-get (type $1) (result i32) + ;; RRTRP-NEXT: (local $pos i32) + ;; RRTRP-NEXT: (stringview_wtf16.get_codeunit + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: (local.get $pos) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $codeunit-get (result i32) (local $pos i32) ;; This will not use a scratch local for pos. @@ -130,29 +130,29 @@ ;; RTRIP-NEXT: (local.get $1) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $slice (type $0) (result stringref) - ;; 2TRIP-NEXT: (local $0 i32) - ;; 2TRIP-NEXT: (local $1 i32) - ;; 2TRIP-NEXT: (local $2 i32) - ;; 2TRIP-NEXT: (local $3 (ref string)) - ;; 2TRIP-NEXT: (local.set $3 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (i32.const 1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $1 - ;; 2TRIP-NEXT: (i32.const 2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $0 - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (local.get $3) - ;; 2TRIP-NEXT: (local.get $0) - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $slice (type $0) (result stringref) + ;; RRTRP-NEXT: (local $0 i32) + ;; RRTRP-NEXT: (local $1 i32) + ;; RRTRP-NEXT: (local $2 i32) + ;; RRTRP-NEXT: (local $3 (ref string)) + ;; RRTRP-NEXT: (local.set $3 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $2 + ;; RRTRP-NEXT: (i32.const 1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 2) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $0 + ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (stringview_wtf16.slice + ;; RRTRP-NEXT: (local.get $3) + ;; RRTRP-NEXT: (local.get $0) + ;; RRTRP-NEXT: (local.get $1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $slice (result stringref) ;; This should parse ok with the conversion skipped. The roundtrip will ;; include scratch locals. @@ -191,22 +191,22 @@ ;; RTRIP-NEXT: (local.get $1) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $slice-start-get (type $0) (result stringref) - ;; 2TRIP-NEXT: (local $start i32) - ;; 2TRIP-NEXT: (local $1 i32) - ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $1 - ;; 2TRIP-NEXT: (i32.const 2) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: (local.get $start) - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $slice-start-get (type $0) (result stringref) + ;; RRTRP-NEXT: (local $start i32) + ;; RRTRP-NEXT: (local $1 i32) + ;; RRTRP-NEXT: (local $2 (ref string)) + ;; RRTRP-NEXT: (local.set $2 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 2) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (stringview_wtf16.slice + ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: (local.get $start) + ;; RRTRP-NEXT: (local.get $1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $slice-start-get (result stringref) (local $start i32) (stringview_wtf16.slice @@ -243,22 +243,22 @@ ;; RTRIP-NEXT: (local.get $end) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $slice-end-get (type $0) (result stringref) - ;; 2TRIP-NEXT: (local $end i32) - ;; 2TRIP-NEXT: (local $1 i32) - ;; 2TRIP-NEXT: (local $2 (ref string)) - ;; 2TRIP-NEXT: (local.set $2 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (local.set $1 - ;; 2TRIP-NEXT: (i32.const 1) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (local.get $2) - ;; 2TRIP-NEXT: (local.get $1) - ;; 2TRIP-NEXT: (local.get $end) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $slice-end-get (type $0) (result stringref) + ;; RRTRP-NEXT: (local $end i32) + ;; RRTRP-NEXT: (local $1 i32) + ;; RRTRP-NEXT: (local $2 (ref string)) + ;; RRTRP-NEXT: (local.set $2 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (stringview_wtf16.slice + ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: (local.get $1) + ;; RRTRP-NEXT: (local.get $end) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $slice-end-get (result stringref) (local $end i32) (stringview_wtf16.slice @@ -286,15 +286,15 @@ ;; RTRIP-NEXT: (local.get $end) ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $slice-both-get (type $0) (result stringref) - ;; 2TRIP-NEXT: (local $start i32) - ;; 2TRIP-NEXT: (local $end i32) - ;; 2TRIP-NEXT: (stringview_wtf16.slice - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: (local.get $start) - ;; 2TRIP-NEXT: (local.get $end) - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $slice-both-get (type $0) (result stringref) + ;; RRTRP-NEXT: (local $start i32) + ;; RRTRP-NEXT: (local $end i32) + ;; RRTRP-NEXT: (stringview_wtf16.slice + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: (local.get $start) + ;; RRTRP-NEXT: (local.get $end) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $slice-both-get (result stringref) (local $start i32) (local $end i32) @@ -315,11 +315,11 @@ ;; RTRIP-NEXT: (string.const "abc") ;; RTRIP-NEXT: ) ;; RTRIP-NEXT: ) - ;; 2TRIP: (func $length (type $1) (result i32) - ;; 2TRIP-NEXT: (string.measure_wtf16 - ;; 2TRIP-NEXT: (string.const "abc") - ;; 2TRIP-NEXT: ) - ;; 2TRIP-NEXT: ) + ;; RRTRP: (func $length (type $1) (result i32) + ;; RRTRP-NEXT: (string.measure_wtf16 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) (func $length (result i32) ;; This should be parsed as string.measure_wtf16 instead. (stringview_wtf16.length From 8fa2cc9cb1574e8c0f8b746ad028bc59facaaad8 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 14 May 2024 22:13:18 -0700 Subject: [PATCH 7/7] shrink level 3 to exercise stack ir changes --- test/lit/string.as_wtf16.wast | 87 ++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/test/lit/string.as_wtf16.wast b/test/lit/string.as_wtf16.wast index 6a550bdd92c..97a5d90559f 100644 --- a/test/lit/string.as_wtf16.wast +++ b/test/lit/string.as_wtf16.wast @@ -4,8 +4,8 @@ ;; into any IR. ;; RUN: wasm-opt %s -all -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP -;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip --roundtrip -S -o - | filecheck %s --check-prefix=RRTRP +;; RUN: wasm-opt %s -all --shrink-level=3 --roundtrip -S -o - | filecheck %s --check-prefix=RTRIP +;; RUN: wasm-opt %s -all --shrink-level=3 --roundtrip --roundtrip -S -o - | filecheck %s --check-prefix=RRTRP (module ;; CHECK: (func $empty (type $2) @@ -44,14 +44,17 @@ ;; RRTRP: (func $codeunit (type $1) (result i32) ;; RRTRP-NEXT: (local $0 i32) ;; RRTRP-NEXT: (local $1 (ref string)) - ;; RRTRP-NEXT: (local.set $1 - ;; RRTRP-NEXT: (string.const "abc") - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $0 - ;; RRTRP-NEXT: (i32.const 0) - ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local $2 (ref string)) ;; RRTRP-NEXT: (stringview_wtf16.get_codeunit - ;; RRTRP-NEXT: (local.get $1) + ;; RRTRP-NEXT: (block (result (ref string)) + ;; RRTRP-NEXT: (local.set $2 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $0 + ;; RRTRP-NEXT: (i32.const 0) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: ) ;; RRTRP-NEXT: (local.get $0) ;; RRTRP-NEXT: ) ;; RRTRP-NEXT: ) @@ -135,20 +138,26 @@ ;; RRTRP-NEXT: (local $1 i32) ;; RRTRP-NEXT: (local $2 i32) ;; RRTRP-NEXT: (local $3 (ref string)) - ;; RRTRP-NEXT: (local.set $3 - ;; RRTRP-NEXT: (string.const "abc") - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $2 - ;; RRTRP-NEXT: (i32.const 1) - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $1 - ;; RRTRP-NEXT: (i32.const 2) - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $0 - ;; RRTRP-NEXT: (local.get $2) - ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local $4 i32) + ;; RRTRP-NEXT: (local $5 (ref string)) ;; RRTRP-NEXT: (stringview_wtf16.slice - ;; RRTRP-NEXT: (local.get $3) + ;; RRTRP-NEXT: (block (result (ref string)) + ;; RRTRP-NEXT: (local.set $5 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $0 + ;; RRTRP-NEXT: (block (result i32) + ;; RRTRP-NEXT: (local.set $4 + ;; RRTRP-NEXT: (i32.const 1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 2) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.get $4) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.get $5) + ;; RRTRP-NEXT: ) ;; RRTRP-NEXT: (local.get $0) ;; RRTRP-NEXT: (local.get $1) ;; RRTRP-NEXT: ) @@ -195,14 +204,17 @@ ;; RRTRP-NEXT: (local $start i32) ;; RRTRP-NEXT: (local $1 i32) ;; RRTRP-NEXT: (local $2 (ref string)) - ;; RRTRP-NEXT: (local.set $2 - ;; RRTRP-NEXT: (string.const "abc") - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $1 - ;; RRTRP-NEXT: (i32.const 2) - ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local $3 (ref string)) ;; RRTRP-NEXT: (stringview_wtf16.slice - ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: (block (result (ref string)) + ;; RRTRP-NEXT: (local.set $3 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 2) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.get $3) + ;; RRTRP-NEXT: ) ;; RRTRP-NEXT: (local.get $start) ;; RRTRP-NEXT: (local.get $1) ;; RRTRP-NEXT: ) @@ -247,14 +259,17 @@ ;; RRTRP-NEXT: (local $end i32) ;; RRTRP-NEXT: (local $1 i32) ;; RRTRP-NEXT: (local $2 (ref string)) - ;; RRTRP-NEXT: (local.set $2 - ;; RRTRP-NEXT: (string.const "abc") - ;; RRTRP-NEXT: ) - ;; RRTRP-NEXT: (local.set $1 - ;; RRTRP-NEXT: (i32.const 1) - ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local $3 (ref string)) ;; RRTRP-NEXT: (stringview_wtf16.slice - ;; RRTRP-NEXT: (local.get $2) + ;; RRTRP-NEXT: (block (result (ref string)) + ;; RRTRP-NEXT: (local.set $3 + ;; RRTRP-NEXT: (string.const "abc") + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.set $1 + ;; RRTRP-NEXT: (i32.const 1) + ;; RRTRP-NEXT: ) + ;; RRTRP-NEXT: (local.get $3) + ;; RRTRP-NEXT: ) ;; RRTRP-NEXT: (local.get $1) ;; RRTRP-NEXT: (local.get $end) ;; RRTRP-NEXT: )