From 4f4425840dac441e1050319893882177d040c4f3 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Tue, 14 Jul 2015 15:49:03 -0700 Subject: [PATCH] Add some SIMD target_feature cfg's when appropriate. NB. this may not be 100% perfect. --- src/librustc_driver/lib.rs | 4 +- src/librustc_driver/target_features.rs | 98 ++++++++++++++++++++++++++ src/librustdoc/core.rs | 5 +- 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/librustc_driver/target_features.rs diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 1d440af26971..60eaffd71cbc 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -89,6 +89,7 @@ pub mod test; pub mod driver; pub mod pretty; +pub mod target_features; const BUG_REPORT_URL: &'static str = @@ -136,7 +137,8 @@ pub fn run_compiler<'a>(args: &[String], if sess.unstable_options() { sess.opts.show_span = matches.opt_str("show-span"); } - let cfg = config::build_configuration(&sess); + let mut cfg = config::build_configuration(&sess); + target_features::add_configuration(&mut cfg, &sess); do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile)); diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs new file mode 100644 index 000000000000..ca76046acf0f --- /dev/null +++ b/src/librustc_driver/target_features.rs @@ -0,0 +1,98 @@ +// 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. + +use syntax::{ast, attr}; +use rustc::session::Session; +use syntax::parse::token::InternedString; +use syntax::parse::token::intern_and_get_ident as intern; + +/// Add `target_feature = "..."` cfgs for a variety of platform +/// specific features (SSE, NEON etc.). +/// +/// This uses a scheme similar to that employed by clang: reimplement +/// the target feature knowledge. *Theoretically* we could query LLVM +/// since that has perfect knowledge about what things are enabled in +/// code-generation, however, it is extremely non-obvious how to do +/// this successfully. Each platform defines a subclass of a +/// SubtargetInfo, which knows all this information, but the ways to +/// query them do not seem to be public. +pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { + let tf = InternedString::new("target_feature"); + macro_rules! fillout { + ($($func: ident, $name: expr;)*) => {{ + $(if $func(sess) { + cfg.push(attr::mk_name_value_item_str(tf.clone(), intern($name))) + })* + }} + } + fillout! { + has_sse, "sse"; + has_sse2, "sse2"; + has_sse3, "sse3"; + has_ssse3, "ssse3"; + has_sse41, "sse4.1"; + has_sse42, "sse4.2"; + has_avx, "avx"; + has_avx2, "avx2"; + has_neon, "neon"; + has_vfp, "vfp"; + } +} + + +fn features_contain(sess: &Session, s: &str) -> bool { + sess.target.target.options.features.contains(s) || + sess.opts.cg.target_feature.contains(s) +} + +pub fn has_sse(sess: &Session) -> bool { + features_contain(sess, "+sse") || + has_sse2(sess) +} +pub fn has_sse2(sess: &Session) -> bool { + // x86-64 requires at least SSE2 support + sess.target.target.arch == "x86_64" || + features_contain(sess, "+sse2") || + has_sse3(sess) +} +pub fn has_sse3(sess: &Session) -> bool { + features_contain(sess, "+sse3") || + has_ssse3(sess) +} +pub fn has_ssse3(sess: &Session) -> bool { + features_contain(sess, "+ssse3") || + has_sse41(sess) +} +pub fn has_sse41(sess: &Session) -> bool { + features_contain(sess, "+sse4.1") || + has_sse42(sess) +} +pub fn has_sse42(sess: &Session) -> bool { + features_contain(sess, "+sse4.2") || + has_avx(sess) +} +pub fn has_avx(sess: &Session) -> bool { + features_contain(sess, "+avx") || + has_avx2(sess) +} +pub fn has_avx2(sess: &Session) -> bool { + features_contain(sess, "+avx2") +} + +pub fn has_neon(sess: &Session) -> bool { + // AArch64 requires NEON support + sess.target.target.arch == "aarch64" || + features_contain(sess, "+neon") +} +pub fn has_vfp(sess: &Session) -> bool { + // AArch64 requires VFP support + sess.target.target.arch == "aarch64" || + features_contain(sess, "+vfp") +} diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ba9caa2f3f35..81399938f27c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,7 +10,7 @@ pub use self::MaybeTyped::*; use rustc_lint; -use rustc_driver::driver; +use rustc_driver::{driver, target_features}; use rustc::session::{self, config}; use rustc::middle::{privacy, ty}; use rustc::ast_map; @@ -119,7 +119,8 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, span_diagnostic_handler); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - let cfg = config::build_configuration(&sess); + let mut cfg = config::build_configuration(&sess); + target_features::add_configuration(&mut cfg, &sess); let krate = driver::phase_1_parse_input(&sess, cfg, &input);