diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/example/module-splitting.cpp | 289 | ||||
-rw-r--r-- | test/example/module-splitting.txt | 641 |
2 files changed, 930 insertions, 0 deletions
diff --git a/test/example/module-splitting.cpp b/test/example/module-splitting.cpp new file mode 100644 index 000000000..50fb0f4c5 --- /dev/null +++ b/test/example/module-splitting.cpp @@ -0,0 +1,289 @@ +#include <cassert> +#include <iostream> + +#include "ir/module-splitting.h" +#include "ir/stack-utils.h" +#include "wasm-features.h" +#include "wasm-printing.h" +#include "wasm-s-parser.h" +#include "wasm-validator.h" +#include "wasm.h" + +using namespace wasm; + +std::unique_ptr<Module> parse(char* module) { + auto wasm = std::make_unique<Module>(); + wasm->features = FeatureSet::All; + try { + SExpressionParser parser(module); + Element& root = *parser.root; + SExpressionWasmBuilder builder(*wasm, *root[0], IRProfile::Normal); + } catch (ParseException& p) { + p.dump(std::cerr); + Fatal() << "error in parsing wasm text"; + } + return wasm; +} + +void do_test(const std::set<Name>& keptFuncs, std::string&& module) { + WasmValidator validator; + bool valid; + + auto primary = parse(&module.front()); + valid = validator.validate(*primary); + assert(valid && "before invalid!"); + + std::cout << "Before:\n"; + WasmPrinter::printModule(primary.get()); + + std::cout << "Keeping: "; + if (keptFuncs.size()) { + auto it = keptFuncs.begin(); + std::cout << *it++; + while (it != keptFuncs.end()) { + std::cout << ", " << *it++; + } + } else { + std::cout << "<none>"; + } + std::cout << "\n"; + + ModuleSplitting::Config config; + config.primaryFuncs = keptFuncs; + config.newExportPrefix = "%"; + auto secondary = splitFunctions(*primary, config); + + std::cout << "After:\n"; + WasmPrinter::printModule(primary.get()); + std::cout << "Secondary:\n"; + WasmPrinter::printModule(secondary.get()); + std::cout << "\n\n"; + + valid = validator.validate(*primary); + assert(valid && "after invalid!"); + valid = validator.validate(*secondary); + assert(valid && "secondary invalid!"); +} + +int main() { + // Trivial module + do_test({}, "(module)"); + + // Global stuff + do_test({}, R"( + (module + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) + ))"); + + // Imported global stuff + do_test({}, R"( + (module + (import "env" "mem" (memory $mem (shared 3 42))) + (import "env" "tab" (table $tab 3 42 funcref)) + (import "env" "glob" (global $glob (mut i32))) + (import "env" "e" (event $e (attr 0) (param i32))) + ))"); + + // Exported global stuff + do_test({}, R"( + (module + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (event $e)) + ))"); + + // Non-deferred function + do_test({"foo"}, R"( + (module + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Non-deferred exported function + do_test({"foo"}, R"( + (module + (export "foo" (func $foo)) + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Non-deferred function in table + do_test({"foo"}, R"( + (module + (table $table 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Non-deferred imported function + do_test({"foo"}, R"( + (module + (import "env" "foo" (func $foo (param i32) (result i32))) + ))"); + + // Non-deferred exported imported function in table at a weird offset + do_test({"foo"}, R"( + (module + (import "env" "foo" (func $foo (param i32) (result i32))) + (table $table 1000 funcref) + (elem (i32.const 42) $foo) + (export "foo" (func $foo)) + ))"); + + // Deferred function + do_test({}, R"( + (module + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Deferred exported function + do_test({}, R"( + (module + (export "foo" (func $foo)) + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Deferred function in table + do_test({}, R"( + (module + (table $table 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Deferred exported function in table at a weird offset + do_test({}, R"( + (module + (table $table 1000 funcref) + (elem (i32.const 42) $foo) + (export "foo" (func $foo)) + (func $foo (param i32) (result i32) + (local.get 0) + ) + ))"); + + // Non-deferred function calling non-deferred function + do_test({"foo", "bar"}, R"( + (module + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) + ))"); + + // Deferred function calling non-deferred function + do_test({"bar"}, R"( + (module + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) + ))"); + + // Non-deferred function calling deferred function + do_test({"foo"}, R"( + (module + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) + ))"); + + // Deferred function calling deferred function + do_test({}, R"( + (module + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) + ))"); + + // Deferred function calling non-deferred function with clashing export name + do_test({"foo"}, R"( + (module + (export "%foo" (func $bar)) + (func $foo + (nop) + ) + (func $bar + (call $foo) + ) + ))"); + + // Mixed table 1 + do_test({"bar", "quux"}, R"( + (module + (table $table 4 funcref) + (elem (i32.const 0) $foo $bar $baz $quux) + (func $foo + (nop) + ) + (func $bar + (nop) + ) + (func $baz + (nop) + ) + (func $quux + (nop) + ) + ))"); + + // Mixed table 2 + do_test({"baz"}, R"( + (module + (table $table 4 funcref) + (elem (i32.const 0) $foo $bar $baz $quux) + (func $foo + (nop) + ) + (func $bar + (nop) + ) + (func $baz + (nop) + ) + (func $quux + (nop) + ) + ))"); + + // Mutual recursion with table growth + do_test({"foo"}, R"( + (module + (table $table 1 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param i32) (result i32) + (call $bar (i32.const 0)) + ) + (func $bar (param i32) (result i32) + (call $foo (i32.const 1)) + ) + ))"); +} diff --git a/test/example/module-splitting.txt b/test/example/module-splitting.txt new file mode 100644 index 000000000..4d79688f7 --- /dev/null +++ b/test/example/module-splitting.txt @@ -0,0 +1,641 @@ +Before: +(module +) +Keeping: <none> +After: +(module +) +Secondary: +(module +) + + +Before: +(module + (type $i32_=>_none (func (param i32))) + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) +) +Keeping: <none> +After: +(module + (type $i32_=>_none (func (param i32))) + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) + (export "%memory" (memory $mem)) + (export "%table" (table $tab)) + (export "%global" (global $glob)) + (export "%event" (event $e)) +) +Secondary: +(module + (type $i32_=>_none (func (param i32))) + (import "primary" "%memory" (memory $mem (shared 3 42))) + (import "primary" "%table" (table $tab 3 42 funcref)) + (import "primary" "%global" (global $glob (mut i32))) + (import "primary" "%event" (event $e (attr 0) (param i32))) +) + + +Before: +(module + (type $i32_=>_none (func (param i32))) + (import "env" "mem" (memory $mem (shared 3 42))) + (import "env" "tab" (table $tab 3 42 funcref)) + (import "env" "glob" (global $glob (mut i32))) + (import "env" "e" (event $e (attr 0) (param i32))) +) +Keeping: <none> +After: +(module + (type $i32_=>_none (func (param i32))) + (import "env" "mem" (memory $mem (shared 3 42))) + (import "env" "tab" (table $tab 3 42 funcref)) + (import "env" "glob" (global $glob (mut i32))) + (import "env" "e" (event $e (attr 0) (param i32))) + (export "%memory" (memory $mem)) + (export "%table" (table $tab)) + (export "%global" (global $glob)) + (export "%event" (event $e)) +) +Secondary: +(module + (type $i32_=>_none (func (param i32))) + (import "primary" "%memory" (memory $mem (shared 3 42))) + (import "primary" "%table" (table $tab 3 42 funcref)) + (import "primary" "%global" (global $glob (mut i32))) + (import "primary" "%event" (event $e (attr 0) (param i32))) +) + + +Before: +(module + (type $i32_=>_none (func (param i32))) + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (event $e)) +) +Keeping: <none> +After: +(module + (type $i32_=>_none (func (param i32))) + (memory $mem (shared 3 42)) + (table $tab 3 42 funcref) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) + (export "mem" (memory $mem)) + (export "tab" (table $tab)) + (export "glob" (global $glob)) + (export "e" (event $e)) +) +Secondary: +(module + (type $i32_=>_none (func (param i32))) + (import "primary" "mem" (memory $mem (shared 3 42))) + (import "primary" "tab" (table $tab 3 42 funcref)) + (import "primary" "glob" (global $glob (mut i32))) + (import "primary" "e" (event $e (attr 0) (param i32))) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Secondary: +(module +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (export "foo" (func $foo)) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (export "foo" (func $foo)) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Secondary: +(module +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $table 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $table 1 funcref) + (elem (i32.const 0) $foo) + (export "%table" (table $table)) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Secondary: +(module + (import "primary" "%table" (table $table 1 funcref)) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo (param i32) (result i32))) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo (param i32) (result i32))) +) +Secondary: +(module +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo (param i32) (result i32))) + (table $table 1000 funcref) + (elem (i32.const 42) $foo) + (export "foo" (func $foo)) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "foo" (func $foo (param i32) (result i32))) + (table $table 1000 funcref) + (elem (i32.const 42) $foo) + (export "foo" (func $foo)) + (export "%table" (table $table)) +) +Secondary: +(module + (import "primary" "%table" (table $table 1000 funcref)) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: <none> +After: +(module +) +Secondary: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (export "foo" (func $foo)) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: <none> +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) + (table $0 1 funcref) + (elem (i32.const 0) $placeholder_0) + (export "foo" (func $foo)) + (export "%table" (table $0)) + (func $foo (param $0 i32) (result i32) + (call_indirect (type $i32_=>_i32) + (local.get $0) + (i32.const 0) + ) + ) +) +Secondary: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "primary" "%table" (table $0 1 funcref)) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $table 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: <none> +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) + (table $table 1 funcref) + (elem (i32.const 0) $placeholder_0) + (export "%table" (table $table)) +) +Secondary: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "primary" "%table" (table $table 1 funcref)) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $table 1000 funcref) + (elem (i32.const 42) $foo) + (export "foo" (func $foo)) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) +Keeping: <none> +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "placeholder" "42" (func $placeholder_42 (param i32) (result i32))) + (table $table 1000 funcref) + (elem (i32.const 42) $placeholder_42) + (export "foo" (func $foo)) + (export "%table" (table $table)) + (func $foo (param $0 i32) (result i32) + (call_indirect (type $i32_=>_i32) + (local.get $0) + (i32.const 42) + ) + ) +) +Secondary: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "primary" "%table" (table $table 1000 funcref)) + (elem (i32.const 42) $foo) + (func $foo (param $0 i32) (result i32) + (local.get $0) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) +) +Keeping: bar, foo +After: +(module + (type $none_=>_none (func)) + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) +) +Secondary: +(module +) + + +Before: +(module + (type $none_=>_none (func)) + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) +) +Keeping: bar +After: +(module + (type $none_=>_none (func)) + (export "%bar" (func $bar)) + (func $bar + (nop) + ) +) +Secondary: +(module + (type $none_=>_none (func)) + (import "primary" "%bar" (func $bar)) + (func $foo + (call $bar) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) +) +Keeping: foo +After: +(module + (type $none_=>_none (func)) + (import "placeholder" "0" (func $placeholder_0)) + (table $0 1 funcref) + (elem (i32.const 0) $placeholder_0) + (export "%table" (table $0)) + (func $foo + (call_indirect (type $none_=>_none) + (i32.const 0) + ) + ) +) +Secondary: +(module + (type $none_=>_none (func)) + (import "primary" "%table" (table $0 1 funcref)) + (elem (i32.const 0) $bar) + (func $bar + (nop) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (func $foo + (call $bar) + ) + (func $bar + (nop) + ) +) +Keeping: <none> +After: +(module +) +Secondary: +(module + (type $none_=>_none (func)) + (func $bar + (nop) + ) + (func $foo + (call $bar) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (export "%foo" (func $bar)) + (func $foo + (nop) + ) + (func $bar + (call $foo) + ) +) +Keeping: foo +After: +(module + (type $none_=>_none (func)) + (import "placeholder" "0" (func $placeholder_0)) + (table $0 1 funcref) + (elem (i32.const 0) $placeholder_0) + (export "%foo" (func $bar)) + (export "%foo_0" (func $foo)) + (export "%table" (table $0)) + (func $foo + (nop) + ) + (func $bar + (call_indirect (type $none_=>_none) + (i32.const 0) + ) + ) +) +Secondary: +(module + (type $none_=>_none (func)) + (import "primary" "%table" (table $0 1 funcref)) + (elem (i32.const 0) $bar) + (import "primary" "%foo_0" (func $foo)) + (func $bar + (call $foo) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (table $table 4 funcref) + (elem (i32.const 0) $foo $bar $baz $quux) + (func $foo + (nop) + ) + (func $bar + (nop) + ) + (func $baz + (nop) + ) + (func $quux + (nop) + ) +) +Keeping: bar, quux +After: +(module + (type $none_=>_none (func)) + (import "placeholder" "0" (func $placeholder_0)) + (import "placeholder" "2" (func $placeholder_2)) + (table $table 4 funcref) + (elem (i32.const 0) $placeholder_0 $bar $placeholder_2 $quux) + (export "%table" (table $table)) + (func $bar + (nop) + ) + (func $quux + (nop) + ) +) +Secondary: +(module + (type $none_=>_none (func)) + (import "primary" "%table" (table $table 4 funcref)) + (elem (i32.const 0) $foo) + (elem (i32.const 2) $baz) + (func $baz + (nop) + ) + (func $foo + (nop) + ) +) + + +Before: +(module + (type $none_=>_none (func)) + (table $table 4 funcref) + (elem (i32.const 0) $foo $bar $baz $quux) + (func $foo + (nop) + ) + (func $bar + (nop) + ) + (func $baz + (nop) + ) + (func $quux + (nop) + ) +) +Keeping: baz +After: +(module + (type $none_=>_none (func)) + (import "placeholder" "0" (func $placeholder_0)) + (import "placeholder" "1" (func $placeholder_1)) + (import "placeholder" "3" (func $placeholder_3)) + (table $table 4 funcref) + (elem (i32.const 0) $placeholder_0 $placeholder_1 $baz $placeholder_3) + (export "%table" (table $table)) + (func $baz + (nop) + ) +) +Secondary: +(module + (type $none_=>_none (func)) + (import "primary" "%table" (table $table 4 funcref)) + (elem (i32.const 0) $foo $bar) + (elem (i32.const 3) $quux) + (func $bar + (nop) + ) + (func $foo + (nop) + ) + (func $quux + (nop) + ) +) + + +Before: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $table 1 1 funcref) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (result i32) + (call $bar + (i32.const 0) + ) + ) + (func $bar (param $0 i32) (result i32) + (call $foo + (i32.const 1) + ) + ) +) +Keeping: foo +After: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) + (table $table 2 2 funcref) + (elem (i32.const 0) $foo $placeholder_1) + (export "%foo" (func $foo)) + (export "%table" (table $table)) + (func $foo (param $0 i32) (result i32) + (call_indirect (type $i32_=>_i32) + (i32.const 0) + (i32.const 1) + ) + ) +) +Secondary: +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "primary" "%table" (table $table 2 2 funcref)) + (elem (i32.const 1) $bar) + (import "primary" "%foo" (func $foo (param i32) (result i32))) + (func $bar (param $0 i32) (result i32) + (call $foo + (i32.const 1) + ) + ) +) + + |