From 622371153c66f9e371f587205d14040534060c18 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Apr 2018 15:17:07 -0700 Subject: [PATCH] Add `-C target-feature` to all functions Previously the features specified to LLVM via `-C target-feature` were only reflected in the `TargetMachine` but this change *also* reflects these and the base features inside each function itself. This change matches clang and... Closes rust-lang-nursery/stdsimd#427 --- src/librustc_trans/attributes.rs | 30 +++++++++++++----- src/librustc_trans/back/write.rs | 31 +++---------------- .../codegen/target-feature-on-functions.rs | 19 ++++++++++++ 3 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 src/test/codegen/target-feature-on-functions.rs diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index eb5c7396ae055..f455c19cc0bbe 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -14,6 +14,7 @@ use std::ffi::{CStr, CString}; use rustc::hir::{self, TransFnAttrFlags}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::session::Session; use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; @@ -104,6 +105,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { cstr("probe-stack\0"), cstr("__rust_probestack\0")); } +pub fn llvm_target_features(sess: &Session) -> impl Iterator { + const RUSTC_SPECIFIC_FEATURES: &[&str] = &[ + "crt-static", + ]; + + let cmdline = sess.opts.cg.target_feature.split(',') + .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s))); + sess.target.target.options.features.split(',') + .chain(cmdline) + .filter(|l| !l.is_empty()) +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { @@ -131,13 +144,16 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { unwind(llfn, false); } - let features = - trans_fn_attrs.target_features - .iter() - .map(|f| { - let feature = &*f.as_str(); - format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) - }) + let features = llvm_target_features(cx.tcx.sess) + .map(|s| s.to_string()) + .chain( + trans_fn_attrs.target_features + .iter() + .map(|f| { + let feature = &*f.as_str(); + format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) + }) + ) .collect::>() .join(","); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 613a07cd2695d..148e3d0025c83 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer}; use back::link::{self, get_linker, remove}; @@ -111,31 +112,6 @@ pub fn write_output_file( } } -// On android, we by default compile for armv7 processors. This enables -// things like double word CAS instructions (rather than emulating them) -// which are *far* more efficient. This is obviously undesirable in some -// cases, so if any sort of target feature is specified we don't append v7 -// to the feature list. -// -// On iOS only armv7 and newer are supported. So it is useful to -// get all hardware potential via VFP3 (hardware floating point) -// and NEON (SIMD) instructions supported by LLVM. -// Note that without those flags various linking errors might -// arise as some of intrinsics are converted into function calls -// and nobody provides implementations those functions -fn target_feature(sess: &Session) -> String { - let rustc_features = [ - "crt-static", - ]; - let requested_features = sess.opts.cg.target_feature.split(','); - let llvm_features = requested_features.filter(|f| { - !rustc_features.iter().any(|s| f.contains(s)) - }); - format!("{},{}", - sess.target.target.options.features, - llvm_features.collect::>().join(",")) -} - fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { match optimize { config::OptLevel::No => llvm::CodeGenOptLevel::None, @@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) None => &*sess.target.target.options.cpu }; let cpu = CString::new(cpu.as_bytes()).unwrap(); - let features = CString::new(target_feature(sess).as_bytes()).unwrap(); + let features = attributes::llvm_target_features(sess) + .collect::>() + .join(","); + let features = CString::new(features).unwrap(); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; diff --git a/src/test/codegen/target-feature-on-functions.rs b/src/test/codegen/target-feature-on-functions.rs new file mode 100644 index 0000000000000..e3cc2c753e55e --- /dev/null +++ b/src/test/codegen/target-feature-on-functions.rs @@ -0,0 +1,19 @@ +// Copyright 2017 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. + +// only-x86_64 +// compile-flags: -C target-feature=+avx + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} } +}