Skip to content

feat: support i64::checked_mod#1196

Draft
mooori wants to merge 2 commits into
nextfrom
mooori/checked-mod-i64
Draft

feat: support i64::checked_mod#1196
mooori wants to merge 2 commits into
nextfrom
mooori/checked-mod-i64

Conversation

@mooori

@mooori mooori commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Closes #1000 and unlocks i64::overflowing_rem, i64::checked_rem.

@mooori

This comment was marked as outdated.

@mooori mooori force-pushed the mooori/checked-mod-i64 branch from a279fa6 to 2c4a9b3 Compare June 19, 2026 09:22
@mooori mooori marked this pull request as ready for review June 19, 2026 11:45
@mooori mooori requested review from bitwalker and greenhat June 19, 2026 11:45

@greenhat greenhat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking good overall! Please check my note.
Also, IIRC we have arith.smod. Should we use it here?

|(a, b): &(i64, i64)| {
if *b == 0 {
Err(TrapExpectation::DivideByZero)
} else if *a == i64::MIN && *b == -1 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WebAssembly signed remainder is only undefined for a zero divisor; i64.rem_s(i64::MIN, -1) should return 0, not trap (WebAssembly numerics, irem_s).

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.

i64.rem_s(i64::MIN, -1) should return 0, not trap

I think this means we have a bug in the lowering of Wasm's i64.rem_s which tests do not catch:

  • Wasm i64.rem_s is probably compiled to i64::checked_mod intrinsic
  • For (i64::MIN, -1) Wasm returns 0 but the intrinsic traps

The arith tests i64::checked_rem and i64::overflowing_rem do hit the intrinsic i64::checked_mod. Though when compiling i64::checked_rem, i64::overflowing_rem from Rust to Wasm, the generated Wasm handles edge cases explicitly, thus hiding the bug.

My plan is:

  • Add test(s) to check whether the i64.rem_s lowering is fine or not
  • Fix it if needed. Maybe by adding intrinsic i64::wrapping_mod and lowering i64.rem_s to that.

The same issue should then also exist for i32.rem_s and the i32::checked_mod intrinsic.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sounds good!

@bitwalker bitwalker left a comment

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.

Looks good! Aside from @greenhat's notes, I just had one nit, otherwise 👍

# Computes `a % b`, asserting that both inputs are valid i64 values (u32 limbs).
#
# Execution traps on division by zero, and on `i64::MIN % -1` (the underlying division overflows).
pub proc checked_mod # [b_lo, b_hi, a_lo, a_hi]

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.

We should add type signatures to all new intrinsics

@mooori mooori marked this pull request as draft June 26, 2026 08:20
@mooori

mooori commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Reverted to draft to work on #1206 first.

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.

Implement checked_mod for i64

3 participants