Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,14 @@ class EffectAnalyzer {
// traps when an input is null.
parent.implicitTrap = true;
}
void visitStringEq(StringEq* curr) {}
void visitStringEq(StringEq* curr) {
if (curr->op == StringEqCompare) {
// traps when either input is null.
if (curr->left->type.isNullable() || curr->right->type.isNullable()) {
parent.implicitTrap = true;
}
}
}
void visitStringAs(StringAs* curr) {
// traps when ref is null.
parent.implicitTrap = true;
Expand Down
3 changes: 2 additions & 1 deletion src/tools/fuzzing.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ class TranslateToFuzzReader {
Expression* makeStringNewArray();
Expression* makeStringNewCodePoint();
Expression* makeStringConcat();
Expression* makeStringEq(Type type);
Expression* makeStringEncode(Type type);

// Similar to makeBasic/CompoundRef, but indicates that this value will be
Expand Down Expand Up @@ -398,7 +399,7 @@ class TranslateToFuzzReader {
Nullability getSuperType(Nullability nullability);
HeapType getSuperType(HeapType type);
Type getSuperType(Type type);
Type getArrayTypeForString();
HeapType getArrayTypeForString();

// Utilities
Name getTargetName(Expression* target);
Expand Down
34 changes: 24 additions & 10 deletions src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,8 @@ Expression* TranslateToFuzzReader::_makeConcrete(Type type) {
&Self::makeI31Get);
options.add(FeatureSet::ReferenceTypes | FeatureSet::GC |
FeatureSet::Strings,
&Self::makeStringEncode);
&Self::makeStringEncode,
&Self::makeStringEq);
}
if (type.isTuple()) {
options.add(FeatureSet::Multivalue, &Self::makeTupleMake);
Expand Down Expand Up @@ -2755,7 +2756,7 @@ Expression* TranslateToFuzzReader::makeCompoundRef(Type type) {
}

Expression* TranslateToFuzzReader::makeStringNewArray() {
auto* array = make(getArrayTypeForString());
auto* array = makeTrappingRefUse(getArrayTypeForString());
auto* start = make(Type::i32);
auto* end = make(Type::i32);
return builder.makeStringNew(StringNewWTF16Array, array, start, end, false);
Expand Down Expand Up @@ -2812,11 +2813,26 @@ Expression* TranslateToFuzzReader::makeStringConst() {
}

Expression* TranslateToFuzzReader::makeStringConcat() {
auto* left = make(Type(HeapType::string, getNullability()));
auto* right = make(Type(HeapType::string, getNullability()));
auto* left = makeTrappingRefUse(HeapType::string);
auto* right = makeTrappingRefUse(HeapType::string);
return builder.makeStringConcat(left, right);
}

Expression* TranslateToFuzzReader::makeStringEq(Type type) {
assert(type == Type::i32);

if (oneIn(2)) {
auto* left = make(Type(HeapType::string, getNullability()));
auto* right = make(Type(HeapType::string, getNullability()));
return builder.makeStringEq(StringEqEqual, left, right);
}

// string.compare may trap if the either input is null.
auto* left = makeTrappingRefUse(HeapType::string);
auto* right = makeTrappingRefUse(HeapType::string);
return builder.makeStringEq(StringEqCompare, left, right);
}

Expression* TranslateToFuzzReader::makeTrappingRefUse(HeapType type) {
auto percent = upTo(100);
// Only give a low probability to emit a nullable reference.
Expand Down Expand Up @@ -3920,8 +3936,8 @@ Expression* TranslateToFuzzReader::makeArrayBulkMemoryOp(Type type) {
Expression* TranslateToFuzzReader::makeStringEncode(Type type) {
assert(type == Type::i32);

auto* ref = make(Type(HeapType::string, getNullability()));
auto* array = make(getArrayTypeForString());
auto* ref = makeTrappingRefUse(HeapType::string);
auto* array = makeTrappingRefUse(getArrayTypeForString());
auto* start = make(Type::i32);

// Only rarely emit without a bounds check, which might trap. See related
Expand Down Expand Up @@ -4307,12 +4323,10 @@ Type TranslateToFuzzReader::getSuperType(Type type) {
return superType;
}

Type TranslateToFuzzReader::getArrayTypeForString() {
HeapType TranslateToFuzzReader::getArrayTypeForString() {
// Emit an array that can be used with JS-style strings, containing 16-bit
// elements. For now, this must be a mutable type as that is all V8 accepts.
auto arrayHeapType = HeapType(Array(Field(Field::PackedType::i16, Mutable)));
auto nullability = getNullability();
return Type(arrayHeapType, nullability);
return HeapType(Array(Field(Field::PackedType::i16, Mutable)));
}

Name TranslateToFuzzReader::getTargetName(Expression* target) {
Expand Down
84 changes: 84 additions & 0 deletions test/lit/passes/vacuum-strings.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s

(module
;; CHECK: (func $compare (type $0)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (string.compare
;; CHECK-NEXT: (string.const "hello")
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (string.compare
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (string.const "world")
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (string.compare
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $compare
;; We cannot vacuum away compares that might trap.
(drop
(string.compare
(string.const "hello")
(string.const "world")
)
)
(drop
(string.compare
(string.const "hello")
(ref.null none)
)
)
(drop
(string.compare
(ref.null none)
(string.const "world")
)
)
(drop
(string.compare
(ref.null none)
(ref.null none)
)
)
)

;; CHECK: (func $eq (type $0)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $eq
;; Equals, however, never traps so all these can be removed.
(drop
(string.eq
(string.const "hello")
(string.const "world")
)
)
(drop
(string.eq
(string.const "hello")
(ref.null none)
)
)
(drop
(string.eq
(ref.null none)
(string.const "world")
)
)
(drop
(string.eq
(ref.null none)
(ref.null none)
)
)
)
)

68 changes: 35 additions & 33 deletions test/passes/translate-to-fuzz_all-features_metrics_noprint.txt
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
total
[exports] : 7
[funcs] : 12
[exports] : 4
[funcs] : 6
[globals] : 14
[imports] : 5
[memories] : 1
[memory-data] : 20
[table-data] : 6
[table-data] : 1
[tables] : 1
[tags] : 1
[total] : 493
[vars] : 31
ArrayNew : 1
ArrayNewFixed : 1
Binary : 61
Block : 59
Break : 2
Call : 29
CallRef : 1
Const : 101
Drop : 10
[total] : 533
[vars] : 24
ArrayNew : 11
ArrayNewFixed : 2
AtomicFence : 1
Binary : 79
Block : 57
Break : 6
Call : 8
Const : 137
Drop : 1
GlobalGet : 28
GlobalSet : 26
I31Get : 1
If : 17
Load : 16
LocalGet : 36
LocalSet : 29
Loop : 2
Nop : 5
GlobalSet : 28
If : 15
Load : 17
LocalGet : 40
LocalSet : 23
Loop : 9
Nop : 4
RefAs : 1
RefCast : 2
RefFunc : 8
RefI31 : 4
RefNull : 4
Return : 3
SIMDExtract : 1
StringConst : 1
StructNew : 5
TupleExtract : 1
TupleMake : 7
Unary : 16
RefFunc : 2
RefI31 : 2
RefIsNull : 1
RefNull : 5
Return : 2
SIMDExtract : 2
Select : 1
Store : 2
StringConst : 4
StringEq : 1
StructGet : 1
StructNew : 9
TupleMake : 4
Unary : 15
Unreachable : 15