From acd6ba4edbd847cb80ae140298701c13824852e8 Mon Sep 17 00:00:00 2001 From: Edvin Bryntesson Date: Sat, 20 Dec 2025 14:50:13 +0100 Subject: [PATCH 1/4] Port `#[instruction_set]` to attribute parser --- compiler/rustc_attr_parsing/messages.ftl | 2 + .../src/attributes/instruction_set.rs | 73 ++++++++++++ .../rustc_attr_parsing/src/attributes/mod.rs | 1 + compiler/rustc_attr_parsing/src/context.rs | 2 + .../src/session_diagnostics.rs | 10 ++ compiler/rustc_codegen_ssa/messages.ftl | 8 -- .../rustc_codegen_ssa/src/codegen_attrs.rs | 41 +------ compiler/rustc_codegen_ssa/src/errors.rs | 28 ----- .../src/error_codes/E0778.md | 3 +- .../src/error_codes/E0779.md | 3 +- .../rustc_hir/src/attrs/data_structures.rs | 15 ++- .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 + tests/ui/attributes/instruction-set.rs | 111 ++++++++++++++++++ tests/ui/attributes/instruction-set.stderr | 31 +++++ .../invalid-instruction-set-target.rs | 6 + .../invalid-instruction-set-target.stderr | 8 ++ tests/ui/attributes/malformed-attrs.stderr | 19 +-- tests/ui/error-codes/E0778.rs | 4 - tests/ui/error-codes/E0778.stderr | 9 -- tests/ui/error-codes/E0779.rs | 2 - tests/ui/error-codes/E0779.stderr | 9 -- 23 files changed, 281 insertions(+), 109 deletions(-) create mode 100644 compiler/rustc_attr_parsing/src/attributes/instruction_set.rs create mode 100644 tests/ui/attributes/instruction-set.rs create mode 100644 tests/ui/attributes/instruction-set.stderr create mode 100644 tests/ui/attributes/invalid-instruction-set-target.rs create mode 100644 tests/ui/attributes/invalid-instruction-set-target.stderr delete mode 100644 tests/ui/error-codes/E0778.rs delete mode 100644 tests/ui/error-codes/E0778.stderr delete mode 100644 tests/ui/error-codes/E0779.rs delete mode 100644 tests/ui/error-codes/E0779.stderr diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 5caa98b053576..36213e68a52be 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -229,6 +229,8 @@ attr_parsing_unstable_cfg_target_compact = attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable .help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]` +attr_parsing_unsupported_instruction_set = target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]` + attr_parsing_unsupported_literal_suggestion = consider removing the prefix diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs new file mode 100644 index 0000000000000..3be9b9ded9c1f --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs @@ -0,0 +1,73 @@ +use rustc_hir::attrs::InstructionSetAttr; + +use super::prelude::*; +use crate::session_diagnostics; + +pub(crate) struct InstructionSetParser; + +impl SingleAttributeParser for InstructionSetParser { + const PATH: &[Symbol] = &[sym::instruction_set]; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: true })), + ]); + const TEMPLATE: AttributeTemplate = template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"); + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32]; + const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32]; + let Some(maybe_meta_item) = args.list().and_then(MetaItemListParser::single) else { + cx.expected_specific_argument(cx.attr_span, POSSIBLE_SYMBOLS); + return None; + }; + + let Some(meta_item) = maybe_meta_item.meta_item() else { + cx.expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS); + return None; + }; + + let mut segments = meta_item.path().segments(); + + let Some(architecture) = segments.next() else { + cx.expected_specific_argument(meta_item.span(), POSSIBLE_SYMBOLS); + return None; + }; + + let Some(instruction_set) = segments.next() else { + cx.expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS); + return None; + }; + + let instruction_set = match architecture.name { + sym::arm => { + if !cx.sess.target.has_thumb_interworking { + cx.dcx().emit_err(session_diagnostics::UnsupportedInstructionSet { + span: cx.attr_span, + instruction_set: sym::arm, + current_target: &cx.sess.opts.target_triple, + }); + return None; + } + match instruction_set.name { + sym::a32 => InstructionSetAttr::ArmA32, + sym::t32 => InstructionSetAttr::ArmT32, + _ => { + cx.expected_specific_argument(instruction_set.span, POSSIBLE_ARM_SYMBOLS); + return None; + } + } + } + _ => { + cx.expected_specific_argument(architecture.span, POSSIBLE_SYMBOLS); + return None; + } + }; + + Some(AttributeKind::InstructionSet(instruction_set)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index c39c60ea7e391..fafac7ea909da 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -42,6 +42,7 @@ pub(crate) mod deprecation; pub(crate) mod doc; pub(crate) mod dummy; pub(crate) mod inline; +pub(crate) mod instruction_set; pub(crate) mod link_attrs; pub(crate) mod lint_helpers; pub(crate) mod loop_match; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9a443dfbb842a..57962f0ce8b1a 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -37,6 +37,7 @@ use crate::attributes::deprecation::DeprecationParser; use crate::attributes::doc::DocParser; use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; +use crate::attributes::instruction_set::InstructionSetParser; use crate::attributes::link_attrs::{ ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser, @@ -197,6 +198,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index d9998a15f233d..5b6aaf1d4f045 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -9,6 +9,7 @@ use rustc_feature::AttributeTemplate; use rustc_hir::AttrPath; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; +use rustc_target::spec::TargetTuple; use crate::fluent_generated as fluent; @@ -930,3 +931,12 @@ pub(crate) struct DocAliasMalformed { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(attr_parsing_unsupported_instruction_set)] +pub(crate) struct UnsupportedInstructionSet<'a> { + #[primary_span] + pub span: Span, + pub instruction_set: Symbol, + pub current_target: &'a TargetTuple, +} diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index ff78bea5b67c5..1d87dc5da8d2d 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -8,8 +8,6 @@ codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} -codegen_ssa_bare_instruction_set = `#[instruction_set]` requires an argument - codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty codegen_ssa_cgu_not_recorded = @@ -90,8 +88,6 @@ codegen_ssa_incorrect_cgu_reuse_type = codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient. -codegen_ssa_invalid_instruction_set = invalid instruction set specified - codegen_ssa_invalid_literal_value = invalid literal value .label = value must be an integer between `0` and `255` @@ -215,8 +211,6 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions -codegen_ssa_multiple_instruction_set = cannot specify more than one instruction set - codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times .help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point @@ -383,8 +377,6 @@ codegen_ssa_unstable_ctarget_feature = unstable feature specified for `-Ctarget-feature`: `{$feature}` .note = this feature is not stably supported; its behavior can change in the future -codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]` - codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 8135fd43dd93f..6056b1582e427 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -3,9 +3,7 @@ use std::str::FromStr; use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; -use rustc_hir::attrs::{ - AttributeKind, InlineAttr, InstructionSetAttr, Linkage, RtsanSetting, UsedBy, -}; +use rustc_hir::attrs::{AttributeKind, InlineAttr, Linkage, RtsanSetting, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; @@ -47,37 +45,6 @@ fn try_fn_sig<'tcx>( } } -// FIXME(jdonszelmann): remove when instruction_set becomes a parsed attr -fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option { - let list = attr.meta_item_list()?; - - match &list[..] { - [MetaItemInner::MetaItem(set)] => { - let segments = set.path.segments.iter().map(|x| x.ident.name).collect::>(); - match segments.as_slice() { - [sym::arm, sym::a32 | sym::t32] if !tcx.sess.target.has_thumb_interworking => { - tcx.dcx().emit_err(errors::UnsupportedInstructionSet { span: attr.span() }); - None - } - [sym::arm, sym::a32] => Some(InstructionSetAttr::ArmA32), - [sym::arm, sym::t32] => Some(InstructionSetAttr::ArmT32), - _ => { - tcx.dcx().emit_err(errors::InvalidInstructionSet { span: attr.span() }); - None - } - } - } - [] => { - tcx.dcx().emit_err(errors::BareInstructionSet { span: attr.span() }); - None - } - _ => { - tcx.dcx().emit_err(errors::MultipleInstructionSet { span: attr.span() }); - None - } - } -} - // FIXME(jdonszelmann): remove when patchable_function_entry becomes a parsed attr fn parse_patchable_function_entry( tcx: TyCtxt<'_>, @@ -353,6 +320,9 @@ fn process_builtin_attrs( AttributeKind::ThreadLocal => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL } + AttributeKind::InstructionSet(instruction_set) => { + codegen_fn_attrs.instruction_set = Some(*instruction_set) + } _ => {} } } @@ -369,9 +339,6 @@ fn process_builtin_attrs( sym::rustc_allocator_zeroed => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } - sym::instruction_set => { - codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr) - } sym::patchable_function_entry => { codegen_fn_attrs.patchable_function_entry = parse_patchable_function_entry(tcx, attr); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index c3d63e3329895..95306c140895c 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -136,34 +136,6 @@ pub(crate) struct RequiresRustAbi { pub span: Span, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_unsupported_instruction_set, code = E0779)] -pub(crate) struct UnsupportedInstructionSet { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_invalid_instruction_set, code = E0779)] -pub(crate) struct InvalidInstructionSet { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_bare_instruction_set, code = E0778)] -pub(crate) struct BareInstructionSet { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(codegen_ssa_multiple_instruction_set, code = E0779)] -pub(crate) struct MultipleInstructionSet { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_expected_name_value_pair)] pub(crate) struct ExpectedNameValuePair { diff --git a/compiler/rustc_error_codes/src/error_codes/E0778.md b/compiler/rustc_error_codes/src/error_codes/E0778.md index 467362dca58fd..4bdf85451c9bd 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0778.md +++ b/compiler/rustc_error_codes/src/error_codes/E0778.md @@ -1,8 +1,9 @@ +#### Note: this error code is no longer emitted by the compiler The `instruction_set` attribute was malformed. Erroneous code example: -```compile_fail,E0778 +```compile_fail #![feature(isa_attribute)] #[instruction_set()] // error: expected one argument diff --git a/compiler/rustc_error_codes/src/error_codes/E0779.md b/compiler/rustc_error_codes/src/error_codes/E0779.md index 146e20c262659..036931379a069 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0779.md +++ b/compiler/rustc_error_codes/src/error_codes/E0779.md @@ -1,8 +1,9 @@ +#### Note: this error code is no longer emitted by the compiler An unknown argument was given to the `instruction_set` attribute. Erroneous code example: -```compile_fail,E0779 +```compile_fail #![feature(isa_attribute)] #[instruction_set(intel::x64)] // error: invalid argument diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 39530f5c3f8b0..55207a14ff51a 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -60,7 +60,17 @@ impl InlineAttr { } } -#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)] +#[derive( + Copy, + Clone, + Encodable, + Decodable, + Debug, + PartialEq, + Eq, + HashStable_Generic, + PrintAttribute +)] pub enum InstructionSetAttr { ArmA32, ArmT32, @@ -807,6 +817,9 @@ pub enum AttributeKind { /// Represents `#[inline]` and `#[rustc_force_inline]`. Inline(InlineAttr, Span), + /// Represents `#[instruction_set]` + InstructionSet(InstructionSetAttr), + /// Represents `#[link]`. Link(ThinVec, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 6d159a6ee68a7..8d83efd48f266 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -54,6 +54,7 @@ impl AttributeKind { Fundamental { .. } => Yes, Ignore { .. } => No, Inline(..) => No, + InstructionSet(..) => No, Link(..) => No, LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fae269bfdcf13..7367879687fe8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -229,6 +229,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::Dummy | AttributeKind::RustcBuiltinMacro { .. } | AttributeKind::Ignore { .. } + | AttributeKind::InstructionSet(..) | AttributeKind::Path(..) | AttributeKind::NoImplicitPrelude(..) | AttributeKind::AutomaticallyDerived(..) @@ -337,7 +338,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfg_trace | sym::cfg_attr_trace // need to be fixed - | sym::instruction_set // broken on stable!!! | sym::patchable_function_entry // FIXME(patchable_function_entry) | sym::deprecated_safe // FIXME(deprecated_safe) // internal diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0e30abccb62b3..72709753b1dff 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -472,6 +472,8 @@ symbols! { arith_offset, arm, arm64ec, + arm_a32: "arm::a32", + arm_t32: "arm::t32", arm_target_feature, array, as_dash_needed: "as-needed", diff --git a/tests/ui/attributes/instruction-set.rs b/tests/ui/attributes/instruction-set.rs new file mode 100644 index 0000000000000..dafa907cb5684 --- /dev/null +++ b/tests/ui/attributes/instruction-set.rs @@ -0,0 +1,111 @@ +//@ add-minicore +//@ compile-flags: --target armv5te-none-eabi +//@ needs-llvm-components: arm +//@ ignore-backends: gcc +//@ edition: 2024 + +#![crate_type = "lib"] +#![feature(no_core, lang_items,)] +#![no_core] + +extern crate minicore; +use minicore::*; + + + + +#[instruction_set(arm::a32)] +fn foo() { +} + +#[instruction_set(arm)] +//~^ ERROR malformed `instruction_set` attribute input [E0539] +fn bar() { +} + +#[instruction_set(arm::)] +//~^ ERROR expected identifier, found `` +fn bazz() { +} + +#[instruction_set(arm::magic)] +//~^ ERROR malformed `instruction_set` attribute input [E0539] +fn bazzer() { + +} + +fn all_instruction_set_cases() { + #[instruction_set(arm::a32)] + || { + 0 + }; + #[instruction_set(arm::t32)] + async || { + 0 + }; +} + +struct Fooer; + +impl Fooer { + #[instruction_set(arm::a32)] + fn fooest() { + + } +} + +trait Bazzest { + fn bazz(); + + #[instruction_set(arm::a32)] + fn bazziest() { + + } +} +impl Bazzest for Fooer { + #[instruction_set(arm::t32)] + fn bazz() {} +} + + +// The following lang items need to be defined for the async closure to work +#[lang = "ResumeTy"] +pub struct ResumeTy(NonNull>); + +#[lang = "future_trait"] +pub trait Future { + /// The type of value produced on completion. + #[lang = "future_output"] + type Output; + + // NOTE: misses the `poll` method. +} + +#[lang = "async_drop"] +pub trait AsyncDrop { + // NOTE: misses the `drop` method. +} + +#[lang = "Poll"] +pub enum Poll { + #[lang = "Ready"] + Ready(T), + + #[lang = "Pending"] + Pending, +} + +#[lang = "Context"] +pub struct Context<'a> { + // NOTE: misses a bunch of fields. + _marker: PhantomData &'a ()>, +} + +#[lang = "get_context"] +pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { + // NOTE: the actual implementation looks different. + unsafe {mem::transmute(cx.0)} +} + +#[lang = "pin"] +pub struct Pin(T); diff --git a/tests/ui/attributes/instruction-set.stderr b/tests/ui/attributes/instruction-set.stderr new file mode 100644 index 0000000000000..c5aea396b53ee --- /dev/null +++ b/tests/ui/attributes/instruction-set.stderr @@ -0,0 +1,31 @@ +error[E0539]: malformed `instruction_set` attribute input + --> $DIR/instruction-set.rs:21:1 + | +LL | #[instruction_set(arm)] + | ^^^^^^^^^^^^^^^^^^---^^ + | | | + | | valid arguments are `arm::a32` or `arm::t32` + | help: must be of the form: `#[instruction_set(set)]` + | + = note: for more information, visit + +error: expected identifier, found `` + --> $DIR/instruction-set.rs:26:22 + | +LL | #[instruction_set(arm::)] + | ^^ expected identifier + +error[E0539]: malformed `instruction_set` attribute input + --> $DIR/instruction-set.rs:31:1 + | +LL | #[instruction_set(arm::magic)] + | ^^^^^^^^^^^^^^^^^^^^^^^-----^^ + | | | + | | valid arguments are `a32` or `t32` + | help: must be of the form: `#[instruction_set(set)]` + | + = note: for more information, visit + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/attributes/invalid-instruction-set-target.rs b/tests/ui/attributes/invalid-instruction-set-target.rs new file mode 100644 index 0000000000000..08b261c1b309a --- /dev/null +++ b/tests/ui/attributes/invalid-instruction-set-target.rs @@ -0,0 +1,6 @@ +//@ only-x86_64-unknown-linux-gnu + +#[instruction_set(arm::a32)] +//~^ ERROR target `x86_64-unknown-linux-gnu` does not support `#[instruction_set(arm::*)]` +fn main() { +} diff --git a/tests/ui/attributes/invalid-instruction-set-target.stderr b/tests/ui/attributes/invalid-instruction-set-target.stderr new file mode 100644 index 0000000000000..d99fbd369a0e9 --- /dev/null +++ b/tests/ui/attributes/invalid-instruction-set-target.stderr @@ -0,0 +1,8 @@ +error: target `x86_64-unknown-linux-gnu` does not support `#[instruction_set(arm::*)]` + --> $DIR/invalid-instruction-set-target.rs:3:1 + | +LL | #[instruction_set(arm::a32)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 860dcdb349bfe..7027328bc27b7 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -26,14 +26,6 @@ error[E0463]: can't find crate for `wloop` LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate -error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:112:1 - | -LL | #[instruction_set] - | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` - | - = note: for more information, visit - error: malformed `patchable_function_entry` attribute input --> $DIR/malformed-attrs.rs:114:1 | @@ -456,6 +448,17 @@ LL | #[proc_macro = 18] | | didn't expect any arguments here | help: must be of the form: `#[proc_macro]` +error[E0539]: malformed `instruction_set` attribute input + --> $DIR/malformed-attrs.rs:112:1 + | +LL | #[instruction_set] + | ^^^^^^^^^^^^^^^^^^ + | | + | valid arguments are `arm::a32` or `arm::t32` + | help: must be of the form: `#[instruction_set(set)]` + | + = note: for more information, visit + error[E0565]: malformed `coroutine` attribute input --> $DIR/malformed-attrs.rs:117:5 | diff --git a/tests/ui/error-codes/E0778.rs b/tests/ui/error-codes/E0778.rs deleted file mode 100644 index 74653886d4154..0000000000000 --- a/tests/ui/error-codes/E0778.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[instruction_set()] //~ ERROR -fn no_isa_defined() {} - -fn main() {} diff --git a/tests/ui/error-codes/E0778.stderr b/tests/ui/error-codes/E0778.stderr deleted file mode 100644 index 7eb24c493bf54..0000000000000 --- a/tests/ui/error-codes/E0778.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0778]: `#[instruction_set]` requires an argument - --> $DIR/E0778.rs:1:1 - | -LL | #[instruction_set()] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0778`. diff --git a/tests/ui/error-codes/E0779.rs b/tests/ui/error-codes/E0779.rs deleted file mode 100644 index c32dae12c9cbf..0000000000000 --- a/tests/ui/error-codes/E0779.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[instruction_set(arm::magic)] //~ ERROR -fn main() {} diff --git a/tests/ui/error-codes/E0779.stderr b/tests/ui/error-codes/E0779.stderr deleted file mode 100644 index a01aa98b914c5..0000000000000 --- a/tests/ui/error-codes/E0779.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0779]: invalid instruction set specified - --> $DIR/E0779.rs:1:1 - | -LL | #[instruction_set(arm::magic)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0779`. From 9d8b4cc70d8f1e8db49999120baaa254034baafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Dom=C3=ADnguez?= Date: Tue, 30 Dec 2025 15:02:22 +0100 Subject: [PATCH 2/4] Restore builder at the end of saved bb --- .../src/builder/gpu_offload.rs | 4 +-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 -- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 33 ------------------- 3 files changed, 2 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 046501d08c482..5c4aa7da51431 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -430,7 +430,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( let fn_ty = offload_globals.mapper_fn_ty; let num_args = types.len() as u64; - let ip = unsafe { llvm::LLVMRustGetInsertPoint(&builder.llbuilder) }; + let bb = builder.llbb(); // FIXME(Sa4dUs): dummy loads are a temp workaround, we should find a proper way to prevent these // variables from being optimized away @@ -468,7 +468,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>( // Step 1) unsafe { - llvm::LLVMRustRestoreInsertPoint(&builder.llbuilder, ip); + llvm::LLVMPositionBuilderAtEnd(&builder.llbuilder, bb); } builder.memset(tgt_bin_desc_alloca, cx.get_const_i8(0), cx.get_const_i64(32), Align::EIGHT); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 75b3e5955b78f..1476927218457 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2443,8 +2443,6 @@ unsafe extern "C" { pub(crate) fn LLVMRustPositionBuilderPastAllocas<'a>(B: &Builder<'a>, Fn: &'a Value); pub(crate) fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); - pub(crate) fn LLVMRustGetInsertPoint<'a>(B: &Builder<'a>) -> &'a Value; - pub(crate) fn LLVMRustRestoreInsertPoint<'a>(B: &Builder<'a>, IP: &'a Value); pub(crate) fn LLVMRustSetModulePICLevel(M: &Module); pub(crate) fn LLVMRustSetModulePIELevel(M: &Module); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 02e6abf24627f..b1cccd62d0a55 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1458,39 +1458,6 @@ extern "C" void LLVMRustPositionAfter(LLVMBuilderRef B, LLVMValueRef Instr) { } } -extern "C" LLVMValueRef LLVMRustGetInsertPoint(LLVMBuilderRef B) { - llvm::IRBuilderBase &IRB = *unwrap(B); - - llvm::IRBuilderBase::InsertPoint ip = IRB.saveIP(); - llvm::BasicBlock *BB = ip.getBlock(); - - if (!BB) - return nullptr; - - auto it = ip.getPoint(); - - if (it == BB->end()) - return nullptr; - - llvm::Instruction *I = &*it; - return wrap(I); -} - -extern "C" void LLVMRustRestoreInsertPoint(LLVMBuilderRef B, - LLVMValueRef Instr) { - llvm::IRBuilderBase &IRB = *unwrap(B); - - if (!Instr) { - llvm::BasicBlock *BB = IRB.GetInsertBlock(); - if (BB) - IRB.SetInsertPoint(BB); - return; - } - - llvm::Instruction *I = unwrap(Instr); - IRB.SetInsertPoint(I); -} - extern "C" LLVMValueRef LLVMRustGetFunctionCall(LLVMValueRef Fn, const char *Name, size_t NameLen) { auto targetName = StringRef(Name, NameLen); From 41a24c4b583f0cbeb52001d093fe3486009fcd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelo=20Dom=C3=ADnguez?= Date: Wed, 31 Dec 2025 13:11:28 +0100 Subject: [PATCH 3/4] Add offload test for control flow handling --- .../codegen-llvm/gpu_offload/control_flow.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/codegen-llvm/gpu_offload/control_flow.rs diff --git a/tests/codegen-llvm/gpu_offload/control_flow.rs b/tests/codegen-llvm/gpu_offload/control_flow.rs new file mode 100644 index 0000000000000..4a213f5a33a8d --- /dev/null +++ b/tests/codegen-llvm/gpu_offload/control_flow.rs @@ -0,0 +1,37 @@ +//@ compile-flags: -Zoffload=Test -Zunstable-options -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-offload + +// This test verifies that the offload intrinsic is correctly lowered even when the caller +// contains control flow. + +#![feature(abi_gpu_kernel)] +#![feature(rustc_attrs)] +#![feature(core_intrinsics)] +#![no_main] + +// CHECK: define{{( dso_local)?}} void @main() +// CHECK-NOT: define +// CHECK: %EmptyDesc = alloca %struct.__tgt_bin_desc, align 8 +// CHECK-NEXT: %.offload_baseptrs = alloca [1 x ptr], align 8 +// CHECK-NEXT: %.offload_ptrs = alloca [1 x ptr], align 8 +// CHECK-NEXT: %.offload_sizes = alloca [1 x i64], align 8 +// CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 +// CHECK: br label %bb3 +// CHECK-NOT define +// CHECK: bb3 +// CHECK: call void @__tgt_target_data_begin_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo, ptr null, ptr null) +// CHECK: %10 = call i32 @__tgt_target_kernel(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 2097152, i32 256, ptr nonnull @.foo.region_id, ptr nonnull %kernel_args) +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr nonnull @anon.{{.*}}.1, i64 -1, i32 1, ptr nonnull %.offload_baseptrs, ptr nonnull %.offload_ptrs, ptr nonnull %.offload_sizes, ptr nonnull @.offload_maptypes.foo, ptr null, ptr null) +#[unsafe(no_mangle)] +unsafe fn main() { + let A = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; + + for i in 0..100 { + core::intrinsics::offload::<_, _, ()>(foo, (A.as_ptr() as *const [f32; 6],)); + } +} + +unsafe extern "C" { + pub fn foo(A: *const [f32; 6]) -> (); +} From 4e90a965422a42c3c2c161f45543148a9eae429a Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:54:03 +0100 Subject: [PATCH 4/4] Corretly link URL in internal Windows docs ``` warning: this URL is not a hyperlink --> library/std/src/sys/pal/windows/mod.rs:337:5 | 337 | /// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: bare URLs are not automatically turned into clickable links = note: `#[warn(rustdoc::bare_urls)]` on by default help: use an automatic link instead | 337 | /// | + + ``` --- library/std/src/sys/pal/windows/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 32bd6ea3a4f6c..457b1fd70562b 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -334,7 +334,7 @@ pub fn dur2timeout(dur: Duration) -> u32 { /// this sequence of instructions will be treated as an access violation, which /// will still terminate the process but might run some exception handlers. /// -/// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail +/// #[cfg(not(miri))] // inline assembly does not work in Miri pub fn abort_internal() -> ! { unsafe {