diff options
author | Alon Zakai <azakai@google.com> | 2024-05-08 10:07:32 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-08 10:07:32 -0700 |
commit | ed2cec473a03c83d169775fb47c5bef89e312719 (patch) | |
tree | edeb683b2d8433a124d09970a0fc651a697df9ec /test/lit/wasm-split | |
parent | 4b7c610f14329dfe045534ec1cde7f28330393f9 (diff) | |
download | binaryen-ed2cec473a03c83d169775fb47c5bef89e312719.tar.gz binaryen-ed2cec473a03c83d169775fb47c5bef89e312719.tar.bz2 binaryen-ed2cec473a03c83d169775fb47c5bef89e312719.zip |
wasm-split: Handle RefFuncs (#6513)
When we have a ref.func that refers to the secondary module then make a trampoline
that calls it directly. The trampoline's call is then fixed up like all direct calls to the
secondary module.
Diffstat (limited to 'test/lit/wasm-split')
-rw-r--r-- | test/lit/wasm-split/passive.wast | 54 | ||||
-rw-r--r-- | test/lit/wasm-split/ref.func.wast | 106 |
2 files changed, 160 insertions, 0 deletions
diff --git a/test/lit/wasm-split/passive.wast b/test/lit/wasm-split/passive.wast new file mode 100644 index 000000000..a72dcada5 --- /dev/null +++ b/test/lit/wasm-split/passive.wast @@ -0,0 +1,54 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-split %s --split-funcs=second-in-table -g -o1 %t.1.wasm -o2 %t.2.wasm -all +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY + +(module + (type $func-array (array (mut funcref))) + + ;; PRIMARY: (type $0 (func)) + + ;; PRIMARY: (import "placeholder" "0" (func $placeholder_0)) + + ;; PRIMARY: (table $table 3 funcref) + (table $table 3 funcref) + + ;; Workaround for https://github.com/WebAssembly/binaryen/issues/6572 - we + ;; error without an active segment. + (elem (i32.const 0)) + + ;; PRIMARY: (elem $0 (i32.const 0) $placeholder_0) + + ;; PRIMARY: (elem $passive func $in-table $1) + (elem $passive func $in-table $second-in-table) + + ;; PRIMARY: (export "table" (table $table)) + + ;; PRIMARY: (func $in-table + ;; PRIMARY-NEXT: (nop) + ;; PRIMARY-NEXT: ) + (func $in-table + ;; This is in a passive segment, but it is in the main module so we need no + ;; special handling. + ) + + ;; SECONDARY: (type $0 (func)) + + ;; SECONDARY: (import "primary" "table" (table $table 3 funcref)) + + ;; SECONDARY: (elem $0 (i32.const 0) $second-in-table) + + ;; SECONDARY: (func $second-in-table + ;; SECONDARY-NEXT: (nop) + ;; SECONDARY-NEXT: ) + (func $second-in-table + ;; This is in a passive segment, and it is in the secondary module, so we will + ;; handle it by adding a trampoline from the segment as a new function "$1". + ) +) +;; PRIMARY: (func $1 +;; PRIMARY-NEXT: (call_indirect (type $0) +;; PRIMARY-NEXT: (i32.const 0) +;; PRIMARY-NEXT: ) +;; PRIMARY-NEXT: ) diff --git a/test/lit/wasm-split/ref.func.wast b/test/lit/wasm-split/ref.func.wast new file mode 100644 index 000000000..f7832dcf4 --- /dev/null +++ b/test/lit/wasm-split/ref.func.wast @@ -0,0 +1,106 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: wasm-split %s --split-funcs=second,second-in-table -g -o1 %t.1.wasm -o2 %t.2.wasm -all +;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY +;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY + +;; Test that we handle ref.func operations properly as we split out $second. +;; ref.funcs that refer to the other module must be fixed up to refer to +;; something in the same module, that then trampolines to the other. +(module + ;; PRIMARY: (type $0 (func)) + + ;; PRIMARY: (import "placeholder" "1" (func $placeholder_1)) + + ;; PRIMARY: (import "placeholder" "2" (func $placeholder_2)) + + ;; PRIMARY: (global $glob1 (ref func) (ref.func $prime)) + + ;; PRIMARY: (global $glob2 (ref func) (ref.func $2)) + + ;; PRIMARY: (table $table 3 3 funcref) + (table $table 1 1 funcref) + + (global $glob1 (ref func) (ref.func $prime)) + + (global $glob2 (ref func) (ref.func $second)) + + ;; PRIMARY: (elem $elem (i32.const 0) $in-table $placeholder_1 $placeholder_2) + (elem $elem (i32.const 0) $in-table $second-in-table) + + ;; PRIMARY: (export "prime" (func $prime)) + + ;; PRIMARY: (export "table" (table $table)) + + ;; PRIMARY: (export "global" (global $glob1)) + + ;; PRIMARY: (export "global_3" (global $glob2)) + + ;; PRIMARY: (func $prime + ;; PRIMARY-NEXT: (drop + ;; PRIMARY-NEXT: (ref.func $prime) + ;; PRIMARY-NEXT: ) + ;; PRIMARY-NEXT: (drop + ;; PRIMARY-NEXT: (ref.func $2) + ;; PRIMARY-NEXT: ) + ;; PRIMARY-NEXT: ) + (func $prime + (drop + (ref.func $prime) + ) + (drop + (ref.func $second) + ) + ) + + ;; SECONDARY: (type $0 (func)) + + ;; SECONDARY: (import "primary" "table" (table $table 3 3 funcref)) + + ;; SECONDARY: (import "primary" "global" (global $glob1 (ref func))) + + ;; SECONDARY: (import "primary" "global_3" (global $glob2 (ref func))) + + ;; SECONDARY: (import "primary" "prime" (func $prime)) + + ;; SECONDARY: (elem $0 (i32.const 1) $second-in-table $second) + + ;; SECONDARY: (func $second + ;; SECONDARY-NEXT: (drop + ;; SECONDARY-NEXT: (ref.func $prime) + ;; SECONDARY-NEXT: ) + ;; SECONDARY-NEXT: (drop + ;; SECONDARY-NEXT: (ref.func $second) + ;; SECONDARY-NEXT: ) + ;; SECONDARY-NEXT: ) + (func $second + (drop + (ref.func $prime) + ) + (drop + (ref.func $second) + ) + ) + + ;; PRIMARY: (func $in-table + ;; PRIMARY-NEXT: (nop) + ;; PRIMARY-NEXT: ) + (func $in-table + ;; This empty function is in the table. Just being present in the table is not + ;; enough of a reason for us to make a trampoline, even though in our IR the + ;; table is a list of ref.funcs. + ) + + ;; SECONDARY: (func $second-in-table + ;; SECONDARY-NEXT: (nop) + ;; SECONDARY-NEXT: ) + (func $second-in-table + ;; As above, but in the secondary module. We still don't need a trampoline + ;; (but we will get a placeholder, as all split-out functions do). + ) +) +;; PRIMARY: (func $2 +;; PRIMARY-NEXT: (call_indirect (type $0) +;; PRIMARY-NEXT: (i32.const 2) +;; PRIMARY-NEXT: ) +;; PRIMARY-NEXT: ) |