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

Implementation of RFC2867 #76260

Merged
merged 2 commits into from
Oct 9, 2020
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
6 changes: 6 additions & 0 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::attributes;
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;
Expand Down Expand Up @@ -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(",");

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ E0774: include_str!("./error_codes/E0774.md"),
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
Expand Down
35 changes: 35 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0778.md
Original file line number Diff line number Diff line change
@@ -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
32 changes: 32 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0779.md
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,9 @@ declare_features! (
/// 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
// -------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
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)),
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
}
}

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);
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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! {
Expand Down Expand Up @@ -98,6 +102,7 @@ impl CodegenFnAttrs {
linkage: None,
link_section: None,
no_sanitize: SanitizerSet::empty(),
instruction_set: None,
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ symbols! {
_d,
_e,
_task_context,
a32,
aarch64_target_feature,
abi,
abi_amdgpu_kernel,
Expand Down Expand Up @@ -256,6 +257,7 @@ symbols! {
arbitrary_enum_discriminant,
arbitrary_self_types,
arith_offset,
arm,
arm_target_feature,
array,
arrays,
Expand Down Expand Up @@ -592,11 +594,13 @@ symbols! {
inlateout,
inline,
inout,
instruction_set,
intel,
into_iter,
into_result,
intrinsics,
irrefutable_let_patterns,
isa_attribute,
isize,
issue,
issue_5723_bootstrap,
Expand Down Expand Up @@ -1065,6 +1069,7 @@ symbols! {
sym,
sync,
sync_trait,
t32,
target_arch,
target_endian,
target_env,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
})
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -1086,6 +1090,7 @@ impl Default for TargetOptions {
llvm_args: vec![],
use_ctors_section: false,
eh_frame_header: true,
has_thumb_interworking: false,
}
}
}
Expand Down Expand Up @@ -1479,6 +1484,7 @@ impl Target {
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.
Expand Down Expand Up @@ -1717,6 +1723,7 @@ impl ToJson for Target {
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(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
},
Expand Down
73 changes: 71 additions & 2 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crate::constrained_generic_params as cgp;
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};
Expand Down Expand Up @@ -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
}
xd009642 marked this conversation as resolved.
Show resolved Hide resolved
}
}
[] => {
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
}
};
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/error-codes/E0778.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![feature(isa_attribute)]

#[instruction_set()] //~ ERROR
fn no_isa_defined() {
}

fn main() {
}
9 changes: 9 additions & 0 deletions src/test/ui/error-codes/E0778.stderr
Original file line number Diff line number Diff line change
@@ -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`.
6 changes: 6 additions & 0 deletions src/test/ui/error-codes/E0779.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![feature(isa_attribute)]

#[instruction_set(arm::magic)] //~ ERROR
fn main() {

}
9 changes: 9 additions & 0 deletions src/test/ui/error-codes/E0779.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading