Skip to content

Commit 6223711

Browse files
committed
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
1 parent 68a09fc commit 6223711

File tree

3 files changed

+47
-33
lines changed

3 files changed

+47
-33
lines changed

src/librustc_trans/attributes.rs

+23-7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::ffi::{CStr, CString};
1414
use rustc::hir::{self, TransFnAttrFlags};
1515
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
1616
use rustc::hir::itemlikevisit::ItemLikeVisitor;
17+
use rustc::session::Session;
1718
use rustc::session::config::Sanitizer;
1819
use rustc::ty::TyCtxt;
1920
use rustc::ty::maps::Providers;
@@ -104,6 +105,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
104105
cstr("probe-stack\0"), cstr("__rust_probestack\0"));
105106
}
106107

108+
pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
109+
const RUSTC_SPECIFIC_FEATURES: &[&str] = &[
110+
"crt-static",
111+
];
112+
113+
let cmdline = sess.opts.cg.target_feature.split(',')
114+
.filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
115+
sess.target.target.options.features.split(',')
116+
.chain(cmdline)
117+
.filter(|l| !l.is_empty())
118+
}
119+
107120
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
108121
/// attributes.
109122
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) {
131144
unwind(llfn, false);
132145
}
133146

134-
let features =
135-
trans_fn_attrs.target_features
136-
.iter()
137-
.map(|f| {
138-
let feature = &*f.as_str();
139-
format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
140-
})
147+
let features = llvm_target_features(cx.tcx.sess)
148+
.map(|s| s.to_string())
149+
.chain(
150+
trans_fn_attrs.target_features
151+
.iter()
152+
.map(|f| {
153+
let feature = &*f.as_str();
154+
format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
155+
})
156+
)
141157
.collect::<Vec<String>>()
142158
.join(",");
143159

src/librustc_trans/back/write.rs

+5-26
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use attributes;
1112
use back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
1213
use back::lto::{self, ModuleBuffer, ThinBuffer};
1314
use back::link::{self, get_linker, remove};
@@ -111,31 +112,6 @@ pub fn write_output_file(
111112
}
112113
}
113114

114-
// On android, we by default compile for armv7 processors. This enables
115-
// things like double word CAS instructions (rather than emulating them)
116-
// which are *far* more efficient. This is obviously undesirable in some
117-
// cases, so if any sort of target feature is specified we don't append v7
118-
// to the feature list.
119-
//
120-
// On iOS only armv7 and newer are supported. So it is useful to
121-
// get all hardware potential via VFP3 (hardware floating point)
122-
// and NEON (SIMD) instructions supported by LLVM.
123-
// Note that without those flags various linking errors might
124-
// arise as some of intrinsics are converted into function calls
125-
// and nobody provides implementations those functions
126-
fn target_feature(sess: &Session) -> String {
127-
let rustc_features = [
128-
"crt-static",
129-
];
130-
let requested_features = sess.opts.cg.target_feature.split(',');
131-
let llvm_features = requested_features.filter(|f| {
132-
!rustc_features.iter().any(|s| f.contains(s))
133-
});
134-
format!("{},{}",
135-
sess.target.target.options.features,
136-
llvm_features.collect::<Vec<_>>().join(","))
137-
}
138-
139115
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
140116
match optimize {
141117
config::OptLevel::No => llvm::CodeGenOptLevel::None,
@@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool)
203179
None => &*sess.target.target.options.cpu
204180
};
205181
let cpu = CString::new(cpu.as_bytes()).unwrap();
206-
let features = CString::new(target_feature(sess).as_bytes()).unwrap();
182+
let features = attributes::llvm_target_features(sess)
183+
.collect::<Vec<_>>()
184+
.join(",");
185+
let features = CString::new(features).unwrap();
207186
let is_pie_binary = !find_features && is_pie_binary(sess);
208187
let trap_unreachable = sess.target.target.options.trap_unreachable;
209188

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2017 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+
// only-x86_64
12+
// compile-flags: -C target-feature=+avx
13+
14+
#![crate_type = "lib"]
15+
16+
#[no_mangle]
17+
pub fn foo() {
18+
// CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} }
19+
}

0 commit comments

Comments
 (0)