-
Notifications
You must be signed in to change notification settings - Fork 1.5k
x64: refactor the representation of *Mem
and *MemImm
#10775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
While reflecting on why bytecodealliance#10762 is hard, it seemed that the underlying problem to many ISLE matching issues is our inability to actually inspect the variants of the register specific versions of `RegMem` and `RegMemImm`. We had been wrapping instances of these `Reg*` types, but this change pushes the variants down to: `GprMem`, `GprMemImm`, `XmmMem`, `XmmMemAligned`, `XmmMemImm`, and `XmmMemAlignedImm`. With this, it should be possible to match directly on the variants in ISLE. This does not change any functionality.
(type GprMemImm extern (enum)) | ||
(type GprMem extern | ||
(enum | ||
(Reg (reg Reg)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it now theoretically possible to create a GprMem.Reg
in ISLE using the wrong kind of register? If so, we could alter this type to Gpr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to type this as (Gpr (reg Gpr))
? That more closely matches the semantics of the GprMem
constructor in Rust
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following up from today's Cranelift meeting, where we briefly discussed this PR: I want to +1 Alex's comment here.
We want to maintain the invariant that all Gpr*
newtypes can only ever contain GPR registers when they aren't a memory or immediate or whatever. If we expose raw Reg
s in these enum
variants, then users can accidentally (say transitively through a series of abstractions) do something like
if let GprMem::Reg { reg } = &mut gpr_mem {
std::mem::swap(reg, my_xmm_reg);
}
which would break that invariant.
In order to both allow matching on GprMem
et al and preserve that invariant, we need to define new enum
s (to allow matching) but keep the register variants as Gpr
s (to preserve encapsulation and the GPR invariant). This would look like the ISLE equivalent of something like this:
enum GprMem {
Gpr { reg: Gpr },
Mem { addr: SyntheticAmode },
}
Which is, I believe, what Alex is suggesting just above this comment.
I will say, having tried to use this in #10762, that it doesn't just "solve everything." So we should judge this on whether it will make future matching easier. I know that I've reached for this kind of matching in the past but was frustrated it didn't exist. |
While reflecting on why #10762 is hard, it seemed that the underlying problem to many ISLE matching issues is our inability to actually inspect the variants of the register specific versions of
RegMem
andRegMemImm
. We had been wrapping instances of theseReg*
types, but this change pushes the variants down to:GprMem
,GprMemImm
,XmmMem
,XmmMemAligned
,XmmMemImm
, andXmmMemAlignedImm
. With this, it should be possible to match directly on the variants in ISLE. This does not change any functionality.