diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h index 884f2309797..c1035c008d5 100644 --- a/src/ir/table-utils.h +++ b/src/ir/table-utils.h @@ -17,7 +17,6 @@ #ifndef wasm_ir_table_h #define wasm_ir_table_h -#include "ir/element-utils.h" #include "ir/literal-utils.h" #include "ir/module-utils.h" #include "support/stdckdint.h" @@ -51,8 +50,19 @@ struct FlatTable { if (end > names.size()) { names.resize(end); } - ElementUtils::iterElementSegmentFunctionNames( - segment, [&](Name entry, Index i) { names[start + i] = entry; }); + for (Index i = 0; i < segment->data.size(); i++) { + auto* item = segment->data[i]; + if (auto* refFunc = item->dynCast()) { + names[start + i] = refFunc->func; + } else if (item->is()) { + names[start + i] = Name(); + } else { + // Anything else, we can't represent. + // TODO: mark only this index as unoptimizable? + valid = false; + return; + } + } }); } }; diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast index 8cbe6092dbc..8973492c671 100644 --- a/test/lit/passes/directize_all-features.wast +++ b/test/lit/passes/directize_all-features.wast @@ -2148,3 +2148,50 @@ (func $target ) ) + +;; Set a function using one elem, then trample it with a null. We should use the +;; null for the call_indirect. +(module + ;; CHECK: (type $func (func)) + ;; IMMUT: (type $func (func)) + (type $func (func)) + + ;; CHECK: (table $table 6 funcref) + ;; IMMUT: (table $table 6 funcref) + (table $table 6 funcref) + + ;; CHECK: (elem $5 (i32.const 0) $nop) + ;; IMMUT: (elem $5 (i32.const 0) $nop) + (elem $5 (i32.const 0) $nop) + + ;; CHECK: (elem $6 (table $table) (i32.const 0) funcref (item (ref.null nofunc))) + ;; IMMUT: (elem $6 (table $table) (i32.const 0) funcref (item (ref.null nofunc))) + (elem $6 (i32.const 0) funcref (item (ref.null nofunc))) + + ;; CHECK: (export "call" (func $call)) + + ;; CHECK: (func $nop (type $func) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; IMMUT: (export "call" (func $call)) + + ;; IMMUT: (func $nop (type $func) + ;; IMMUT-NEXT: (nop) + ;; IMMUT-NEXT: ) + (func $nop (type $func) + (nop) + ) + + ;; CHECK: (func $call (type $func) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; IMMUT: (func $call (type $func) + ;; IMMUT-NEXT: (unreachable) + ;; IMMUT-NEXT: ) + (func $call (export "call") + ;; This can be optimized to an unreachable. + (call_indirect $table (type $func) + (i32.const 0) + ) + ) +)