]> git.lizzy.rs Git - rust.git/commitdiff
Implement the instruction_set attribute
authorxd009642 <danielmckenna93@gmail.com>
Thu, 8 Oct 2020 22:23:27 +0000 (23:23 +0100)
committerxd009642 <danielmckenna93@gmail.com>
Thu, 8 Oct 2020 22:32:20 +0000 (23:32 +0100)
22 files changed:
compiler/rustc_attr/src/builtin.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0778.md [new file with mode: 0644]
compiler/rustc_error_codes/src/error_codes/E0779.md [new file with mode: 0644]
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_middle/src/ich/impls_hir.rs
compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/armv5te_unknown_linux_gnueabi.rs
compiler/rustc_target/src/spec/armv5te_unknown_linux_musleabi.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
compiler/rustc_typeck/src/collect.rs
src/test/ui/error-codes/E0778.rs [new file with mode: 0644]
src/test/ui/error-codes/E0778.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0779.rs [new file with mode: 0644]
src/test/ui/error-codes/E0779.stderr [new file with mode: 0644]
src/test/ui/feature-gate-isa_attribute.rs [new file with mode: 0644]
src/test/ui/feature-gate-isa_attribute.stderr [new file with mode: 0644]

index 94e2a40e1fe368ca2da564cb0d568d6d711426e5..325af56f3cd8cf9a198c34db759322c685cb28f5 100644 (file)
@@ -75,6 +75,12 @@ pub enum InlineAttr {
     Never,
 }
 
+#[derive(Clone, Encodable, Decodable)]
+pub enum InstructionSetAttr {
+    ArmA32,
+    ArmT32,
+}
+
 #[derive(Clone, Encodable, Decodable)]
 pub enum OptimizeAttr {
     None,
index a633ea5e5a9ae558a1c8b7c66097a52b51191e24..f02c30c3ee392046301ecb97c583c1f785d982ab 100644 (file)
@@ -18,7 +18,7 @@
 use crate::llvm::AttributePlace::Function;
 use crate::llvm::{self, Attribute};
 use crate::llvm_util;
-pub use rustc_attr::{InlineAttr, OptimizeAttr};
+pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
 
 use crate::context::CodegenCx;
 use crate::value::Value;
@@ -310,6 +310,10 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
             let feature = &f.as_str();
             format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
         }))
+        .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
+            InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
+            InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(),
+        }))
         .collect::<Vec<String>>()
         .join(",");
 
index 981b5bb8ba72f43599ca439fcfc39e9ca330baa8..0a88759f84c9ab77975922a5bbb86cbff2b43fb1 100644 (file)
 E0775: include_str!("./error_codes/E0775.md"),
 E0776: include_str!("./error_codes/E0776.md"),
 E0777: include_str!("./error_codes/E0777.md"),
+E0778: include_str!("./error_codes/E0778.md"),
+E0779: include_str!("./error_codes/E0779.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0778.md b/compiler/rustc_error_codes/src/error_codes/E0778.md
new file mode 100644 (file)
index 0000000..467362d
--- /dev/null
@@ -0,0 +1,35 @@
+The `instruction_set` attribute was malformed.
+
+Erroneous code example:
+
+```compile_fail,E0778
+#![feature(isa_attribute)]
+
+#[instruction_set()] // error: expected one argument
+pub fn something() {}
+fn main() {}
+```
+
+The parenthesized `instruction_set` attribute requires the parameter to be
+specified:
+
+```
+#![feature(isa_attribute)]
+
+#[cfg_attr(target_arch="arm", instruction_set(arm::a32))]
+fn something() {}
+```
+
+or:
+
+```
+#![feature(isa_attribute)]
+
+#[cfg_attr(target_arch="arm", instruction_set(arm::t32))]
+fn something() {}
+```
+
+For more information see the [`instruction_set` attribute][isa-attribute]
+section of the Reference.
+
+[isa-attribute]: https://doc.rust-lang.org/reference/attributes/codegen.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0779.md b/compiler/rustc_error_codes/src/error_codes/E0779.md
new file mode 100644 (file)
index 0000000..146e20c
--- /dev/null
@@ -0,0 +1,32 @@
+An unknown argument was given to the `instruction_set` attribute.
+
+Erroneous code example:
+
+```compile_fail,E0779
+#![feature(isa_attribute)]
+
+#[instruction_set(intel::x64)] // error: invalid argument
+pub fn something() {}
+fn main() {}
+```
+
+The `instruction_set` attribute only supports two arguments currently:
+
+ * arm::a32
+ * arm::t32
+
+All other arguments given to the `instruction_set` attribute will return this
+error. Example:
+
+```
+#![feature(isa_attribute)]
+
+#[cfg_attr(target_arch="arm", instruction_set(arm::a32))] // ok!
+pub fn something() {}
+fn main() {}
+```
+
+For more information see the [`instruction_set` attribute][isa-attribute]
+section of the Reference.
+
+[isa-attribute]: https://doc.rust-lang.org/reference/attributes/codegen.html
index 1982d098542baf6fa63a70049028dceca53e6a6c..8a7f0517e732b1a7354adcae35b9d7bac64589df 100644 (file)
@@ -599,6 +599,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows argument and return position `impl Trait` in a `const fn`.
     (active, const_impl_trait, "1.48.0", Some(77463), None),
 
+    /// Allows `#[instruction_set(_)]` attribute
+    (active, isa_attribute, "1.48.0", Some(74727), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index b7e113e601007b3d39a3096966bf0cfae158573e..527a49b05389af33e4e5aabf7ce0601637406c1f 100644 (file)
@@ -336,6 +336,8 @@ macro_rules! experimental {
         optimize, AssumedUsed, template!(List: "size|speed"), optimize_attribute,
         experimental!(optimize),
     ),
+    // RFC 2867
+    gated!(instruction_set, AssumedUsed, template!(List: "set"), isa_attribute, experimental!(instruction_set)),
 
     gated!(ffi_returns_twice, AssumedUsed, template!(Word), experimental!(ffi_returns_twice)),
     gated!(ffi_pure, AssumedUsed, template!(Word), experimental!(ffi_pure)),
index c2d177b69b6b95409d95d90593de14b12f9a70d4..d6c6cef17513dc732cb4852731569a43ddbbbd84 100644 (file)
@@ -221,6 +221,12 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableH
     }
 }
 
+impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InstructionSetAttr {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+    }
+}
+
 impl<'hir> HashStable<StableHashingContext<'hir>> for attr::OptimizeAttr {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
index d71cdc4e67de4885ecd0587cf2731d859785ed16..a4363bb580a2f6c6ad5db697126e765debd23f11 100644 (file)
@@ -1,5 +1,5 @@
 use crate::mir::mono::Linkage;
-use rustc_attr::{InlineAttr, OptimizeAttr};
+use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_session::config::SanitizerSet;
 use rustc_span::symbol::Symbol;
 
@@ -34,6 +34,10 @@ pub struct CodegenFnAttrs {
     /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which
     /// instrumentation should be disabled inside the annotated function.
     pub no_sanitize: SanitizerSet,
+    /// The `#[instruction_set(set)]` attribute. Indicates if the generated code should
+    /// be generated against a specific instruction set. Only usable on architectures which allow
+    /// switching between multiple instruction sets.
+    pub instruction_set: Option<InstructionSetAttr>,
 }
 
 bitflags! {
@@ -98,6 +102,7 @@ pub fn new() -> CodegenFnAttrs {
             linkage: None,
             link_section: None,
             no_sanitize: SanitizerSet::empty(),
+            instruction_set: None,
         }
     }
 
index a2184c00a28fb1b0f8ac0adccff3f770674031a1..223a0758f008bc2f98c22cc9a14a6b25c2e8cba2 100644 (file)
         _d,
         _e,
         _task_context,
+        a32,
         aarch64_target_feature,
         abi,
         abi_amdgpu_kernel,
         arbitrary_enum_discriminant,
         arbitrary_self_types,
         arith_offset,
+        arm,
         arm_target_feature,
         array,
         arrays,
         inlateout,
         inline,
         inout,
+        instruction_set,
         intel,
         into_iter,
         into_result,
         intrinsics,
         irrefutable_let_patterns,
+        isa_attribute,
         isize,
         issue,
         issue_5723_bootstrap,
         sym,
         sync,
         sync_trait,
+        t32,
         target_arch,
         target_endian,
         target_env,
index 2580e8b0f851593ef08e6adf08e6563083a6a74d..a184934a99d868c5c959f032b03f72f65456a499 100644 (file)
@@ -20,6 +20,7 @@ pub fn target() -> TargetResult {
             max_atomic_width: Some(32),
             unsupported_abis: super::arm_base::unsupported_abis(),
             target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            has_thumb_interworking: true,
             ..base
         },
     })
index f28421dc77593c1f23b5e3b0447ef131db863176..015d27415ace9525379f15ca10c4b6ec39e7b797 100644 (file)
@@ -20,6 +20,7 @@ pub fn target() -> TargetResult {
             max_atomic_width: Some(32),
             unsupported_abis: super::arm_base::unsupported_abis(),
             target_mcount: "\u{1}__gnu_mcount_nc".to_string(),
+            has_thumb_interworking: true,
             ..base
         },
     })
index fe1fa88883d3e05035a3c9ef9aeeaebd4cba8b07..e35d805126164ab70070c6b8a4eb9f6fe54f98a2 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> TargetResult {
             max_atomic_width: Some(32),
             unsupported_abis: super::arm_base::unsupported_abis(),
             target_mcount: "\u{1}mcount".to_string(),
+            has_thumb_interworking: true,
             ..base
         },
     })
index f1e8330425e25c099c5e3669e6c64dfa57045939..a98dbbc4ed1446a9771ec19be43be9155cc65104 100644 (file)
@@ -994,6 +994,10 @@ pub struct TargetOptions {
     /// used to locate unwinding information is passed
     /// (only has effect if the linker is `ld`-like).
     pub eh_frame_header: bool,
+
+    /// Is true if the target is an ARM architecture using thumb v1 which allows for
+    /// thumb and arm interworking.
+    pub has_thumb_interworking: bool,
 }
 
 impl Default for TargetOptions {
@@ -1086,6 +1090,7 @@ fn default() -> TargetOptions {
             llvm_args: vec![],
             use_ctors_section: false,
             eh_frame_header: true,
+            has_thumb_interworking: false,
         }
     }
 }
@@ -1479,6 +1484,7 @@ macro_rules! key {
         key!(llvm_args, list);
         key!(use_ctors_section, bool);
         key!(eh_frame_header, bool);
+        key!(has_thumb_interworking, bool);
 
         // NB: The old name is deprecated, but support for it is retained for
         // compatibility.
@@ -1717,6 +1723,7 @@ macro_rules! target_option_val {
         target_option_val!(llvm_args);
         target_option_val!(use_ctors_section);
         target_option_val!(eh_frame_header);
+        target_option_val!(has_thumb_interworking);
 
         if default.unsupported_abis != self.options.unsupported_abis {
             d.insert(
index a8c78f057fc8a1333ad9f8aa08c5a9b8a425a529..e8b614e8345ee8f3c84a1f5b763c067b329d2599 100644 (file)
@@ -55,6 +55,7 @@ pub fn target() -> TargetResult {
 
             // don't have atomic compare-and-swap
             atomic_cas: false,
+            has_thumb_interworking: true,
 
             ..super::thumb_base::opts()
         },
index 092dae18192e51e03100ab4b632af06fa7a3ee5a..b64a1ce7c308269846c10c2a2fea30da21522cad 100644 (file)
@@ -21,8 +21,8 @@
 use crate::errors;
 use crate::middle::resolve_lifetime as rl;
 use rustc_ast as ast;
-use rustc_ast::MetaItemKind;
-use rustc_attr::{list_contains_name, InlineAttr, OptimizeAttr};
+use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{struct_span_err, Applicability};
@@ -2647,6 +2647,75 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
                     }
                 }
             }
+        } else if tcx.sess.check_name(attr, sym::instruction_set) {
+            codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) {
+                Some(MetaItemKind::List(ref items)) => match items.as_slice() {
+                    [NestedMetaItem::MetaItem(set)] => {
+                        let segments =
+                            set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+                        match segments.as_slice() {
+                            [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+                                if !tcx.sess.target.target.options.has_thumb_interworking {
+                                    struct_span_err!(
+                                        tcx.sess.diagnostic(),
+                                        attr.span,
+                                        E0779,
+                                        "target does not support `#[instruction_set]`"
+                                    )
+                                    .emit();
+                                    None
+                                } else if segments[1] == sym::a32 {
+                                    Some(InstructionSetAttr::ArmA32)
+                                } else if segments[1] == sym::t32 {
+                                    Some(InstructionSetAttr::ArmT32)
+                                } else {
+                                    unreachable!()
+                                }
+                            }
+                            _ => {
+                                struct_span_err!(
+                                    tcx.sess.diagnostic(),
+                                    attr.span,
+                                    E0779,
+                                    "invalid instruction set specified",
+                                )
+                                .emit();
+                                None
+                            }
+                        }
+                    }
+                    [] => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0778,
+                            "`#[instruction_set]` requires an argument"
+                        )
+                        .emit();
+                        None
+                    }
+                    _ => {
+                        struct_span_err!(
+                            tcx.sess.diagnostic(),
+                            attr.span,
+                            E0779,
+                            "cannot specify more than one instruction set"
+                        )
+                        .emit();
+                        None
+                    }
+                },
+                _ => {
+                    struct_span_err!(
+                        tcx.sess.diagnostic(),
+                        attr.span,
+                        E0778,
+                        "must specify an instruction set"
+                    )
+                    .emit();
+                    None
+                }
+            };
         }
     }
 
diff --git a/src/test/ui/error-codes/E0778.rs b/src/test/ui/error-codes/E0778.rs
new file mode 100644 (file)
index 0000000..60e5c25
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(isa_attribute)]
+
+#[instruction_set()] //~ ERROR
+fn no_isa_defined() {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0778.stderr b/src/test/ui/error-codes/E0778.stderr
new file mode 100644 (file)
index 0000000..6ecae79
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0778]: `#[instruction_set]` requires an argument
+  --> $DIR/E0778.rs:3:1
+   |
+LL | #[instruction_set()]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0778`.
diff --git a/src/test/ui/error-codes/E0779.rs b/src/test/ui/error-codes/E0779.rs
new file mode 100644 (file)
index 0000000..1b4dbce
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(isa_attribute)]
+
+#[instruction_set(arm::magic)] //~ ERROR
+fn main() {
+
+}
diff --git a/src/test/ui/error-codes/E0779.stderr b/src/test/ui/error-codes/E0779.stderr
new file mode 100644 (file)
index 0000000..4abe0c0
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0779]: Invalid instruction set specified
+  --> $DIR/E0779.rs:3:1
+   |
+LL | #[instruction_set(arm::magic)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0779`.
diff --git a/src/test/ui/feature-gate-isa_attribute.rs b/src/test/ui/feature-gate-isa_attribute.rs
new file mode 100644 (file)
index 0000000..cb02a09
--- /dev/null
@@ -0,0 +1,6 @@
+#[instruction_set]
+//~^ ERROR the `#[instruction_set]` attribute is an experimental feature [E0658]
+//~| ERROR malformed `instruction_set` attribute input
+//~| ERROR must specify an instruction set [E0778]
+fn main() {
+}
diff --git a/src/test/ui/feature-gate-isa_attribute.stderr b/src/test/ui/feature-gate-isa_attribute.stderr
new file mode 100644 (file)
index 0000000..2a95a80
--- /dev/null
@@ -0,0 +1,25 @@
+error: malformed `instruction_set` attribute input
+  --> $DIR/feature-gate-isa_attribute.rs:1:1
+   |
+LL | #[instruction_set]
+   | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]`
+
+error[E0658]: the `#[instruction_set]` attribute is an experimental feature
+  --> $DIR/feature-gate-isa_attribute.rs:1:1
+   |
+LL | #[instruction_set]
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #74727 <https://github.com/rust-lang/rust/issues/74727> for more information
+   = help: add `#![feature(isa_attribute)]` to the crate attributes to enable
+
+error[E0778]: must specify an instruction set
+  --> $DIR/feature-gate-isa_attribute.rs:1:1
+   |
+LL | #[instruction_set]
+   | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0658, E0778.
+For more information about an error, try `rustc --explain E0658`.