diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index fb61bab6ade2..abb961d87de9 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -36,6 +36,7 @@ use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; use syntax::{ast}; use syntax::{attr, ast_map}; +use syntax::print::pprust; use util::ppaux::Repr; /////////////////////////////////////////////////////////////////////////// @@ -426,16 +427,47 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } +// feature gate SIMD types in FFI, since I (huonw) am not sure the +// ABIs are handled at all correctly. +fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) { + if !tcx.sess.features.borrow().simd_ffi { + let check = |&: ast_ty: &ast::Ty, ty: ty::Ty| { + if ty::type_is_simd(tcx, ty) { + tcx.sess.span_err(ast_ty.span, + &format!("use of SIMD type `{}` in FFI is highly experimental and \ + may result in invalid code", + pprust::ty_to_string(ast_ty))[]); + tcx.sess.span_help(ast_ty.span, + "add #![feature(simd_ffi)] to the crate attributes to enable"); + } + }; + let sig = &ty.sig.0; + for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) { + check(&*input.ty, *ty) + } + match decl.output { + ast::NoReturn(_) => {} + ast::Return(ref ty) => check(&**ty, sig.output.unwrap()) + } + } +} + pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { let _icx = push_ctxt("foreign::trans_foreign_mod"); for foreign_item in foreign_mod.items.iter() { let lname = link_name(&**foreign_item); - if let ast::ForeignItemFn(..) = foreign_item.node { + if let ast::ForeignItemFn(ref decl, _) = foreign_item.node { match foreign_mod.abi { Rust | RustIntrinsic => {} abi => { let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); + match ty.sty { + ty::ty_bare_fn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft), + _ => ccx.tcx().sess.span_bug(foreign_item.span, + "foreign fn's sty isn't a bare_fn_ty?") + } + register_foreign_item_fn(ccx, abi, ty, &lname.get()[]); // Unlike for other items, we shouldn't call diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8929bbe0232e..9231d4ad6594 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -72,6 +72,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("slicing_syntax", Active), ("box_syntax", Active), ("on_unimplemented", Active), + ("simd_ffi", Active), ("if_let", Accepted), ("while_let", Accepted), @@ -128,6 +129,7 @@ pub struct Features { pub visible_private_types: bool, pub quote: bool, pub old_orphan_check: bool, + pub simd_ffi: bool, } impl Features { @@ -139,6 +141,7 @@ impl Features { visible_private_types: false, quote: false, old_orphan_check: false, + simd_ffi: false, } } } @@ -524,6 +527,7 @@ fn check_crate_inner(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C visible_private_types: cx.has_feature("visible_private_types"), quote: cx.has_feature("quote"), old_orphan_check: cx.has_feature("old_orphan_check"), + simd_ffi: cx.has_feature("simd_ffi"), }, unknown_features) } diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/compile-fail/feature-gate-simd-ffi.rs new file mode 100644 index 000000000000..409c85b71980 --- /dev/null +++ b/src/test/compile-fail/feature-gate-simd-ffi.rs @@ -0,0 +1,26 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(simd)] +#![allow(dead_code)] + +use std::simd::f32x4; + +#[simd] #[derive(Copy)] #[repr(C)] struct LocalSimd(u8, u8); + +extern { + fn foo() -> f32x4; //~ ERROR use of SIMD type + fn bar(x: f32x4); //~ ERROR use of SIMD type + + fn baz() -> LocalSimd; //~ ERROR use of SIMD type + fn qux(x: LocalSimd); //~ ERROR use of SIMD type +} + +fn main() {} diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index d5945db94791..76079ddb8bd9 100755 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -14,7 +14,7 @@ // cross-compiled standard libraries. #![no_std] -#![feature(simd, link_llvm_intrinsics, lang_items)] +#![feature(simd, simd_ffi, link_llvm_intrinsics, lang_items)] #[repr(C)]