diff options
-rw-r--r-- | src/passes/Directize.cpp | 18 | ||||
-rw-r--r-- | test/lit/passes/directize_all-features.wast | 95 |
2 files changed, 110 insertions, 3 deletions
diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 0bb5aebd9..34930d127 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -251,9 +251,21 @@ struct Directize : public Pass { if (func->imported()) { return; } - for (auto* set : FindAll<TableSet>(func->body).list) { - tablesWithSet.insert(set->table); - } + + struct Finder : public PostWalker<Finder> { + TablesWithSet& tablesWithSet; + + Finder(TablesWithSet& tablesWithSet) : tablesWithSet(tablesWithSet) {} + + void visitTableSet(TableSet* curr) { + tablesWithSet.insert(curr->table); + } + void visitTableFill(TableFill* curr) { + tablesWithSet.insert(curr->table); + } + }; + + Finder(tablesWithSet).walkFunction(func); }); for (auto& [_, names] : analysis.map) { diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast index 0b55679c4..53ff29ab6 100644 --- a/test/lit/passes/directize_all-features.wast +++ b/test/lit/passes/directize_all-features.wast @@ -1451,3 +1451,98 @@ ) ) ) + +;; A table.fill prevents optimization. +(module + ;; CHECK: (type $i32 (func (result i32))) + ;; IMMUT: (type $i32 (func (result i32))) + (type $i32 (func (result i32))) + + ;; CHECK: (type $1 (func)) + + ;; CHECK: (table $table 111 funcref) + ;; IMMUT: (type $1 (func)) + + ;; IMMUT: (table $table 111 funcref) + (table $table 111 funcref) + (elem (i32.const 0) $func-A) + + ;; CHECK: (elem $0 (i32.const 0) $func-A) + + ;; CHECK: (elem declare func $func-B) + + ;; CHECK: (export "a" (func $fill)) + ;; IMMUT: (elem $0 (i32.const 0) $func-A) + + ;; IMMUT: (elem declare func $func-B) + + ;; IMMUT: (export "a" (func $fill)) + (export "a" (func $fill)) + ;; CHECK: (export "b" (func $call)) + ;; IMMUT: (export "b" (func $call)) + (export "b" (func $call)) + + ;; CHECK: (func $func-A (type $i32) (result i32) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; IMMUT: (func $func-A (type $i32) (result i32) + ;; IMMUT-NEXT: (i32.const 0) + ;; IMMUT-NEXT: ) + (func $func-A (result i32) + (i32.const 0) + ) + + ;; CHECK: (func $func-B (type $i32) (result i32) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; IMMUT: (func $func-B (type $i32) (result i32) + ;; IMMUT-NEXT: (unreachable) + ;; IMMUT-NEXT: ) + (func $func-B (result i32) + (unreachable) + ) + + ;; CHECK: (func $fill (type $1) + ;; CHECK-NEXT: (table.fill $table + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (ref.func $func-B) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; IMMUT: (func $fill (type $1) + ;; IMMUT-NEXT: (table.fill $table + ;; IMMUT-NEXT: (i32.const 0) + ;; IMMUT-NEXT: (ref.func $func-B) + ;; IMMUT-NEXT: (i32.const 1) + ;; IMMUT-NEXT: ) + ;; IMMUT-NEXT: ) + (func $fill + (table.fill $table + (i32.const 0) + (ref.func $func-B) + (i32.const 1) + ) + ) + + ;; CHECK: (func $call (type $1) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call_indirect $table (type $i32) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; IMMUT: (func $call (type $1) + ;; IMMUT-NEXT: (drop + ;; IMMUT-NEXT: (call $func-A) + ;; IMMUT-NEXT: ) + ;; IMMUT-NEXT: ) + (func $call + (drop + ;; This cannot be turned into a direct call due to the table.fill, unless we + ;; assume initial contents are immutable. + (call_indirect (type $i32) + (i32.const 0) + ) + ) + ) +) |