| #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)); | |
| #define assertShallowEqual(left, right) \ | |
| assert(ExpressionAnalyzer::shallowHash(&left) == \ | |
| ExpressionAnalyzer::shallowHash(&right)); | |
| #define assertShallowNotEqual(left, right) \ | |
| assert(ExpressionAnalyzer::shallowHash(&left) != \ | |
| ExpressionAnalyzer::shallowHash(&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 identical 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 identical child, checked shallowly. | |
| Drop dx, dy; | |
| Const x, y; | |
| x.set(Literal(int32_t(10))); | |
| y.set(Literal(int32_t(10))); | |
| dx.value = &x; | |
| dy.value = &y; | |
| assertShallowEqual(dx, dy); | |
| } | |
| { | |
| // Nested different 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); | |
| } | |
| { | |
| // Nested different child, checked shallowly (so we ignore the difference, | |
| // and return equal). | |
| Drop dx, dy; | |
| Const x, y; | |
| x.set(Literal(int32_t(10))); | |
| y.set(Literal(int32_t(11))); | |
| dx.value = &x; | |
| dy.value = &y; | |
| assertShallowEqual(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); | |
| } | |
| { | |
| // It is ok to hash something that refers to an unknown name, like a break | |
| // without the outside context that it branches to. And different names | |
| // should have different hashes. | |
| Break x; | |
| x.name = "foo"; | |
| Break y; | |
| y.name = "bar"; | |
| assertNotEqual(x, y); | |
| } | |
| std::cout << "success.\n"; | |
| } |