diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 230e11f274eae..68f319ade1e79 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -164,7 +164,8 @@ pub fn target_machine_factory( let code_model = to_llvm_code_model(sess.code_model()); - let features = attributes::llvm_target_features(sess).collect::>(); + let mut features = llvm_util::handle_native_features(sess); + features.extend(attributes::llvm_target_features(sess).map(|s| s.to_owned())); let mut singlethread = sess.target.singlethread; // On the wasm target once the `atomics` feature is enabled that means that diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 707aaa2b53ffc..e359d9f8c9c77 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1708,6 +1708,10 @@ extern "C" { PM: &PassManager<'_>, ); + pub fn LLVMGetHostCPUFeatures() -> *mut c_char; + + pub fn LLVMDisposeMessage(message: *mut c_char); + // Stuff that's in llvm-wrapper/ because it's not upstream yet. /// Opens an object file. diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a3139ce5a3455..a9d57ea8b8aa4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -8,7 +8,7 @@ use rustc_session::config::PrintRequest; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; -use std::ffi::CString; +use std::ffi::{CStr, CString}; use std::slice; use std::str; @@ -221,6 +221,37 @@ pub fn target_cpu(sess: &Session) -> &str { handle_native(name) } +pub fn handle_native_features(sess: &Session) -> Vec { + match sess.opts.cg.target_cpu { + Some(ref s) => { + if s != "native" { + return vec![]; + } + + let features_string = unsafe { + let ptr = llvm::LLVMGetHostCPUFeatures(); + let features_string = if !ptr.is_null() { + CStr::from_ptr(ptr) + .to_str() + .unwrap_or_else(|e| { + bug!("LLVM returned a non-utf8 features string: {}", e); + }) + .to_owned() + } else { + bug!("could not allocate host CPU features, LLVM returned a `null` string"); + }; + + llvm::LLVMDisposeMessage(ptr); + + features_string + }; + + features_string.split(",").map(|s| s.to_owned()).collect() + } + None => vec![], + } +} + pub fn tune_cpu(sess: &Session) -> Option<&str> { match sess.opts.debugging_opts.tune_cpu { Some(ref s) => Some(handle_native(&**s)),