-
Notifications
You must be signed in to change notification settings - Fork 13.4k
rustdoc-json: Output target feature information #139393
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc | |
/// This integer is incremented with every breaking change to the API, | ||
/// and is returned along with the JSON blob as [`Crate::format_version`]. | ||
/// Consuming code should assert that this value matches the format version(s) that it supports. | ||
pub const FORMAT_VERSION: u32 = 43; | ||
pub const FORMAT_VERSION: u32 = 44; | ||
|
||
/// The root of the emitted JSON blob. | ||
/// | ||
|
@@ -52,11 +52,67 @@ pub struct Crate { | |
pub paths: HashMap<Id, ItemSummary>, | ||
/// Maps `crate_id` of items to a crate name and html_root_url if it exists. | ||
pub external_crates: HashMap<u32, ExternalCrate>, | ||
/// Information about the target for which this documentation was generated | ||
pub target: Target, | ||
/// A single version number to be used in the future when making backwards incompatible changes | ||
/// to the JSON output. | ||
pub format_version: u32, | ||
} | ||
|
||
/// Information about a target | ||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] | ||
pub struct Target { | ||
/// The target triple for which this documentation was generated | ||
pub triple: String, | ||
/// A list of features valid for use in `#[target_feature]` attributes | ||
/// for the target where this rustdoc JSON was generated. | ||
pub target_features: Vec<TargetFeature>, | ||
} | ||
|
||
/// Information about a target feature. | ||
/// | ||
/// Rust target features are used to influence code generation, especially around selecting | ||
/// instructions which are not universally supported by the target architecture. | ||
/// | ||
/// Target features are commonly enabled by the [`#[target_feature]` attribute][1] to influence code | ||
/// generation for a particular function, and less commonly enabled by compiler options like | ||
/// `-Ctarget-feature` or `-Ctarget-cpu`. Targets themselves automatically enable certain target | ||
/// features by default, for example because the target's ABI specification requires saving specific | ||
/// registers which only exist in an architectural extension. | ||
/// | ||
/// Target features can imply other target features: for example, x86-64 `avx2` implies `avx`, and | ||
/// aarch64 `sve2` implies `sve`, since both of these architectural extensions depend on their | ||
/// predecessors. | ||
/// | ||
/// Target features can be probed at compile time by [`#[cfg(target_feature)]`][2] or `cfg!(…)` | ||
/// conditional compilation to determine whether a target feature is enabled in a particular | ||
/// context. | ||
/// | ||
/// [1]: https://doc.rust-lang.org/stable/reference/attributes/codegen.html#the-target_feature-attribute | ||
/// [2]: https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature | ||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] | ||
pub struct TargetFeature { | ||
/// The name of this target feature. | ||
pub name: String, | ||
/// Other target features which are implied by this target feature, if any. | ||
pub implies_features: Vec<String>, | ||
Comment on lines
+97
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume:
If all this is true, perhaps we should note it in the doc comment. If not, we should definitely note that it isn't true :) The first two items can be made obvious by making this set instead of a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This all should be true, but it's not ensured by the underlying data structures. If we're providing these guarantees, I'd be inclined to have Separately, I note that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll defer to rustdoc JSON maintainers on whether From my point of view, it's fine to expose either a If the properties are expected but not able to be guaranteed, I'd also be in favor of documenting them with weaker language. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be a But maybe we should separately think about if we want to only use As for testing the validity of features, that shouldn't live in rustdoc, but in rustc_target (and done in a separate PR). What guarantees they make are up to T-compiler (and maybe T-lang??) and if their broken, it'd be much nicer to get the error from compiler tests than rustdoc tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have strong feelings either way on |
||
/// If this target feature is unstable, the name of the associated language feature gate. | ||
pub unstable_feature_gate: Option<String>, | ||
/// Whether this feature is globally enabled for this compilation session. | ||
/// | ||
/// Target features can be globally enabled implicitly as a result of the target's definition. | ||
/// For example, x86-64 hardware floating point ABIs require saving x87 and SSE2 registers, | ||
/// which in turn requires globally enabling the `x87` and `sse2` target features so that the | ||
/// generated machine code conforms to the target's ABI. | ||
/// | ||
/// Target features can also be globally enabled explicitly as a result of compiler flags like | ||
/// [`-Ctarget-feature`][1] or [`-Ctarget-cpu`][2]. | ||
/// | ||
/// [1]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-feature | ||
/// [2]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-cpu | ||
pub globally_enabled: bool, | ||
Comment on lines
+101
to
+113
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just checking my understanding of the implication here: the set of features with No change needed if that's the case, I just wanted to make sure there's no additional hidden meaning behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 I chose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure either — this is also why I was asking :) I'm not familiar with the specific definition of a "session" either so it might be good to try to work out more precise language, together with the rustdoc JSON maintainers. I'd be perfectly happy with a TODO on that more precise language though — what this PR has is certainly a large improvement over the status quo and would be valuable to have already. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe something along the lines of "in this compilation"/"in this rustdoc invocation". I think saying "session" is precise, but it isn't accessible, as it's not used in a user facing way. (I agree it'd be fine to clear this up later) |
||
} | ||
|
||
/// Metadata of a crate, either the same crate on which `rustdoc` was invoked, or its dependency. | ||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
pub struct ExternalCrate { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-aarch64-apple-darwin | ||
|
||
//@ is "$.target.triple" \"aarch64-apple-darwin\" | ||
//@ is "$.target.target_features[?(@.name=='vh')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]' | ||
//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"' | ||
//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"' | ||
|
||
// Ensure we don't look like x86-64 | ||
//@ !has "$.target.target_features[?(@.name=='avx2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
//@ only-aarch64 | ||
|
||
// If we enable SVE Bit Permute, we should see that it is enabled | ||
//@ compile-flags: -Ctarget-feature=+sve2-bitperm | ||
//@ is "$.target.target_features[?(@.name=='sve2-bitperm')].globally_enabled" true | ||
|
||
// As well as its dependency chain | ||
//@ is "$.target.target_features[?(@.name=='sve2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-aarch64-unknown-linux-gnu | ||
|
||
//@ is "$.target.triple" \"aarch64-unknown-linux-gnu\" | ||
//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]' | ||
//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"' | ||
//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"' | ||
|
||
// Ensure we don't look like x86-64 | ||
//@ !has "$.target.target_features[?(@.name=='avx2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-i686-pc-windows-msvc | ||
|
||
//@ is "$.target.triple" \"i686-pc-windows-msvc\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-i686-unknown-linux-gnu | ||
|
||
//@ is "$.target.triple" \"i686-unknown-linux-gnu\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-x86_64-apple-darwin | ||
|
||
//@ is "$.target.triple" \"x86_64-apple-darwin\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-x86_64-pc-windows-gnu | ||
|
||
//@ is "$.target.triple" \"x86_64-pc-windows-gnu\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-x86_64-pc-windows-msvc | ||
|
||
//@ is "$.target.triple" \"x86_64-pc-windows-msvc\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
//@ only-x86_64 | ||
|
||
// If we enable AVX2, we should see that it is enabled | ||
//@ compile-flags: -Ctarget-feature=+avx2 | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" true | ||
|
||
// As well as its dependency chain | ||
//@ is "$.target.target_features[?(@.name=='avx')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='sse4.2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='sse4.1')].globally_enabled" true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
//@ only-x86_64-unknown-linux-gnu | ||
|
||
//@ is "$.target.triple" \"x86_64-unknown-linux-gnu\" | ||
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true | ||
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false | ||
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' | ||
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null | ||
|
||
// If this breaks due to stabilization, check rustc_target::target_features for a replacement | ||
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' | ||
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' | ||
|
||
// Ensure we don't look like aarch64 | ||
//@ !has "$.target.target_features[?(@.name=='sve2')]" |
Uh oh!
There was an error while loading. Please reload this page.