summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gen-s-parser.inc50
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/cost.h1
-rw-r--r--src/ir/effects.h4
-rw-r--r--src/ir/possible-contents.cpp4
-rw-r--r--src/passes/Print.cpp15
-rw-r--r--src/wasm-binary.h4
-rw-r--r--src/wasm-builder.h7
-rw-r--r--src/wasm-delegations-fields.def7
-rw-r--r--src/wasm-delegations.def1
-rw-r--r--src/wasm-interpreter.h3
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm.h18
-rw-r--r--src/wasm/wasm-binary.cpp19
-rw-r--r--src/wasm/wasm-s-parser.cpp4
-rw-r--r--src/wasm/wasm-stack.cpp17
-rw-r--r--src/wasm/wasm.cpp20
-rw-r--r--src/wasm/wat-parser.cpp8
-rw-r--r--src/wasm2js.h4
19 files changed, 188 insertions, 0 deletions
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 809fa7837..8ab31afb9 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -3129,6 +3129,25 @@ switch (op[0]) {
switch (op[3]) {
case 'i': {
switch (op[7]) {
+ case 'a': {
+ switch (op[10]) {
+ case 'i':
+ if (strcmp(op, "string.as_iter") == 0) { return makeStringAs(s, StringAsIter); }
+ goto parse_error;
+ case 'w': {
+ switch (op[13]) {
+ case '1':
+ if (strcmp(op, "string.as_wtf16") == 0) { return makeStringAs(s, StringAsWTF16); }
+ goto parse_error;
+ case '8':
+ if (strcmp(op, "string.as_wtf8") == 0) { return makeStringAs(s, StringAsWTF8); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
case 'c': {
switch (op[10]) {
case 'c':
@@ -8731,6 +8750,37 @@ switch (op[0]) {
switch (op[3]) {
case 'i': {
switch (op[7]) {
+ case 'a': {
+ switch (op[10]) {
+ case 'i':
+ if (op == "string.as_iter"sv) {
+ auto ret = makeStringAs(ctx, in, StringAsIter);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'w': {
+ switch (op[13]) {
+ case '1':
+ if (op == "string.as_wtf16"sv) {
+ auto ret = makeStringAs(ctx, in, StringAsWTF16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "string.as_wtf8"sv) {
+ auto ret = makeStringAs(ctx, in, StringAsWTF8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
case 'c': {
switch (op[10]) {
case 'c':
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index f509ab261..bdb04f2b4 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -178,6 +178,7 @@ 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::visitFunction(Function* curr) {
// we may have changed the body from unreachable to none, which might be bad
diff --git a/src/ir/cost.h b/src/ir/cost.h
index ea07e6109..6a508db2d 100644
--- a/src/ir/cost.h
+++ b/src/ir/cost.h
@@ -688,6 +688,7 @@ 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); }
private:
CostType nullCheckCost(Expression* ref) {
diff --git a/src/ir/effects.h b/src/ir/effects.h
index 0dd0902b1..393285924 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -747,6 +747,10 @@ private:
parent.implicitTrap = true;
}
void visitStringEq(StringEq* curr) {}
+ void visitStringAs(StringAs* curr) {
+ // traps when ref is null.
+ parent.implicitTrap = true;
+ }
};
public:
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp
index 7db493f00..f2839347d 100644
--- a/src/ir/possible-contents.cpp
+++ b/src/ir/possible-contents.cpp
@@ -697,6 +697,10 @@ struct InfoCollector
// TODO: optimize when possible
addRoot(curr);
}
+ void visitStringAs(StringAs* 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/passes/Print.cpp b/src/passes/Print.cpp
index ec9926a30..781c72376 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2279,6 +2279,21 @@ struct PrintExpressionContents
printMedium(o, "string.concat");
}
void visitStringEq(StringEq* curr) { printMedium(o, "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*");
+ }
+ }
};
// Prints an expression in s-expr format, including both the
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 97f6bc24e..8a03cb8af 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1147,6 +1147,9 @@ enum ASTNodes {
StringConcat = 0x88,
StringEq = 0x89,
StringIsUSV = 0x8a,
+ StringAsWTF8 = 0x90,
+ StringAsWTF16 = 0x98,
+ StringAsIter = 0xa0,
};
enum MemoryAccess {
@@ -1733,6 +1736,7 @@ public:
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);
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 507aa510b..9fe039af1 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -1034,6 +1034,13 @@ 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;
+ }
// Additional helpers
diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def
index 0ac154726..83483fbf4 100644
--- a/src/wasm-delegations-fields.def
+++ b/src/wasm-delegations-fields.def
@@ -756,6 +756,13 @@ switch (DELEGATE_ID) {
DELEGATE_END(StringEq);
break;
}
+ case Expression::Id::StringAsId: {
+ DELEGATE_START(StringAs);
+ DELEGATE_FIELD_INT(StringAs, op);
+ DELEGATE_FIELD_CHILD(StringAs, ref);
+ DELEGATE_END(StringAs);
+ break;
+ }
}
#undef DELEGATE_ID
diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def
index c5cfa6932..ed4f056c5 100644
--- a/src/wasm-delegations.def
+++ b/src/wasm-delegations.def
@@ -91,5 +91,6 @@ DELEGATE(StringMeasure);
DELEGATE(StringEncode);
DELEGATE(StringConcat);
DELEGATE(StringEq);
+DELEGATE(StringAs);
#undef DELEGATE
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 02c95957d..6921220c2 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1973,6 +1973,9 @@ public:
Flow visitStringEq(StringEq* curr) {
WASM_UNREACHABLE("unimplemented string.eq");
}
+ Flow visitStringAs(StringAs* curr) {
+ WASM_UNREACHABLE("unimplemented string.as");
+ }
virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); }
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 777d33e30..c85b8875c 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -309,6 +309,7 @@ private:
Expression* makeStringEncode(Element& s, StringEncodeOp op);
Expression* makeStringConcat(Element& s);
Expression* makeStringEq(Element& s);
+ Expression* makeStringAs(Element& s, StringAsOp op);
// Helper functions
Type parseOptionalResultType(Element& s, Index& i);
diff --git a/src/wasm.h b/src/wasm.h
index 42de60a98..41fffb2e9 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -603,6 +603,12 @@ enum StringEncodeOp {
StringEncodeWTF16,
};
+enum StringAsOp {
+ StringAsWTF8,
+ StringAsWTF16,
+ StringAsIter,
+};
+
//
// Expressions
//
@@ -704,6 +710,7 @@ public:
StringEncodeId,
StringConcatId,
StringEqId,
+ StringAsId,
NumExpressionIds
};
Id _id;
@@ -1737,6 +1744,17 @@ public:
void finalize();
};
+class StringAs : public SpecificExpression<Expression::StringAsId> {
+public:
+ StringAs(MixedArena& allocator) {}
+
+ StringAsOp op;
+
+ Expression* ref;
+
+ void finalize();
+};
+
// Globals
struct Named {
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 0ae17f47c..ee1f4929b 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3936,6 +3936,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitStringEq(curr, opcode)) {
break;
}
+ if (maybeVisitStringAs(curr, opcode)) {
+ break;
+ }
if (opcode == BinaryConsts::RefIsFunc ||
opcode == BinaryConsts::RefIsData ||
opcode == BinaryConsts::RefIsI31) {
@@ -7249,6 +7252,22 @@ bool WasmBinaryBuilder::maybeVisitStringEq(Expression*& out, uint32_t code) {
return true;
}
+bool WasmBinaryBuilder::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;
+}
+
void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) {
BYN_TRACE("zz node: RefAs\n");
switch (code) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index ecb8c2432..b3779e5e5 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -3000,6 +3000,10 @@ Expression* SExpressionWasmBuilder::makeStringEq(Element& s) {
parseExpression(s[2]));
}
+Expression* SExpressionWasmBuilder::makeStringAs(Element& s, StringAsOp op) {
+ return Builder(wasm).makeStringAs(op, parseExpression(s[1]));
+}
+
// converts an s-expression string representing binary data into an output
// sequence of raw bytes this appends to data, which may already contain
// content.
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index e1b093b26..9c1933067 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2311,6 +2311,23 @@ void BinaryInstWriter::visitStringEq(StringEq* curr) {
o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringEq);
}
+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::emitScopeEnd(Expression* curr) {
assert(!breakStack.empty());
breakStack.pop_back();
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 5e316d4f4..6568c907e 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1216,6 +1216,26 @@ 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");
+ }
+ }
+}
+
size_t Function::getNumParams() { return getParams().size(); }
size_t Function::getNumVars() { return vars.size(); }
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index aa059b1db..47fb8ef03 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -673,6 +673,8 @@ template<typename Ctx>
Result<typename Ctx::InstrT> makeStringConcat(Ctx&, ParseInput&);
template<typename Ctx>
Result<typename Ctx::InstrT> makeStringEq(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringAs(Ctx&, ParseInput&, StringAsOp op);
// Modules
template<typename Ctx>
@@ -1661,6 +1663,12 @@ Result<typename Ctx::InstrT> makeStringEq(Ctx& ctx, ParseInput& in) {
return in.err("unimplemented instruction");
}
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringAs(Ctx& ctx, ParseInput& in, StringAsOp op) {
+ return in.err("unimplemented instruction");
+}
+
// =======
// Modules
// =======
diff --git a/src/wasm2js.h b/src/wasm2js.h
index f8179379d..ba6832540 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -2327,6 +2327,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
unimplemented(curr);
WASM_UNREACHABLE("unimp");
}
+ Ref visitStringAs(StringAs* curr) {
+ unimplemented(curr);
+ WASM_UNREACHABLE("unimp");
+ }
Ref visitRefAs(RefAs* curr) {
unimplemented(curr);
WASM_UNREACHABLE("unimp");