about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2015-01-16 10:16:20 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2015-01-17 11:55:46 +1100
commitc8e0e9549d4327c54d9eb5fd0de5e23312c34fe9 (patch)
tree7fffb2a1707a94f4ad61f207700b8bb8ca3b8919 /src
parent4f08de84c923f08535e9a6f754b2776286ebcd01 (diff)
downloadrust-c8e0e9549d4327c54d9eb5fd0de5e23312c34fe9.tar.gz
rust-c8e0e9549d4327c54d9eb5fd0de5e23312c34fe9.zip
Feature gate SIMD in FFI, due to unknown ABIs.
I don't know if this handling of SIMD types is correct for the C ABI on
all platforms, so lets add an even finer feature gate than just the
`simd` one.

The `simd` one can be used with (relatively) little risk of complete
nonsense, the reason for it is that it is likely that things will
change. Using the types in FFI with an incorrect ABI will at best give
absolute nonsense results, but possibly cause serious breakage too, so
this is a step up in badness, hence a new feature gate.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/trans/foreign.rs34
-rw-r--r--src/libsyntax/feature_gate.rs4
-rw-r--r--src/test/compile-fail/feature-gate-simd-ffi.rs26
-rwxr-xr-xsrc/test/run-make/simd-ffi/simd.rs2
4 files changed, 64 insertions, 2 deletions
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index fb61bab6ade..abb961d87de 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 8929bbe0232..9231d4ad659 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<F>(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 00000000000..409c85b7198
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 d5945db9479..76079ddb8bd 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)]