From e3f6e68d633040be0b88a0e11e6645bc506f8655 Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Sun, 30 Apr 2017 20:33:25 +0200 Subject: [PATCH] Remove (direct) rustc_llvm dependency from rustc_driver This does not actually improve build times, since it still depends on rustc_trans, but is better layering and fits the multi-backend future slightly better. --- src/Cargo.lock | 1 - src/librustc/session/config.rs | 2 +- src/librustc_driver/Cargo.toml | 1 - src/librustc_driver/lib.rs | 25 ++--- src/librustc_driver/target_features.rs | 34 +------ src/librustc_trans/lib.rs | 54 +---------- src/librustc_trans/llvm_util.rs | 125 +++++++++++++++++++++++++ 7 files changed, 139 insertions(+), 103 deletions(-) create mode 100644 src/librustc_trans/llvm_util.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 8bf360751c5..05b99b07007 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -560,7 +560,6 @@ dependencies = [ "rustc_errors 0.0.0", "rustc_incremental 0.0.0", "rustc_lint 0.0.0", - "rustc_llvm 0.0.0", "rustc_metadata 0.0.0", "rustc_mir 0.0.0", "rustc_passes 0.0.0", diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 884a71f0d32..4212fa1f8b1 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -328,7 +328,7 @@ top_level_options!( } ); -#[derive(Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PrintRequest { FileNames, Sysroot, diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 5b5113caa8e..2e949f48c17 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -22,7 +22,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_incremental = { path = "../librustc_incremental" } rustc_lint = { path = "../librustc_lint" } -rustc_llvm = { path = "../librustc_llvm" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_passes = { path = "../librustc_passes" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 20eba802e85..34f636d0b9a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -56,7 +56,6 @@ extern crate rustc_save_analysis; extern crate rustc_trans; extern crate rustc_typeck; extern crate serialize; -extern crate rustc_llvm as llvm; #[macro_use] extern crate log; extern crate syntax; @@ -70,7 +69,7 @@ use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_trans::back::link; -use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; +use rustc_trans::back::write::{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}; @@ -182,7 +181,7 @@ pub fn run_compiler<'a>(args: &[String], let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); if sopts.debugging_opts.debug_llvm { - unsafe { llvm::LLVMRustSetDebug(1); } + rustc_trans::enable_llvm_debug(); } let descriptions = diagnostics_registry(); @@ -671,14 +670,6 @@ impl RustcDefaultCalls { println!("{}", cfg); } } - 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() { @@ -693,6 +684,9 @@ impl RustcDefaultCalls { } println!(""); } + PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => { + rustc_trans::print(*req, sess); + } } } return Compilation::Stop; @@ -730,10 +724,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("commit-date: {}", unw(commit_date_str())); println!("host: {}", config::host_triple()); println!("release: {}", unw(release_str())); - unsafe { - println!("LLVM version: {}.{}", - llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor()); - } + rustc_trans::print_version(); } } @@ -1026,9 +1017,7 @@ pub fn handle_options(args: &[String]) -> Option { } if cg_flags.contains(&"passes=list".to_string()) { - unsafe { - ::llvm::LLVMRustPrintPasses(); - } + rustc_trans::print_passes(); return None; } diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index 61bc7c6eb4c..bee61bb3980 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -9,24 +9,9 @@ // except according to those terms. use syntax::ast; -use llvm::LLVMRustHasFeature; use rustc::session::Session; -use rustc_trans::back::write::create_target_machine; use syntax::symbol::Symbol; -use libc::c_char; - -// WARNING: the features must be known to LLVM or the feature -// detection code will walk past the end of the feature array, -// leading to crashes. - -const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"]; - -const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0", - "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0", - "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0", - "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"]; - -const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"]; +use rustc_trans; /// Add `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). @@ -34,21 +19,10 @@ const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"]; /// This is performed by checking whether a whitelisted set of /// features is available on the target machine, by querying LLVM. pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { - let target_machine = create_target_machine(sess); - - let whitelist = match &*sess.target.target.arch { - "arm" => ARM_WHITELIST, - "x86" | "x86_64" => X86_WHITELIST, - "hexagon" => HEXAGON_WHITELIST, - _ => &[], - }; - let tf = Symbol::intern("target_feature"); - for feat in whitelist { - assert_eq!(feat.chars().last(), Some('\0')); - if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } { - cfg.insert((tf, Some(Symbol::intern(&feat[..feat.len() - 1])))); - } + + for feat in rustc_trans::target_features(sess) { + cfg.insert((tf, Some(feat))); } let requested_features = sess.opts.cg.target_feature.split(','); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index d9552eb08b4..3ac0d88b90d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -72,6 +72,7 @@ pub use base::trans_crate; pub use back::symbol_names::provide; pub use metadata::LlvmMetadataLoader; +pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug}; pub mod back { pub use rustc::hir::svh; @@ -122,6 +123,7 @@ mod debuginfo; mod declare; mod glue; mod intrinsic; +mod llvm_util; mod machine; mod metadata; mod meth; @@ -178,55 +180,3 @@ pub struct CrateTranslation { } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } - -use rustc::session::Session; -pub fn init(sess: &Session) { - unsafe { - // Before we touch LLVM, make sure that multithreading is enabled. - use std::sync::Once; - static INIT: Once = Once::new(); - static mut POISONED: bool = false; - INIT.call_once(|| { - if llvm::LLVMStartMultithreaded() != 1 { - // use an extra bool to make sure that all future usage of LLVM - // cannot proceed despite the Once not running more than once. - POISONED = true; - } - - configure_llvm(sess); - }); - - if POISONED { - bug!("couldn't enable multi-threaded LLVM"); - } - } -} - -use std::ffi::CString; -use libc::c_int; -unsafe fn configure_llvm(sess: &Session) { - let mut llvm_c_strs = Vec::new(); - let mut llvm_args = Vec::new(); - - { - let mut add = |arg: &str| { - let s = CString::new(arg).unwrap(); - llvm_args.push(s.as_ptr()); - llvm_c_strs.push(s); - }; - add("rustc"); // fake program name - if sess.time_llvm_passes() { add("-time-passes"); } - if sess.print_llvm_passes() { add("-debug-pass=Structure"); } - - for arg in &sess.opts.cg.llvm_args { - add(&(*arg)); - } - } - - llvm::LLVMInitializePasses(); - - llvm::initialize_available_targets(); - - llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, - llvm_args.as_ptr()); -} diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs new file mode 100644 index 00000000000..0f4c6b64080 --- /dev/null +++ b/src/librustc_trans/llvm_util.rs @@ -0,0 +1,125 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use syntax_pos::symbol::Symbol; +use back::write::create_target_machine; +use llvm; +use rustc::session::Session; +use rustc::session::config::PrintRequest; +use libc::{c_int, c_char}; +use std::ffi::CString; + +pub fn init(sess: &Session) { + unsafe { + // Before we touch LLVM, make sure that multithreading is enabled. + use std::sync::Once; + static INIT: Once = Once::new(); + static mut POISONED: bool = false; + INIT.call_once(|| { + if llvm::LLVMStartMultithreaded() != 1 { + // use an extra bool to make sure that all future usage of LLVM + // cannot proceed despite the Once not running more than once. + POISONED = true; + } + + configure_llvm(sess); + }); + + if POISONED { + bug!("couldn't enable multi-threaded LLVM"); + } + } +} + +unsafe fn configure_llvm(sess: &Session) { + let mut llvm_c_strs = Vec::new(); + let mut llvm_args = Vec::new(); + + { + let mut add = |arg: &str| { + let s = CString::new(arg).unwrap(); + llvm_args.push(s.as_ptr()); + llvm_c_strs.push(s); + }; + add("rustc"); // fake program name + if sess.time_llvm_passes() { add("-time-passes"); } + if sess.print_llvm_passes() { add("-debug-pass=Structure"); } + + for arg in &sess.opts.cg.llvm_args { + add(&(*arg)); + } + } + + llvm::LLVMInitializePasses(); + + llvm::initialize_available_targets(); + + llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, + llvm_args.as_ptr()); +} + +// WARNING: the features must be known to LLVM or the feature +// detection code will walk past the end of the feature array, +// leading to crashes. + +const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"]; + +const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0", + "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0", + "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0", + "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"]; + +const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"]; + +pub fn target_features(sess: &Session) -> Vec { + let target_machine = create_target_machine(sess); + + let whitelist = match &*sess.target.target.arch { + "arm" => ARM_WHITELIST, + "x86" | "x86_64" => X86_WHITELIST, + "hexagon" => HEXAGON_WHITELIST, + _ => &[], + }; + + let mut features = Vec::new(); + for feat in whitelist { + assert_eq!(feat.chars().last(), Some('\0')); + if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } { + features.push(Symbol::intern(&feat[..feat.len() - 1])); + } + } + features +} + +pub fn print_version() { + unsafe { + println!("LLVM version: {}.{}", + llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor()); + } +} + +pub fn print_passes() { + unsafe { llvm::LLVMRustPrintPasses(); } +} + +pub fn print(req: PrintRequest, sess: &Session) { + let tm = create_target_machine(sess); + unsafe { + match req { + PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm), + PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm), + _ => bug!("rustc_trans can't handle print request: {:?}", req), + } + } +} + +pub fn enable_llvm_debug() { + unsafe { llvm::LLVMRustSetDebug(1); } +}