diff --git a/.travis.yml b/.travis.yml index 7985b6c0e191f..6613a9423b018 100644 --- a/.travis.yml +++ b/.travis.yml @@ -119,13 +119,13 @@ matrix: - env: IMAGE=arm-android if: branch = auto - env: IMAGE=armhf-gnu - if: branch = auto + #if: branch = auto - env: IMAGE=dist-various-1 DEPLOY=1 if: branch = auto - env: IMAGE=dist-various-2 DEPLOY=1 if: branch = auto - env: IMAGE=dist-aarch64-linux DEPLOY=1 - if: branch = auto + #if: branch = auto - env: IMAGE=dist-android DEPLOY=1 if: branch = auto - env: IMAGE=dist-arm-linux DEPLOY=1 @@ -153,7 +153,7 @@ matrix: - env: IMAGE=dist-powerpc64-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-powerpc64le-linux DEPLOY=1 - if: branch = auto + #if: branch = auto - env: IMAGE=dist-s390x-linux DEPLOY=1 if: branch = auto - env: IMAGE=dist-x86_64-freebsd DEPLOY=1 diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index afe658767f327..2b47eaa36012a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -47,7 +47,7 @@ use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::GenericParamKind; -use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; +use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, /*Unsafety*/}; use std::iter; @@ -1599,7 +1599,7 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig let icx = ItemCtxt::new(tcx, def_id); - match tcx.hir().get_by_hir_id(hir_id) { + let sig = match tcx.hir().get_by_hir_id(hir_id) { TraitItem(hir::TraitItem { node: TraitItemKind::Method(sig, _), .. @@ -1669,7 +1669,18 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig x => { bug!("unexpected sort of node in fn_sig(): {:?}", x); } + }; + + let attrs = tcx.codegen_fn_attrs(def_id); + if !attrs.target_features.is_empty() { + if sig.unsafety() == Unsafety::Normal { + let msg = "#[target_feature(..)] can only be applied to \ + `unsafe` function"; + let span = tcx.def_span(def_id); + tcx.sess.span_err(span, msg); + } } + sig } fn impl_trait_ref<'a, 'tcx>( @@ -2256,6 +2267,175 @@ fn predicates_from_bound<'tcx>( } } +/// Returns the minimum required target-feature name to use a SIMD type on C FFI: +fn simd_ffi_min_target_feature( + target: &str, simd_width: usize, simd_elem_width: usize +) -> Option<&'static str> { + // FIXME: this needs to be architecture dependent and + // should probably belong somewhere else: + // * on mips: 16 => msa, + // * wasm: 16 => simd128 + match target { + t if t.contains("x86") => { + match simd_width { + 8 => Some("mmx"), + 16 => Some("sse"), + 32 => Some("avx"), + 64 => Some("avx512f"), + _ => None, + } + }, + t if t.contains("arm") => { + match simd_width { + // 32-bit arm does not support vectors with 64-bit wide elements + 8 | 16 if simd_elem_width < 8 => Some("neon"), + _ => None, + } + }, + t if t.contains("aarch64") => { + match simd_width { + 8 | 16 => Some("neon"), + _ => None, + } + }, + t if t.contains("powerpc") => { + match simd_width { + // 64-bit wide elements are only available in VSX: + 16 if simd_elem_width == 8 => Some("vsx"), + 16 if simd_elem_width < 8 => Some("altivec"), + _ => None, + } + }, + t if t.contains("mips") => { + match simd_width { + 16 => Some("msa"), + _ => None, + } + }, + _ => None, + } +} + +/// Returns true if the target-feature allows using the SIMD type on C FFI: +fn simd_ffi_feature_check( + target: &str, simd_width: usize, simd_elem_width: usize, feature: &'static str +) -> bool { + match target { + t if t.contains("x86") => { + // FIXME: see simd_ffi_min_target_feature + match simd_width { + 8 => feature.contains("mmx") + || feature.contains("sse") + || feature.contains("ssse") + || feature.contains("avx"), + 16 => feature.contains("sse") + || feature.contains("ssse") + || feature.contains("avx"), + 32 => feature.contains("avx"), + 64 => feature.contains("avx512"), + _ => false, + } + + }, + t if t.contains("arm") => { + match simd_width { + // 32-bit arm does not support vectors with 64-bit wide elements + 8 | 16 if simd_elem_width < 8 => feature.contains("neon"), + _ => false, + } + }, + t if t.contains("aarch64") => { + match simd_width { + 8 | 16 => feature.contains("neon"), + _ => false, + } + }, + t if t.contains("powerpc") => { + match simd_width { + // 64-bit wide elements are only available in VSX: + 16 if simd_elem_width == 8 => feature.contains("vsx"), + 16 if simd_elem_width < 8 => feature.contains("altivec"), + _ => false, + } + }, + t if t.contains("mips") => { + match simd_width { + 16 => feature.contains("msa"), + _ => false, + } + }, + _ => false, + } +} + +fn simd_ffi_check<'a, 'tcx, 'b: 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ast_ty: &hir::Ty, ty: Ty<'b>, +) { + if !ty.is_simd() { + return; + } + + // The use of SIMD types in FFI is feature-gated: + if !tcx.features().simd_ffi { + tcx.sess + .struct_span_err( + ast_ty.span, + &format!( + "use of SIMD type `{}` in FFI is unstable", + tcx.hir().hir_to_pretty_string(ast_ty.hir_id) + ), + ) + .help("add #![feature(simd_ffi)] to the crate attributes to enable") + .emit(); + return; + } + + // If rustdoc, then we don't type check SIMD on FFI because rustdoc requires + // being able to compile a target, with features of other targets enabled + // (e.g. `x86+neon`, yikes). + if tcx.sess.opts.actually_rustdoc { + return; + } + + let attrs = tcx.codegen_fn_attrs(def_id); + + // Skip LLVM intrinsics: + if let Some(link_name) = attrs.link_name { + if link_name.as_str().get().starts_with("llvm.") { + return; + } + } + + let features = &attrs.target_features; + let simd_len = tcx.layout_of(ty::ParamEnvAnd{ + param_env: ty::ParamEnv::empty(), + value: ty, + }).unwrap().details.size.bytes() as usize; + let simd_elem_width = simd_len / ty.simd_size(tcx); + let target: &str = &tcx.sess.target.target.arch; + if !features.iter().any(|f| simd_ffi_feature_check( + target, simd_len, simd_elem_width, f.as_str().get()) + ) { + let type_str = tcx.hir().hir_to_pretty_string(ast_ty.hir_id); + let error_msg = if let Some(min_feature) = simd_ffi_min_target_feature( + target, simd_len, simd_elem_width + ) { + format!( + "use of SIMD type `{}` in FFI requires `#[target_feature(enable = \"{}\")]`", + type_str, min_feature, + ) + } else { + format!( + "use of SIMD type `{}` in FFI not supported by any target features", + type_str + ) + }; + tcx.sess + .struct_span_err(ast_ty.span, &error_msg) + .emit(); + } +} + fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -2269,32 +2449,16 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( }; let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl); - // feature gate SIMD types in FFI, since I (huonw) am not sure the - // ABIs are handled at all correctly. + // Using SIMD types in FFI signatures requires the + // signature to have appropriate `#[target_feature]`s enabled. if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic - && !tcx.features().simd_ffi { - let check = |ast_ty: &hir::Ty, ty: Ty<'_>| { - if ty.is_simd() { - tcx.sess - .struct_span_err( - ast_ty.span, - &format!( - "use of SIMD type `{}` in FFI is highly experimental and \ - may result in invalid code", - tcx.hir().hir_to_pretty_string(ast_ty.hir_id) - ), - ) - .help("add #![feature(simd_ffi)] to the crate attributes to enable") - .emit(); - } - }; for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) { - check(&input, ty) + simd_ffi_check(tcx, def_id, &input, ty) } if let hir::Return(ref ty) = decl.output { - check(&ty, *fty.output().skip_binder()) + simd_ffi_check(tcx, def_id, &ty, *fty.output().skip_binder()) } } @@ -2488,11 +2652,6 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen codegen_fn_attrs.export_name = Some(s); } } else if attr.check_name("target_feature") { - if tcx.fn_sig(id).unsafety() == Unsafety::Normal { - let msg = "#[target_feature(..)] can only be applied to \ - `unsafe` function"; - tcx.sess.span_err(attr.span, msg); - } from_target_feature( tcx, id, diff --git a/src/llvm-project b/src/llvm-project index 38ad31bde8ff6..4fc9fb8245abe 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 38ad31bde8ff681d862dc0f96930a5dd9b7a472e +Subproject commit 4fc9fb8245abe24680192535870c4522644a4212 diff --git a/src/test/codegen/target-feature-on-foreign-function.rs b/src/test/codegen/target-feature-on-foreign-function.rs new file mode 100644 index 0000000000000..8da2c1808d0d5 --- /dev/null +++ b/src/test/codegen/target-feature-on-foreign-function.rs @@ -0,0 +1,25 @@ +// ignore-emscripten +// ignore-s390x +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 +// ignore-mips +// ignore-mips64 +// ignore-aarch64 +// ignore-arm + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +pub unsafe fn bar() { foo() } + +extern "C" { + // CHECK-LABEL: declare void @foo() + // CHECK-SAME: [[ATTRS:#[0-9]+]] + // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}"target-features"="+avx2"{{.*}} } + #[target_feature(enable = "avx2")] + pub fn foo(); +} diff --git a/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr b/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr index 11e095fef3da9..fe104e6e47e53 100644 --- a/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr +++ b/src/test/ui/feature-gates/feature-gate-simd-ffi.stderr @@ -1,4 +1,4 @@ -error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code +error: use of SIMD type `LocalSimd` in FFI is unstable --> $DIR/feature-gate-simd-ffi.rs:9:17 | LL | fn baz() -> LocalSimd; @@ -6,7 +6,7 @@ LL | fn baz() -> LocalSimd; | = help: add #![feature(simd_ffi)] to the crate attributes to enable -error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code +error: use of SIMD type `LocalSimd` in FFI is unstable --> $DIR/feature-gate-simd-ffi.rs:10:15 | LL | fn qux(x: LocalSimd); diff --git a/src/test/ui/issues/issue-49851/compiler-builtins-error.rs b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs index 0163da0771e9b..3484ff3b87432 100644 --- a/src/test/ui/issues/issue-49851/compiler-builtins-error.rs +++ b/src/test/ui/issues/issue-49851/compiler-builtins-error.rs @@ -8,4 +8,3 @@ #![no_std] extern crate cortex_m; - diff --git a/src/test/ui/simd-ffi-aarch64.rs b/src/test/ui/simd-ffi-aarch64.rs new file mode 100644 index 0000000000000..3a58e033e043e --- /dev/null +++ b/src/test/ui/simd-ffi-aarch64.rs @@ -0,0 +1,57 @@ +// ignore-tidy-linelength +// ignore-s390x +// ignore-emscripten +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 +// ignore-mips +// ignore-mips64 +// ignore-arm +// ignore-x86 +// ignore-x86_64 + +#![feature(repr_simd)] +#![feature(simd_ffi)] +#![allow(non_camel_case_types)] +#![cfg(target_arch = "aarch64")] + +#[repr(simd)] +struct v1024(i128, i128, i128, i128, i128, i128, i128, i128); + +extern { + fn foo(x: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn bar(x: i32, y: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn baz(x: i32) -> v1024; //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + + fn qux_fail(x: v64); //~ ERROR use of SIMD type `v64` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn qux(x: v64); + + fn quux_fail(x: v64i); //~ ERROR use of SIMD type `v64i` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn quux(x: v64i); + + fn quuux_fail(x: v128); //~ ERROR use of SIMD type `v128` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn quuux(x: v128); + + fn quuuux_fail(x: v128i); //~ ERROR use of SIMD type `v128i` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn quuuux(x: v128); //~ ERROR use of SIMD type `v128i` in FFI not supported by any target features +} + +fn main() {} + +#[repr(simd)] +struct v128(i32, i32, i32, i32); + +#[repr(simd)] +struct v64(i32, i32); + +#[repr(simd)] +struct v128i(i64, i64); + +#[repr(simd)] +struct v64i(i64); diff --git a/src/test/ui/simd-ffi-aarch64.stderr b/src/test/ui/simd-ffi-aarch64.stderr new file mode 100644 index 0000000000000..2e65efe2a145d --- /dev/null +++ b/src/test/ui/simd-ffi-aarch64.stderr @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/src/test/ui/simd-ffi-arm.rs b/src/test/ui/simd-ffi-arm.rs new file mode 100644 index 0000000000000..b6391d2ff131b --- /dev/null +++ b/src/test/ui/simd-ffi-arm.rs @@ -0,0 +1,57 @@ +// ignore-tidy-linelength +// ignore-s390x +// ignore-emscripten +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 +// ignore-mips +// ignore-mips64 +// ignore-aarch64 +// ignore-x86 +// ignore-x86_64 + +#![feature(repr_simd)] +#![feature(simd_ffi)] +#![allow(non_camel_case_types)] +#![cfg(target_arch = "arm")] + +#[repr(simd)] +struct v1024(i128, i128, i128, i128, i128, i128, i128, i128); + +extern { + fn foo(x: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn bar(x: i32, y: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn baz(x: i32) -> v1024; //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + + fn qux_fail(x: v64); //~ ERROR use of SIMD type `v64` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn qux(x: v64); + + fn quux_fail(x: v64i); //~ ERROR use of SIMD type `v64i` in FFI not supported by any target features + #[target_feature(enable = "neon")] + fn quux_fail2(x: v64i); //~ ERROR use of SIMD type `v64i` in FFI not supported by any target features + + fn quuux_fail(x: v128); //~ ERROR use of SIMD type `v128` in FFI requires `#[target_feature(enable = "neon")]` + #[target_feature(enable = "neon")] + fn quuux(x: v128); + + fn quuuux_fail(x: v128i); //~ ERROR use of SIMD type `v128i` in FFI not supported by any target features + #[target_feature(enable = "neon")] + fn quuuux_fail2(x: v128i); //~ ERROR use of SIMD type `v128i` in FFI not supported by any target features +} + +fn main() {} + +#[repr(simd)] +struct v128(i32, i32, i32, i32); + +#[repr(simd)] +struct v64(i32, i32); + +#[repr(simd)] +struct v128i(i64, i64); + +#[repr(simd)] +struct v64i(i64); diff --git a/src/test/ui/simd-ffi-arm.stderr b/src/test/ui/simd-ffi-arm.stderr new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/src/test/ui/simd-ffi-arm.stderr @@ -0,0 +1 @@ + diff --git a/src/test/ui/simd-ffi-x86.rs b/src/test/ui/simd-ffi-x86.rs new file mode 100644 index 0000000000000..d63b434739224 --- /dev/null +++ b/src/test/ui/simd-ffi-x86.rs @@ -0,0 +1,70 @@ +// ignore-tidy-linelength +// ignore-s390x +// ignore-emscripten +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 +// ignore-mips +// ignore-mips64 +// ignore-arm +// ignore-aarch64 + +#![feature(repr_simd)] +#![feature(simd_ffi)] +#![feature(avx512_target_feature)] +#![allow(non_camel_case_types)] +#![cfg(any(target_arch = "x86", target_arch = "x86_64"))] + +#[repr(simd)] +struct v1024(i128, i128, i128, i128, i128, i128, i128, i128); + +extern { + fn foo(x: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn bar(x: i32, y: v1024); //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + fn baz(x: i32) -> v1024; //~ ERROR use of SIMD type `v1024` in FFI not supported by any target features + + fn qux_fail(x: v128); //~ ERROR use of SIMD type `v128` in FFI requires `#[target_feature(enable = "sse")]` + #[target_feature(enable = "sse")] + fn qux(x: v128); + #[target_feature(enable = "sse4.2")] + fn qux2(x: v128); + #[target_feature(enable = "ssse3")] + fn qux3(x: v128); + #[target_feature(enable = "avx")] + fn qux4(x: v128); + #[target_feature(enable = "avx2")] + fn qux5(x: v128); + #[target_feature(enable = "avx512f")] + fn qux6(x: v128); + + fn quux_fail(x: v256); //~ ERROR use of SIMD type `v256` in FFI requires `#[target_feature(enable = "avx")]` + #[target_feature(enable = "sse4.2")] + fn quux_fail2(x: v256); //~ ERROR use of SIMD type `v256` in FFI requires `#[target_feature(enable = "avx")]` + #[target_feature(enable = "avx")] + fn quux(x: v256); + #[target_feature(enable = "avx2")] + fn quux2(x: v256); + #[target_feature(enable = "avx512f")] + fn quux3(x: v256); + + fn quuux_fail(x: v512); //~ ERROR use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + #[target_feature(enable = "sse")] + fn quuux_fail2(x: v512); //~ ERROR use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + #[target_feature(enable = "avx2")] + fn quuux_fail3(x: v512); //~ ERROR use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + #[target_feature(enable = "avx512f")] + fn quuux(x: v512); +} + +fn main() {} + +#[repr(simd)] +struct v128(i128); + +#[repr(simd)] +struct v256(i128, i128); + +#[repr(simd)] +struct v512(i128, i128, i128, i128); diff --git a/src/test/ui/simd-ffi-x86.stderr b/src/test/ui/simd-ffi-x86.stderr new file mode 100644 index 0000000000000..2e2d11d1f3b32 --- /dev/null +++ b/src/test/ui/simd-ffi-x86.stderr @@ -0,0 +1,56 @@ +error: use of SIMD type `v1024` in FFI not supported by any target features + --> $DIR/simd-ffi-x86.rs:24:15 + | +LL | fn foo(x: v1024); + | ^^^^^ + +error: use of SIMD type `v1024` in FFI not supported by any target features + --> $DIR/simd-ffi-x86.rs:25:23 + | +LL | fn bar(x: i32, y: v1024); + | ^^^^^ + +error: use of SIMD type `v1024` in FFI not supported by any target features + --> $DIR/simd-ffi-x86.rs:26:23 + | +LL | fn baz(x: i32) -> v1024; + | ^^^^^ + +error: use of SIMD type `v128` in FFI requires `#[target_feature(enable = "sse")]` + --> $DIR/simd-ffi-x86.rs:28:20 + | +LL | fn qux_fail(x: v128); + | ^^^^ + +error: use of SIMD type `v256` in FFI requires `#[target_feature(enable = "avx")]` + --> $DIR/simd-ffi-x86.rs:42:21 + | +LL | fn quux_fail(x: v256); + | ^^^^ + +error: use of SIMD type `v256` in FFI requires `#[target_feature(enable = "avx")]` + --> $DIR/simd-ffi-x86.rs:44:22 + | +LL | fn quux_fail2(x: v256); + | ^^^^ + +error: use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + --> $DIR/simd-ffi-x86.rs:52:22 + | +LL | fn quuux_fail(x: v512); + | ^^^^ + +error: use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + --> $DIR/simd-ffi-x86.rs:54:23 + | +LL | fn quuux_fail2(x: v512); + | ^^^^ + +error: use of SIMD type `v512` in FFI requires `#[target_feature(enable = "avx512f")]` + --> $DIR/simd-ffi-x86.rs:56:23 + | +LL | fn quuux_fail3(x: v512); + | ^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/tools/clippy b/src/tools/clippy index 016d92d6ed5ae..92612c9de1598 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 016d92d6ed5ae8a3785b65aa300768abbc26f818 +Subproject commit 92612c9de159889f77f05855a77482ee1d895f51 diff --git a/src/tools/rls b/src/tools/rls index 6840dd69af3ad..90f7ab070321e 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 6840dd69af3ada1f8a432075f1f0be679ea8a468 +Subproject commit 90f7ab070321ebc5ad217dc0d6db163c029dffd9 diff --git a/src/tools/rustfmt b/src/tools/rustfmt index d6829d62dca64..1427e4c20ba5c 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit d6829d62dca64dfe7ceaa96d1a9c1cd36428221d +Subproject commit 1427e4c20ba5cdc80a338347585c9de71a0dea4d