diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ef81cd3a4575e..c8c0d4c38a221 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -649,13 +649,6 @@ impl Session { } } - pub fn target_cpu(&self) -> &str { - match self.opts.cg.target_cpu { - Some(ref s) => &**s, - None => &*self.target.target.options.cpu - } - } - pub fn must_not_eliminate_frame_pointers(&self) -> bool { if let Some(x) = self.opts.cg.force_frame_pointers { x diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 2b64642b766ab..c8a2b47e98d77 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -124,7 +124,8 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { } pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { - let target_cpu = CString::new(cx.tcx.sess.target_cpu().to_string()).unwrap(); + let cpu = llvm_util::target_cpu(cx.tcx.sess); + let target_cpu = CString::new(cpu).unwrap(); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_llvm/back/linker.rs index a429e8f2d815d..eee60b262a1c7 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_llvm/back/linker.rs @@ -26,6 +26,7 @@ use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; +use llvm_util; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -202,7 +203,7 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", self.sess.target_cpu())); + self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); match self.sess.opts.cg.lto { config::Lto::Thin | diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 80e9965e39cd8..2373428d68c0d 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -25,6 +25,7 @@ use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; +use llvm_util; use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -173,7 +174,7 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) let singlethread = sess.target.target.options.singlethread; let triple = SmallCStr::new(&sess.target.target.llvm_target); - let cpu = SmallCStr::new(sess.target_cpu()); + let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = attributes::llvm_target_features(sess) .collect::>() .join(","); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index d3039a05b6db8..51b0299e63f46 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1449,6 +1449,7 @@ extern "C" { pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine); + pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char; pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index ff26e0f35f00f..9fcc33d82cfa4 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -17,6 +17,8 @@ use libc::c_int; use std::ffi::CString; use syntax::feature_gate::UnstableFeatures; +use std::str; +use std::slice; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; @@ -262,3 +264,19 @@ pub(crate) fn print(req: PrintRequest, sess: &Session) { } } } + +pub fn target_cpu(sess: &Session) -> &str { + let name = match sess.opts.cg.target_cpu { + Some(ref s) => &**s, + None => &*sess.target.target.options.cpu + }; + if name != "native" { + return name + } + + unsafe { + let mut len = 0; + let ptr = llvm::LLVMRustGetHostCPUName(&mut len); + str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap() + } +} diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 46825efeee276..09befdaae37c5 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -359,6 +359,12 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { } #endif +extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { + StringRef Name = sys::getHostCPUName(); + *len = Name.size(); + return Name.data(); +} + extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( const char *TripleStr, const char *CPU, const char *Feature, LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, @@ -381,11 +387,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( return nullptr; } - StringRef RealCPU = CPU; - if (RealCPU == "native") { - RealCPU = sys::getHostCPUName(); - } - TargetOptions Options; Options.FloatABIType = FloatABI::Default; @@ -417,7 +418,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( if (RustCM != LLVMRustCodeModel::None) CM = fromRust(RustCM); TargetMachine *TM = TheTarget->createTargetMachine( - Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel); + Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel); return wrap(TM); } diff --git a/src/test/run-make-fulldeps/target-cpu-native/Makefile b/src/test/run-make-fulldeps/target-cpu-native/Makefile index 0c9d93ecb2af7..fee41461612db 100644 --- a/src/test/run-make-fulldeps/target-cpu-native/Makefile +++ b/src/test/run-make-fulldeps/target-cpu-native/Makefile @@ -1,5 +1,20 @@ -include ../tools.mk -all: - $(RUSTC) foo.rs -C target-cpu=native +# I *really* don't want to deal with a cross-platform way to compare file sizes, +# tests in `make` sort of are awful +ifeq ($(TARGET),x86_64-unknown-linux-gnu) +all: $(TMPDIR)/out.log + # Make sure no warnings about "unknown CPU `native`" were emitted + if [ "$$(wc -c $(TMPDIR)/out.log | cut -d' ' -f 1)" = "0" ]; then \ + echo no warnings generated; \ + else \ + exit 1; \ + fi +else +all: $(TMPDIR)/out.log +endif + + +$(TMPDIR)/out.log: + $(RUSTC) foo.rs -C target-cpu=native 2>&1 | tee $(TMPDIR)/out.log $(call RUN,foo)