Skip to content

Commit 5ef1aba

Browse files
authored
Strings: Add some interpreter support (#6304)
This adds just enough support to be able to --fuzz-exec a small but realistic fuzz testcase from Java. To that end, just implement the minimal ops we need, which are all related to JS-style strings.
1 parent df3784e commit 5ef1aba

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

src/wasm-interpreter.h

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,21 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
19021902
Flow visitStringConst(StringConst* curr) {
19031903
return Literal(curr->string.toString());
19041904
}
1905-
Flow visitStringMeasure(StringMeasure* curr) { WASM_UNREACHABLE("unimp"); }
1905+
Flow visitStringMeasure(StringMeasure* curr) {
1906+
// For now we only support JS-style strings.
1907+
assert(curr->op == StringMeasureWTF16View);
1908+
1909+
Flow flow = visit(curr->ref);
1910+
if (flow.breaking()) {
1911+
return flow;
1912+
}
1913+
auto value = flow.getSingleValue();
1914+
auto data = value.getGCData();
1915+
if (!data) {
1916+
trap("null ref");
1917+
}
1918+
return Literal(int32_t(data->values.size()));
1919+
}
19061920
Flow visitStringEncode(StringEncode* curr) { WASM_UNREACHABLE("unimp"); }
19071921
Flow visitStringConcat(StringConcat* curr) { WASM_UNREACHABLE("unimp"); }
19081922
Flow visitStringEq(StringEq* curr) {
@@ -1971,11 +1985,49 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
19711985
}
19721986
return Literal(result);
19731987
}
1974-
Flow visitStringAs(StringAs* curr) { WASM_UNREACHABLE("unimp"); }
1988+
Flow visitStringAs(StringAs* curr) {
1989+
// For now we only support JS-style strings.
1990+
assert(curr->op == StringAsWTF16);
1991+
1992+
Flow flow = visit(curr->ref);
1993+
if (flow.breaking()) {
1994+
return flow;
1995+
}
1996+
auto value = flow.getSingleValue();
1997+
auto data = value.getGCData();
1998+
if (!data) {
1999+
trap("null ref");
2000+
}
2001+
2002+
// A JS-style string can be viewed simply as the underlying data. All we
2003+
// need to do is fix up the type.
2004+
return Literal(data, curr->type.getHeapType());
2005+
}
19752006
Flow visitStringWTF8Advance(StringWTF8Advance* curr) {
19762007
WASM_UNREACHABLE("unimp");
19772008
}
1978-
Flow visitStringWTF16Get(StringWTF16Get* curr) { WASM_UNREACHABLE("unimp"); }
2009+
Flow visitStringWTF16Get(StringWTF16Get* curr) {
2010+
NOTE_ENTER("StringEq");
2011+
Flow ref = visit(curr->ref);
2012+
if (ref.breaking()) {
2013+
return ref;
2014+
}
2015+
Flow pos = visit(curr->pos);
2016+
if (pos.breaking()) {
2017+
return pos;
2018+
}
2019+
auto refValue = ref.getSingleValue();
2020+
auto data = refValue.getGCData();
2021+
if (!data) {
2022+
trap("null ref");
2023+
}
2024+
auto& values = data->values;
2025+
Index i = pos.getSingleValue().geti32();
2026+
if (i >= values.size()) {
2027+
trap("string oob");
2028+
}
2029+
return Literal(values[i].geti32());
2030+
}
19792031
Flow visitStringIterNext(StringIterNext* curr) { WASM_UNREACHABLE("unimp"); }
19802032
Flow visitStringIterMove(StringIterMove* curr) { WASM_UNREACHABLE("unimp"); }
19812033
Flow visitStringSliceWTF(StringSliceWTF* curr) { WASM_UNREACHABLE("unimp"); }

src/wasm/wasm-type.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,8 @@ bool HeapType::isFunction() const {
11631163

11641164
bool HeapType::isData() const {
11651165
if (isBasic()) {
1166-
return id == struct_ || id == array || id == string;
1166+
return id == struct_ || id == array || id == string ||
1167+
id == stringview_wtf16;
11671168
} else {
11681169
return getHeapTypeInfo(*this)->isData();
11691170
}

test/lit/exec/strings.wast

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,29 @@
162162
(string.const "hf")
163163
)
164164
)
165+
166+
;; CHECK: [fuzz-exec] calling get_codeunit
167+
;; CHECK-NEXT: [fuzz-exec] note result: get_codeunit => 99
168+
(func $get_codeunit (export "get_codeunit") (result i32)
169+
;; Reads 'c' which is code 99.
170+
(stringview_wtf16.get_codeunit
171+
(string.as_wtf16
172+
(string.const "abcdefg")
173+
)
174+
(i32.const 2)
175+
)
176+
)
177+
178+
;; CHECK: [fuzz-exec] calling get_length
179+
;; CHECK-NEXT: [fuzz-exec] note result: get_length => 7
180+
(func $get_length (export "get_length") (result i32)
181+
;; This should return 7.
182+
(stringview_wtf16.length
183+
(string.as_wtf16
184+
(string.const "1234567")
185+
)
186+
)
187+
)
165188
)
166189
;; CHECK: [fuzz-exec] calling new_wtf16_array
167190
;; CHECK-NEXT: [fuzz-exec] note result: new_wtf16_array => string("ello")
@@ -213,6 +236,12 @@
213236

214237
;; CHECK: [fuzz-exec] calling compare.10
215238
;; CHECK-NEXT: [fuzz-exec] note result: compare.10 => -1
239+
240+
;; CHECK: [fuzz-exec] calling get_codeunit
241+
;; CHECK-NEXT: [fuzz-exec] note result: get_codeunit => 99
242+
243+
;; CHECK: [fuzz-exec] calling get_length
244+
;; CHECK-NEXT: [fuzz-exec] note result: get_length => 7
216245
;; CHECK-NEXT: [fuzz-exec] comparing compare.1
217246
;; CHECK-NEXT: [fuzz-exec] comparing compare.10
218247
;; CHECK-NEXT: [fuzz-exec] comparing compare.2
@@ -229,4 +258,6 @@
229258
;; CHECK-NEXT: [fuzz-exec] comparing eq.3
230259
;; CHECK-NEXT: [fuzz-exec] comparing eq.4
231260
;; CHECK-NEXT: [fuzz-exec] comparing eq.5
261+
;; CHECK-NEXT: [fuzz-exec] comparing get_codeunit
262+
;; CHECK-NEXT: [fuzz-exec] comparing get_length
232263
;; CHECK-NEXT: [fuzz-exec] comparing new_wtf16_array

0 commit comments

Comments
 (0)