Skip to content

Commit 92e24b9

Browse files
committed
Expose the features computed from LLVM in cfg!
Instead of relying on the features explicitly passed through the command line, compute them from the LLVM `TargetMachine`.
1 parent c883463 commit 92e24b9

File tree

1 file changed

+31
-63
lines changed

1 file changed

+31
-63
lines changed

src/librustc_driver/target_features.rs

Lines changed: 31 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -9,79 +9,47 @@
99
// except according to those terms.
1010

1111
use syntax::{ast, attr};
12+
use llvm::LLVMRustHasFeature;
1213
use rustc::session::Session;
14+
use rustc_trans::back::write::create_target_machine;
1315
use syntax::parse::token::InternedString;
1416
use syntax::parse::token::intern_and_get_ident as intern;
17+
use libc::c_char;
1518

1619
/// Add `target_feature = "..."` cfgs for a variety of platform
1720
/// specific features (SSE, NEON etc.).
1821
///
19-
/// This uses a scheme similar to that employed by clang: reimplement
20-
/// the target feature knowledge. *Theoretically* we could query LLVM
21-
/// since that has perfect knowledge about what things are enabled in
22-
/// code-generation, however, it is extremely non-obvious how to do
23-
/// this successfully. Each platform defines a subclass of a
24-
/// SubtargetInfo, which knows all this information, but the ways to
25-
/// query them do not seem to be public.
22+
/// This is performed by checking whether a whitelisted set of
23+
/// features is available on the target machine, by querying LLVM.
2624
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
27-
let tf = InternedString::new("target_feature");
28-
macro_rules! fillout {
29-
($($func: ident, $name: expr;)*) => {{
30-
$(if $func(sess) {
31-
cfg.push(attr::mk_name_value_item_str(tf.clone(), intern($name)))
32-
})*
33-
}}
34-
}
35-
fillout! {
36-
has_sse, "sse";
37-
has_sse2, "sse2";
38-
has_sse3, "sse3";
39-
has_ssse3, "ssse3";
40-
has_sse41, "sse4.1";
41-
has_sse42, "sse4.2";
42-
has_avx, "avx";
43-
has_avx2, "avx2";
44-
has_neon, "neon";
45-
has_vfp, "vfp";
46-
}
47-
}
25+
let target_machine = create_target_machine(sess);
4826

27+
let arm_whitelist = [
28+
"neon\0",
29+
"vfp\0",
30+
];
4931

50-
fn features_contain(sess: &Session, s: &str) -> bool {
51-
sess.target.target.options.features.contains(s) || sess.opts.cg.target_feature.contains(s)
52-
}
32+
let x86_whitelist = [
33+
"avx\0",
34+
"avx2\0",
35+
"sse\0",
36+
"sse2\0",
37+
"sse3\0",
38+
"sse4.1\0",
39+
"sse4.2\0",
40+
"ssse3\0",
41+
];
5342

54-
pub fn has_sse(sess: &Session) -> bool {
55-
features_contain(sess, "+sse") || has_sse2(sess)
56-
}
57-
pub fn has_sse2(sess: &Session) -> bool {
58-
// x86-64 requires at least SSE2 support
59-
sess.target.target.arch == "x86_64" || features_contain(sess, "+sse2") || has_sse3(sess)
60-
}
61-
pub fn has_sse3(sess: &Session) -> bool {
62-
features_contain(sess, "+sse3") || has_ssse3(sess)
63-
}
64-
pub fn has_ssse3(sess: &Session) -> bool {
65-
features_contain(sess, "+ssse3") || has_sse41(sess)
66-
}
67-
pub fn has_sse41(sess: &Session) -> bool {
68-
features_contain(sess, "+sse4.1") || has_sse42(sess)
69-
}
70-
pub fn has_sse42(sess: &Session) -> bool {
71-
features_contain(sess, "+sse4.2") || has_avx(sess)
72-
}
73-
pub fn has_avx(sess: &Session) -> bool {
74-
features_contain(sess, "+avx") || has_avx2(sess)
75-
}
76-
pub fn has_avx2(sess: &Session) -> bool {
77-
features_contain(sess, "+avx2")
78-
}
43+
let whitelist = match &*sess.target.target.arch {
44+
"arm" => &arm_whitelist[..],
45+
"x86" | "x86_64" => &x86_whitelist[..],
46+
_ => &[][..],
47+
};
7948

80-
pub fn has_neon(sess: &Session) -> bool {
81-
// AArch64 requires NEON support
82-
sess.target.target.arch == "aarch64" || features_contain(sess, "+neon")
83-
}
84-
pub fn has_vfp(sess: &Session) -> bool {
85-
// AArch64 requires VFP support
86-
sess.target.target.arch == "aarch64" || features_contain(sess, "+vfp")
49+
let tf = InternedString::new("target_feature");
50+
for feat in whitelist {
51+
if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
52+
cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(feat)))
53+
}
54+
}
8755
}

0 commit comments

Comments
 (0)