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

reject unsound toggling of RISCV target features #134337

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3166,7 +3166,7 @@ impl Target {
// Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
check_matches!(
&*self.llvm_abiname,
"lp64" | "lp64f" | "lp64d" | "lp64q" | "lp64e",
workingjubilee marked this conversation as resolved.
Show resolved Hide resolved
"lp64" | "lp64f" | "lp64d" | "lp64e",
"invalid RISC-V ABI name"
);
}
Expand Down
75 changes: 71 additions & 4 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub enum Stability<Toggleability> {
allow_toggle: Toggleability,
},
/// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be
/// set in the basic target definition. It is never set in `cfg(target_feature)`. Used in
/// set in the target spec. It is never set in `cfg(target_feature)`. Used in
/// particular for features that change the floating-point ABI.
Forbidden { reason: &'static str },
}
Expand Down Expand Up @@ -590,9 +590,76 @@ const RISCV_FEATURES: &[(&str, StabilityUncomputed, ImpliedFeatures)] = &[
// tidy-alphabetical-start
("a", STABLE, &["zaamo", "zalrsc"]),
("c", STABLE, &[]),
("d", unstable(sym::riscv_target_feature), &["f"]),
("e", unstable(sym::riscv_target_feature), &[]),
("f", unstable(sym::riscv_target_feature), &[]),
(
"d",
Stability::Unstable {
nightly_feature: sym::riscv_target_feature,
allow_toggle: |target, enable| match &*target.llvm_abiname {
"ilp32d" | "lp64d" if !enable => {
Copy link
Member Author

Choose a reason for hiding this comment

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

Btw do you know why the 32bit ABIs start with "ilp" but the 64bit ABIs start with "lp"?

Copy link
Member

Choose a reason for hiding this comment

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

  • ILP32: Int, Long, and Pointer are 32-bit
  • LP64: Long and Pointer are 64-bit (int is 32-bit)

(see also "Data models" section in https://en.cppreference.com/w/cpp/language/types)

Copy link
Member Author

Choose a reason for hiding this comment

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

So it should really be I32LP64 then...

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but a convention at some point developed that

  • we omit the "c8s16" prefix... types that are the smallest possible value
  • we all quietly pretend the smallest possible value of int is 32 bits and not 16

names deeply fermented in tradition.

// The ABI requires the `d` feature, so it cannot be disabled.
Err("feature is required by ABI")
}
"ilp32e" if enable => {
// ilp32e is incompatible with features that need aligned load/stores > 32 bits,
// like `d`.
Err("feature is incompatible with ABI")
}
_ => Ok(()),
},
},
&["f"],
),
(
"e",
Stability::Unstable {
// Given that this is a negative feature, consider this before stabilizing:
// does it really make sense to enable this feature in an individual
// function with `#[target_feature]`?
nightly_feature: sym::riscv_target_feature,
Comment on lines +615 to +618
Copy link
Member

Choose a reason for hiding this comment

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

not really, but it does allow #[cfg(target_feature = "e")], unfortunately, but that may not be correct if it tries to be dependent on the ABI

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds like we may want to mark this feature as "forbidden", i.e., "must be fixed by target spec and cannot be queried by cfg", and have a separate way to query the ABI.

But anyway it's a nightly-only feature so that can be done in a future PR.

allow_toggle: |target, enable| {
match &*target.llvm_abiname {
_ if !enable => {
// Disabling this feature means we can use more registers (x16-x31).
// The "e" ABIs treat them as caller-save, so it is safe to use them only
// in some parts of a program while the rest doesn't know they even exist.
// On other ABIs, the feature is already disabled anyway.
Ok(())
}
"ilp32e" | "lp64e" => {
// Embedded ABIs should already have the feature anyway, it's fine to enable
// it again from an ABI perspective.
Ok(())
}
_ => {
// *Not* an embedded ABI. Enabling `e` is invalid.
Err("feature is incompatible with ABI")
}
}
},
},
&[],
),
(
"f",
Stability::Unstable {
nightly_feature: sym::riscv_target_feature,
allow_toggle: |target, enable| {
match &*target.llvm_abiname {
"ilp32f" | "ilp32d" | "lp64f" | "lp64d" if !enable => {
// The ABI requires the `f` feature, so it cannot be disabled.
Err("feature is required by ABI")
}
_ => Ok(()),
}
},
},
&[],
),
(
"forced-atomics",
Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" },
&[],
),
("m", STABLE, &[]),
("relax", unstable(sym::riscv_target_feature), &[]),
("unaligned-scalar-mem", unstable(sym::riscv_target_feature), &[]),
Expand Down
Loading