From 1fd45a13dee17701fc0aeaa847c1919d485d09fd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 23 Aug 2018 11:03:22 -0700 Subject: [PATCH] Fix warnings about the `native` target-cpu This fixes a regression from #53031 where specifying `-C target-cpu=native` is printing a lot of warnings from LLVM about `native` being an unknown CPU. It turns out that `native` is indeed an unknown CPU and we have to perform a mapping to an actual CPU name, but this mapping is only performed in one location rather than all locations we inform LLVM about the target CPU. This commit centralizes the mapping of `native` to LLVM's value of the native CPU, ensuring that all locations we inform LLVM about the `target-cpu` it's never `native`. Closes #53322 --- src/librustc/session/mod.rs | 7 ------- src/librustc_codegen_llvm/attributes.rs | 3 ++- src/librustc_codegen_llvm/back/linker.rs | 3 ++- src/librustc_codegen_llvm/back/write.rs | 3 ++- src/librustc_codegen_llvm/llvm/ffi.rs | 1 + src/librustc_codegen_llvm/llvm_util.rs | 18 ++++++++++++++++++ src/rustllvm/PassWrapper.cpp | 13 +++++++------ .../target-cpu-native/Makefile | 19 +++++++++++++++++-- 8 files changed, 49 insertions(+), 18 deletions(-) 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)