Auto merge of #41565 - rkruppe:llvm-sys, r=eddyb
Make only rustc_trans depend on rustc_llvm With these changes, only rustc_trans depends directly on rustc_llvm (and no crate gained a new dependency on trans). This means changing LLVM doesn't rebuild librustc or rustc_metadata, only rustc_trans, rustc_driver and the rustc executable Also, rustc_driver technically doesn't know about LLVM any more (of course, it still handles a ton of options that conceptually refer to LLVM, but it delegates their implementation to trans). What I *didn't* implement was merging most or all of rustc_llvm into rustc_trans. I ran into a nasty bug, which was probably just a silly typo somewhere but I probably won't have the time to figure it out in the next week or two. I opened #41699 for that step. Fixes #41473
This commit is contained in:
commit
fa78d5bb87
21
src/Cargo.lock
generated
21
src/Cargo.lock
generated
@ -405,6 +405,14 @@ name = "open"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "owning_ref"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "panic_abort"
|
||||
version = "0.0.0"
|
||||
@ -531,12 +539,12 @@ dependencies = [
|
||||
"fmt_macros 0.0.0",
|
||||
"graphviz 0.0.0",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_bitflags 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -646,7 +654,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",
|
||||
@ -720,13 +727,13 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"flate 0.0.0",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc_macro 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_ext 0.0.0",
|
||||
@ -828,6 +835,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"flate 0.0.0",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_bitflags 0.0.0",
|
||||
@ -923,6 +931,11 @@ dependencies = [
|
||||
name = "serialize"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "std"
|
||||
version = "0.0.0"
|
||||
@ -1167,6 +1180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
|
||||
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
|
||||
"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
|
||||
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
|
||||
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
|
||||
"checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
|
||||
"checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
|
||||
@ -1180,6 +1194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
||||
"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
|
||||
"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
|
||||
"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ab0ef9ead2fe0aa9e18475a96a207bfd5143f4124779ef7429503a8665416ce8"
|
||||
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
|
||||
|
@ -13,12 +13,12 @@ arena = { path = "../libarena" }
|
||||
fmt_macros = { path = "../libfmt_macros" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
log = "0.3"
|
||||
owning_ref = "0.3.3"
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
@ -54,7 +54,7 @@
|
||||
extern crate getopts;
|
||||
extern crate graphviz;
|
||||
extern crate libc;
|
||||
extern crate rustc_llvm as llvm;
|
||||
extern crate owning_ref;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate serialize;
|
||||
|
@ -36,8 +36,9 @@
|
||||
use util::nodemap::{NodeSet, DefIdMap};
|
||||
|
||||
use std::any::Any;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use owning_ref::ErasedBoxRef;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
@ -201,11 +202,33 @@ pub fn new() -> EncodedMetadataHashes {
|
||||
}
|
||||
}
|
||||
|
||||
/// The backend's way to give the crate store access to the metadata in a library.
|
||||
/// Note that it returns the raw metadata bytes stored in the library file, whether
|
||||
/// it is compressed, uncompressed, some weird mix, etc.
|
||||
/// rmeta files are backend independent and not handled here.
|
||||
///
|
||||
/// At the time of this writing, there is only one backend and one way to store
|
||||
/// metadata in library -- this trait just serves to decouple rustc_metadata from
|
||||
/// the archive reader, which depends on LLVM.
|
||||
pub trait MetadataLoader {
|
||||
fn get_rlib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
}
|
||||
|
||||
/// A store of Rust crates, through with their metadata
|
||||
/// can be accessed.
|
||||
pub trait CrateStore {
|
||||
fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
|
||||
|
||||
// access to the metadata loader
|
||||
fn metadata_loader(&self) -> &MetadataLoader;
|
||||
|
||||
// item info
|
||||
fn visibility(&self, def: DefId) -> ty::Visibility;
|
||||
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
|
||||
@ -275,8 +298,6 @@ fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
fn used_link_args(&self) -> Vec<String>;
|
||||
|
||||
// utility functions
|
||||
fn metadata_filename(&self) -> &str;
|
||||
fn metadata_section_name(&self, target: &Target) -> &str;
|
||||
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
|
||||
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
|
||||
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
|
||||
@ -413,8 +434,6 @@ fn used_libraries(&self) -> Vec<NativeLibrary> { vec![] }
|
||||
fn used_link_args(&self) -> Vec<String> { vec![] }
|
||||
|
||||
// utility functions
|
||||
fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
|
||||
fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
|
||||
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
|
||||
{ vec![] }
|
||||
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
|
||||
@ -427,6 +446,9 @@ fn encode_metadata<'a, 'tcx>(&self,
|
||||
bug!("encode_metadata")
|
||||
}
|
||||
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
|
||||
|
||||
// access to the metadata loader
|
||||
fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
|
||||
}
|
||||
|
||||
pub trait CrateLoader {
|
||||
|
@ -328,7 +328,7 @@ pub struct Options {
|
||||
}
|
||||
);
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum PrintRequest {
|
||||
FileNames,
|
||||
Sysroot,
|
||||
|
@ -37,19 +37,16 @@
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy};
|
||||
use rustc_back::target::Target;
|
||||
use rustc_data_structures::flock;
|
||||
use llvm;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::cell::{self, Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::io::Write;
|
||||
use std::rc::Rc;
|
||||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
use std::sync::Arc;
|
||||
use libc::c_int;
|
||||
|
||||
mod code_stats;
|
||||
pub mod config;
|
||||
@ -713,8 +710,6 @@ pub fn build_session_(sopts: config::Options,
|
||||
out_of_fuel: Cell::new(false),
|
||||
};
|
||||
|
||||
init_llvm(&sess);
|
||||
|
||||
sess
|
||||
}
|
||||
|
||||
@ -743,55 +738,6 @@ pub enum IncrCompSession {
|
||||
}
|
||||
}
|
||||
|
||||
fn init_llvm(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());
|
||||
}
|
||||
|
||||
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
|
||||
let emitter: Box<Emitter> = match output {
|
||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
||||
|
@ -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" }
|
||||
|
@ -56,7 +56,6 @@
|
||||
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_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 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
|
||||
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();
|
||||
@ -204,13 +203,14 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
|
||||
};
|
||||
|
||||
let dep_graph = DepGraph::new(sopts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
|
||||
let loader = file_loader.unwrap_or(box RealFileLoader);
|
||||
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
|
||||
let mut sess = session::build_session_with_codemap(
|
||||
sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
|
||||
);
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let mut cfg = config::build_configuration(&sess, cfg);
|
||||
@ -409,12 +409,13 @@ fn no_input(&mut self,
|
||||
return None;
|
||||
}
|
||||
let dep_graph = DepGraph::new(sopts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = build_session(sopts.clone(),
|
||||
&dep_graph,
|
||||
None,
|
||||
descriptions.clone(),
|
||||
cstore.clone());
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let mut cfg = config::build_configuration(&sess, cfg.clone());
|
||||
target_features::add_configuration(&mut cfg, &sess);
|
||||
@ -558,7 +559,11 @@ pub fn list_metadata(sess: &Session, matches: &getopts::Matches, input: &Input)
|
||||
&Input::File(ref ifile) => {
|
||||
let path = &(*ifile);
|
||||
let mut v = Vec::new();
|
||||
locator::list_file_metadata(&sess.target.target, path, &mut v).unwrap();
|
||||
locator::list_file_metadata(&sess.target.target,
|
||||
path,
|
||||
sess.cstore.metadata_loader(),
|
||||
&mut v)
|
||||
.unwrap();
|
||||
println!("{}", String::from_utf8(v).unwrap());
|
||||
}
|
||||
&Input::Str { .. } => {
|
||||
@ -665,14 +670,6 @@ fn print_crate_info(sess: &Session,
|
||||
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() {
|
||||
@ -687,6 +684,9 @@ fn print_crate_info(sess: &Session,
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
|
||||
rustc_trans::print(*req, sess);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Compilation::Stop;
|
||||
@ -724,10 +724,7 @@ fn unw(x: Option<&str>) -> &str {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1020,9 +1017,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
||||
}
|
||||
|
||||
if cg_flags.contains(&"passes=list".to_string()) {
|
||||
unsafe {
|
||||
::llvm::LLVMRustPrintPasses();
|
||||
}
|
||||
rustc_trans::print_passes();
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -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 @@
|
||||
/// 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(',');
|
||||
|
@ -14,6 +14,7 @@
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_lint;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_trans;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
use rustc::middle::region::{CodeExtent, RegionMaps};
|
||||
@ -104,13 +105,14 @@ fn test_env<F>(source_string: &str,
|
||||
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let sess = session::build_session_(options,
|
||||
&dep_graph,
|
||||
None,
|
||||
diagnostic_handler,
|
||||
Rc::new(CodeMap::new(FilePathMapping::empty())),
|
||||
cstore.clone());
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let input = config::Input::Str {
|
||||
name: driver::anon_src(),
|
||||
|
@ -11,13 +11,13 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
flate = { path = "../libflate" }
|
||||
log = "0.3"
|
||||
owning_ref = "0.3.3"
|
||||
proc_macro = { path = "../libproc_macro" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_ext = { path = "../libsyntax_ext" }
|
||||
|
@ -393,6 +393,7 @@ fn resolve_crate(&mut self,
|
||||
rejected_via_filename: vec![],
|
||||
should_match_name: true,
|
||||
is_proc_macro: Some(false),
|
||||
metadata_loader: &*self.cstore.metadata_loader,
|
||||
};
|
||||
|
||||
self.load(&mut locate_ctxt).or_else(|| {
|
||||
@ -554,6 +555,7 @@ fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> Extens
|
||||
rejected_via_filename: vec![],
|
||||
should_match_name: true,
|
||||
is_proc_macro: None,
|
||||
metadata_loader: &*self.cstore.metadata_loader,
|
||||
};
|
||||
let library = self.load(&mut locate_ctxt).or_else(|| {
|
||||
if !is_cross {
|
||||
|
@ -11,21 +11,20 @@
|
||||
// The crate store - a central repo for information collected about external
|
||||
// crates and libraries
|
||||
|
||||
use locator;
|
||||
use schema::{self, Tracked};
|
||||
|
||||
use rustc::dep_graph::{DepGraph, DepNode, GlobalMetaDataKind};
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
|
||||
use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::{DepKind, ExternCrate};
|
||||
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use std::rc::Rc;
|
||||
use flate::Bytes;
|
||||
use owning_ref::ErasedBoxRef;
|
||||
use syntax::{ast, attr};
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
@ -43,11 +42,7 @@
|
||||
// own crate numbers.
|
||||
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
|
||||
|
||||
pub enum MetadataBlob {
|
||||
Inflated(Bytes),
|
||||
Archive(locator::ArchiveMetadata),
|
||||
Raw(Vec<u8>),
|
||||
}
|
||||
pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
|
||||
|
||||
/// Holds information about a syntax_pos::FileMap imported from another crate.
|
||||
/// See `imported_filemaps()` for more information.
|
||||
@ -103,10 +98,11 @@ pub struct CStore {
|
||||
statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
||||
pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
|
||||
pub visible_parent_map: RefCell<DefIdMap<DefId>>,
|
||||
pub metadata_loader: Box<MetadataLoader>,
|
||||
}
|
||||
|
||||
impl CStore {
|
||||
pub fn new(dep_graph: &DepGraph) -> CStore {
|
||||
pub fn new(dep_graph: &DepGraph, metadata_loader: Box<MetadataLoader>) -> CStore {
|
||||
CStore {
|
||||
dep_graph: dep_graph.clone(),
|
||||
metas: RefCell::new(FxHashMap()),
|
||||
@ -116,6 +112,7 @@ pub fn new(dep_graph: &DepGraph) -> CStore {
|
||||
statically_included_foreign_items: RefCell::new(FxHashSet()),
|
||||
dllimport_foreign_items: RefCell::new(FxHashSet()),
|
||||
visible_parent_map: RefCell::new(FxHashMap()),
|
||||
metadata_loader: metadata_loader,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,11 @@
|
||||
|
||||
use cstore;
|
||||
use encoder;
|
||||
use locator;
|
||||
use schema;
|
||||
|
||||
use rustc::dep_graph::DepTrackingMapConfig;
|
||||
use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
|
||||
ExternCrate, NativeLibrary, LinkMeta,
|
||||
ExternCrate, NativeLibrary, MetadataLoader, LinkMeta,
|
||||
LinkagePreference, LoadedMacro, EncodedMetadata};
|
||||
use rustc::hir::def;
|
||||
use rustc::middle::lang_items;
|
||||
@ -38,7 +37,6 @@
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{Span, NO_EXPANSION};
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc_back::target::Target;
|
||||
use rustc::hir;
|
||||
|
||||
macro_rules! provide {
|
||||
@ -135,6 +133,10 @@ fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any> {
|
||||
self.get_crate_data(krate)
|
||||
}
|
||||
|
||||
fn metadata_loader(&self) -> &MetadataLoader {
|
||||
&*self.metadata_loader
|
||||
}
|
||||
|
||||
fn visibility(&self, def: DefId) -> ty::Visibility {
|
||||
self.dep_graph.read(DepNode::MetaData(def));
|
||||
self.get_crate_data(def.krate).get_visibility(def.index)
|
||||
@ -420,17 +422,6 @@ fn used_link_args(&self) -> Vec<String>
|
||||
{
|
||||
self.get_used_link_args().borrow().clone()
|
||||
}
|
||||
|
||||
fn metadata_filename(&self) -> &str
|
||||
{
|
||||
locator::METADATA_FILENAME
|
||||
}
|
||||
|
||||
fn metadata_section_name(&self, target: &Target) -> &str
|
||||
{
|
||||
locator::meta_section_name(target)
|
||||
}
|
||||
|
||||
fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
|
||||
{
|
||||
self.do_get_used_crates(prefer)
|
||||
@ -522,4 +513,4 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
|
||||
drop(visible_parent_map);
|
||||
self.visible_parent_map.borrow()
|
||||
}
|
||||
}
|
||||
}
|
@ -77,11 +77,7 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
match *self {
|
||||
MetadataBlob::Inflated(ref vec) => vec,
|
||||
MetadataBlob::Archive(ref ar) => ar.as_slice(),
|
||||
MetadataBlob::Raw(ref vec) => vec,
|
||||
}
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
extern crate syntax_pos;
|
||||
extern crate flate;
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
extern crate owning_ref;
|
||||
extern crate rustc_errors as errors;
|
||||
extern crate syntax_ext;
|
||||
extern crate proc_macro;
|
||||
@ -46,7 +47,6 @@
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_llvm;
|
||||
|
||||
mod diagnostics;
|
||||
|
||||
|
@ -224,15 +224,12 @@
|
||||
use schema::{METADATA_HEADER, rustc_version};
|
||||
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::util::common;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use rustc_llvm as llvm;
|
||||
use rustc_llvm::{False, ObjectFile, mk_section_iter};
|
||||
use rustc_llvm::archive_ro::ArchiveRO;
|
||||
use errors::DiagnosticBuilder;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
@ -243,11 +240,10 @@
|
||||
use std::fs::{self, File};
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::time::Instant;
|
||||
|
||||
use flate;
|
||||
use owning_ref::{ErasedBoxRef, OwningRef};
|
||||
|
||||
pub struct CrateMismatch {
|
||||
path: PathBuf,
|
||||
@ -272,12 +268,7 @@ pub struct Context<'a> {
|
||||
pub rejected_via_filename: Vec<CrateMismatch>,
|
||||
pub should_match_name: bool,
|
||||
pub is_proc_macro: Option<bool>,
|
||||
}
|
||||
|
||||
pub struct ArchiveMetadata {
|
||||
_archive: ArchiveRO,
|
||||
// points into self._archive
|
||||
data: *const [u8],
|
||||
pub metadata_loader: &'a MetadataLoader,
|
||||
}
|
||||
|
||||
pub struct CratePaths {
|
||||
@ -287,8 +278,6 @@ pub struct CratePaths {
|
||||
pub rmeta: Option<PathBuf>,
|
||||
}
|
||||
|
||||
pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
enum CrateFlavor {
|
||||
Rlib,
|
||||
@ -596,20 +585,21 @@ fn extract_one(&mut self,
|
||||
let mut err: Option<DiagnosticBuilder> = None;
|
||||
for (lib, kind) in m {
|
||||
info!("{} reading metadata from: {}", flavor, lib.display());
|
||||
let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) {
|
||||
Ok(blob) => {
|
||||
if let Some(h) = self.crate_matches(&blob, &lib) {
|
||||
(h, blob)
|
||||
} else {
|
||||
info!("metadata mismatch");
|
||||
let (hash, metadata) =
|
||||
match get_metadata_section(self.target, flavor, &lib, self.metadata_loader) {
|
||||
Ok(blob) => {
|
||||
if let Some(h) = self.crate_matches(&blob, &lib) {
|
||||
(h, blob)
|
||||
} else {
|
||||
info!("metadata mismatch");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
info!("no metadata found: {}", err);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
info!("no metadata found: {}", err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
};
|
||||
// If we see multiple hashes, emit an error about duplicate candidates.
|
||||
if slot.as_ref().map_or(false, |s| s.0 != hash) {
|
||||
let mut e = struct_span_err!(self.sess,
|
||||
@ -833,50 +823,14 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
|
||||
err.note(&format!("crate name: {}", name));
|
||||
}
|
||||
|
||||
impl ArchiveMetadata {
|
||||
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
|
||||
let data = {
|
||||
let section = ar.iter()
|
||||
.filter_map(|s| s.ok())
|
||||
.find(|sect| sect.name() == Some(METADATA_FILENAME));
|
||||
match section {
|
||||
Some(s) => s.data() as *const [u8],
|
||||
None => {
|
||||
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Some(ArchiveMetadata {
|
||||
_archive: ar,
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
|
||||
unsafe { &*self.data }
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_decompressed_encoding_version(blob: &MetadataBlob,
|
||||
filename: &Path)
|
||||
-> Result<(), String> {
|
||||
if !blob.is_compatible() {
|
||||
Err((format!("incompatible metadata version found: '{}'",
|
||||
filename.display())))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Just a small wrapper to time how long reading metadata takes.
|
||||
fn get_metadata_section(target: &Target,
|
||||
flavor: CrateFlavor,
|
||||
filename: &Path)
|
||||
filename: &Path,
|
||||
loader: &MetadataLoader)
|
||||
-> Result<MetadataBlob, String> {
|
||||
let start = Instant::now();
|
||||
let ret = get_metadata_section_imp(target, flavor, filename);
|
||||
let ret = get_metadata_section_imp(target, flavor, filename, loader);
|
||||
info!("reading {:?} => {:?}",
|
||||
filename.file_name().unwrap(),
|
||||
start.elapsed());
|
||||
@ -885,118 +839,61 @@ fn get_metadata_section(target: &Target,
|
||||
|
||||
fn get_metadata_section_imp(target: &Target,
|
||||
flavor: CrateFlavor,
|
||||
filename: &Path)
|
||||
filename: &Path,
|
||||
loader: &MetadataLoader)
|
||||
-> Result<MetadataBlob, String> {
|
||||
if !filename.exists() {
|
||||
return Err(format!("no such file: '{}'", filename.display()));
|
||||
}
|
||||
if flavor == CrateFlavor::Rlib {
|
||||
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
|
||||
// internally to read the file. We also avoid even using a memcpy by
|
||||
// just keeping the archive along while the metadata is in use.
|
||||
let archive = match ArchiveRO::open(filename) {
|
||||
Some(ar) => ar,
|
||||
None => {
|
||||
debug!("llvm didn't like `{}`", filename.display());
|
||||
return Err(format!("failed to read rlib metadata: '{}'", filename.display()));
|
||||
let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
|
||||
CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
|
||||
CrateFlavor::Dylib => {
|
||||
let buf = loader.get_dylib_metadata(target, filename)?;
|
||||
// The header is uncompressed
|
||||
let header_len = METADATA_HEADER.len();
|
||||
debug!("checking {} bytes of metadata-version stamp", header_len);
|
||||
let header = &buf[..cmp::min(header_len, buf.len())];
|
||||
if header != METADATA_HEADER {
|
||||
return Err(format!("incompatible metadata version found: '{}'",
|
||||
filename.display()));
|
||||
}
|
||||
};
|
||||
return match ArchiveMetadata::new(archive).map(|ar| MetadataBlob::Archive(ar)) {
|
||||
None => Err(format!("failed to read rlib metadata: '{}'", filename.display())),
|
||||
Some(blob) => {
|
||||
verify_decompressed_encoding_version(&blob, filename)?;
|
||||
Ok(blob)
|
||||
}
|
||||
};
|
||||
} else if flavor == CrateFlavor::Rmeta {
|
||||
let mut file = File::open(filename).map_err(|_|
|
||||
format!("could not open file: '{}'", filename.display()))?;
|
||||
let mut buf = vec![];
|
||||
file.read_to_end(&mut buf).map_err(|_|
|
||||
format!("failed to read rlib metadata: '{}'", filename.display()))?;
|
||||
let blob = MetadataBlob::Raw(buf);
|
||||
verify_decompressed_encoding_version(&blob, filename)?;
|
||||
return Ok(blob);
|
||||
}
|
||||
unsafe {
|
||||
let buf = common::path2cstr(filename);
|
||||
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
||||
if mb as isize == 0 {
|
||||
return Err(format!("error reading library: '{}'", filename.display()));
|
||||
}
|
||||
let of = match ObjectFile::new(mb) {
|
||||
Some(of) => of,
|
||||
_ => {
|
||||
return Err((format!("provided path not an object file: '{}'", filename.display())))
|
||||
}
|
||||
};
|
||||
let si = mk_section_iter(of.llof);
|
||||
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
|
||||
let mut name_buf = ptr::null();
|
||||
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
|
||||
let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
|
||||
let name = String::from_utf8(name).unwrap();
|
||||
debug!("get_metadata_section: name {}", name);
|
||||
if read_meta_section_name(target) == name {
|
||||
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
||||
let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
|
||||
let cvbuf: *const u8 = cbuf as *const u8;
|
||||
let vlen = METADATA_HEADER.len();
|
||||
debug!("checking {} bytes of metadata-version stamp", vlen);
|
||||
let minsz = cmp::min(vlen, csz);
|
||||
let buf0 = slice::from_raw_parts(cvbuf, minsz);
|
||||
let version_ok = buf0 == METADATA_HEADER;
|
||||
if !version_ok {
|
||||
return Err((format!("incompatible metadata version found: '{}'",
|
||||
filename.display())));
|
||||
}
|
||||
|
||||
let cvbuf1 = cvbuf.offset(vlen as isize);
|
||||
debug!("inflating {} bytes of compressed metadata", csz - vlen);
|
||||
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
|
||||
match flate::inflate_bytes(bytes) {
|
||||
Ok(inflated) => {
|
||||
let blob = MetadataBlob::Inflated(inflated);
|
||||
verify_decompressed_encoding_version(&blob, filename)?;
|
||||
return Ok(blob);
|
||||
}
|
||||
Err(_) => {}
|
||||
// Header is okay -> inflate the actual metadata
|
||||
let compressed_bytes = &buf[header_len..];
|
||||
debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
|
||||
match flate::inflate_bytes(compressed_bytes) {
|
||||
Ok(inflated) => {
|
||||
let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
|
||||
buf.map_owner_box().erase_owner()
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(format!("failed to decompress metadata: {}", filename.display()));
|
||||
}
|
||||
}
|
||||
llvm::LLVMMoveToNextSection(si.llsi);
|
||||
}
|
||||
Err(format!("metadata not found: '{}'", filename.display()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn meta_section_name(target: &Target) -> &'static str {
|
||||
// Historical note:
|
||||
//
|
||||
// When using link.exe it was seen that the section name `.note.rustc`
|
||||
// was getting shortened to `.note.ru`, and according to the PE and COFF
|
||||
// specification:
|
||||
//
|
||||
// > Executable images do not use a string table and do not support
|
||||
// > section names longer than 8 characters
|
||||
//
|
||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
|
||||
//
|
||||
// As a result, we choose a slightly shorter name! As to why
|
||||
// `.note.rustc` works on MinGW, that's another good question...
|
||||
|
||||
if target.options.is_like_osx {
|
||||
"__DATA,.rustc"
|
||||
CrateFlavor::Rmeta => {
|
||||
let mut file = File::open(filename).map_err(|_|
|
||||
format!("could not open file: '{}'", filename.display()))?;
|
||||
let mut buf = vec![];
|
||||
file.read_to_end(&mut buf).map_err(|_|
|
||||
format!("failed to read rmeta metadata: '{}'", filename.display()))?;
|
||||
OwningRef::new(buf).map_owner_box().erase_owner()
|
||||
}
|
||||
};
|
||||
let blob = MetadataBlob(raw_bytes);
|
||||
if blob.is_compatible() {
|
||||
Ok(blob)
|
||||
} else {
|
||||
".rustc"
|
||||
Err(format!("incompatible metadata version found: '{}'", filename.display()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_meta_section_name(_target: &Target) -> &'static str {
|
||||
".rustc"
|
||||
}
|
||||
|
||||
// A diagnostic function for dumping crate metadata to an output stream
|
||||
pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> io::Result<()> {
|
||||
pub fn list_file_metadata(target: &Target,
|
||||
path: &Path,
|
||||
loader: &MetadataLoader,
|
||||
out: &mut io::Write)
|
||||
-> io::Result<()> {
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
let flavor = if filename.ends_with(".rlib") {
|
||||
CrateFlavor::Rlib
|
||||
@ -1005,7 +902,7 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) ->
|
||||
} else {
|
||||
CrateFlavor::Dylib
|
||||
};
|
||||
match get_metadata_section(target, flavor, path) {
|
||||
match get_metadata_section(target, flavor, path, loader) {
|
||||
Ok(metadata) => metadata.list_crate_metadata(out),
|
||||
Err(msg) => write!(out, "{}\n", msg),
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ test = false
|
||||
[dependencies]
|
||||
flate = { path = "../libflate" }
|
||||
log = "0.3"
|
||||
owning_ref = "0.3.3"
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
|
@ -20,6 +20,7 @@
|
||||
use libc;
|
||||
use llvm::archive_ro::{ArchiveRO, Child};
|
||||
use llvm::{self, ArchiveKind};
|
||||
use metadata::METADATA_FILENAME;
|
||||
use rustc::session::Session;
|
||||
|
||||
pub struct ArchiveConfig<'a> {
|
||||
@ -158,11 +159,9 @@ pub fn add_rlib(&mut self,
|
||||
// Ignoring all bytecode files, no matter of
|
||||
// name
|
||||
let bc_ext = ".bytecode.deflate";
|
||||
let metadata_filename =
|
||||
self.config.sess.cstore.metadata_filename().to_owned();
|
||||
|
||||
self.add_archive(rlib, move |fname: &str| {
|
||||
if fname.ends_with(bc_ext) || fname == metadata_filename {
|
||||
if fname.ends_with(bc_ext) || fname == METADATA_FILENAME {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
use super::rpath::RPathConfig;
|
||||
use super::rpath;
|
||||
use super::msvc;
|
||||
use metadata::METADATA_FILENAME;
|
||||
use session::config;
|
||||
use session::config::NoDebugInfo;
|
||||
use session::config::{OutputFilenames, Input, OutputType};
|
||||
@ -521,7 +522,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||
// contain the metadata in a separate file. We use a temp directory
|
||||
// here so concurrent builds in the same directory don't try to use
|
||||
// the same filename for metadata (stomping over one another)
|
||||
let metadata = tmpdir.join(sess.cstore.metadata_filename());
|
||||
let metadata = tmpdir.join(METADATA_FILENAME);
|
||||
emit_metadata(sess, trans, &metadata);
|
||||
ab.add_file(&metadata);
|
||||
|
||||
@ -1141,8 +1142,7 @@ fn link_sanitizer_runtime(cmd: &mut Linker,
|
||||
archive.update_symbols();
|
||||
|
||||
for f in archive.src_files() {
|
||||
if f.ends_with("bytecode.deflate") ||
|
||||
f == sess.cstore.metadata_filename() {
|
||||
if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
|
||||
archive.remove_file(&f);
|
||||
continue
|
||||
}
|
||||
@ -1217,8 +1217,7 @@ fn add_static_crate(cmd: &mut Linker,
|
||||
|
||||
let mut any_objects = false;
|
||||
for f in archive.src_files() {
|
||||
if f.ends_with("bytecode.deflate") ||
|
||||
f == sess.cstore.metadata_filename() {
|
||||
if f.ends_with("bytecode.deflate") || f == METADATA_FILENAME {
|
||||
archive.remove_file(&f);
|
||||
continue
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
use back::symbol_export::{self, ExportedSymbols};
|
||||
use llvm::{ContextRef, Linkage, ModuleRef, ValueRef, Vector, get_param};
|
||||
use llvm;
|
||||
use metadata;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use middle::lang_items::StartFnLangItem;
|
||||
use middle::cstore::EncodedMetadata;
|
||||
@ -778,8 +779,7 @@ enum MetadataKind {
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section_name =
|
||||
tcx.sess.cstore.metadata_section_name(&tcx.sess.target.target);
|
||||
let section_name = metadata::metadata_section_name(&tcx.sess.target.target);
|
||||
let name = CString::new(section_name).unwrap();
|
||||
llvm::LLVMSetSection(llglobal, name.as_ptr());
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
extern crate flate;
|
||||
extern crate libc;
|
||||
extern crate owning_ref;
|
||||
#[macro_use] extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_data_structures;
|
||||
@ -70,6 +71,9 @@
|
||||
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;
|
||||
|
||||
@ -119,7 +123,9 @@ pub mod back {
|
||||
mod declare;
|
||||
mod glue;
|
||||
mod intrinsic;
|
||||
mod llvm_util;
|
||||
mod machine;
|
||||
mod metadata;
|
||||
mod meth;
|
||||
mod mir;
|
||||
mod monomorphize;
|
||||
|
127
src/librustc_trans/llvm_util.rs
Normal file
127
src/librustc_trans/llvm_util.rs
Normal file
@ -0,0 +1,127 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Once;
|
||||
|
||||
pub fn init(sess: &Session) {
|
||||
unsafe {
|
||||
// Before we touch LLVM, make sure that multithreading is enabled.
|
||||
static POISONED: AtomicBool = AtomicBool::new(false);
|
||||
static INIT: Once = Once::new();
|
||||
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.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
configure_llvm(sess);
|
||||
});
|
||||
|
||||
if POISONED.load(Ordering::SeqCst) {
|
||||
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<Symbol> {
|
||||
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); }
|
||||
}
|
122
src/librustc_trans/metadata.rs
Normal file
122
src/librustc_trans/metadata.rs
Normal file
@ -0,0 +1,122 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::util::common;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc_back::target::Target;
|
||||
use llvm;
|
||||
use llvm::{False, ObjectFile, mk_section_iter};
|
||||
use llvm::archive_ro::ArchiveRO;
|
||||
|
||||
use owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
pub const METADATA_FILENAME: &str = "rust.metadata.bin";
|
||||
|
||||
pub struct LlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoader for LlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
|
||||
// internally to read the file. We also avoid even using a memcpy by
|
||||
// just keeping the archive along while the metadata is in use.
|
||||
let archive = ArchiveRO::open(filename)
|
||||
.map(|ar| OwningRef::new(box ar))
|
||||
.ok_or_else(|| {
|
||||
debug!("llvm didn't like `{}`", filename.display());
|
||||
format!("failed to read rlib metadata: '{}'", filename.display())
|
||||
})?;
|
||||
let buf: OwningRef<_, [u8]> = archive
|
||||
.try_map(|ar| {
|
||||
ar.iter()
|
||||
.filter_map(|s| s.ok())
|
||||
.find(|sect| sect.name() == Some(METADATA_FILENAME))
|
||||
.map(|s| s.data())
|
||||
.ok_or_else(|| {
|
||||
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
|
||||
format!("failed to read rlib metadata: '{}'",
|
||||
filename.display())
|
||||
})
|
||||
})?;
|
||||
Ok(buf.erase_owner())
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String> {
|
||||
unsafe {
|
||||
let buf = common::path2cstr(filename);
|
||||
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
||||
if mb as isize == 0 {
|
||||
return Err(format!("error reading library: '{}'", filename.display()));
|
||||
}
|
||||
let of = ObjectFile::new(mb)
|
||||
.map(|of| OwningRef::new(box of))
|
||||
.ok_or_else(|| format!("provided path not an object file: '{}'",
|
||||
filename.display()))?;
|
||||
let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
|
||||
Ok(buf.erase_owner())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn search_meta_section<'a>(of: &'a ObjectFile,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<&'a [u8], String> {
|
||||
unsafe {
|
||||
let si = mk_section_iter(of.llof);
|
||||
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
|
||||
let mut name_buf = ptr::null();
|
||||
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
|
||||
let name = slice::from_raw_parts(name_buf as *const u8, name_len as usize).to_vec();
|
||||
let name = String::from_utf8(name).unwrap();
|
||||
debug!("get_metadata_section: name {}", name);
|
||||
if read_metadata_section_name(target) == name {
|
||||
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
||||
let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
|
||||
// The buffer is valid while the object file is around
|
||||
let buf: &'a [u8] = slice::from_raw_parts(cbuf as *const u8, csz);
|
||||
return Ok(buf);
|
||||
}
|
||||
llvm::LLVMMoveToNextSection(si.llsi);
|
||||
}
|
||||
}
|
||||
Err(format!("metadata not found: '{}'", filename.display()))
|
||||
}
|
||||
|
||||
pub fn metadata_section_name(target: &Target) -> &'static str {
|
||||
// Historical note:
|
||||
//
|
||||
// When using link.exe it was seen that the section name `.note.rustc`
|
||||
// was getting shortened to `.note.ru`, and according to the PE and COFF
|
||||
// specification:
|
||||
//
|
||||
// > Executable images do not use a string table and do not support
|
||||
// > section names longer than 8 characters
|
||||
//
|
||||
// https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
|
||||
//
|
||||
// As a result, we choose a slightly shorter name! As to why
|
||||
// `.note.rustc` works on MinGW, that's another good question...
|
||||
|
||||
if target.options.is_like_osx {
|
||||
"__DATA,.rustc"
|
||||
} else {
|
||||
".rustc"
|
||||
}
|
||||
}
|
||||
|
||||
fn read_metadata_section_name(_target: &Target) -> &'static str {
|
||||
".rustc"
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_trans;
|
||||
use rustc_trans::back::link;
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
@ -138,10 +139,11 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, &dep_graph, cpath, diagnostic_handler, codemap, cstore.clone()
|
||||
);
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
|
||||
|
@ -34,6 +34,7 @@
|
||||
use rustc_driver::driver::phase_2_configure_and_expand;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_trans;
|
||||
use rustc_trans::back::link;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::CodeMap;
|
||||
@ -81,10 +82,11 @@ pub fn run(input: &str,
|
||||
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone(), cstore.clone(),
|
||||
);
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
sess.parse_sess.config =
|
||||
config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
|
||||
@ -229,10 +231,11 @@ fn drop(&mut self) {
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
|
||||
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let mut sess = session::build_session_(
|
||||
sessopts, &dep_graph, None, diagnostic_handler, codemap, cstore.clone(),
|
||||
);
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
|
||||
|
@ -15,6 +15,7 @@
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_trans;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
@ -58,8 +59,9 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
|
||||
|
||||
let descriptions = Registry::new(&rustc::DIAGNOSTICS);
|
||||
let dep_graph = DepGraph::new(opts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, Box::new(rustc_trans::LlvmMetadataLoader)));
|
||||
let sess = build_session(opts, &dep_graph, None, descriptions, cstore.clone());
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
(sess, cstore)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
extern crate rustc;
|
||||
extern crate rustc_plugin;
|
||||
extern crate rustc_trans;
|
||||
|
||||
#[link(name = "llvm-function-pass", kind = "static")]
|
||||
#[link(name = "llvm-module-pass", kind = "static")]
|
||||
|
Loading…
Reference in New Issue
Block a user