close
Skip to content

Emit nofree attribute#156281

Open
nikic wants to merge 2 commits into
rust-lang:mainfrom
nikic:nofree
Open

Emit nofree attribute#156281
nikic wants to merge 2 commits into
rust-lang:mainfrom
nikic:nofree

Conversation

@nikic
Copy link
Copy Markdown
Contributor

@nikic nikic commented May 7, 2026

Treat the semantics of pointee.size as "dereferenceable-at-point" and always specify the size. Instead, use a separate NoFree attribute to determine whether dereferenceability extends to the whole function.

Then in the LLVM backend, only actually emit dereferenceable if nofree is also set, as dereferenceable currently implies nofree.

In addition, explicitly emit the nofree attribute, which will help when LLVM switches dereferenceable to be at-point.

Relevant recent LLVM PR: llvm/llvm-project#195658

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. 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. labels May 7, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 7, 2026

r? @jdonszelmann

rustbot has assigned @jdonszelmann.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 73 candidates
  • Random selection from 18 candidates

@rust-log-analyzer

This comment has been minimized.

Treat the semantics of pointee.size as "dereferenceable-at-point"
and always specify the size. Instead, use a separate NoFree attribute
to determine whether dereferenceability extends to the whole function.

Then in the LLVM backend, only actually emit dereferenceable if
nofree is also set, as dereferenceable currently implies nofree.

In addition, explicitly emit the nofree attribute, which will help
when LLVM switches dereferenceable to be at-point.
@nikic
Copy link
Copy Markdown
Contributor Author

nikic commented May 27, 2026

r? @RalfJung

@rustbot rustbot assigned RalfJung and unassigned jdonszelmann May 27, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 27, 2026

RalfJung is not on the review rotation at the moment.
They may take a while to respond.

Comment thread compiler/rustc_target/src/callconv/mod.rs
Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

Generally 👍 but I have two questions.
@rustbot author

View changes since this review

if deref != 0 {
// dereferenceable in LLVM currently implies nofree, so only emit dereferenceable if nofree
// is also set.
if deref != 0 && regular.contains(ArgAttribute::NoFree) {
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.

We also don't want LLVM dereferenceable on return values (see the comment in compiler/rustc_ty_utils/src/abi.rs that you removed). Where is that handled now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's handled here: https://github.com/rust-lang/rust/pull/156281/changes#diff-eb5b0fc5c9734679907fdb908c3a6b424ff723c4dceb364eef2588c996366708R404 That is, we never set NoFree on return values (and thus also not dereferenceable).

Copy link
Copy Markdown
Member

@RalfJung RalfJung May 30, 2026

Choose a reason for hiding this comment

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

That's a subtle non-local invariant and you removed the comment that explains it. Please add that comment back.

// <https://github.com/rust-lang/miri/issues/3341> for why.) The second argument is the allocator,
// which is a reference here that still carries `noalias` as usual.
// CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias noundef nonnull readonly{{( captures\(address, read_provenance\))?}} %x.1)
// CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias nofree noundef nonnull readonly{{( captures\(address, read_provenance\))?}} %x.1)
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.

Is this a nofree without a dereferenceable? I guess this is the &Global field and the pointee size is 0. The comment currently says that's not a valid combination. Given that we allow ZST references to even have dangling provenance, I don't think marking them nofree makes sense.

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 30, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 30, 2026

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

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label May 30, 2026
const NoUndef = 1 << 7;
const Writable = 1 << 8;
/// It is UB for the allocation that this pointer points to to be freed
/// while the function is executing. Only valid if pointee_size > 0.
Copy link
Copy Markdown
Member

@RalfJung RalfJung May 30, 2026

Choose a reason for hiding this comment

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

Suggested change
/// while the function is executing. Only valid if pointee_size > 0.
/// while the function is executing. Only valid if pointee_size > 0,
/// and only valid on arguments (not return types).

View changes since the review

const NoUndef = 1 << 7;
const Writable = 1 << 8;
/// It is UB for the allocation that this pointer points to to be freed
/// while the function is executing. Only valid if pointee_size > 0.
Copy link
Copy Markdown
Member

@RalfJung RalfJung May 30, 2026

Choose a reason for hiding this comment

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

Is there some good place to assert! that NoFree implies "not a return type" and "pointee_size > 0"? I guess that should be in compiler/rustc_codegen_llvm/src/abi.rs where we consume such values.

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. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants