Backport rust-lang/rust#134117 and allow only <*T>::offset
-like "GEPs".
#327
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(Each commit should be reviewed separately)
LLVM's
GetElementPointer
(akin to SPIR-VOpAccessChain
/OpPtrAccessChain
) was, for a long time, the main way to interact with pointers, as it could perform, in one go, all ofe.g.:
&(*(p: *Foo).add(i)).outer_field3[j].0.inner_field1[k].leaf_field2
, even today:continues to work, even in the "untyped pointer" world (i.e.
%p
having typeptr
instead ofFoo*
).However, both in LLVM itself, and in
rustc_codegen_llvm
, its patterns have been shrinking with time:gep [0 x %Type]
togep %Type
rust-lang/rust#134117encountered in (yet-unlanded) rustup: update to
nightly-2025-05-09
(~1.88) and Rust 2024 edition. #249And they're generally converging on
<*T>::offset
-like pointer arithmetic, whereT
is:[T; N]
or[T]
type<[T]>::get_unchecked(xs, i)
is&*(xs as *const [T] as *const T).add(i)
i8
/u8
for arbitrary byte offsettingstruct
fieldsT
s could go through byte offsetts by multiplying w/ the size ofT
, aka "stride", but having that multiplication in the IR is not (yet) on the table(even SPIR-T
qptr
uses a special "strided offset", even if it erases the specific typeT
)Instead of keeping the increasingly-gnarly
maybe_inbounds_gep
(see also e.g. #233 - a valiant effort at reconciling several of its conflicting needs), this PR moves the core logic to a new method,named
ptr_offset_strided
(suffixed_strided
to hopefully avoid confusion with the byte-orientedptradd
).By only handling
(p: *T).offset(i)
, no more, no less (i.e. no intra-T
offsetting), a lot of the decision logic/correctness subtleties/etc., vanish away, fixing edge cases like #233 (comment) without breaking theissue-46
test (which #233 itself first fixed).Sadly I wasn't able to keep a lot of the comments/
trace!
s added in #233, but I tried to have a bare minimum, combined with the continued existence of#[instrument]
on/trace!
in, several helper methods.EDIT: on top of "future
rustup
PRs", the SPIR-V validation error described in issue #323 appears to disappear on top of this PR (as reported in #323 (comment)) - so it's possible none of this code was ever bug-free.