Skip to content

WIP: [PAC] Add intrinsic based support for transmute_copy - #162121

Draft
jchlanda wants to merge 10 commits into
rust-lang:mainfrom
jchlanda:jakub/pac_transmute_copy
Draft

WIP: [PAC] Add intrinsic based support for transmute_copy#162121
jchlanda wants to merge 10 commits into
rust-lang:mainfrom
jchlanda:jakub/pac_transmute_copy

Conversation

@jchlanda

@jchlanda jchlanda commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Lower the intrinsic to a dedicated TransmuteCopy cast and, when available, insert the library precondition check requiring the source to contain at least size_of::<Dst>() bytes.

Handle TransmuteCopy as a direct read of Dst from the source address, allowing shrinking transmutes and unsized sources. Use the source's known alignment together with the destination alignment to avoid emitting loads with stronger alignment requirements than the source can guarantee.

Statically provable size violations are treated as unreachable during codegen, while dynamically-sized sources retain the runtime precondition check. For slices and str, known length metadata is used to prove that the source is too short; for dyn Trait no such support is provided (to avoid reading v-tables).

Intrinsic-based implementation makes it possible for the codegen to provide support for function pointer type discrimination, in particular the need to resign function pointers when a transmute changes their discriminator.

This patch introduces the following:

* Extends `FnAbi` (`callconv`) with a `ptrauth_type_discriminator`
  field. This field is only used when emitting pointer authentication
  call bundles. It is stored in `FnAbi` because the call site is not
  guaranteed to have access to an `Instance`, so the discriminator
  cannot always be computed on demand.
* Adds support for `llvm.ptrauth.resign`. This intrinsic will be used
  when support for semantic transmute is added.
* Performs a minor API redesign as groundwork for allowing call sites to
  modify schemas in place.
Also remove error messages/tests that used to guarded it.
The codegen now walks the layout of static initializer types to find extern "C"
function pointer fields, computes their type discriminators, and applies those
discriminators when emitting authenticated function pointer relocations.

Also make sure that type discrimination is never applied to init/fini
entries.
This covers standalone function pointer constants, promoted temporaries,
immutable and mutable statics, arrays of function pointers, and mixed
structs containing function pointers. Consult
pauth-fn-ptr-type-discrimination-static-allocs.rs test for example uses.

Revolves around threading PAC information through:
* static_addr_of (StaticCodegenMethods)
* from_const and from_const_alloc (both on rustc_codegen_ssa::mir::operand / OperandRef)
Implement pointer authentication resigning for function pointer
transmutes that differ in their discriminators. Resigning only happens
for function pointers (their transparent wrappers and Option<T>).
Aggregates (even those containing function pointer members) are deliberately
kept as opaque values with no resigning.
…addr` call sites

Fill in function pointer type discriminators logic across remaining
`get_fn_addr` call sites and explicitly avoid applying it where
discrimination is not meaningful.

Some uses of `get_fn_addr` are intentionally left unsigned, including
the EH personality function, entry wrappers, and compiler-generated Rust
ABI shims.
And update to the main pauthtest document:
* list new tests
* remove the need for patching `libc` as the changes to it already went
  in. Unfortunately `cc-rs` is held back by
  `compiler/rustc_llvm/Cargo.toml` which pins to an old version:
  `cc = "=1.2.16"`
@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 1, 2026
@rust-log-analyzer

This comment has been minimized.

@jchlanda
jchlanda force-pushed the jakub/pac_transmute_copy branch from 3b55b24 to 36f5b8e Compare September 1, 2026 14:23
@rust-log-analyzer

This comment has been minimized.

Lower the intrinsic to a dedicated `TransmuteCopy` cast and, when available,
insert the library precondition check requiring the source to contain at least
`size_of::<Dst>()` bytes.

Handle `TransmuteCopy` as a direct read of `Dst` from the source address,
allowing shrinking transmutes and unsized sources. Use the source's known
alignment together with the destination alignment to avoid emitting loads with
stronger alignment requirements than the source can guarantee.

Statically provable size violations are treated as unreachable during codegen,
while dynamically-sized sources retain the runtime precondition check. For
slices and `str`, known length metadata is used to prove that the source is
too short; for `dyn Trait` no such support is provided (to avoid reading
v-tables).

Intrinsic-based implementation makes it possible for the codegen to provide
support for function pointer type discrimination, in particular the need to
resign function pointers when a transmute changes their discriminator.
@jchlanda
jchlanda force-pushed the jakub/pac_transmute_copy branch from 36f5b8e to 5df4c89 Compare September 1, 2026 14:36
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[RUSTC-TIMING] syn test:false 4.831
   Compiling zerofrom-derive v0.1.6
[RUSTC-TIMING] gimli test:false 1.800
   Compiling yoke-derive v0.8.2
error[E0004]: non-exhaustive patterns: `&rustc_middle::mir::Rvalue::Cast(rustc_middle::mir::CastKind::TransmuteCopy, _, _)` not covered
    --> src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs:138:11
     |
 138 |     match rvalue {
     |           ^^^^^^ pattern `&rustc_middle::mir::Rvalue::Cast(rustc_middle::mir::CastKind::TransmuteCopy, _, _)` not covered
     |
note: `rustc_middle::mir::Rvalue<'_>` defined here
    --> compiler/rustc_middle/src/mir/syntax.rs:1362:1
     |
1362 | pub enum Rvalue<'tcx> {
     | ^^^^^^^^^^^^^^^^^^^^^
...
1407 |     Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
     |     ---- not covered
     = note: the matched value is of type `&rustc_middle::mir::Rvalue<'_>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
     |
 226 ~         },
 227 ~         &rustc_middle::mir::Rvalue::Cast(rustc_middle::mir::CastKind::TransmuteCopy, _, _) => todo!(),
     |

For more information about this error, try `rustc --explain E0004`.
[RUSTC-TIMING] clippy_utils test:false 1.861
error: could not compile `clippy_utils` (lib) due to 1 previous error

/// [core::mem::transmute_copy]. It is intended for use by the standard
/// library and compiler and should not be called directly.
#[stable(feature = "transmute_copy", since = "1.0.0")]
#[rustc_allowed_through_unstable_modules = "import this function via std::mem instead"]

@mejrs mejrs Sep 1, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
#[rustc_allowed_through_unstable_modules = "import this function via std::mem instead"]

Please do not add more uses of this attribute. We are trying very hard to get rid of it entirely.

View changes since the review

@rustbot

rustbot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs A-test-infra-minicore Area: `minicore` test auxiliary and `//@ add-core-stubs` S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants