Skip to content

Commit c8e0e95

Browse files
committed
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.
1 parent 4f08de8 commit c8e0e95

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

src/librustc_trans/trans/foreign.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use syntax::parse::token::{InternedString, special_idents};
3636
use syntax::parse::token;
3737
use syntax::{ast};
3838
use syntax::{attr, ast_map};
39+
use syntax::print::pprust;
3940
use util::ppaux::Repr;
4041

4142
///////////////////////////////////////////////////////////////////////////
@@ -426,16 +427,47 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
426427
return bcx;
427428
}
428429

430+
// feature gate SIMD types in FFI, since I (huonw) am not sure the
431+
// ABIs are handled at all correctly.
432+
fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
433+
if !tcx.sess.features.borrow().simd_ffi {
434+
let check = |&: ast_ty: &ast::Ty, ty: ty::Ty| {
435+
if ty::type_is_simd(tcx, ty) {
436+
tcx.sess.span_err(ast_ty.span,
437+
&format!("use of SIMD type `{}` in FFI is highly experimental and \
438+
may result in invalid code",
439+
pprust::ty_to_string(ast_ty))[]);
440+
tcx.sess.span_help(ast_ty.span,
441+
"add #![feature(simd_ffi)] to the crate attributes to enable");
442+
}
443+
};
444+
let sig = &ty.sig.0;
445+
for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) {
446+
check(&*input.ty, *ty)
447+
}
448+
match decl.output {
449+
ast::NoReturn(_) => {}
450+
ast::Return(ref ty) => check(&**ty, sig.output.unwrap())
451+
}
452+
}
453+
}
454+
429455
pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
430456
let _icx = push_ctxt("foreign::trans_foreign_mod");
431457
for foreign_item in foreign_mod.items.iter() {
432458
let lname = link_name(&**foreign_item);
433459

434-
if let ast::ForeignItemFn(..) = foreign_item.node {
460+
if let ast::ForeignItemFn(ref decl, _) = foreign_item.node {
435461
match foreign_mod.abi {
436462
Rust | RustIntrinsic => {}
437463
abi => {
438464
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
465+
match ty.sty {
466+
ty::ty_bare_fn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
467+
_ => ccx.tcx().sess.span_bug(foreign_item.span,
468+
"foreign fn's sty isn't a bare_fn_ty?")
469+
}
470+
439471
register_foreign_item_fn(ccx, abi, ty,
440472
&lname.get()[]);
441473
// Unlike for other items, we shouldn't call

src/libsyntax/feature_gate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
7272
("slicing_syntax", Active),
7373
("box_syntax", Active),
7474
("on_unimplemented", Active),
75+
("simd_ffi", Active),
7576

7677
("if_let", Accepted),
7778
("while_let", Accepted),
@@ -128,6 +129,7 @@ pub struct Features {
128129
pub visible_private_types: bool,
129130
pub quote: bool,
130131
pub old_orphan_check: bool,
132+
pub simd_ffi: bool,
131133
}
132134

133135
impl Features {
@@ -139,6 +141,7 @@ impl Features {
139141
visible_private_types: false,
140142
quote: false,
141143
old_orphan_check: false,
144+
simd_ffi: false,
142145
}
143146
}
144147
}
@@ -524,6 +527,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
524527
visible_private_types: cx.has_feature("visible_private_types"),
525528
quote: cx.has_feature("quote"),
526529
old_orphan_check: cx.has_feature("old_orphan_check"),
530+
simd_ffi: cx.has_feature("simd_ffi"),
527531
},
528532
unknown_features)
529533
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(simd)]
12+
#![allow(dead_code)]
13+
14+
use std::simd::f32x4;
15+
16+
#[simd] #[derive(Copy)] #[repr(C)] struct LocalSimd(u8, u8);
17+
18+
extern {
19+
fn foo() -> f32x4; //~ ERROR use of SIMD type
20+
fn bar(x: f32x4); //~ ERROR use of SIMD type
21+
22+
fn baz() -> LocalSimd; //~ ERROR use of SIMD type
23+
fn qux(x: LocalSimd); //~ ERROR use of SIMD type
24+
}
25+
26+
fn main() {}

src/test/run-make/simd-ffi/simd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// cross-compiled standard libraries.
1515
#![no_std]
1616

17-
#![feature(simd, link_llvm_intrinsics, lang_items)]
17+
#![feature(simd, simd_ffi, link_llvm_intrinsics, lang_items)]
1818

1919

2020
#[repr(C)]

0 commit comments

Comments
 (0)