Skip to content

RemoveUnusedModuleElements drops an active elem segment whose items are global.get, so call_indirect traps #9366

Open

Description

@trackoor

An active element segment whose item is global.get (the "Initializing a table with imported funcref global" case in the spec's elem.wast) is removed by --remove-unused-module-elements and at -O1 and above. The table slot stays null and call_indirect traps.

;; b2.wat
(module
  (type $f (func (result i32)))
  (import "env" "g" (global $g funcref))
  (table 1 funcref)
  (elem (i32.const 0) funcref (global.get $g))
  (func (export "call") (result i32)
    (call_indirect (type $f) (i32.const 0))))

wasm-opt b2.wat --enable-reference-types --remove-unused-module-elements -S -o - prints:

(module
 (type $f (func (result i32)))
 (table $0 1 funcref)
 (export "call" (func $0))
 (func $0 (result i32)
  (call_indirect $0 (type $f)
   (i32.const 0)
  )
 )
)

The segment and the import are gone. Instantiated in Node.js 26.13.0 with env.g set to a function returning 42:

unoptimized:                       call() = 42
--remove-unused-module-elements:   RuntimeError: function signature mismatch
-O1:                               RuntimeError: unreachable

The same happens when $g is a defined global initialized with ref.func (with --enable-gc).

Tested with wasm-opt version_133; on main (95a214d) the pass differs from version_133 only by the NFC renames in #9286/#9288.

In src/passes/RemoveUnusedModuleElements.cpp, notePossibleFunc in Analyzer::prepare() only looks at item->dynCast<RefFunc>(), so a segment with global.get items never gets into FlatTableInfo::typeElems and is considered unused.

Found with a differential-testing tool; the report was drafted with AI assistance and reviewed and edited by me.

Credit: https://ucsbplse.github.io/

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions