diff options
Diffstat (limited to 'src')
40 files changed, 255 insertions, 1619 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 1c9a5be0e..a9a21bc14 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<BinaryenHeapType>(HeapType::BasicHeapType::string); } -BinaryenHeapType BinaryenHeapTypeStringviewWTF8() { - return static_cast<BinaryenHeapType>( - HeapType::BasicHeapType::stringview_wtf8); -} -BinaryenHeapType BinaryenHeapTypeStringviewWTF16() { - return static_cast<BinaryenHeapType>( - HeapType::BasicHeapType::stringview_wtf16); -} -BinaryenHeapType BinaryenHeapTypeStringviewIter() { - return static_cast<BinaryenHeapType>( - HeapType::BasicHeapType::stringview_iter); -} BinaryenHeapType BinaryenHeapTypeNone() { return static_cast<BinaryenHeapType>(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<Expression*>( - Builder(*(Module*)module).makeStringAs(StringAsOp(op), (Expression*)ref)); -} -BinaryenExpressionRef BinaryenStringWTF8Advance(BinaryenModuleRef module, - BinaryenExpressionRef ref, - BinaryenExpressionRef pos, - BinaryenExpressionRef bytes) { - return static_cast<Expression*>(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<Expression*>( - Builder(*(Module*)module).makeStringIterNext((Expression*)ref)); -} -BinaryenExpressionRef BinaryenStringIterMove(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef ref, - BinaryenExpressionRef num) { - return static_cast<Expression*>(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<Expression*>(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<Expression*>( - Builder(*(Module*)module) - .makeStringSliceIter((Expression*)ref, (Expression*)num)); -} // Expression utility @@ -4720,69 +4645,6 @@ void BinaryenStringEqSetRight(BinaryenExpressionRef expr, assert(rightExpr); static_cast<StringEq*>(expression)->right = (Expression*)rightExpr; } -// StringAs -BinaryenOp BinaryenStringAsGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringAs>()); - return static_cast<StringAs*>(expression)->op; -} -void BinaryenStringAsSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is<StringAs>()); - static_cast<StringAs*>(expression)->op = StringAsOp(op); -} -BinaryenExpressionRef BinaryenStringAsGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringAs>()); - return static_cast<StringAs*>(expression)->ref; -} -void BinaryenStringAsSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringAs>()); - assert(refExpr); - static_cast<StringAs*>(expression)->ref = (Expression*)refExpr; -} -// StringWTF8Advance -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - return static_cast<StringWTF8Advance*>(expression)->ref; -} -void BinaryenStringWTF8AdvanceSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - assert(refExpr); - static_cast<StringWTF8Advance*>(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetPos(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - return static_cast<StringWTF8Advance*>(expression)->pos; -} -void BinaryenStringWTF8AdvanceSetPos(BinaryenExpressionRef expr, - BinaryenExpressionRef posExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - assert(posExpr); - static_cast<StringWTF8Advance*>(expression)->pos = (Expression*)posExpr; -} -BinaryenExpressionRef -BinaryenStringWTF8AdvanceGetBytes(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - return static_cast<StringWTF8Advance*>(expression)->bytes; -} -void BinaryenStringWTF8AdvanceSetBytes(BinaryenExpressionRef expr, - BinaryenExpressionRef bytesExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringWTF8Advance>()); - assert(bytesExpr); - static_cast<StringWTF8Advance*>(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<StringWTF16Get*>(expression)->pos = (Expression*)posExpr; } -// StringIterNext -BinaryenExpressionRef BinaryenStringIterNextGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterNext>()); - return static_cast<StringIterNext*>(expression)->ref; -} -void BinaryenStringIterNextSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterNext>()); - assert(refExpr); - static_cast<StringIterNext*>(expression)->ref = (Expression*)refExpr; -} -// StringIterMove -BinaryenOp BinaryenStringIterMoveGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - return static_cast<StringIterMove*>(expression)->op; -} -void BinaryenStringIterMoveSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - static_cast<StringIterMove*>(expression)->op = StringIterMoveOp(op); -} -BinaryenExpressionRef BinaryenStringIterMoveGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - return static_cast<StringIterMove*>(expression)->ref; -} -void BinaryenStringIterMoveSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - assert(refExpr); - static_cast<StringIterMove*>(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef BinaryenStringIterMoveGetNum(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - return static_cast<StringIterMove*>(expression)->num; -} -void BinaryenStringIterMoveSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringIterMove>()); - assert(numExpr); - static_cast<StringIterMove*>(expression)->num = (Expression*)numExpr; -} // StringSliceWTF -BinaryenOp BinaryenStringSliceWTFGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceWTF>()); - return static_cast<StringSliceWTF*>(expression)->op; -} -void BinaryenStringSliceWTFSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceWTF>()); - static_cast<StringSliceWTF*>(expression)->op = StringSliceWTFOp(op); -} BinaryenExpressionRef BinaryenStringSliceWTFGetRef(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<StringSliceWTF>()); @@ -4904,33 +4708,6 @@ void BinaryenStringSliceWTFSetEnd(BinaryenExpressionRef expr, assert(endExpr); static_cast<StringSliceWTF*>(expression)->end = (Expression*)endExpr; } -// StringSliceIter -BinaryenExpressionRef -BinaryenStringSliceIterGetRef(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceIter>()); - return static_cast<StringSliceIter*>(expression)->ref; -} -void BinaryenStringSliceIterSetRef(BinaryenExpressionRef expr, - BinaryenExpressionRef refExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceIter>()); - assert(refExpr); - static_cast<StringSliceIter*>(expression)->ref = (Expression*)refExpr; -} -BinaryenExpressionRef -BinaryenStringSliceIterGetNum(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceIter>()); - return static_cast<StringSliceIter*>(expression)->num; -} -void BinaryenStringSliceIterSetNum(BinaryenExpressionRef expr, - BinaryenExpressionRef numExpr) { - auto* expression = (Expression*)expr; - assert(expression->is<StringSliceIter>()); - assert(numExpr); - static_cast<StringSliceIter*>(expression)->num = (Expression*)numExpr; -} // Functions diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 595086d6a..f01b4c3be 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 939031020..b76a26ea1 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 c8f83f1ba..8fae5d073 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 94ef11d77..e015f3db8 100644 --- a/src/ir/child-typer.h +++ b/src/ir/child-typer.h @@ -991,11 +991,7 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> { 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<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> { 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 edb39546d..8af68dbf1 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -706,25 +706,12 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { // "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 b1b4c7053..87b77601f 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -997,45 +997,14 @@ private: } } } - 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 c44cd7ce1..ac320c419 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 1457e1ef5..f563cce14 100644 --- a/src/ir/subtype-exprs.h +++ b/src/ir/subtype-exprs.h @@ -383,13 +383,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> { 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 0144b9330..12a8c7c36 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 dfde2d7ef..86a6e8df9 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 f66e3d051..b32e32a15 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -217,9 +217,6 @@ template<typename Ctx> 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<Annotation>&, StringEqOp) { return Ok{}; } - Result<> makeStringAs(Index, const std::vector<Annotation>&, StringAsOp) { - return Ok{}; - } Result<> makeStringWTF8Advance(Index, const std::vector<Annotation>&) { return Ok{}; } @@ -811,15 +805,7 @@ struct NullInstrParserCtx { Result<> makeStringIterNext(Index, const std::vector<Annotation>&) { return Ok{}; } - Result<> - makeStringIterMove(Index, const std::vector<Annotation>&, StringIterMoveOp) { - return Ok{}; - } - Result<> - makeStringSliceWTF(Index, const std::vector<Annotation>&, StringSliceWTFOp) { - return Ok{}; - } - Result<> makeStringSliceIter(Index, const std::vector<Annotation>&) { + Result<> makeStringSliceWTF(Index, const std::vector<Annotation>&) { return Ok{}; } template<typename HeapTypeT> @@ -2562,42 +2548,14 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> { return withLoc(pos, irBuilder.makeStringEq(op)); } - Result<> makeStringAs(Index pos, - const std::vector<Annotation>& annotations, - StringAsOp op) { - return withLoc(pos, irBuilder.makeStringAs(op)); - } - - Result<> makeStringWTF8Advance(Index pos, - const std::vector<Annotation>& annotations) { - return withLoc(pos, irBuilder.makeStringWTF8Advance()); - } - Result<> makeStringWTF16Get(Index pos, const std::vector<Annotation>& annotations) { return withLoc(pos, irBuilder.makeStringWTF16Get()); } - Result<> makeStringIterNext(Index pos, - const std::vector<Annotation>& annotations) { - return withLoc(pos, irBuilder.makeStringIterNext()); - } - - Result<> makeStringIterMove(Index pos, - const std::vector<Annotation>& annotations, - StringIterMoveOp op) { - return withLoc(pos, irBuilder.makeStringIterMove(op)); - } - Result<> makeStringSliceWTF(Index pos, - const std::vector<Annotation>& annotations, - StringSliceWTFOp op) { - return withLoc(pos, irBuilder.makeStringSliceWTF(op)); - } - - Result<> makeStringSliceIter(Index pos, - const std::vector<Annotation>& annotations) { - return withLoc(pos, irBuilder.makeStringSliceIter()); + const std::vector<Annotation>& annotations) { + return withLoc(pos, irBuilder.makeStringSliceWTF()); } Result<> makeContBind(Index pos, diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 30a828822..60d3f0391 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -285,26 +285,9 @@ Result<> makeStringConcat(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> Result<> makeStringEq(Ctx&, Index, const std::vector<Annotation>&, StringEqOp); template<typename Ctx> -Result<> -makeStringAs(Ctx&, Index, const std::vector<Annotation>&, StringAsOp op); -template<typename Ctx> -Result<> makeStringWTF8Advance(Ctx&, Index, const std::vector<Annotation>&); -template<typename Ctx> Result<> makeStringWTF16Get(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> -Result<> makeStringIterNext(Ctx&, Index, const std::vector<Annotation>&); -template<typename Ctx> -Result<> makeStringIterMove(Ctx&, - Index, - const std::vector<Annotation>&, - StringIterMoveOp op); -template<typename Ctx> -Result<> makeStringSliceWTF(Ctx&, - Index, - const std::vector<Annotation>&, - StringSliceWTFOp op); -template<typename Ctx> -Result<> makeStringSliceIter(Ctx&, Index, const std::vector<Annotation>&); +Result<> makeStringSliceWTF(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> Result<> makeContBind(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> @@ -314,6 +297,11 @@ Result<> makeResume(Ctx&, Index, const std::vector<Annotation>&); template<typename Ctx> Result<> makeSuspend(Ctx&, Index, const std::vector<Annotation>&); +template<typename Ctx> +Result<> ignore(Ctx&, Index, const std::vector<Annotation>&) { + return Ok{}; +} + // Modules template<typename Ctx> MaybeResult<Index> maybeTypeidx(Ctx& ctx); template<typename Ctx> Result<typename Ctx::HeapTypeT> typeidx(Ctx&); @@ -421,15 +409,6 @@ template<typename Ctx> Result<typename Ctx::HeapTypeT> 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<typename Ctx> MaybeResult<typename Ctx::TypeT> 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); } @@ -2436,21 +2406,6 @@ Result<> makeStringEq(Ctx& ctx, } template<typename Ctx> -Result<> makeStringAs(Ctx& ctx, - Index pos, - const std::vector<Annotation>& annotations, - StringAsOp op) { - return ctx.makeStringAs(pos, annotations, op); -} - -template<typename Ctx> -Result<> makeStringWTF8Advance(Ctx& ctx, - Index pos, - const std::vector<Annotation>& annotations) { - return ctx.makeStringWTF8Advance(pos, annotations); -} - -template<typename Ctx> Result<> makeStringWTF16Get(Ctx& ctx, Index pos, const std::vector<Annotation>& annotations) { @@ -2458,33 +2413,10 @@ Result<> makeStringWTF16Get(Ctx& ctx, } template<typename Ctx> -Result<> makeStringIterNext(Ctx& ctx, - Index pos, - const std::vector<Annotation>& annotations) { - return ctx.makeStringIterNext(pos, annotations); -} - -template<typename Ctx> -Result<> makeStringIterMove(Ctx& ctx, - Index pos, - const std::vector<Annotation>& annotations, - StringIterMoveOp op) { - return ctx.makeStringIterMove(pos, annotations, op); -} - -template<typename Ctx> Result<> makeStringSliceWTF(Ctx& ctx, Index pos, - const std::vector<Annotation>& annotations, - StringSliceWTFOp op) { - return ctx.makeStringSliceWTF(pos, annotations, op); -} - -template<typename Ctx> -Result<> makeStringSliceIter(Ctx& ctx, - Index pos, - const std::vector<Annotation>& annotations) { - return ctx.makeStringSliceIter(pos, annotations); + const std::vector<Annotation>& annotations) { + return ctx.makeStringSliceWTF(pos, annotations); } // contbind ::= 'cont.bind' typeidx typeidx diff --git a/src/parser/wat-parser.cpp b/src/parser/wat-parser.cpp index 2bc222d6b..85ef1e80f 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/passes/Print.cpp b/src/passes/Print.cpp index 21b5e6b20..ab5e0db90 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2300,9 +2300,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; @@ -2355,56 +2352,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 5b5a5b551..27f4e9c07 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 26a0f1eab..81dd0a39e 100644 --- a/src/passes/TypeGeneralizing.cpp +++ b/src/passes/TypeGeneralizing.cpp @@ -865,15 +865,8 @@ struct TransferFn : OverriddenVisitor<TransferFn> { 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 3378d0745..d6f8e0f12 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 = makeTrappingRefUse(HeapType::string); 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 = makeTrappingRefUse(HeapType::string); 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 3d0d29153..08b4c4453 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 d3f798084..c025764e7 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -93,14 +93,6 @@ public: // 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 9610aed9f..449c03699 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,9 @@ 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, @@ -1777,18 +1759,14 @@ public: 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); 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 54766a789..784521c73 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1151,22 +1151,6 @@ public: ret->finalize(); return ret; } - StringAs* makeStringAs(StringAsOp op, Expression* ref) { - auto* ret = wasm.allocator.alloc<StringAs>(); - ret->op = op; - ret->ref = ref; - ret->finalize(); - return ret; - } - StringWTF8Advance* - makeStringWTF8Advance(Expression* ref, Expression* pos, Expression* bytes) { - auto* ret = wasm.allocator.alloc<StringWTF8Advance>(); - ret->ref = ref; - ret->pos = pos; - ret->bytes = bytes; - ret->finalize(); - return ret; - } StringWTF16Get* makeStringWTF16Get(Expression* ref, Expression* pos) { auto* ret = wasm.allocator.alloc<StringWTF16Get>(); ret->ref = ref; @@ -1174,41 +1158,15 @@ public: ret->finalize(); return ret; } - StringIterNext* makeStringIterNext(Expression* ref) { - auto* ret = wasm.allocator.alloc<StringIterNext>(); - ret->ref = ref; - ret->finalize(); - return ret; - } - StringIterMove* - makeStringIterMove(StringIterMoveOp op, Expression* ref, Expression* num) { - auto* ret = wasm.allocator.alloc<StringIterMove>(); - 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<StringSliceWTF>(); - 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<StringSliceIter>(); - ret->ref = ref; - ret->num = num; - ret->finalize(); - return ret; - } - ContBind* makeContBind(HeapType contTypeBefore, HeapType contTypeAfter, const std::vector<Expression*>& operands, diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index 3ffd29534..898c3a361 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -748,44 +748,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 ca07356b9..ea801ab9b 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 ec1ba7707..bd7d78a6e 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1919,7 +1919,7 @@ public: 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 @@ public: } 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 @@ public: 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 @@ public: } 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 650462e12..17ec28f2f 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -212,13 +212,10 @@ public: [[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 7b8faa16b..cfd21661d 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -321,18 +321,16 @@ private: 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>& memory); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index fc38d07a4..e51e5eb91 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -155,10 +155,15 @@ private: // Return the type and number of required scratch locals. InsertOrderedMap<Type, Index> 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<Expression*, Index> 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<LocalGet*> deferredGets; }; // Takes binaryen IR and converts it to something else (binary or stack IR) @@ -543,6 +548,7 @@ private: void removeAt(Index i); Index getNumConsumedValues(StackInst* inst); bool canRemoveSetGetPair(Index setIndex, Index getIndex); + std::unordered_set<LocalGet*> findStringViewDeferredGets(); }; // Generate and emit StackIR. diff --git a/src/wasm-type.h b/src/wasm-type.h index b18eaa6db..6422d09ad 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -329,9 +329,6 @@ public: array, exn, string, - stringview_wtf8, - stringview_wtf16, - stringview_iter, none, noext, nofunc, diff --git a/src/wasm.h b/src/wasm.h index 29240723f..e39d3d527 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 @@ public: StringEncodeId, StringConcatId, StringEqId, - StringAsId, - StringWTF8AdvanceId, StringWTF16GetId, - StringIterNextId, - StringIterMoveId, StringSliceWTFId, - StringSliceIterId, ContBindId, ContNewId, ResumeId, @@ -1908,31 +1886,6 @@ public: void finalize(); }; -class StringAs : public SpecificExpression<Expression::StringAsId> { -public: - StringAs() = default; - StringAs(MixedArena& allocator) {} - - StringAsOp op; - - Expression* ref; - - void finalize(); -}; - -class StringWTF8Advance - : public SpecificExpression<Expression::StringWTF8AdvanceId> { -public: - StringWTF8Advance() = default; - StringWTF8Advance(MixedArena& allocator) {} - - Expression* ref; - Expression* pos; - Expression* bytes; - - void finalize(); -}; - class StringWTF16Get : public SpecificExpression<Expression::StringWTF16GetId> { public: StringWTF16Get() = default; @@ -1944,39 +1897,11 @@ public: void finalize(); }; -class StringIterNext : public SpecificExpression<Expression::StringIterNextId> { -public: - StringIterNext() = default; - StringIterNext(MixedArena& allocator) {} - - Expression* ref; - - void finalize(); -}; - -class StringIterMove : public SpecificExpression<Expression::StringIterMoveId> { -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<Expression::StringSliceWTFId> { public: StringSliceWTF() = default; StringSliceWTF(MixedArena& allocator) {} - StringSliceWTFOp op; - Expression* ref; Expression* start; Expression* end; @@ -1984,18 +1909,6 @@ public: void finalize(); }; -class StringSliceIter - : public SpecificExpression<Expression::StringSliceIterId> { -public: - StringSliceIter() = default; - StringSliceIter(MixedArena& allocator) {} - - Expression* ref; - Expression* num; - - void finalize(); -}; - class ContBind : public SpecificExpression<Expression::ContBindId> { public: ContBind(MixedArena& allocator) : operands(allocator) {} diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 48ade5447..2c61be12a 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 c8ced1327..c8dd7bace 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; @@ -4277,6 +4241,9 @@ BinaryConsts::ASTNodes WasmBinaryReader::readExpression(Expression*& curr) { if (maybeVisitStringNew(curr, opcode)) { break; } + if (maybeVisitStringAsWTF16(curr, opcode)) { + break; + } if (maybeVisitStringConst(curr, opcode)) { break; } @@ -4292,27 +4259,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<RefAs>())->cast<RefAs>(), opcode); @@ -7623,6 +7575,19 @@ bool WasmBinaryReader::maybeVisitStringNew(Expression*& out, uint32_t code) { return true; } +bool WasmBinaryReader::maybeVisitStringAsWTF16(Expression*& out, + uint32_t code) { + if (code != BinaryConsts::StringAsWTF16) { + return false; + } + // 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; +} + bool WasmBinaryReader::maybeVisitStringConst(Expression*& out, uint32_t code) { if (code != BinaryConsts::StringConst) { return false; @@ -7646,8 +7611,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 +7691,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 +7702,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 f816d4d1e..a4b7becf8 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -1891,20 +1891,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)); @@ -1912,32 +1898,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 aa386f841..978ea6a9b 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1289,15 +1289,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); } @@ -1352,15 +1343,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; } @@ -3387,39 +3369,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-opts.cpp b/src/wasm/wasm-stack-opts.cpp index eac423fbd..ae9fee394 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<LocalGet>(); - 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,25 @@ bool StackIROptimizer::canRemoveSetGetPair(Index setIndex, Index getIndex) { return true; } +std::unordered_set<LocalGet*> StackIROptimizer::findStringViewDeferredGets() { + std::unordered_set<LocalGet*> deferred; + auto note = [&](Expression* e) { + if (auto* get = e->dynCast<LocalGet>()) { + deferred.insert(get); + } + }; + for (auto* inst : insts) { + if (!inst) { + continue; + } + if (auto* curr = inst->origin->dynCast<StringWTF16Get>()) { + note(curr->pos); + } else if (auto* curr = inst->origin->dynCast<StringSliceWTF>()) { + 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 53a25d52b..a817e5294 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. @@ -2089,24 +2094,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 +2372,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 +2439,66 @@ 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::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. 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<LocalGet>()) { + assert(deferredGets.count(get)); + posDeferred = true; + posIndex = mappedLocals[{get->index, 0}]; + } else { + posIndex = scratchLocals[Type::i32]; } -} - -void BinaryInstWriter::visitStringWTF8Advance(StringWTF8Advance* curr) { - o << int8_t(BinaryConsts::GCPrefix) - << U32LEB(BinaryConsts::StringViewWTF8Advance); -} -void BinaryInstWriter::visitStringWTF16Get(StringWTF16Get* curr) { + if (!posDeferred) { + o << int8_t(BinaryConsts::LocalSet) << U32LEB(posIndex); + } + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringAsWTF16); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(posIndex); 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*"); + // 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. 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<LocalGet>()) { + assert(deferredGets.count(get)); + startDeferred = true; + startIndex = mappedLocals[{get->index, 0}]; + } else { + startIndex = scratchLocals[Type::i32]; + } + if (auto* get = curr->end->dynCast<LocalGet>()) { + assert(deferredGets.count(get)); + endDeferred = true; + endIndex = mappedLocals[{get->index, 0}]; + } else { + endIndex = scratchLocals[Type::i32]; + if (!startDeferred) { + ++endIndex; + } } -} -void BinaryInstWriter::visitStringSliceIter(StringSliceIter* curr) { + 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(startIndex); + o << int8_t(BinaryConsts::LocalGet) << U32LEB(endIndex); o << int8_t(BinaryConsts::GCPrefix) - << U32LEB(BinaryConsts::StringViewIterSlice); + << U32LEB(BinaryConsts::StringViewWTF16Slice); } void BinaryInstWriter::visitContBind(ContBind* curr) { @@ -2707,6 +2688,43 @@ InsertOrderedMap<Type, Index> BinaryInstWriter::countScratchLocals() { count = std::max(count, 1u); } } + + void visitStringWTF16Get(StringWTF16Get* curr) { + 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<LocalGet>()) { + 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]; + count = std::max(count, 1u); + } + + void visitStringSliceWTF(StringSliceWTF* curr) { + 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<LocalGet>()) { + parent.deferredGets.insert(get); + --numScratches; + } + if (auto* get = curr->end->dynCast<LocalGet>()) { + 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, numScratches); + } }; ScratchLocalFinder finder(*this); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 155d8556e..2eb5369d0 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -496,11 +496,6 @@ std::optional<HeapType> 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> 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 8f3082b41..e9bee8e08 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -478,13 +478,8 @@ public: 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 82ddd553f..22ea4d86f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1289,35 +1289,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; @@ -1326,22 +1297,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) { @@ -1351,14 +1306,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 3ac4d2b4d..7540bd71a 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"); |