Skip to content
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

Add an intrinsic for ptr::metadata #124251

Merged
merged 4 commits into from
May 29, 2024
Merged

Conversation

scottmcm
Copy link
Member

@scottmcm scottmcm commented Apr 22, 2024

The follow-up to #123840, so we can remove PtrComponents and PtrRepr from libcore entirely (well, after a bootstrap update).

As discussed in https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/.60ptr_metadata.60.20in.20MIR/near/435637808, this introduces UnOp::PtrMetadata taking a raw pointer and returning the associated metadata value.

By no longer going through a union, this should also help future PRs better optimize pointer operations.

r? @oli-obk

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. 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 Apr 22, 2024
@rustbot
Copy link
Collaborator

rustbot commented Apr 22, 2024

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the CTFE / Miri engine

cc @rust-lang/miri

This PR changes MIR

cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

This PR changes Stable MIR

cc @oli-obk, @celinval, @ouz-a

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Comment on lines +31 to +34
// CHECK: %[[Q:.+]] = getelementptr inbounds i8, ptr %p.0, i64 %n
// CHECK: %[[TEMP1:.+]] = insertvalue { ptr, ptr } poison, ptr %[[Q]], 0
// CHECK: %[[TEMP2:.+]] = insertvalue { ptr, ptr } %[[TEMP1]], ptr %p.1, 1
// CHECK: ret { ptr, ptr } %[[TEMP2]]
Copy link
Member Author

@scottmcm scottmcm Apr 22, 2024

Choose a reason for hiding this comment

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

This is a -C no-prepopulate-passes test, so this is actually what we output directly, no optimization needed.

Compare to what you get on nightly 2024-04-20 https://rust.godbolt.org/z/6zP58xoT4

define { ptr, ptr } @dyn_byte_offset(ptr noundef %p.0, ptr noalias noundef readonly align 8 dereferenceable(24) %p.1, i64 noundef %n) unnamed_addr #0 {
  %_9 = alloca %"core::ptr::metadata::PtrComponents<dyn core::fmt::Debug>", align 8
  %_8 = alloca %"core::ptr::metadata::PtrRepr<dyn core::fmt::Debug>", align 8
  %_7 = alloca %"core::ptr::metadata::PtrRepr<dyn core::fmt::Debug>", align 8
  %_3 = getelementptr inbounds i8, ptr %p.0, i64 %n
  call void @llvm.lifetime.start.p0(i64 16, ptr %_7)
  store ptr %p.0, ptr %_7, align 8
  %0 = getelementptr inbounds i8, ptr %_7, i64 8
  store ptr %p.1, ptr %0, align 8
  %1 = getelementptr inbounds i8, ptr %_7, i64 8
  %_6 = load ptr, ptr %1, align 8, !nonnull !3, !align !4, !noundef !3
  call void @llvm.lifetime.end.p0(i64 16, ptr %_7)
  call void @llvm.lifetime.start.p0(i64 16, ptr %_8)
  call void @llvm.lifetime.start.p0(i64 16, ptr %_9)
  store ptr %_3, ptr %_9, align 8
  %2 = getelementptr inbounds i8, ptr %_9, i64 8
  store ptr %_6, ptr %2, align 8
  %3 = load ptr, ptr %_9, align 8, !noundef !3
  %4 = getelementptr inbounds i8, ptr %_9, i64 8
  %5 = load ptr, ptr %4, align 8, !nonnull !3, !align !4, !noundef !3
  store ptr %3, ptr %_8, align 8
  %6 = getelementptr inbounds i8, ptr %_8, i64 8
  store ptr %5, ptr %6, align 8
  call void @llvm.lifetime.end.p0(i64 16, ptr %_9)
  %_0.0 = load ptr, ptr %_8, align 8, !noundef !3
  %7 = getelementptr inbounds i8, ptr %_8, i64 8
  %_0.1 = load ptr, ptr %7, align 8, !nonnull !3, !align !5, !noundef !3
  call void @llvm.lifetime.end.p0(i64 16, ptr %_8)
  %8 = insertvalue { ptr, ptr } poison, ptr %_0.0, 0
  %9 = insertvalue { ptr, ptr } %8, ptr %_0.1, 1
  ret { ptr, ptr } %9
}

@rustbot
Copy link
Collaborator

rustbot commented Apr 22, 2024

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

ImmTy::uninit(cast_to)
}
Immediate::ScalarPair(_, meta) => ImmTy::from_scalar(meta, cast_to),
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
Copy link
Contributor

Choose a reason for hiding this comment

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

Unsure whether we want to raise UB here. We don't raise UB for offsetting an immediate to get a sub-immeidate

Copy link
Contributor

Choose a reason for hiding this comment

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

either way, needs const-eval and miri tests

Copy link
Member

Choose a reason for hiding this comment

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

We generally raise UB for by-val operations on uninit immediates. This is a cast, not a projection, so I'd say it's a by-val operation and as such should be UB when the input is uninit.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, what about for reading the metadata of an uninit thin pointer? Should that be UB because of an uninit pointer, or defined because the metadata of a thin pointer is trivially () without even looking at the input?

This would affect whether removing the unit StatementKind::Assign could hide UB...

Copy link
Member

Choose a reason for hiding this comment

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

An uninit thin pointer violates the thin pointer validity invariant. I don't think we have any case here that we want to allow -- all our pointers are noundef on both the data and metadata component.

/// Convert a raw pointer to an `impl Pointee<Metadata = M>` into `M`.
///
/// For example, this will give a `()` from `*const i32`, a `usize` from
/// `*mut [u8]`, or a vtable from a `*const dyn Foo`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// `*mut [u8]`, or a vtable from a `*const dyn Foo`.
/// `*mut [u8]`, or a pointer to a vtable from a `*const dyn Foo`.

@the8472
Copy link
Member

the8472 commented Apr 22, 2024

Wouldn't adding support for the metadata to offset_of! be a more general solution? It'd allow both read and write and also let users build their own transmutable PtrComponents as long as they check the offsets.

@saethlin
Copy link
Member

I'm not sure how that would fix the size of the MIR.

@the8472
Copy link
Member

the8472 commented Apr 22, 2024

Oh I thought it was just about removing layout assumptions from the library.

/// Convert a raw pointer to an `impl Pointee<Metadata = M>` into `M`.
///
/// For example, this will give a `()` from `*const i32`, a `usize` from
/// `*mut [u8]`, or a vtable from a `*const dyn Foo`.
Copy link
Member

Choose a reason for hiding this comment

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

What will the type of the vtable be?

@@ -64,6 +64,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_immediate(*res, dest)?;
}

CastKind::PtrToMetadata => {
Copy link
Member

Choose a reason for hiding this comment

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

Is this covered by Miri tests? Not sure how well we are covering the ptr::metadata API surface.

@scottmcm scottmcm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 23, 2024
@bors

This comment was marked as resolved.

Comment on lines 703 to 713
Rvalue::Cast(CastKind::PtrToMetadata, ref operand, _to_ty) => {
let operand = codegen_operand(fx, operand);
let meta = match operand.layout().abi {
Abi::Scalar(_) => CValue::zst(dest_layout),
Abi::ScalarPair(_, _) => {
CValue::by_val(operand.load_scalar_pair(fx).1, dest_layout)
}
_ => bug!("Unexpected `PtrToMetadata` operand: {operand:?}"),
};
lval.write_cvalue(fx, meta);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

@bjorn3 Since I broke stuff in my last PR, please take a look at this one and let me know whether this is the right approach for getting metadata in cg_clif.

Copy link
Member

Choose a reason for hiding this comment

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

This looks correct to me.

@scottmcm scottmcm marked this pull request as draft April 30, 2024 07:36
@bors
Copy link
Contributor

bors commented May 2, 2024

☔ The latest upstream changes (presumably #124521) made this pull request unmergeable. Please resolve the merge conflicts.

@oli-obk
Copy link
Contributor

oli-obk commented May 28, 2024

@bors r+

@bors
Copy link
Contributor

bors commented May 28, 2024

📌 Commit 713ddc2 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 28, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request May 28, 2024
Add an intrinsic for `ptr::metadata`

The follow-up to rust-lang#123840, so we can remove `PtrComponents` and `PtrRepr` from libcore entirely (well, after a bootstrap update).

As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/.60ptr_metadata.60.20in.20MIR/near/435637808>, this introduces `UnOp::PtrMetadata` taking a raw pointer and returning the associated metadata value.

By no longer going through a `union`, this should also help future PRs better optimize pointer operations.

r? `@oli-obk`
bors added a commit to rust-lang-ci/rust that referenced this pull request May 28, 2024
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#117671 (NVPTX: Avoid PassMode::Direct for args in C abi)
 - rust-lang#124251 (Add an intrinsic for `ptr::metadata`)
 - rust-lang#125573 (Migrate `run-make/allow-warnings-cmdline-stability` to `rmake.rs`)
 - rust-lang#125590 (Add a "Setup Python" action for github-hosted runners and remove unnecessary `CUSTOM_MINGW` environment variable)
 - rust-lang#125598 (Make `ProofTreeBuilder` actually generic over `Interner`)
 - rust-lang#125637 (rustfmt fixes)

r? `@ghost`
`@rustbot` modify labels: rollup
@matthiaskrgr
Copy link
Member

@bors r-
#125663 (comment)

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 28, 2024
@scottmcm
Copy link
Member Author

scottmcm commented May 28, 2024

Oh, ./x fmt doesn't fix cg_cranelift. Fixed. (I'll wait for ci before r=ing.)

@scottmcm
Copy link
Member Author

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented May 28, 2024

📌 Commit 57948c8 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 28, 2024
jieyouxu added a commit to jieyouxu/rust that referenced this pull request May 28, 2024
Add an intrinsic for `ptr::metadata`

The follow-up to rust-lang#123840, so we can remove `PtrComponents` and `PtrRepr` from libcore entirely (well, after a bootstrap update).

As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/.60ptr_metadata.60.20in.20MIR/near/435637808>, this introduces `UnOp::PtrMetadata` taking a raw pointer and returning the associated metadata value.

By no longer going through a `union`, this should also help future PRs better optimize pointer operations.

r? `@oli-obk`
bors added a commit to rust-lang-ci/rust that referenced this pull request May 29, 2024
Rollup of 8 pull requests

Successful merges:

 - rust-lang#124251 (Add an intrinsic for `ptr::metadata`)
 - rust-lang#124320 (Add `--print=check-cfg` to get the expected configs)
 - rust-lang#125226 (Make more of the test suite run on Mac Catalyst)
 - rust-lang#125381 (Silence some resolve errors when there have been glob import errors)
 - rust-lang#125633 (miri: avoid making a full copy of all new allocations)
 - rust-lang#125638 (Rewrite `lto-smoke`, `simple-rlib` and `mixing-deps` `run-make` tests in `rmake.rs` format)
 - rust-lang#125639 (Support `./x doc run-make-support --open`)
 - rust-lang#125664 (Tweak relations to no longer rely on `TypeTrace`)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request May 29, 2024
Rollup of 8 pull requests

Successful merges:

 - rust-lang#124251 (Add an intrinsic for `ptr::metadata`)
 - rust-lang#124320 (Add `--print=check-cfg` to get the expected configs)
 - rust-lang#125226 (Make more of the test suite run on Mac Catalyst)
 - rust-lang#125381 (Silence some resolve errors when there have been glob import errors)
 - rust-lang#125633 (miri: avoid making a full copy of all new allocations)
 - rust-lang#125638 (Rewrite `lto-smoke`, `simple-rlib` and `mixing-deps` `run-make` tests in `rmake.rs` format)
 - rust-lang#125639 (Support `./x doc run-make-support --open`)
 - rust-lang#125664 (Tweak relations to no longer rely on `TypeTrace`)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 2d3b1e0 into rust-lang:master May 29, 2024
6 checks passed
@rustbot rustbot added this to the 1.80.0 milestone May 29, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request May 29, 2024
Rollup merge of rust-lang#124251 - scottmcm:unop-ptr-metadata, r=oli-obk

Add an intrinsic for `ptr::metadata`

The follow-up to rust-lang#123840, so we can remove `PtrComponents` and `PtrRepr` from libcore entirely (well, after a bootstrap update).

As discussed in <https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/.60ptr_metadata.60.20in.20MIR/near/435637808>, this introduces `UnOp::PtrMetadata` taking a raw pointer and returning the associated metadata value.

By no longer going through a `union`, this should also help future PRs better optimize pointer operations.

r? ``@oli-obk``
@scottmcm scottmcm deleted the unop-ptr-metadata branch May 29, 2024 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

None yet