Skip to content

Conversation

@kulst
Copy link
Contributor

@kulst kulst commented Jan 6, 2026

Crates built for AVR, AMDGCN and NVPTX that specify different values for -Ctarget-cpu cannot be soundly linked together. Therefore need_explicit_cpu was already set in their target specifications (NVPTX has the same issue, but conversely this flag was never set for it).

This PR attempts to make rustc ensure that no crates with disagreeing values for -Ctarget-cpu are linked together by it. This is achieved by converting -Ctarget-cpu into a target-modifier. The agreement is only enforced for the mentioned targets based on the value in need_explicit_cpu To express this additional requirement, the flag is renamed into requires_explicit_and_consistent_cpu.

Why should -Ctarget-cpu be a target-modifier for nvptx?

PTX is a single-module contract

PTX requires a binary to start with .version (`ptx$$`) then .target (`sm_$$`). If the ptx contains instructions that are not supported by either .version or .target, the binary is ill-formed and will be rejected by ptxas. The concept of features that can be mixed and matched in a binary does not exist for nvptx and is therefore not supported by LLVM.

It prevents the production of bitcode that cannot be codegen'd after linking

A target modifier should prevent configurations that are not composable across crates when those crates are linked together. The most prominent example is when enabling a target feature changes the ABI, making cross-crate calls inherently unsound.

In the case of nvptx, ABI mismatch is (at least for now) not the core problem motivating target modifiers. NVIDIA’s documented PTX calling convention has remained stable since ptx20.

However, in the current state it is possible to produce bitcode that cannot be codegen'd after linking, because some operations are only lowerable for sufficiently new SM/PTX levels. In the best case this results in an LLVM error during the final llc step, but this is not something we should rely on for correctness.

nvptx has a special compilation pipeline where instead of linking the final PTX object, instead LLVM bitcode is linked. The resulting artifact is then compiled in one invocation.
Now consider crate A which is independently compiled into bitcode with the following rustc arguments:

//@ compile-flags: --target nvptx64-nvidia-cuda -C target-cpu=sm_70 --crate-type=rlib
#[cfg(target_feature = "sm_70")]
fn foo() { 
    // cannot be lowered to ptx before "sm_70: so currently produces an LLVM error
}
#[cfg(not(target_feature = "sm_70"))]
fn foo() {
    // can be lowered to ptx before "sm_70"
}
pub fn bar() {
    foo()
}

Crate A is a dependency of crate B. In the rustc invocation of crate B

  1. crate B is compiled into bitcode, too
  2. both bitcode artifacts are bitcode-linked by llvm-link
  3. the resulting bitcode artifact is compiled by llc -mcpu=sm_60

This should now ideally create an LLVM error, because the linked bitcode contains code paths that were selected under sm_70 assumptions but the final NVPTX codegen is targeting sm_60, where those operations are not lowerable. An LLVM error here is better than silent miscompilation, but it’s not a promise we should rely on.

A real example where this could happen is the lowering of atomic loads and stores with non-relaxed orderings, which is known to depend on the selected SM level.

Why should -Ctarget-cpu be a target-modifier for amdgcn and avr?

  • In case of AVR the target-cpu defines the ISA, which is encoded in the ELF header flags, amdgcn also encodes the cpu directly into those flags
  • To not rely on lld which currently prevents it for both by looking at those flags AVR and amdgcn

Previous discussions about the topic can be found here and here.

I also created a Zulip discussion.

I am unsure if a MCP is needed before proceeding. If you think so please let me know.

Creating target-modifiers for NVPTX target-features is to be done in a follow-up.

cc @kjetilkjeka as target maintainer for NVPTX
cc @Flakebi as target maintainer for amdgcn
cc @Patryk27 as target maintainer for AVR
cc @RalfJung you were very involved in the discussions so far

Target modifier tracking issue: #136966

@rustbot rustbot added 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. labels Jan 6, 2026
@kulst kulst changed the title Making -Ctarget-cpu a target-modifier on NVPTX Make -Ctarget-cpu a target-modifier on NVPTX Jan 6, 2026
@kulst
Copy link
Contributor Author

kulst commented Jan 6, 2026

@rustbot label: +O-NVPTX

@rustbot rustbot added the O-NVPTX Target: the NVPTX LLVM backend for running rust on GPUs, https://llvm.org/docs/NVPTXUsage.html label Jan 6, 2026
@kulst kulst changed the title Make -Ctarget-cpu a target-modifier on NVPTX Convert -Ctarget-cpu into a target-modifier on NVPTX Jan 7, 2026
@kulst kulst changed the title Convert -Ctarget-cpu into a target-modifier on NVPTX Convert -Ctarget-cpu into a target-modifier for NVPTX Jan 7, 2026
@kulst kulst force-pushed the cpu_is_target_modifier branch from 7164067 to a8f5e96 Compare January 7, 2026 21:26
@kulst kulst marked this pull request as ready for review January 7, 2026 21:34
@rustbot
Copy link
Collaborator

rustbot commented Jan 7, 2026

Some changes occurred in src/doc/rustc/src/platform-support

cc @Noratrieb

These commits modify compiler targets.
(See the Target Tier Policy.)

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 7, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jan 7, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 7, 2026

r? @nnethercote

rustbot has assigned @nnethercote.
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

@kulst
Copy link
Contributor Author

kulst commented Jan 7, 2026

r? @bjorn3 as you suggested this change.

@rustbot rustbot assigned bjorn3 and unassigned nnethercote Jan 7, 2026
@kjetilkjeka
Copy link
Contributor

It works out really nice with -CTarget-cpu being able to be a target modifier.

It would be nice to know what the plan was with the ptx isa version as well. I asked that question here

@RalfJung
Copy link
Member

RalfJung commented Jan 8, 2026

I can't vouch for the implementation, but the approach sounds good. :)

Cc @Darksonn

@kulst
Copy link
Contributor Author

kulst commented Jan 10, 2026

I have added some explanation of why -Ctarget-cpu should be a target-modifier for nvptx to the PR. Please let me know if something is missing or if there are other assumptions about the topic.

Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

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

There might already be relevant tests, but I want to see tests that this only makes -Ctarget-cpu into a target modifier in this case, and not for all targets.

View changes since this review

@Darksonn Darksonn added the F-target_modifiers `#![feature(target_modifiers)]` label Jan 10, 2026
Comment on lines 128 to 137
pub(super) fn target_cpu(
sess: &Session,
l: &TargetModifier,
r: Option<&TargetModifier>,
) -> bool {
if sess.target.cpu_is_target_modifier {
if let Some(r) = r {
return l.extend().tech_value == r.extend().tech_value;
} else {
return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if -Ctarget-cpu appears multiple times on the command line? Please add a test.

Copy link
Contributor Author

@kulst kulst Jan 11, 2026

Choose a reason for hiding this comment

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

The value of the last appearance in matches is used. In practice this is probably the value of -Ctarget-cpus last appearance in the command line arguments of the rustc invocation.

Will add a test soon, but I am asking myself what is the intended behavior? I assume we should error if a target-modifier appears more than once, would you agree?

Copy link
Member

Choose a reason for hiding this comment

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

At the very least we have to ensure that whatever values rustc actually uses and what is recorded as target modifier are the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Last argument taking precedence is the desired functionality:
Corresponding MCP

Copy link
Contributor

Choose a reason for hiding this comment

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

Behavior as per MCP is fine. Whichever value ends up being used should be tracked and verified.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is checked now by tests/run-make/target-cpu-is-target-modifier/rmake.rs
Does that match what you had in mind?

@kulst kulst force-pushed the cpu_is_target_modifier branch from a8f5e96 to e5cbf49 Compare January 11, 2026 00:43
@rustbot
Copy link
Collaborator

rustbot commented Jan 11, 2026

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

The reflection data structures are tied exactly to the implementation
in the compiler. Make sure to also adjust `rustc_const_eval/src/const_eval/type_info.rs

cc @oli-obk

triagebot.toml has been modified, there may have been changes to the review queue.

cc @davidtwco, @wesleywiser

Some changes occurred in tests/ui/stack-protector

cc @rust-lang/project-exploit-mitigations, @rcvalle

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

@rustbot rustbot added A-CI Area: Our Github Actions CI A-meta Area: Issues & PRs about the rust-lang/rust repository itself labels Jan 11, 2026
@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs A-testsuite Area: The testsuite used to check the correctness of rustc PG-exploit-mitigations Project group: Exploit mitigations T-clippy Relevant to the Clippy team. T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Jan 11, 2026
@rustbot

This comment has been minimized.

@kulst kulst force-pushed the cpu_is_target_modifier branch from e5cbf49 to 7a07c8d Compare January 11, 2026 00:44
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@kulst kulst force-pushed the cpu_is_target_modifier branch from 7a07c8d to 7333203 Compare January 11, 2026 21:29
@kulst kulst changed the title Convert -Ctarget-cpu into a target-modifier for NVPTX Convert -Ctarget-cpu into a target-modifier for AVR, AMDGCN and NVPTX Jan 11, 2026
@rust-log-analyzer

This comment has been minimized.

@kulst kulst force-pushed the cpu_is_target_modifier branch from 7333203 to c9bc79b Compare January 11, 2026 23:08
@rustbot
Copy link
Collaborator

rustbot commented Jan 11, 2026

The run-make-support library was changed

cc @jieyouxu

@kulst
Copy link
Contributor Author

kulst commented Jan 11, 2026

Thanks for the reviews so far! I have updated the PR and its description. I hope that I was able to address all mentioned concerns:

  • Unified need_explicit_cpu and target_cpu_is_target_modifier into requires_explicit_and_consistent_cpu which is now responsible to ensure both. To not create failing nvptx tests I needed to adjust all of them. I took the opportunity to convert most of them into no_std tests with or without minicore and to reenable some of the disabled tests.
  • Added a run-make test which checks that only amdgcn, avr and nvptx enforce unique values for -Ctarget-cpu and all other targets don't
  • Added a run-make test which checks that the target-modifier value for -Ctarget-cpu is the same as the target-cpu value in LLVM-IR and both are equal to the value of the last -Ctarget-cpu specified on the command line
  • Improved the error messages for target-modifiers
  • removed NVPTX from building in CI which makes no sense for targets that need a explicit cpu

I split the changes into 4 commits which I hope makes them easier to review.

When updating at one point I mistakenly included commits that didn't belong to this PR. So some wrong labels had been added:
@rustbot label -WG-trait-system-refactor -T-clippy +O-AVR +O-amdgcn

@rustbot rustbot added O-amdgcn Target: the Radeon 9001XT and such O-AVR Target: AVR processors (ATtiny, ATmega, etc.) and removed WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) T-clippy Relevant to the Clippy team. labels Jan 11, 2026
@rust-log-analyzer

This comment has been minimized.

kulst and others added 2 commits January 12, 2026 01:18
This commit renames the `need_explicit_cpu` flag in the target
specification into `requires_explicit_and_consistent_cpu`. This flag is now additionally enabled for NVPTX.

Crates built for AVR, AMDGCN and NVPTX that specify different values for `-Ctarget-cpu` cannot soundly be linked together.
Therefore this commit converts `-Ctarget-cpu` into a target-modifier. However, the agreement
about it is only enforced when compiling for targets where `requires_explicit_and_consistent_cpu` is set. This makes `-Ctarget-cpu` effectively a target-modifier only for AVR, AMDGCN and NVPTX.
- Boolean target modifiers are now mentioned without a trailing `=` in the
messages.
- Wording improved for unset target modifiers.
@kulst kulst force-pushed the cpu_is_target_modifier branch from c9bc79b to ba01dc2 Compare January 12, 2026 00:19
@rustbot
Copy link
Collaborator

rustbot commented Jan 12, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

kulst added 2 commits January 12, 2026 02:43
- added `-Ctarget-cpu` flags
- removed `core`-dependency where possible and added `minicore` where
  necessary
- reenabled some tests
@kulst kulst force-pushed the cpu_is_target_modifier branch from ba01dc2 to 5cbc2a1 Compare January 12, 2026 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CI Area: Our Github Actions CI A-meta Area: Issues & PRs about the rust-lang/rust repository itself A-run-make Area: port run-make Makefiles to rmake.rs A-testsuite Area: The testsuite used to check the correctness of rustc F-target_modifiers `#![feature(target_modifiers)]` O-amdgcn Target: the Radeon 9001XT and such O-AVR Target: AVR processors (ATtiny, ATmega, etc.) O-NVPTX Target: the NVPTX LLVM backend for running rust on GPUs, https://llvm.org/docs/NVPTXUsage.html PG-exploit-mitigations Project group: Exploit mitigations 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-infra Relevant to the infrastructure team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants