Skip to content

Conversation

@samcowger
Copy link
Contributor

Towards #1666, this makes crucible-mir construct and eliminate MirAggregates representing Rust arrays with offsets and sizes that match those used in Rust, rather than hardcoding all element sizes as 1. (This does not change that same hardcoding in structs or tuples.)

The first two commits in this essentially supersede #1700. A major motivation of that PR was to give access to slice element types in order to be able to provide their proper width when accessing them, but it turns out that we can avoid accessing individual slice elements in a way that requires their width.

@samcowger samcowger added crucible MIR Issues relating to Rust/MIR support memory-model labels Jan 13, 2026
Copy link
Contributor

@spernsteiner spernsteiner left a comment

Choose a reason for hiding this comment

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

Just reviewed Intrinsics.hs so far

Copy link
Contributor

@spernsteiner spernsteiner left a comment

Choose a reason for hiding this comment

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

Reviewed the rest of it

Comment on lines +6 to +7
[Crux] Total: 9
[Crux] Proved: 9
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this test producing extra subgoals? It would be good to know if we can eliminate those, to reduce the chances of introducing a new performance regression

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The excess goals come from checking the validity of an offset into an aggregate, arising in this case from indexing the 1-length slice. The statement to be proved is that the index (if c { 1 } else { 0 }) is valid, and in this case, that means checking it for equality against the only valid offset, 0. So, this ended up in what4 as roughly if c then 1 else 0 == 0, and what4 then recognized that this could reduce to not c. (I learned this from printing out several intermediate expressions within Mir.Intrinsics.offsetInSpans.) I surmise that not c was simple enough not to show up as a proved goal. With my changes, we're still checking for equality with 0, but because the offset needs to account for the elements' width, the goal statement looks more like 4 * (if c then 1 else 0) == 0, which what4 doesn't seem able to simplify.

I don't know that there's much we can do about this (though perhaps we could to try to patch what4 to recognize and simplify expressions like the one we're producing here). On the bright side, these goals shouldn't grow in size with the number of array elements, because with any length above 1 we should be generating validity expressions using the "run" recognition functionality of #1625 instead.

Comment on lines +2682 to +2758
subindexMirRefSim sym tpr ref idx elemSize = do
modifyRefMuxSim (\ref' -> subindexMirRefLeaf sym tpr ref' idx elemSize) ref
Copy link
Contributor

Choose a reason for hiding this comment

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

As an FYI, adding a sym argument will require some minor changes on the SAW and crucible-mir-comp side to accommodate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, indeed. I see two calls in crucible-mir-comp's Mir.Compositional.Override to subindexMirRefSim, and both appear to have the necessary sym parameter in scope at the call site already, so this should be fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Indeed, I don't expect it to be difficult to adapt to these changes. This is more of a "please hold off on merging this until the Crux/SAW releases are done" warning.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, I certainly will.

Avoid substantial ad-hoc evaluation effort for slices at the cost of supporting
evaluation of entire symbolic arrays, which should be pretty uncommon in the
first place.
NFCI - the element type size is still hardcoded as 1, but this is appropriate,
since we know we're working with `[u8]` slices.
Note that this causes the `indexing.rs` test to fail, though by generating
excess goals to check rather than by failing to verify entirely, making the
issue one of performance rather than correctness. The next commit will address
this.
Addresses the performance regression introduced and mentioned in the previous
commit.
Also add a test case to demonstrate the code pattern this enables.
@samcowger samcowger force-pushed the sc/array-type-sizes branch from 7a5d34c to d2e58da Compare January 28, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crucible memory-model MIR Issues relating to Rust/MIR support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants