Skip to content

Handle constant offsets larger than 4G in memory64-lowering#8316

Merged
dschuff merged 5 commits intomainfrom
mem-offset
Feb 13, 2026
Merged

Handle constant offsets larger than 4G in memory64-lowering#8316
dschuff merged 5 commits intomainfrom
mem-offset

Conversation

@dschuff
Copy link
Member

@dschuff dschuff commented Feb 12, 2026

If memory instructions have constant offsets greater than the maxiumum size of
a 32-bit memory, they become invalid when the memory becomes a 32-bit memory.
In this case the memory operation can never succeed, and if the operation
was legtimate in the first place (rather than e.g. being the result of
an optimization that took advantage of UB in C), then the program cannot be
correctly lowered. So in any case it is better to trap if the instruction
is actually executed.

So this change replaces memory operations with large constant offsets with an
unreachable, and hoists any child operations into a block that runs before it.

If memory instructions have constant offsets greater than the maxiumum size of
a 32-bit memory, they become invalid when the memory becomes a 32-bit memory.
In this case the memory operation can never succeed, and if the operation
was legtimate in the first place (rather than e.g. being the result of
an optimization that took advantage of UB in C), then the program cannot be
correctly lowered. So in anny case it is better to trap if the instruction
is actually executed.
@dschuff dschuff requested a review from kripken February 12, 2026 21:43
if (curr->offset < k32GLimit) {
return wrapAddress64(curr->ptr, curr->memory);
}
replaceCurrent(Builder(*getModule()).makeUnreachable());
Copy link
Member

Choose a reason for hiding this comment

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

This is not quite right as it replaces the entire tree, including the children. A child may branch away, so the program might have executed validly before this.

See ChildLocalizer::getChildrenReplacement() which returns the children of an expression. That returns a block which you can append an unreachable to.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I think I have it. Do you think we need a more complex test that would cover this (beyond the current test that just shows an empty block?) Or maybe that would just be testing ChildLocalizer itself and should be done elsewhere...

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

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

lgtm % comments

;; CHECK-NEXT: )
(func $test_simd_load_large_offset (param $ptr i64)
(drop (v128.load offset=4294967296 (local.get $ptr)))
)
Copy link
Member Author

Choose a reason for hiding this comment

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

When I turn on pass debug I'm getting a validation error:

[wasm-validator error in function test_simd_load_large_offset] stale type found in test_simd_load_large_offset on 0x5647b782bca8
(marked as none, should be unreachable)
, on
(drop
 (block
  (unreachable)
 )
)

I guess I need to propagate the unreachable type from the block up to the drop? Is there a utility for that?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, yes, if you add an unreachable that is a type change. You can note that and then run ReFinalize().walkFunctionInModule(func, module); on the entire function. See e.g. the Heap2Local pass.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, does this look right?

Copy link
Member

Choose a reason for hiding this comment

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

yes, lgtm

@dschuff dschuff enabled auto-merge (squash) February 13, 2026 00:56
@dschuff dschuff merged commit 18ba061 into main Feb 13, 2026
17 checks passed
@dschuff dschuff deleted the mem-offset branch February 13, 2026 03:02
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.

2 participants