Skip to content

Commit

Permalink
Auto merge of rust-lang#50188 - alexcrichton:feature-all-the-things, …
Browse files Browse the repository at this point in the history
…r=eddyb

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/stdarch#427
  • Loading branch information
bors committed Apr 28, 2018
2 parents 66363b2 + 6223711 commit f4c1f0c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 33 deletions.
30 changes: 23 additions & 7 deletions src/librustc_trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Item = &str> {
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) {
Expand Down Expand Up @@ -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::<Vec<String>>()
.join(",");

Expand Down
31 changes: 5 additions & 26 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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::<Vec<_>>().join(","))
}

fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
match optimize {
config::OptLevel::No => llvm::CodeGenOptLevel::None,
Expand Down Expand Up @@ -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::<Vec<_>>()
.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;

Expand Down
19 changes: 19 additions & 0 deletions src/test/codegen/target-feature-on-functions.rs
Original file line number Diff line number Diff line change
@@ -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 <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.

// only-x86_64
// compile-flags: -C target-feature=+avx

#![crate_type = "lib"]

#[no_mangle]
pub fn foo() {
// CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} }
}

0 comments on commit f4c1f0c

Please sign in to comment.