diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index b50dbd01ad0cc..2d63f69960f78 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -32,6 +32,11 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \ $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include) RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o) +# Flag that we are building with Rust's llvm fork +ifeq ($(CFG_LLVM_ROOT),) +RUSTLLVM_CXXFLAGS_$(1) := -DLLVM_RUSTLLVM +endif + # Note that we appease `cl.exe` and its need for some sort of exception # handling flag with the `EHsc` argument here as well. ifeq ($$(findstring msvc,$(1)),msvc) @@ -55,6 +60,7 @@ $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1)) $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \ $$(subst /,//,$$(LLVM_CXXFLAGS_$(1))) \ $$(RUSTLLVM_COMPONENTS_$(1)) \ + $$(RUSTLLVM_CXXFLAGS_$(1)) \ $$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \ $$(RUSTLLVM_INCS_$(1)) \ $$< diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 061192ebd1340..155848901cdb4 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -198,6 +198,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { if !build.unstable_features { cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); } + // Flag that rust llvm is in use + if build.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } cargo.env("LLVM_CONFIG", build.llvm_config(target)); if build.config.llvm_static_stdcpp { cargo.env("LLVM_STATIC_STDCPP", diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index acb7e0fadd90a..5d61abe5e086a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -727,6 +727,16 @@ impl Build { self.out.join(target).join("llvm") } + /// Returns true if no custom `llvm-config` is set for the specified target. + /// + /// If no custom `llvm-config` was specified then Rust's llvm will be used. + fn is_rust_llvm(&self, target: &str) -> bool { + match self.config.target_config.get(target) { + Some(ref c) => c.llvm_config.is_none(), + None => true + } + } + /// Returns the path to `llvm-config` for the specified target. /// /// If a custom `llvm-config` was specified for target then that's returned diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3984d2b3d008b..0fb4d0f8fea5e 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -176,6 +176,10 @@ pub enum PrintRequest { CrateName, Cfg, TargetList, + TargetCPUs, + TargetFeatures, + RelocationModels, + CodeModels, } pub enum Input { @@ -629,9 +633,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, lto: bool = (false, parse_bool, "perform LLVM link-time optimizations"), target_cpu: Option = (None, parse_opt_string, - "select target processor (llc -mcpu=help for details)"), + "select target processor (rustc --print target-cpus for details)"), target_feature: String = ("".to_string(), parse_string, - "target specific attributes (llc -mattr=help for details)"), + "target specific attributes (rustc --print target-features for details)"), passes: Vec = (Vec::new(), parse_list, "a list of extra LLVM passes to run (space separated)"), llvm_args: Vec = (Vec::new(), parse_list, @@ -655,9 +659,9 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, no_redzone: Option = (None, parse_opt_bool, "disable the use of the redzone"), relocation_model: Option = (None, parse_opt_string, - "choose the relocation model to use (llc -relocation-model for details)"), + "choose the relocation model to use (rustc --print relocation-models for details)"), code_model: Option = (None, parse_opt_string, - "choose the code model to use (llc -code-model for details)"), + "choose the code model to use (rustc --print code-models for details)"), metadata: Vec = (Vec::new(), parse_list, "metadata to mangle symbol names with"), extra_filename: String = ("".to_string(), parse_string, @@ -1024,7 +1028,8 @@ pub fn rustc_short_optgroups() -> Vec { "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), opt::multi_s("", "print", "Comma separated list of compiler information to \ print on stdout", - "[crate-name|file-names|sysroot|cfg|target-list]"), + "[crate-name|file-names|sysroot|cfg|target-list|target-cpus|\ + target-features|relocation-models|code-models]"), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), opt::opt_s("o", "", "Write output to ", "FILENAME"), @@ -1238,6 +1243,24 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { early_error(error_format, "Value for codegen units must be a positive nonzero integer"); } + let mut prints = Vec::::new(); + if cg.target_cpu.as_ref().map_or(false, |s| s == "help") { + prints.push(PrintRequest::TargetCPUs); + cg.target_cpu = None; + }; + if cg.target_feature == "help" { + prints.push(PrintRequest::TargetFeatures); + cg.target_feature = "".to_string(); + } + if cg.relocation_model.as_ref().map_or(false, |s| s == "help") { + prints.push(PrintRequest::RelocationModels); + cg.relocation_model = None; + } + if cg.code_model.as_ref().map_or(false, |s| s == "help") { + prints.push(PrintRequest::CodeModels); + cg.code_model = None; + } + let cg = cg; let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); @@ -1315,18 +1338,22 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); - let prints = matches.opt_strs("print").into_iter().map(|s| { + prints.extend(matches.opt_strs("print").into_iter().map(|s| { match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, "sysroot" => PrintRequest::Sysroot, "cfg" => PrintRequest::Cfg, "target-list" => PrintRequest::TargetList, + "target-cpus" => PrintRequest::TargetCPUs, + "target-features" => PrintRequest::TargetFeatures, + "relocation-models" => PrintRequest::RelocationModels, + "code-models" => PrintRequest::CodeModels, req => { early_error(error_format, &format!("unknown print request `{}`", req)) } } - }).collect::>(); + })); if !cg.remark.is_empty() && debuginfo == NoDebugInfo { early_warn(error_format, "-C remark will not show source locations without \ diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 80f1910906b4c..98860c8f900eb 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -68,6 +68,7 @@ use pretty::{PpMode, UserIdentifiedItem}; use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_trans::back::link; +use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; @@ -654,6 +655,28 @@ impl RustcDefaultCalls { } } } + PrintRequest::TargetCPUs => { + let tm = create_target_machine(sess); + unsafe { llvm::LLVMRustPrintTargetCPUs(tm); } + } + PrintRequest::TargetFeatures => { + let tm = create_target_machine(sess); + unsafe { llvm::LLVMRustPrintTargetFeatures(tm); } + } + PrintRequest::RelocationModels => { + println!("Available relocation models:"); + for &(name, _) in RELOC_MODEL_ARGS.iter() { + println!(" {}", name); + } + println!(""); + } + PrintRequest::CodeModels => { + println!("Available code models:"); + for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){ + println!(" {}", name); + } + println!(""); + } } } return Compilation::Stop; diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index b8548aaec5bd7..5f7a0f788ca12 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -112,6 +112,10 @@ fn main() { cfg.flag(&flag); } + if env::var_os("LLVM_RUSTLLVM").is_some() { + cfg.flag("-DLLVM_RUSTLLVM"); + } + cfg.file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") .file("../rustllvm/ArchiveWrapper.cpp") diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 6301c57c55540..b2ffcac365bad 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1940,6 +1940,9 @@ extern { pub fn LLVMRustHasFeature(T: TargetMachineRef, s: *const c_char) -> bool; + pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef); + pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef); + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, CPU: *const c_char, Features: *const c_char, diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 7025de523c378..b5c993b86ecb2 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -36,6 +36,21 @@ use std::sync::mpsc::channel; use std::thread; use libc::{c_uint, c_void}; +pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [ + ("pic", llvm::RelocMode::PIC), + ("static", llvm::RelocMode::Static), + ("default", llvm::RelocMode::Default), + ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic), +]; + +pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [ + ("default", llvm::CodeModel::Default), + ("small", llvm::CodeModel::Small), + ("kernel", llvm::CodeModel::Kernel), + ("medium", llvm::CodeModel::Medium), + ("large", llvm::CodeModel::Large), +]; + pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! { match llvm::last_error() { Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))), @@ -168,12 +183,9 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef { None => &sess.target.target.options.code_model[..], }; - let code_model = match code_model_arg { - "default" => llvm::CodeModel::Default, - "small" => llvm::CodeModel::Small, - "kernel" => llvm::CodeModel::Kernel, - "medium" => llvm::CodeModel::Medium, - "large" => llvm::CodeModel::Large, + let code_model = match CODE_GEN_MODEL_ARGS.iter().find( + |&&arg| arg.0 == code_model_arg) { + Some(x) => x.1, _ => { sess.err(&format!("{:?} is not a valid code model", sess.opts diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 97b03312d7963..65eea1bbb6337 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -337,16 +337,14 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { None => &sess.target.target.options.relocation_model[..], }; - match reloc_model_arg { - "pic" => llvm::RelocMode::PIC, - "static" => llvm::RelocMode::Static, - "default" => llvm::RelocMode::Default, - "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic, + match ::back::write::RELOC_MODEL_ARGS.iter().find( + |&&arg| arg.0 == reloc_model_arg) { + Some(x) => x.1, _ => { sess.err(&format!("{:?} is not a valid relocation mode", sess.opts .cg - .relocation_model)); + .code_model)); sess.abort_if_errors(); bug!(); } diff --git a/src/llvm b/src/llvm index d1cc48989b137..786aad117be48 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d +Subproject commit 786aad117be48547f4ca50fae84c4879fa992d4d diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3a20bb2714ece..0555a96ff24ce 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -226,6 +226,58 @@ from_rust(LLVMRustCodeGenOptLevel level) } } +#if LLVM_RUSTLLVM +/// getLongestEntryLength - Return the length of the longest entry in the table. +/// +static size_t getLongestEntryLength(ArrayRef Table) { + size_t MaxLen = 0; + for (auto &I : Table) + MaxLen = std::max(MaxLen, std::strlen(I.Key)); + return MaxLen; +} + +extern "C" void +LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) { + const TargetMachine *Target = unwrap(TM); + const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); + const ArrayRef CPUTable = MCInfo->getCPUTable(); + unsigned MaxCPULen = getLongestEntryLength(CPUTable); + + printf("Available CPUs for this target:\n"); + for (auto &CPU : CPUTable) + printf(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc); + printf("\n"); +} + +extern "C" void +LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { + const TargetMachine *Target = unwrap(TM); + const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo(); + const ArrayRef FeatTable = MCInfo->getFeatureTable(); + unsigned MaxFeatLen = getLongestEntryLength(FeatTable); + + printf("Available features for this target:\n"); + for (auto &Feature : FeatTable) + printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); + printf("\n"); + + printf("Use +feature to enable a feature, or -feature to disable it.\n" + "For example, rustc -C -target-cpu=mycpu -C target-feature=+feature1,-feature2\n\n"); +} + +#else + +extern "C" void +LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) { + printf("Target CPU help is not supported by this LLVM version.\n\n"); +} + +extern "C" void +LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) { + printf("Target features help is not supported by this LLVM version.\n\n"); +} +#endif + extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(const char *triple, const char *cpu, diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index e871763a48dc3..378810a8b89fc 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2016-07-25b +2016-08-07