diff options
| author | bors <bors@rust-lang.org> | 2015-08-17 23:41:36 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-08-17 23:41:36 +0000 |
| commit | e35fd748114c22df6d08991980c4f7e199414497 (patch) | |
| tree | 1741be330092cf63fa429a6c529430a55db52a54 /src/libsyntax | |
| parent | 6d992728c331128810704d16d8026aa4fa2e0c87 (diff) | |
| parent | 02e97342c136d2d13411ebd0a687100d8be248e0 (diff) | |
| download | rust-e35fd748114c22df6d08991980c4f7e199414497.tar.gz rust-e35fd748114c22df6d08991980c4f7e199414497.zip | |
Auto merge of #27169 - huonw:simd, r=alexcrichton
This implements https://github.com/rust-lang/rfcs/pull/1199 (except for doing all the platform intrinsics). Things remaining for SIMD (not necessarily in this PR): - [x] I (@huonw) am signed up to ensure the compiler matches the RFC, when it lands - [x] the platform specific intrinsics aren't properly type checked at the moment (LLVM will throw a "random" assertion) - [ ] there's a lot of useful intrinsics that are missing, including whole platforms (mips, powerpc) - [ ] the target-feature `cfg` detection/adding is not so great at the moment - [x] I think the platform specific intrinsics should go in their own `extern` ABI (i.e. not `"rust-intrinsic"`) (I'm adjusting the RFC to reflect the latter.) I think it would be very nice for this to land without requiring the RFC to land first, because of the first point, and because this is the only way for any further work to happen/be experimented with, without requiring people to build/install/multirust a compiler from a custom branch. r? @alexcrichton
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/abi.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/cfg.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 94 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 4 |
10 files changed, 168 insertions, 29 deletions
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 50c86a80b4a..c0fe541ead5 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -47,6 +47,7 @@ pub enum Abi { System, RustIntrinsic, RustCall, + PlatformIntrinsic, } #[allow(non_camel_case_types)] @@ -95,6 +96,7 @@ const AbiDatas: &'static [AbiData] = &[ AbiData {abi: System, name: "system" }, AbiData {abi: RustIntrinsic, name: "rust-intrinsic" }, AbiData {abi: RustCall, name: "rust-call" }, + AbiData {abi: PlatformIntrinsic, name: "platform-intrinsic" } ]; /// Returns the ABI with the given name (if any). diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0bcd97cfe87..2d72c8fe2a4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1339,6 +1339,15 @@ impl IntTy { TyI16 | TyI32 | TyI64 => 3, } } + pub fn bit_width(&self) -> Option<usize> { + Some(match *self { + TyIs => return None, + TyI8 => 8, + TyI16 => 16, + TyI32 => 32, + TyI64 => 64, + }) + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] @@ -1357,6 +1366,15 @@ impl UintTy { TyU16 | TyU32 | TyU64 => 3, } } + pub fn bit_width(&self) -> Option<usize> { + Some(match *self { + TyUs => return None, + TyU8 => 8, + TyU16 => 16, + TyU32 => 32, + TyU64 => 64, + }) + } } impl fmt::Debug for UintTy { @@ -1395,6 +1413,12 @@ impl FloatTy { TyF32 | TyF64 => 3, // add F128 handling here } } + pub fn bit_width(&self) -> usize { + match *self { + TyF32 => 32, + TyF64 => 64, + } + } } // Bind a type to an associated type: `A=Foo`. diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 5e16465b4d4..7540c2ff831 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -19,6 +19,7 @@ use ast::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, Meta use codemap::{Span, Spanned, spanned, dummy_spanned}; use codemap::BytePos; use diagnostic::SpanHandler; +use feature_gate::GatedCfg; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use parse::token::{InternedString, intern_and_get_ident}; use parse::token; @@ -357,24 +358,28 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { } /// Tests if a cfg-pattern matches the cfg set -pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::MetaItem) -> bool { +pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::MetaItem, + feature_gated_cfgs: &mut Vec<GatedCfg>) -> bool { match cfg.node { ast::MetaList(ref pred, ref mis) if &pred[..] == "any" => - mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)), ast::MetaList(ref pred, ref mis) if &pred[..] == "all" => - mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi, feature_gated_cfgs)), ast::MetaList(ref pred, ref mis) if &pred[..] == "not" => { if mis.len() != 1 { diagnostic.span_err(cfg.span, "expected 1 cfg-pattern"); return false; } - !cfg_matches(diagnostic, cfgs, &*mis[0]) + !cfg_matches(diagnostic, cfgs, &*mis[0], feature_gated_cfgs) } ast::MetaList(ref pred, _) => { diagnostic.span_err(cfg.span, &format!("invalid predicate `{}`", pred)); false }, - ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg), + ast::MetaWord(_) | ast::MetaNameValue(..) => { + feature_gated_cfgs.extend(GatedCfg::gate(cfg)); + contains(cfgs, cfg) + } } } @@ -579,6 +584,7 @@ pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec<ReprAt // Can't use "extern" because it's not a lexical identifier. "C" => Some(ReprExtern), "packed" => Some(ReprPacked), + "simd" => Some(ReprSimd), _ => match int_type_of_word(&word) { Some(ity) => Some(ReprInt(item.span, ity)), None => { @@ -628,6 +634,7 @@ pub enum ReprAttr { ReprInt(Span, IntType), ReprExtern, ReprPacked, + ReprSimd, } impl ReprAttr { @@ -636,7 +643,8 @@ impl ReprAttr { ReprAny => false, ReprInt(_sp, ity) => ity.is_ffi_safe(), ReprExtern => true, - ReprPacked => false + ReprPacked => false, + ReprSimd => true, } } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 366806bc19b..faf0b51c8de 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -10,6 +10,7 @@ use attr::AttrMetaMethods; use diagnostic::SpanHandler; +use feature_gate::GatedCfg; use fold::Folder; use {ast, fold, attr}; use codemap::{Spanned, respan}; @@ -25,10 +26,13 @@ struct Context<F> where F: FnMut(&[ast::Attribute]) -> bool { // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration -pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { - let krate = process_cfg_attr(diagnostic, krate); +pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate, + feature_gated_cfgs: &mut Vec<GatedCfg>) + -> ast::Crate +{ + let krate = process_cfg_attr(diagnostic, krate, feature_gated_cfgs); let config = krate.config.clone(); - strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs)) + strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs, feature_gated_cfgs)) } impl<F> fold::Folder for Context<F> where F: FnMut(&[ast::Attribute]) -> bool { @@ -248,7 +252,8 @@ fn foreign_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ForeignItem) -> bool // Determine if an item should be translated in the current crate // configuration based on the item's attributes -fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool { +fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute], + feature_gated_cfgs: &mut Vec<GatedCfg>) -> bool { attrs.iter().all(|attr| { let mis = match attr.node.value.node { ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis, @@ -260,25 +265,29 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attr return true; } - attr::cfg_matches(diagnostic, cfg, &*mis[0]) + attr::cfg_matches(diagnostic, cfg, &*mis[0], + feature_gated_cfgs) }) } -struct CfgAttrFolder<'a> { +struct CfgAttrFolder<'a, 'b> { diag: &'a SpanHandler, config: ast::CrateConfig, + feature_gated_cfgs: &'b mut Vec<GatedCfg> } // Process `#[cfg_attr]`. -fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { +fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate, + feature_gated_cfgs: &mut Vec<GatedCfg>) -> ast::Crate { let mut fld = CfgAttrFolder { diag: diagnostic, config: krate.config.clone(), + feature_gated_cfgs: feature_gated_cfgs, }; fld.fold_crate(krate) } -impl<'a> fold::Folder for CfgAttrFolder<'a> { +impl<'a,'b> fold::Folder for CfgAttrFolder<'a,'b> { fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> { if !attr.check_name("cfg_attr") { return fold::noop_fold_attribute(attr, self); @@ -299,7 +308,8 @@ impl<'a> fold::Folder for CfgAttrFolder<'a> { } }; - if attr::cfg_matches(self.diag, &self.config[..], &cfg) { + if attr::cfg_matches(self.diag, &self.config[..], &cfg, + self.feature_gated_cfgs) { Some(respan(mi.span, ast::Attribute_ { id: attr::mk_attr_id(), style: attr.node.style, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index d4b5e67eeb4..ef11a2bd66e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -17,6 +17,7 @@ use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion}; use ext; use ext::expand; use ext::tt::macro_rules; +use feature_gate::GatedCfg; use parse; use parse::parser; use parse::token; @@ -632,6 +633,7 @@ pub struct ExtCtxt<'a> { pub backtrace: ExpnId, pub ecfg: expand::ExpansionConfig<'a>, pub crate_root: Option<&'static str>, + pub feature_gated_cfgs: &'a mut Vec<GatedCfg>, pub mod_path: Vec<ast::Ident> , pub exported_macros: Vec<ast::MacroDef>, @@ -642,7 +644,8 @@ pub struct ExtCtxt<'a> { impl<'a> ExtCtxt<'a> { pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, - ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> { + ecfg: expand::ExpansionConfig<'a>, + feature_gated_cfgs: &'a mut Vec<GatedCfg>) -> ExtCtxt<'a> { let env = initial_syntax_expander_table(&ecfg); ExtCtxt { parse_sess: parse_sess, @@ -651,6 +654,7 @@ impl<'a> ExtCtxt<'a> { mod_path: Vec::new(), ecfg: ecfg, crate_root: None, + feature_gated_cfgs: feature_gated_cfgs, exported_macros: Vec::new(), syntax_env: env, recursion_count: 0, diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index 8af7fb7b268..aa654e30530 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -34,6 +34,7 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, return DummyResult::expr(sp); } - let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg); + let matches_cfg = attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &*cfg, + cx.feature_gated_cfgs); MacEager::expr(cx.expr_bool(sp, matches_cfg)) } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 1f4860b7ec1..f8f63e94ee5 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -739,7 +739,7 @@ fn find_repr_type_name(diagnostic: &SpanHandler, for a in type_attrs { for r in &attr::find_repr_attrs(diagnostic, a) { repr_type_name = match *r { - attr::ReprAny | attr::ReprPacked => continue, + attr::ReprAny | attr::ReprPacked | attr::ReprSimd => continue, attr::ReprExtern => "i32", attr::ReprInt(_, attr::SignedInt(ast::TyIs)) => "isize", diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e61a0b5401e..4f89b3494d4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -21,7 +21,7 @@ use attr::AttrMetaMethods; use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute, CompilerExpansion}; use ext::base::*; -use feature_gate::{self, Features}; +use feature_gate::{self, Features, GatedCfg}; use fold; use fold::*; use parse; @@ -1687,8 +1687,10 @@ pub fn expand_crate<'feat>(parse_sess: &parse::ParseSess, // these are the macros being imported to this crate: imported_macros: Vec<ast::MacroDef>, user_exts: Vec<NamedSyntaxExtension>, + feature_gated_cfgs: &mut Vec<GatedCfg>, c: Crate) -> Crate { - let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); + let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg, + feature_gated_cfgs); if std_inject::no_core(&c) { cx.crate_root = None; } else if std_inject::no_std(&c) { @@ -1878,7 +1880,7 @@ mod tests { src, Vec::new(), &sess); // should fail: - expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast); } // make sure that macros can't escape modules @@ -1891,7 +1893,7 @@ mod tests { "<test>".to_string(), src, Vec::new(), &sess); - expand_crate(&sess,test_ecfg(),vec!(),vec!(),crate_ast); + expand_crate(&sess,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast); } // macro_use modules should allow macros to escape @@ -1903,14 +1905,14 @@ mod tests { "<test>".to_string(), src, Vec::new(), &sess); - expand_crate(&sess, test_ecfg(), vec!(), vec!(), crate_ast); + expand_crate(&sess, test_ecfg(), vec!(), vec!(), &mut vec![], crate_ast); } fn expand_crate_str(crate_str: String) -> ast::Crate { let ps = parse::ParseSess::new(); let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod()); // the cfg argument actually does matter, here... - expand_crate(&ps,test_ecfg(),vec!(),vec!(),crate_ast) + expand_crate(&ps,test_ecfg(),vec!(),vec!(), &mut vec![], crate_ast) } // find the pat_ident paths in a crate diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 694a1a43f59..f5a0a2f4718 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -37,6 +37,7 @@ use visit::Visitor; use parse::token::{self, InternedString}; use std::ascii::AsciiExt; +use std::cmp; // If you change this list without updating src/doc/reference.md, @cmr will be sad // Don't ever remove anything from this list; set them to 'Removed'. @@ -177,6 +178,15 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[ // Allows macros to appear in the type position. ("type_macros", "1.3.0", Active), + + // allow `repr(simd)`, and importing the various simd intrinsics + ("repr_simd", "1.4.0", Active), + + // Allows cfg(target_feature = "..."). + ("cfg_target_feature", "1.4.0", Active), + + // allow `extern "platform-intrinsic" { ... }` + ("platform_intrinsics", "1.4.0", Active), ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -324,6 +334,59 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType)] = &[ ("recursion_limit", CrateLevel), ]; +macro_rules! cfg_fn { + (|$x: ident| $e: expr) => {{ + fn f($x: &Features) -> bool { + $e + } + f as fn(&Features) -> bool + }} +} +// cfg(...)'s that are feature gated +const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[ + // (name in cfg, feature, function to check if the feature is enabled) + ("target_feature", "cfg_target_feature", cfg_fn!(|x| x.cfg_target_feature)), +]; + +#[derive(Debug, Eq, PartialEq)] +pub struct GatedCfg { + span: Span, + index: usize, +} +impl Ord for GatedCfg { + fn cmp(&self, other: &GatedCfg) -> cmp::Ordering { + (self.span.lo.0, self.span.hi.0, self.index) + .cmp(&(other.span.lo.0, other.span.hi.0, other.index)) + } +} +impl PartialOrd for GatedCfg { + fn partial_cmp(&self, other: &GatedCfg) -> Option<cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl GatedCfg { + pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> { + let name = cfg.name(); + GATED_CFGS.iter() + .position(|info| info.0 == name) + .map(|idx| { + GatedCfg { + span: cfg.span, + index: idx + } + }) + } + pub fn check_and_emit(&self, diagnostic: &SpanHandler, features: &Features) { + let (cfg, feature, has_feature) = GATED_CFGS[self.index]; + if !has_feature(features) { + let explain = format!("`cfg({})` is experimental and subject to change", cfg); + emit_feature_err(diagnostic, feature, self.span, &explain); + } + } +} + + #[derive(PartialEq, Copy, Clone, Debug)] pub enum AttributeType { /// Normal, builtin attribute that is consumed @@ -369,6 +432,7 @@ pub struct Features { pub static_recursion: bool, pub default_type_parameter_fallback: bool, pub type_macros: bool, + pub cfg_target_feature: bool, } impl Features { @@ -396,6 +460,7 @@ impl Features { static_recursion: false, default_type_parameter_fallback: false, type_macros: false, + cfg_target_feature: false, } } } @@ -630,10 +695,16 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { across platforms, it is recommended to \ use `#[link(name = \"foo\")]` instead") } - if foreign_module.abi == Abi::RustIntrinsic { - self.gate_feature("intrinsics", - i.span, - "intrinsics are subject to change") + let maybe_feature = match foreign_module.abi { + Abi::RustIntrinsic => Some(("intrinsics", "intrinsics are subject to change")), + Abi::PlatformIntrinsic => { + Some(("platform_intrinsics", + "platform intrinsics are experimental and possibly buggy")) + } + _ => None + }; + if let Some((feature, msg)) = maybe_feature { + self.gate_feature(feature, i.span, msg) } } @@ -660,6 +731,20 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { if attr::contains_name(&i.attrs[..], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); + self.context.span_handler.span_warn(i.span, + "the `#[simd]` attribute is deprecated, \ + use `#[repr(simd)]` instead"); + } + for attr in &i.attrs { + if attr.name() == "repr" { + for item in attr.meta_item_list().unwrap_or(&[]) { + if item.name() == "simd" { + self.gate_feature("repr_simd", i.span, + "SIMD types are experimental and possibly buggy"); + + } + } + } } } @@ -900,6 +985,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, static_recursion: cx.has_feature("static_recursion"), default_type_parameter_fallback: cx.has_feature("default_type_parameter_fallback"), type_macros: cx.has_feature("type_macros"), + cfg_target_feature: cx.has_feature("cfg_target_feature"), } } diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index ea99291d6c2..26fb287ce35 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -246,11 +246,13 @@ fn generate_test_harness(sess: &ParseSess, krate: ast::Crate, cfg: &ast::CrateConfig, sd: &diagnostic::SpanHandler) -> ast::Crate { + let mut feature_gated_cfgs = vec![]; let mut cx: TestCtxt = TestCtxt { sess: sess, span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, cfg.clone(), - ExpansionConfig::default("test".to_string())), + ExpansionConfig::default("test".to_string()), + &mut feature_gated_cfgs), path: Vec::new(), testfns: Vec::new(), reexport_test_harness_main: reexport_test_harness_main, |
