diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 8 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 122 | ||||
-rw-r--r-- | src/passes/Print.cpp | 15 | ||||
-rw-r--r-- | src/wasm-binary.h | 3 | ||||
-rw-r--r-- | src/wasm-builder.h | 11 | ||||
-rw-r--r-- | src/wasm-delegations-fields.def | 1 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 2 | ||||
-rw-r--r-- | src/wasm.h | 8 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 20 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 60 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 17 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 2 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 5 |
13 files changed, 194 insertions, 80 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index cd53f9ced..9bbcbaf9e 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -1836,14 +1836,18 @@ BinaryenExpressionRef BinaryenStringNew(BinaryenModuleRef module, BinaryenExpressionRef length, BinaryenExpressionRef start, BinaryenExpressionRef end) { + // TODO: add API support for this + bool try_ = false; + Builder builder(*(Module*)module); return static_cast<Expression*>( length ? builder.makeStringNew( - StringNewOp(op), (Expression*)ptr, (Expression*)length) + StringNewOp(op), (Expression*)ptr, (Expression*)length, try_) : builder.makeStringNew(StringNewOp(op), (Expression*)ptr, (Expression*)start, - (Expression*)end)); + (Expression*)end, + try_)); } BinaryenExpressionRef BinaryenStringConst(BinaryenModuleRef module, const char* name) { diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 6f2c24a47..489066284 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -3191,6 +3191,9 @@ switch (buf[0]) { default: goto parse_error; } } + case 'f': + if (op == "string.from_code_point"sv) { return makeStringNew(s, StringNewFromCodePoint, false); } + goto parse_error; case 'i': if (op == "string.is_usv_sequence"sv) { return makeStringMeasure(s, StringMeasureIsUSV); } goto parse_error; @@ -3206,26 +3209,42 @@ switch (buf[0]) { } } case 'n': { - switch (buf[14]) { - case '1': { + switch (buf[11]) { + case 'u': { switch (buf[16]) { - case '\0': - if (op == "string.new_wtf16"sv) { return makeStringNew(s, StringNewWTF16); } + case 'a': + if (op == "string.new_utf8_array_try"sv) { return makeStringNew(s, StringNewUTF8Array, true); } goto parse_error; - case '_': - if (op == "string.new_wtf16_array"sv) { return makeStringNew(s, StringNewWTF16Array); } + case 't': + if (op == "string.new_utf8_try"sv) { return makeStringNew(s, StringNewUTF8, true); } goto parse_error; default: goto parse_error; } } - case '8': { - switch (buf[15]) { - case '\0': - if (op == "string.new_wtf8"sv) { return makeStringNew(s, StringNewWTF8); } - goto parse_error; - case '_': - if (op == "string.new_wtf8_array"sv) { return makeStringNew(s, StringNewWTF8Array); } - goto parse_error; + case 'w': { + switch (buf[14]) { + case '1': { + switch (buf[16]) { + case '\0': + if (op == "string.new_wtf16"sv) { return makeStringNew(s, StringNewWTF16, false); } + goto parse_error; + case '_': + if (op == "string.new_wtf16_array"sv) { return makeStringNew(s, StringNewWTF16Array, false); } + goto parse_error; + default: goto parse_error; + } + } + case '8': { + switch (buf[15]) { + case '\0': + if (op == "string.new_wtf8"sv) { return makeStringNew(s, StringNewWTF8, false); } + goto parse_error; + case '_': + if (op == "string.new_wtf8_array"sv) { return makeStringNew(s, StringNewWTF8Array, false); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } @@ -8905,6 +8924,13 @@ switch (buf[0]) { default: goto parse_error; } } + case 'f': + if (op == "string.from_code_point"sv) { + auto ret = makeStringNew(ctx, pos, StringNewFromCodePoint, false); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; case 'i': if (op == "string.is_usv_sequence"sv) { auto ret = makeStringMeasure(ctx, pos, StringMeasureIsUSV); @@ -8932,19 +8958,19 @@ switch (buf[0]) { } } case 'n': { - switch (buf[14]) { - case '1': { + switch (buf[11]) { + case 'u': { switch (buf[16]) { - case '\0': - if (op == "string.new_wtf16"sv) { - auto ret = makeStringNew(ctx, pos, StringNewWTF16); + case 'a': + if (op == "string.new_utf8_array_try"sv) { + auto ret = makeStringNew(ctx, pos, StringNewUTF8Array, true); CHECK_ERR(ret); return *ret; } goto parse_error; - case '_': - if (op == "string.new_wtf16_array"sv) { - auto ret = makeStringNew(ctx, pos, StringNewWTF16Array); + case 't': + if (op == "string.new_utf8_try"sv) { + auto ret = makeStringNew(ctx, pos, StringNewUTF8, true); CHECK_ERR(ret); return *ret; } @@ -8952,22 +8978,46 @@ switch (buf[0]) { default: goto parse_error; } } - case '8': { - switch (buf[15]) { - case '\0': - if (op == "string.new_wtf8"sv) { - auto ret = makeStringNew(ctx, pos, StringNewWTF8); - CHECK_ERR(ret); - return *ret; + case 'w': { + switch (buf[14]) { + case '1': { + switch (buf[16]) { + case '\0': + if (op == "string.new_wtf16"sv) { + auto ret = makeStringNew(ctx, pos, StringNewWTF16, false); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case '_': + if (op == "string.new_wtf16_array"sv) { + auto ret = makeStringNew(ctx, pos, StringNewWTF16Array, false); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + default: goto parse_error; } - goto parse_error; - case '_': - if (op == "string.new_wtf8_array"sv) { - auto ret = makeStringNew(ctx, pos, StringNewWTF8Array); - CHECK_ERR(ret); - return *ret; + } + case '8': { + switch (buf[15]) { + case '\0': + if (op == "string.new_wtf8"sv) { + auto ret = makeStringNew(ctx, pos, StringNewWTF8, false); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + case '_': + if (op == "string.new_wtf8_array"sv) { + auto ret = makeStringNew(ctx, pos, StringNewWTF8Array, false); + CHECK_ERR(ret); + return *ret; + } + goto parse_error; + default: goto parse_error; } - goto parse_error; + } default: goto parse_error; } } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index d9a4c38e5..8c112d6a5 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2345,7 +2345,11 @@ struct PrintExpressionContents void visitStringNew(StringNew* curr) { switch (curr->op) { case StringNewUTF8: - printMedium(o, "string.new_wtf8 utf8"); + if (!curr->try_) { + printMedium(o, "string.new_wtf8 utf8"); + } else { + printMedium(o, "string.new_utf8_try"); + } break; case StringNewWTF8: printMedium(o, "string.new_wtf8 wtf8"); @@ -2357,7 +2361,11 @@ struct PrintExpressionContents printMedium(o, "string.new_wtf16"); break; case StringNewUTF8Array: - printMedium(o, "string.new_wtf8_array utf8"); + if (!curr->try_) { + printMedium(o, "string.new_wtf8_array utf8"); + } else { + printMedium(o, "string.new_utf8_array_try"); + } break; case StringNewWTF8Array: printMedium(o, "string.new_wtf8_array wtf8"); @@ -2368,6 +2376,9 @@ struct PrintExpressionContents case StringNewWTF16Array: printMedium(o, "string.new_wtf16_array"); break; + case StringNewFromCodePoint: + printMedium(o, "string.from_code_point"); + break; default: WASM_UNREACHABLE("invalid string.new*"); } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 9ec097c57..a40a96c00 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1150,6 +1150,7 @@ enum ASTNodes { StringConcat = 0x88, StringEq = 0x89, StringIsUSV = 0x8a, + StringNewUTF8Try = 0x8f, StringAsWTF8 = 0x90, StringViewWTF8Advance = 0x91, StringViewWTF8Slice = 0x93, @@ -1163,10 +1164,12 @@ enum ASTNodes { StringViewIterRewind = 0xa3, StringViewIterSlice = 0xa4, StringCompare = 0xa8, + StringFromCodePoint = 0xa9, StringNewWTF8Array = 0xb0, StringNewWTF16Array = 0xb1, StringEncodeWTF8Array = 0xb2, StringEncodeWTF16Array = 0xb3, + StringNewUTF8ArrayTry = 0xb8, }; enum MemoryAccess { diff --git a/src/wasm-builder.h b/src/wasm-builder.h index c25293999..324ed6fd2 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1004,24 +1004,29 @@ public: ret->finalize(); return ret; } - StringNew* - makeStringNew(StringNewOp op, Expression* ptr, Expression* length) { + StringNew* makeStringNew(StringNewOp op, + Expression* ptr, + Expression* length, + bool try_) { auto* ret = wasm.allocator.alloc<StringNew>(); ret->op = op; ret->ptr = ptr; ret->length = length; + ret->try_ = try_; ret->finalize(); return ret; } StringNew* makeStringNew(StringNewOp op, Expression* ptr, Expression* start, - Expression* end) { + Expression* end, + bool try_) { auto* ret = wasm.allocator.alloc<StringNew>(); ret->op = op; ret->ptr = ptr; ret->start = start; ret->end = end; + ret->try_ = try_; ret->finalize(); return ret; } diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index d9226b3d7..cd182e319 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -719,6 +719,7 @@ switch (DELEGATE_ID) { case Expression::Id::StringNewId: { DELEGATE_START(StringNew); DELEGATE_FIELD_INT(StringNew, op); + DELEGATE_FIELD_INT(StringNew, try_); DELEGATE_FIELD_OPTIONAL_CHILD(StringNew, end); DELEGATE_FIELD_OPTIONAL_CHILD(StringNew, start); DELEGATE_FIELD_OPTIONAL_CHILD(StringNew, length); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 942f4c919..d6a9c86d6 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -304,7 +304,7 @@ private: Expression* makeArrayCopy(Element& s); Expression* makeRefAs(Element& s, RefAsOp op); Expression* makeRefAsNonNull(Element& s); - Expression* makeStringNew(Element& s, StringNewOp op); + Expression* makeStringNew(Element& s, StringNewOp op, bool try_); Expression* makeStringConst(Element& s); Expression* makeStringMeasure(Element& s, StringMeasureOp op); Expression* makeStringEncode(Element& s, StringEncodeOp op); diff --git a/src/wasm.h b/src/wasm.h index d5b52b315..779efe991 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -586,6 +586,8 @@ enum StringNewOp { StringNewWTF8Array, StringNewReplaceArray, StringNewWTF16Array, + // Other + StringNewFromCodePoint, }; enum StringMeasureOp { @@ -1684,7 +1686,7 @@ public: StringNewOp op; // In linear memory variations this is the pointer in linear memory. In the - // GC variations this is an Array. + // GC variations this is an Array. In from_codepoint this is the code point. Expression* ptr; // Used only in linear memory variations. @@ -1694,6 +1696,10 @@ public: Expression* start = nullptr; Expression* end = nullptr; + // The "try" variants will return null if an encoding error happens, rather + // than trap. + bool try_ = false; + void finalize(); }; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 65734e68d..cd5763c12 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -7184,7 +7184,13 @@ bool WasmBinaryBuilder::maybeVisitStringNew(Expression*& out, uint32_t code) { Expression* length = nullptr; Expression* start = nullptr; Expression* end = nullptr; - if (code == BinaryConsts::StringNewWTF8) { + bool try_ = false; + if (code == BinaryConsts::StringNewWTF8 || + code == BinaryConsts::StringNewUTF8Try) { + if (code == BinaryConsts::StringNewUTF8Try) { + try_ = true; + } + // FIXME: the memory index should be an LEB like all other places if (getInt8() != 0) { throwError("Unexpected nonzero memory index"); } @@ -7209,7 +7215,11 @@ bool WasmBinaryBuilder::maybeVisitStringNew(Expression*& out, uint32_t code) { } op = StringNewWTF16; length = popNonVoidExpression(); - } else if (code == BinaryConsts::StringNewWTF8Array) { + } else if (code == BinaryConsts::StringNewWTF8Array || + code == BinaryConsts::StringNewUTF8ArrayTry) { + if (code == BinaryConsts::StringNewUTF8ArrayTry) { + try_ = true; + } auto policy = getU32LEB(); switch (policy) { case BinaryConsts::StringPolicy::UTF8: @@ -7230,14 +7240,16 @@ bool WasmBinaryBuilder::maybeVisitStringNew(Expression*& out, uint32_t code) { op = StringNewWTF16Array; end = popNonVoidExpression(); start = popNonVoidExpression(); + } else if (code == BinaryConsts::StringFromCodePoint) { + op = StringNewFromCodePoint; } else { return false; } auto* ptr = popNonVoidExpression(); if (length) { - out = Builder(wasm).makeStringNew(op, ptr, length); + out = Builder(wasm).makeStringNew(op, ptr, length, try_); } else { - out = Builder(wasm).makeStringNew(op, ptr, start, end); + out = Builder(wasm).makeStringNew(op, ptr, start, end, try_); } return true; } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 829025a2c..6bbd82476 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2990,43 +2990,53 @@ Expression* SExpressionWasmBuilder::makeRefAs(Element& s, RefAsOp op) { return Builder(wasm).makeRefAs(op, value); } -Expression* SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op) { +Expression* +SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op, bool try_) { size_t i = 1; Expression* length = nullptr; - if (op == StringNewWTF8) { - std::string_view str = s[i++]->str().str; - if (str == "utf8") { - op = StringNewUTF8; - } else if (str == "wtf8") { - op = StringNewWTF8; - } else if (str == "replace") { - op = StringNewReplace; - } else { - throw ParseException("bad string.new op", s.line, s.col); + if (op == StringNewWTF8 || op == StringNewUTF8) { + if (!try_) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { + op = StringNewUTF8; + } else if (str == "wtf8") { + op = StringNewWTF8; + } else if (str == "replace") { + op = StringNewReplace; + } else { + throw ParseException("bad string.new op", s.line, s.col); + } } length = parseExpression(s[i + 1]); - return Builder(wasm).makeStringNew(op, parseExpression(s[i]), length); + return Builder(wasm).makeStringNew(op, parseExpression(s[i]), length, try_); } else if (op == StringNewWTF16) { length = parseExpression(s[i + 1]); - return Builder(wasm).makeStringNew(op, parseExpression(s[i]), length); - } else if (op == StringNewWTF8Array) { - std::string_view str = s[i++]->str().str; - if (str == "utf8") { - op = StringNewUTF8Array; - } else if (str == "wtf8") { - op = StringNewWTF8Array; - } else if (str == "replace") { - op = StringNewReplaceArray; - } else { - throw ParseException("bad string.new op", s.line, s.col); + return Builder(wasm).makeStringNew(op, parseExpression(s[i]), length, try_); + } else if (op == StringNewWTF8Array || op == StringNewUTF8Array) { + if (!try_) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { + op = StringNewUTF8Array; + } else if (str == "wtf8") { + op = StringNewWTF8Array; + } else if (str == "replace") { + op = StringNewReplaceArray; + } else { + throw ParseException("bad string.new op", s.line, s.col); + } } auto* start = parseExpression(s[i + 1]); auto* end = parseExpression(s[i + 2]); - return Builder(wasm).makeStringNew(op, parseExpression(s[i]), start, end); + return Builder(wasm).makeStringNew( + op, parseExpression(s[i]), start, end, try_); } else if (op == StringNewWTF16Array) { auto* start = parseExpression(s[i + 1]); auto* end = parseExpression(s[i + 2]); - return Builder(wasm).makeStringNew(op, parseExpression(s[i]), start, end); + return Builder(wasm).makeStringNew( + op, parseExpression(s[i]), start, end, try_); + } else if (op == StringNewFromCodePoint) { + return Builder(wasm).makeStringNew( + op, parseExpression(s[i]), nullptr, try_); } else { throw ParseException("bad string.new op", s.line, s.col); } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1f5722b59..694ed4269 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2264,7 +2264,11 @@ void BinaryInstWriter::visitStringNew(StringNew* curr) { o << int8_t(BinaryConsts::GCPrefix); switch (curr->op) { case StringNewUTF8: - o << U32LEB(BinaryConsts::StringNewWTF8); + if (!curr->try_) { + o << U32LEB(BinaryConsts::StringNewWTF8); + } else { + o << U32LEB(BinaryConsts::StringNewUTF8Try); + } o << int8_t(0); // Memory index. o << U32LEB(BinaryConsts::StringPolicy::UTF8); break; @@ -2283,8 +2287,12 @@ void BinaryInstWriter::visitStringNew(StringNew* curr) { o << int8_t(0); // Memory index. break; case StringNewUTF8Array: - o << U32LEB(BinaryConsts::StringNewWTF8Array) - << U32LEB(BinaryConsts::StringPolicy::UTF8); + if (!curr->try_) { + o << U32LEB(BinaryConsts::StringNewWTF8Array); + } else { + o << U32LEB(BinaryConsts::StringNewUTF8ArrayTry); + } + o << U32LEB(BinaryConsts::StringPolicy::UTF8); break; case StringNewWTF8Array: o << U32LEB(BinaryConsts::StringNewWTF8Array) @@ -2297,6 +2305,9 @@ void BinaryInstWriter::visitStringNew(StringNew* curr) { case StringNewWTF16Array: o << U32LEB(BinaryConsts::StringNewWTF16Array); break; + case StringNewFromCodePoint: + o << U32LEB(BinaryConsts::StringFromCodePoint); + break; default: WASM_UNREACHABLE("invalid string.new*"); } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index fa1351541..f58aaf0da 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1134,7 +1134,7 @@ void StringNew::finalize() { (length && length->type == Type::unreachable)) { type = Type::unreachable; } else { - type = Type(HeapType::string, NonNullable); + type = Type(HeapType::string, try_ ? Nullable : NonNullable); } } diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index dfc2190f3..1408ffe0d 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -2374,7 +2374,8 @@ template<typename Ctx> Result<typename Ctx::InstrT> makeArrayCopy(Ctx&, Index); template<typename Ctx> Result<typename Ctx::InstrT> makeRefAs(Ctx&, Index, RefAsOp op); template<typename Ctx> -Result<typename Ctx::InstrT> makeStringNew(Ctx&, Index, StringNewOp op); +Result<typename Ctx::InstrT> +makeStringNew(Ctx&, Index, StringNewOp op, bool try_); template<typename Ctx> Result<typename Ctx::InstrT> makeStringConst(Ctx&, Index); template<typename Ctx> @@ -3563,7 +3564,7 @@ Result<typename Ctx::InstrT> makeRefAs(Ctx& ctx, Index pos, RefAsOp op) { template<typename Ctx> Result<typename Ctx::InstrT> -makeStringNew(Ctx& ctx, Index pos, StringNewOp op) { +makeStringNew(Ctx& ctx, Index pos, StringNewOp op, bool try_) { return ctx.in.err("unimplemented instruction"); } |