Skip to content

Add memory64 and table64 support to the Canonical ABI#624

Merged
lukewagner merged 58 commits intoWebAssembly:mainfrom
adambratschikaye:abk/memory64
Apr 9, 2026
Merged

Add memory64 and table64 support to the Canonical ABI#624
lukewagner merged 58 commits intoWebAssembly:mainfrom
adambratschikaye:abk/memory64

Conversation

@adambratschikaye
Copy link
Copy Markdown
Contributor

Parameterize the Canonical ABI to handle 32-bit or 64-bit memory addresses and table indices. This is done by adding two new fields to LiftOptions to indicate if the memory64/table64 feature is being used in a core module.

Parameterize the Canonical ABI to handle 32-bit or 64-bit memory
addresses and table indices. This is done by adding two new fields to
`LiftOptions` to indicate if the `memory64`/`table64` feature is being
used in a core module.
Copy link
Copy Markdown
Collaborator

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for helping to pick this up! We chatted a bit on Zulip but for posterity I'll mention here about table-related index types how most of them want to remain 32-bits. I'll take a closer look once that's been passed over here, and in the meantime I skimmed over things and noted a few things here and there. I'm sure though that @lukewagner will have thoughts on this too!

(param $originalSize i32)
(func (param $originalPtr $addr)
(param $originalSize $addr)
(param $alignment i32)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this I might recommend making alignment have type $addr as well for consistency, and I think that matches the signature in Rust/C/etc as well.

| -------------------------- | ------------------------ |
| Approximate WIT signature | `func<T>(t: T) -> T.rep` |
| Canonical ABI signature | `[t:i32] -> [i32]` |
| Canonical ABI signature | `[t:$idx] -> [i32]` |
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This'll be a bit subtle, but this'll actually want to be a mapping of i32 as an argument (I talked with you a bit about this already, but the input here is a host-side index so always 32-bit), but the output here should be something variable. Resource "rep"s are generally pointers in linear memory so 64-bit components are going to want 64-bit storage values. In the component model resources are defined with (rep i32) and validation currently requires that i32 is the only one listed there, but this PR will relax that meaning that the resource type itself stores the lowered type which'll get plumbed here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've now changed it so that the types which are expected to be pointers to memory are allowed to be either i32 or i64 without forcing them to match the memory type (e.g. the return value here, or in context.{get,set}, or thread.new-indirect). This means we don't need to require the memory canonopt anywhere where it didn't previously exist.

Copy link
Copy Markdown
Collaborator

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I think this'll need minor adjustments over time but overall looks good 👍

Comment on lines +244 to +245
if opts.memory is None:
return 'i32'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this have an assert? This in theory shouldn't ever be called dynamically if memory is None

Comment on lines +3209 to +3211
* `memory` - this is a subtype of `(memory 1)`. In the rest of the explainer,
`PTR` will refer to either `i32` or `i64` core Wasm types as determined by the
type of this `memory`.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This'll technically want to say it's a subtype of memory 1 or memory i64 1 since those are separate types

feature (the "stackful" ABI), this restriction is lifted.
* 🔀 `callback` - the function has type `(func (param i32 i32 i32) (result i32))`
and cannot be present without `async` and is only allowed with
* 🔀 `callback` - the function has type `(func (param i32 i32 PTR) (result i32))`
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one may remain a three i32s since they're all async-related codes/events/etc.

Copy link
Copy Markdown
Member

@lukewagner lukewagner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great overall; thanks so much for all the work and adding tests too! There's only one relatively minor, but non-nit, suggestion below that I'm happy to discuss and then re-review based on what we decide.

@adambratschikaye adambratschikaye marked this pull request as ready for review March 26, 2026 15:39
@adambratschikaye
Copy link
Copy Markdown
Contributor Author

Other than that, this looks great to implement. One question is whether we think we'll get implementation feedback soon enough to want to keep the PR open until so we can simply iterate on it here, or whether we think it'd be more valuable to merge it now, and iterate in separate PRs if/when tweaks are found. Happy to hear what you and @alexcrichton think we should do.

We should start work in the next week on implementation.

Copy link
Copy Markdown
Member

@lukewagner lukewagner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, thanks! Now that things are gated, I'll merge once these nits are fixed.

adambratschikaye and others added 18 commits April 9, 2026 08:27
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
Co-authored-by: Luke Wagner <mail@lukewagner.name>
@adambratschikaye
Copy link
Copy Markdown
Contributor Author

Thanks again @lukewagner !

@lukewagner
Copy link
Copy Markdown
Member

And thank you again for working on this!

@lukewagner lukewagner merged commit a6dfd37 into WebAssembly:main Apr 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants