WebAssembly / WebAssembly/binaryen

Difficulties with internally using refined types

Open
#7,403 18 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
WebAssembly
Stars
8.6k
Forks
885
Avg merge
1d 19h
Merged PRs (30d)
69

Description

We currently use or plan to use more refined types in the IR than we will eventually emit in the binary in a couple situations:

  • Function references always use concrete signature types rather than funcref even when GC is not enabled.
  • Strings use stringref rather than externref even when stringref is not enabled.
  • We plan to use exact heap types where possible even when custom descriptors are not enabled.

In each of these cases, we wish to use the more refined types internally because the extra type information can in principle help us optimize better. The binary writer generalizes the internal refined types to their most precise allowed supertype when writing the binary to ensure that our output only uses the allowed features.

However, type generalization in the binary writer is the source of many latent bugs that have not been found by the fuzzer or encountered by users.

  • Casts distinguishing values with refined types from their unrefined supertypes will no longer be able to distinguish these values after their target types have been generalized. Optimizations in OptimizeInstructions, RemoveUnusedBrs, Precompute, and GUFA based on the assumption that these casts fail are incorrect.
  • MinimizeRecGroups and TypeUpdater more generally depend on being able to distinguish rec group structures to ensure that separate types remain separate after optimizations. If the rec groups only differ because one uses a more refined type that will be generalized during binary writing, the types will no longer be separate in the final binary.

These bugs have not been found because they either depend on string lowering, which is not yet fuzzed, or depend on GC being enabled so that casts exist to be optimized, etc. Using exact types with GC modules and optimizations without enabling custom descriptors will surface these bugs.

The plan to fix these bugs is to update the utilities used by these optimizations to evaluate cast results and compare rec group structures to take the enabled features into account and apply the same generalization logic that will eventually be applied in the binary writer.

An alternative plan would be to not use refined types internally when that could lead to bugs. The relative merit of this approach will depend on how much extra optimizing power using the refined types ends up unlocking.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the binary writer’s type-generalization logic and the utilities used by OptimizeInstructions, RemoveUnusedBrs, Precompute, GUFA, MinimizeRecGroups, and TypeUpdater. Compare their cast-result and rec-group comparisons against enabled features; done means these optimizations remain correct when refined types are generalized, including with GC modules and custom descriptors disabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, wasm
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.