diff options
author | Alon Zakai <azakai@google.com> | 2020-11-11 15:35:13 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-11 15:35:13 -0800 |
commit | d0d96a815fb2e6c397dce76fb1b74b803fd431f4 (patch) | |
tree | 93f9c624592a4dd38a53b6ba5ca047cadc7a2d76 /test | |
parent | 32171f1d6ff57fdb31f55d8aa554eac15cb5d8f5 (diff) | |
download | binaryen-d0d96a815fb2e6c397dce76fb1b74b803fd431f4.tar.gz binaryen-d0d96a815fb2e6c397dce76fb1b74b803fd431f4.tar.bz2 binaryen-d0d96a815fb2e6c397dce76fb1b74b803fd431f4.zip |
Avoid boilerplate in ExpressionAnalyzer comparing & hashing (#3332)
Expands on #3294:
* Scope names must be distinguished as either defs or uses.
* Error when a core #define is missing, which is less error-prone, as
suggested by @tlively
* Add DELEGATE_GET_FIELD which lets one define "get the field"
once and then all the loops can use it. This helps avoid boilerplate for
loops at least in some cases (when there is a single object on which
to get the field).
With those, it is possible to replace boilerplate in comparisons and
hashing logic. This also fixes a bug where BrOnExn::sent was not
scanned there.
Add some unit tests for hashing. We didn't have any, and hashing can be
subtly wrong without observable external effects (just more collisions).
Diffstat (limited to 'test')
-rw-r--r-- | test/example/hash.cpp | 142 | ||||
-rw-r--r-- | test/example/hash.txt | 1 |
2 files changed, 143 insertions, 0 deletions
diff --git a/test/example/hash.cpp b/test/example/hash.cpp new file mode 100644 index 000000000..7c3882cc9 --- /dev/null +++ b/test/example/hash.cpp @@ -0,0 +1,142 @@ +#include <cassert> +#include <iostream> + +#include <ir/utils.h> + +using namespace wasm; + +#define assertEqual(left, right) \ + assert(ExpressionAnalyzer::hash(&left) == ExpressionAnalyzer::hash(&right)); + +#define assertNotEqual(left, right) \ + assert(ExpressionAnalyzer::hash(&left) != ExpressionAnalyzer::hash(&right)); + +int main() { + { + Const x, y; + x.set(Literal(int32_t(10))); + y.set(Literal(int32_t(10))); + assertEqual(x, y); + } + { + // The value matters (with extremely high probability...) + Const x, y; + x.set(Literal(int32_t(10))); + y.set(Literal(int32_t(11))); + assertNotEqual(x, y); + } + { + // The type matters. + Const x, y; + x.set(Literal(int32_t(10))); + y.set(Literal(int64_t(10))); + assertNotEqual(x, y); + } + { + // Nested child. + Drop dx, dy; + Const x, y; + x.set(Literal(int32_t(10))); + y.set(Literal(int32_t(10))); + dx.value = &x; + dy.value = &y; + assertEqual(dx, dy); + } + { + // Nested child. + Drop dx, dy; + Const x, y; + x.set(Literal(int32_t(10))); + y.set(Literal(int32_t(11))); + dx.value = &x; + dy.value = &y; + assertNotEqual(dx, dy); + } + MixedArena arena; + { + // Blocks + Block x(arena); + Block y(arena); + assertEqual(x, y); + } + { + // Blocks with contents. + Block x(arena); + Block y(arena); + Nop n; + y.list.push_back(&n); + assertNotEqual(x, y); + } + { + // Blocks with names. + Block x(arena); + x.name = "foo"; + Block y(arena); + y.name = "foo"; + assertEqual(x, y); + } + { + // Different block names hash equally - we ignore internal name differences + // intentionally. + Block x(arena); + x.name = "foo"; + Block y(arena); + y.name = "bar"; + assertEqual(x, y); + } + { + // Different br names are checked relatively as well. + Break x; + x.name = "foo"; + Break y; + y.name = "bar"; + Block z(arena); + z.name = "foo"; + z.list.push_back(&x); + Block w(arena); + w.name = "bar"; + w.list.push_back(&y); + Block outer1(arena); + outer1.name = "outer1"; + outer1.list.push_back(&z); + Block outer2(arena); + outer2.name = "outer2"; + outer2.list.push_back(&w); + assertEqual(outer1, outer2); + } + { + // But referring to different relative names leads to a difference. + Break x; + x.name = "outer1"; // instead of x, go to the outer label this time + Break y; + y.name = "bar"; + Block z(arena); + z.name = "foo"; + z.list.push_back(&x); + Block w(arena); + w.name = "bar"; + w.list.push_back(&y); + Block outer1(arena); + outer1.name = "outer1"; + outer1.list.push_back(&z); + Block outer2(arena); + outer2.name = "outer2"; + outer2.list.push_back(&w); + assertNotEqual(outer1, outer2); + } + { + // Indexes. + LocalGet x, y; + x.index = 10; + y.index = 10; + assertEqual(x, y); + } + { + // Indexes. + LocalGet x, y; + x.index = 10; + y.index = 11; + assertNotEqual(x, y); + } + std::cout << "success.\n"; +} diff --git a/test/example/hash.txt b/test/example/hash.txt new file mode 100644 index 000000000..b32bb74d2 --- /dev/null +++ b/test/example/hash.txt @@ -0,0 +1 @@ +success. |