Skip to content

[mono-move] Implement integer cast micro-op#19936

Open
vgao1996 wants to merge 1 commit into
mainfrom
vgao/mono-move-int-cast
Open

[mono-move] Implement integer cast micro-op#19936
vgao1996 wants to merge 1 commit into
mainfrom
vgao/mono-move-int-cast

Conversation

@vgao1996
Copy link
Copy Markdown
Contributor

@vgao1996 vgao1996 commented May 29, 2026

Summary

Implements the family of integer cast micro-ops for the mono-move VM as a single universal IntCast micro-op that covers all 12×12 (from, to) integer type pairs.

The cast is value-preserving: it reproduces the source's mathematical integer value in the target type and aborts iff that value falls outside the target's [MIN, MAX] range. This matches the existing Move VM's Value::cast_* semantics exactly (widening, narrowing, and signed↔unsigned).

Self-casts (from == to) are accepted and run as identity — the bytecode verifier admits them (the operand only has to be an integer) and the production VM executes them, so mono-move must not reject them.

Changes

  • core: IntCastOp operand + MicroOp::IntCast, with Display, gas cost, is_allocating, and re-exports.
  • runtime: exec_int_cast doing a uniform per-pair <dst>::try_from(src) dispatch (native↔native via std, native↔256-bit via the int256 crate, identity via the blanket impl); a new CastOutOfRange error; verifier frame-access checks.
  • specializer: lowers UnaryOp::Cast* to IntCast, with the target type resolved by a new UnaryOp::extract_to_int_ty helper.

Testing

  • Property tests (runtime/tests/arithmetic_ops.rs): all 144 (from, to) pairs, each checked against an independent num-bigint range-check oracle — one generated test per pair.
  • Differential tests: int_cast.move covers every cast category (widen / narrow / signed↔unsigned, both success and out-of-range) for the wide integer types end-to-end against the legacy VM; self_cast.masm pins the self-cast identity behavior.

Note: the narrow widths (u8..u32, i8..i32) can't yet flow through the .move pipeline (the 8-byte slot-align rule), so they're covered by the property tests rather than the differential .move tests.

🤖 Generated with Claude Code


Note

Medium Risk
Touches VM execution semantics for all integer cast combinations; risk is mitigated by extensive property and differential tests, but incorrect range handling could diverge from the legacy VM.

Overview
Adds a universal MicroOp::IntCast path so mono-move can execute Move integer casts end-to-end: IntCastOp in core (display, gas, non-allocating), exec_int_cast in the runtime via nested try_from over all 12×12 type pairs with CastOutOfRange, verifier frame checks (including identity casts), and specializer lowering of UnaryOp::Cast* through UnaryOp::extract_to_int_ty.

Semantics are value-preserving in the target range (aligned with the legacy VM); out-of-range values abort. Coverage includes 144 proptest pairs in arithmetic_ops.rs plus differential int_cast / self_cast testsuite cases against the production VM.

Reviewed by Cursor Bugbot for commit bad140b. Bugbot is set up for automated code reviews on this repo. Configure here.

Add a universal `IntCast` micro-op covering all 12x12 (from, to)
integer type pairs. Semantics match the existing Move VM: the cast
preserves the source's mathematical value and aborts iff the value
falls outside the target type's range. Self-casts (from == to) are
accepted and run as identity, since the bytecode verifier admits them
and the production VM executes them.

- core: `IntCastOp` + `MicroOp::IntCast`, display, gas, re-exports
- runtime: `exec_int_cast` (uniform per-pair `TryFrom` dispatch),
  `CastOutOfRange` error, verifier frame-access checks
- specializer: lower `UnaryOp::Cast*` to `IntCast`, with the target
  type resolved by `UnaryOp::extract_to_int_ty`
- tests: 144-pair property tests with a BigInt oracle in
  `arithmetic_ops`, plus `.move` / `.masm` differential coverage
  (including the self-cast identity case)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vgao1996 vgao1996 force-pushed the vgao/mono-move-int-cast branch from 9c495ac to bad140b Compare May 29, 2026 23:29
Comment on lines +29 to +31
//!
//! The cast micro-op ([`MicroOp::IntCast`]) is also tested here, in the
//! cast section at the end, reusing the same single-op harness.
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.

Note: my plan is to rename this file to int_ops.rs before landing, but keeping the name now so it doesn't screw up the review.

@vgao1996 vgao1996 marked this pull request as ready for review May 29, 2026 23:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant