mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-02 03:33:59 +00:00
Auto merge of #44085 - bjorn3:no_llvm_write_metadata, r=arielb1
Allow writing metadata without llvm # Todo: * [x] Rebase * [x] Fix eventual errors * [x] <strike>Find some crate to write elf files</strike> (will do it later) Cc #43842
This commit is contained in:
commit
3df1f7b82d
3
.gitignore
vendored
3
.gitignore
vendored
@ -103,3 +103,6 @@ version.texi
|
||||
.cargo
|
||||
!src/vendor/**
|
||||
/src/target/
|
||||
|
||||
no_llvm_build
|
||||
|
||||
|
5
src/Cargo.lock
generated
5
src/Cargo.lock
generated
@ -1778,7 +1778,12 @@ dependencies = [
|
||||
name = "rustc_trans_utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (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",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
@ -531,7 +531,10 @@ impl<'a> Builder<'a> {
|
||||
// For other crates, however, we know that we've already got a standard
|
||||
// library up and running, so we can use the normal compiler to compile
|
||||
// build scripts in that situation.
|
||||
if mode == Mode::Libstd {
|
||||
//
|
||||
// If LLVM support is disabled we need to use the snapshot compiler to compile
|
||||
// build scripts, as the new compiler doesnt support executables.
|
||||
if mode == Mode::Libstd || !self.build.config.llvm_enabled {
|
||||
cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
|
||||
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
|
||||
} else {
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![cfg_attr(not(feature="llvm"), allow(dead_code))]
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::{self, map as hir_map};
|
||||
use rustc::hir::lowering::lower_crate;
|
||||
@ -34,8 +32,8 @@ use rustc_incremental;
|
||||
use rustc_resolve::{MakeGlobMap, Resolver};
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::{self, CStore};
|
||||
use rustc_trans::back::write;
|
||||
use rustc_trans as trans;
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use rustc_typeck as typeck;
|
||||
use rustc_privacy;
|
||||
use rustc_plugin::registry::Registry;
|
||||
@ -43,6 +41,7 @@ use rustc_plugin as plugin;
|
||||
use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
|
||||
use rustc_const_eval::{self, check_match};
|
||||
use super::Compilation;
|
||||
use ::DefaultTransCrate;
|
||||
|
||||
use serialize::json;
|
||||
|
||||
@ -76,7 +75,8 @@ pub fn compile_input(sess: &Session,
|
||||
output: &Option<PathBuf>,
|
||||
addl_plugins: Option<Vec<String>>,
|
||||
control: &CompileController) -> CompileResult {
|
||||
use rustc_trans::back::write::OngoingCrateTranslation;
|
||||
use rustc::session::config::CrateType;
|
||||
|
||||
macro_rules! controller_entry_point {
|
||||
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
|
||||
let state = &mut $make_state;
|
||||
@ -94,17 +94,16 @@ pub fn compile_input(sess: &Session,
|
||||
}
|
||||
|
||||
if cfg!(not(feature="llvm")) {
|
||||
use rustc::session::config::CrateType;
|
||||
if !sess.opts.debugging_opts.no_trans && sess.opts.output_types.should_trans() {
|
||||
sess.err("LLVM is not supported by this rustc. Please use -Z no-trans to compile")
|
||||
}
|
||||
|
||||
if sess.opts.crate_types.iter().all(|&t|{
|
||||
t != CrateType::CrateTypeRlib && t != CrateType::CrateTypeExecutable
|
||||
}) && !sess.opts.crate_types.is_empty() {
|
||||
sess.err(
|
||||
"LLVM is not supported by this rustc, so non rlib libraries are not supported"
|
||||
);
|
||||
for cty in sess.opts.crate_types.iter() {
|
||||
match *cty {
|
||||
CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
|
||||
CrateType::CrateTypeExecutable => {},
|
||||
_ => {
|
||||
sess.parse_sess.span_diagnostic.warn(
|
||||
&format!("LLVM unsupported, so output type {} is not supported", cty)
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
sess.abort_if_errors();
|
||||
@ -117,7 +116,7 @@ pub fn compile_input(sess: &Session,
|
||||
// We need nested scopes here, because the intermediate results can keep
|
||||
// large chunks of memory alive and we want to free them as soon as
|
||||
// possible to keep the peak memory usage low
|
||||
let (outputs, trans, dep_graph): (OutputFilenames, OngoingCrateTranslation, DepGraph) = {
|
||||
let (outputs, trans, dep_graph) = {
|
||||
let krate = match phase_1_parse_input(control, sess, input) {
|
||||
Ok(krate) => krate,
|
||||
Err(mut parse_error) => {
|
||||
@ -246,7 +245,7 @@ pub fn compile_input(sess: &Session,
|
||||
tcx.print_debug_stats();
|
||||
}
|
||||
|
||||
let trans = phase_4_translate_to_llvm(tcx, rx);
|
||||
let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx);
|
||||
|
||||
if log_enabled!(::log::LogLevel::Info) {
|
||||
println!("Post-trans");
|
||||
@ -264,44 +263,42 @@ pub fn compile_input(sess: &Session,
|
||||
})??
|
||||
};
|
||||
|
||||
if cfg!(not(feature="llvm")) {
|
||||
let (_, _) = (outputs, trans);
|
||||
sess.fatal("LLVM is not supported by this rustc");
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.borrow().print_type_sizes();
|
||||
}
|
||||
|
||||
let (phase5_result, trans) =
|
||||
phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans);
|
||||
|
||||
controller_entry_point!(after_llvm,
|
||||
sess,
|
||||
CompileState::state_after_llvm(input, sess, outdir, output, &trans),
|
||||
phase5_result);
|
||||
phase5_result?;
|
||||
|
||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||
// This should produce either a finished executable or library.
|
||||
time(sess.time_passes(), "linking", || {
|
||||
DefaultTransCrate::link_binary(sess, &trans, &outputs)
|
||||
});
|
||||
|
||||
// Now that we won't touch anything in the incremental compilation directory
|
||||
// any more, we can finalize it (which involves renaming it)
|
||||
#[cfg(feature="llvm")]
|
||||
{
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.borrow().print_type_sizes();
|
||||
}
|
||||
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
|
||||
|
||||
let (phase5_result, trans) = phase_5_run_llvm_passes(sess, &dep_graph, trans);
|
||||
|
||||
controller_entry_point!(after_llvm,
|
||||
sess,
|
||||
CompileState::state_after_llvm(input, sess, outdir, output, &trans),
|
||||
phase5_result);
|
||||
phase5_result?;
|
||||
|
||||
phase_6_link_output(sess, &trans, &outputs);
|
||||
|
||||
// Now that we won't touch anything in the incremental compilation directory
|
||||
// any more, we can finalize it (which involves renaming it)
|
||||
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
|
||||
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
}
|
||||
|
||||
controller_entry_point!(
|
||||
compilation_done,
|
||||
sess,
|
||||
CompileState::state_when_compilation_done(input, sess, outdir, output),
|
||||
Ok(())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
}
|
||||
|
||||
controller_entry_point!(
|
||||
compilation_done,
|
||||
sess,
|
||||
CompileState::state_when_compilation_done(input, sess, outdir, output),
|
||||
Ok(())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keep_hygiene_data(sess: &Session) -> bool {
|
||||
@ -970,7 +967,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
mir::provide(&mut local_providers);
|
||||
reachable::provide(&mut local_providers);
|
||||
rustc_privacy::provide(&mut local_providers);
|
||||
trans::provide_local(&mut local_providers);
|
||||
DefaultTransCrate::provide_local(&mut local_providers);
|
||||
typeck::provide(&mut local_providers);
|
||||
ty::provide(&mut local_providers);
|
||||
traits::provide(&mut local_providers);
|
||||
@ -982,7 +979,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
let mut extern_providers = ty::maps::Providers::default();
|
||||
cstore::provide(&mut extern_providers);
|
||||
trans::provide_extern(&mut extern_providers);
|
||||
DefaultTransCrate::provide_extern(&mut extern_providers);
|
||||
ty::provide_extern(&mut extern_providers);
|
||||
traits::provide_extern(&mut extern_providers);
|
||||
// FIXME(eddyb) get rid of this once we replace const_eval with miri.
|
||||
@ -1126,9 +1123,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
/// Run the translation phase to LLVM, after which the AST and analysis can
|
||||
/// be discarded.
|
||||
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>)
|
||||
-> write::OngoingCrateTranslation {
|
||||
-> <Trans as TransCrate>::OngoingCrateTranslation {
|
||||
let time_passes = tcx.sess.time_passes();
|
||||
|
||||
time(time_passes,
|
||||
@ -1137,9 +1134,8 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
let translation =
|
||||
time(time_passes, "translation", move || {
|
||||
trans::trans_crate(tcx, rx)
|
||||
Trans::trans_crate(tcx, rx)
|
||||
});
|
||||
|
||||
if tcx.sess.profile_queries() {
|
||||
profile::dump("profile_queries".to_string())
|
||||
}
|
||||
@ -1149,15 +1145,14 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
/// Run LLVM itself, producing a bitcode file, assembly file or object file
|
||||
/// as a side effect.
|
||||
#[cfg(feature="llvm")]
|
||||
pub fn phase_5_run_llvm_passes(sess: &Session,
|
||||
pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session,
|
||||
dep_graph: &DepGraph,
|
||||
trans: write::OngoingCrateTranslation)
|
||||
-> (CompileResult, trans::CrateTranslation) {
|
||||
let trans = trans.join(sess, dep_graph);
|
||||
trans: <Trans as TransCrate>::OngoingCrateTranslation)
|
||||
-> (CompileResult, <Trans as TransCrate>::TranslatedCrate) {
|
||||
let trans = Trans::join_trans(trans, sess, dep_graph);
|
||||
|
||||
if sess.opts.debugging_opts.incremental_info {
|
||||
write::dump_incremental_data(&trans);
|
||||
Trans::dump_incremental_data(&trans);
|
||||
}
|
||||
|
||||
time(sess.time_passes(),
|
||||
@ -1167,20 +1162,6 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
|
||||
(sess.compile_status(), trans)
|
||||
}
|
||||
|
||||
/// Run the linker on any artifacts that resulted from the LLVM run.
|
||||
/// This should produce either a finished executable or library.
|
||||
#[cfg(feature="llvm")]
|
||||
pub fn phase_6_link_output(sess: &Session,
|
||||
trans: &trans::CrateTranslation,
|
||||
outputs: &OutputFilenames) {
|
||||
time(sess.time_passes(), "linking", || {
|
||||
::rustc_trans::back::link::link_binary(sess,
|
||||
trans,
|
||||
outputs,
|
||||
&trans.crate_name.as_str())
|
||||
});
|
||||
}
|
||||
|
||||
fn escape_dep_filename(filename: &str) -> String {
|
||||
// Apparently clang and gcc *only* escape spaces:
|
||||
// http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
|
||||
|
@ -75,6 +75,7 @@ use rustc::middle::cstore::CrateStore;
|
||||
use rustc_metadata::locator;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc::util::common::{time, ErrorReported};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
|
||||
use serialize::json::ToJson;
|
||||
|
||||
@ -151,101 +152,31 @@ pub fn run<F>(run_compiler: F) -> isize
|
||||
}
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
pub use no_llvm_metadata_loader::NoLLvmMetadataLoader as MetadataLoader;
|
||||
pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCrate;
|
||||
#[cfg(feature="llvm")]
|
||||
pub use rustc_trans::LlvmMetadataLoader as MetadataLoader;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
mod no_llvm_metadata_loader {
|
||||
extern crate ar;
|
||||
extern crate owning_ref;
|
||||
|
||||
use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
|
||||
use rustc_back::target::Target;
|
||||
use std::io;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use self::ar::Archive;
|
||||
use self::owning_ref::{OwningRef, ErasedBoxRef};
|
||||
|
||||
pub struct NoLLvmMetadataLoader;
|
||||
|
||||
impl MetadataLoaderTrait for NoLLvmMetadataLoader {
|
||||
fn get_rlib_metadata(
|
||||
&self,
|
||||
_: &Target,
|
||||
filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
let file = File::open(filename).map_err(|e| {
|
||||
format!("metadata file open err: {:?}", e)
|
||||
})?;
|
||||
let mut archive = Archive::new(file);
|
||||
|
||||
while let Some(entry_result) = archive.next_entry() {
|
||||
let mut entry = entry_result.map_err(|e| {
|
||||
format!("metadata section read err: {:?}", e)
|
||||
})?;
|
||||
if entry.header().identifier() == "rust.metadata.bin" {
|
||||
let mut buf = Vec::new();
|
||||
io::copy(&mut entry, &mut buf).unwrap();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
return Ok(buf.map_owner_box().erase_owner());
|
||||
}
|
||||
}
|
||||
|
||||
Err("Couldnt find metadata section".to_string())
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self,
|
||||
_target: &Target,
|
||||
_filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String> {
|
||||
panic!("Dylib metadata loading not supported without LLVM")
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
mod rustc_trans {
|
||||
use syntax_pos::symbol::Symbol;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{PrintRequest, OutputFilenames};
|
||||
use rustc::ty::{TyCtxt, CrateAnalysis};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc_incremental::IncrementalHashesMap;
|
||||
|
||||
use self::back::write::OngoingCrateTranslation;
|
||||
use rustc::session::config::PrintRequest;
|
||||
pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
|
||||
pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
|
||||
|
||||
pub fn init(_sess: &Session) {}
|
||||
pub fn enable_llvm_debug() {}
|
||||
pub fn provide(_providers: &mut Providers) {}
|
||||
pub fn print_version() {}
|
||||
pub fn print_passes() {}
|
||||
pub fn print(_req: PrintRequest, _sess: &Session) {}
|
||||
pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
|
||||
|
||||
pub fn trans_crate<'a, 'tcx>(
|
||||
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_analysis: CrateAnalysis,
|
||||
_incr_hashes_map: IncrementalHashesMap,
|
||||
_output_filenames: &OutputFilenames
|
||||
) -> OngoingCrateTranslation {
|
||||
OngoingCrateTranslation(())
|
||||
}
|
||||
|
||||
pub struct CrateTranslation(());
|
||||
|
||||
pub mod back {
|
||||
pub mod write {
|
||||
pub struct OngoingCrateTranslation(pub (in ::rustc_trans) ());
|
||||
|
||||
pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
|
||||
pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
|
||||
}
|
||||
}
|
||||
|
||||
__build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
|
||||
}
|
||||
|
||||
// Parse args and run the compiler. This is the primary entry point for rustc.
|
||||
@ -293,7 +224,7 @@ pub fn run_compiler<'a>(args: &[String],
|
||||
},
|
||||
};
|
||||
|
||||
let cstore = Rc::new(CStore::new(box ::MetadataLoader));
|
||||
let cstore = Rc::new(CStore::new(DefaultTransCrate::metadata_loader()));
|
||||
|
||||
let loader = file_loader.unwrap_or(box RealFileLoader);
|
||||
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
|
||||
@ -1331,6 +1262,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
|
||||
all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
|
||||
#[cfg(feature="llvm")]
|
||||
all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
|
||||
|
@ -30,6 +30,7 @@ use rustc::hir::map as hir_map;
|
||||
use rustc::mir::transform::Passes;
|
||||
use rustc::session::{self, config};
|
||||
use rustc::session::config::{OutputFilenames, OutputTypes};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::abi::Abi;
|
||||
@ -105,7 +106,7 @@ fn test_env<F>(source_string: &str,
|
||||
options.unstable_features = UnstableFeatures::Allow;
|
||||
let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
|
||||
|
||||
let cstore = Rc::new(CStore::new(box ::MetadataLoader));
|
||||
let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader()));
|
||||
let sess = session::build_session_(options,
|
||||
None,
|
||||
diagnostic_handler,
|
||||
|
@ -8,8 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate rustc_trans_utils;
|
||||
|
||||
use super::archive::{ArchiveBuilder, ArchiveConfig};
|
||||
use super::linker::Linker;
|
||||
use super::command::Command;
|
||||
@ -20,14 +18,12 @@ use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, Pri
|
||||
use rustc::session::filesearch;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::session::Session;
|
||||
use rustc::ich::Fingerprint;
|
||||
use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind};
|
||||
use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use {CrateTranslation, CrateInfo};
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc_back::tempdir::TempDir;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
use context::get_reloc_model;
|
||||
@ -88,16 +84,9 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize =
|
||||
pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize =
|
||||
RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;
|
||||
|
||||
pub use self::rustc_trans_utils::link::{find_crate_name, filename_for_input,
|
||||
default_output_for_target, invalid_output_for_target};
|
||||
|
||||
pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta {
|
||||
let r = LinkMeta {
|
||||
crate_hash: Svh::new(crate_hash.to_smaller_hash()),
|
||||
};
|
||||
info!("{:?}", r);
|
||||
return r;
|
||||
}
|
||||
pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
|
||||
invalid_output_for_target, build_link_meta, out_filename,
|
||||
check_file_is_writeable};
|
||||
|
||||
// The third parameter is for env vars, used on windows to set up the
|
||||
// path for MSVC to find its DLLs, and gcc to find its bundled
|
||||
@ -225,13 +214,6 @@ pub fn link_binary(sess: &Session,
|
||||
out_filenames
|
||||
}
|
||||
|
||||
fn is_writeable(p: &Path) -> bool {
|
||||
match p.metadata() {
|
||||
Err(..) => true,
|
||||
Ok(m) => !m.permissions().readonly()
|
||||
}
|
||||
}
|
||||
|
||||
fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
|
||||
let out_filename = outputs.single_output_file.clone()
|
||||
.unwrap_or(outputs
|
||||
@ -295,32 +277,6 @@ pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool {
|
||||
info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum)
|
||||
}
|
||||
|
||||
fn out_filename(sess: &Session,
|
||||
crate_type: config::CrateType,
|
||||
outputs: &OutputFilenames,
|
||||
crate_name: &str)
|
||||
-> PathBuf {
|
||||
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
|
||||
let out_filename = outputs.outputs.get(&OutputType::Exe)
|
||||
.and_then(|s| s.to_owned())
|
||||
.or_else(|| outputs.single_output_file.clone())
|
||||
.unwrap_or(default_filename);
|
||||
|
||||
check_file_is_writeable(&out_filename, sess);
|
||||
|
||||
out_filename
|
||||
}
|
||||
|
||||
// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers
|
||||
// check this already -- however, the Linux linker will happily overwrite a
|
||||
// read-only file. We should be consistent.
|
||||
fn check_file_is_writeable(file: &Path, sess: &Session) {
|
||||
if !is_writeable(file) {
|
||||
sess.fatal(&format!("output file {} is not writeable -- check its \
|
||||
permissions", file.display()));
|
||||
}
|
||||
}
|
||||
|
||||
fn link_binary_output(sess: &Session,
|
||||
trans: &CrateTranslation,
|
||||
crate_type: config::CrateType,
|
||||
|
@ -43,7 +43,6 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::dep_graph::{DepNode, DepKind};
|
||||
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::util::common::{time, print_time_passes_entry};
|
||||
use rustc::session::config::{self, NoDebugInfo};
|
||||
use rustc::session::Session;
|
||||
@ -95,6 +94,8 @@ use syntax::ast;
|
||||
|
||||
use mir::lvalue::Alignment;
|
||||
|
||||
pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr};
|
||||
|
||||
pub struct StatRecorder<'a, 'tcx: 'a> {
|
||||
ccx: &'a CrateContext<'a, 'tcx>,
|
||||
name: Option<String>,
|
||||
@ -660,20 +661,6 @@ pub fn set_link_section(ccx: &CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
// check for the #[rustc_error] annotation, which forces an
|
||||
// error in trans. This is used to write compile-fail tests
|
||||
// that actually test that compilation succeeds without
|
||||
// reporting an error.
|
||||
fn check_for_rustc_errors_attr(tcx: TyCtxt) {
|
||||
if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
|
||||
let main_def_id = tcx.hir.local_def_id(id);
|
||||
|
||||
if tcx.has_attr(main_def_id, "rustc_error") {
|
||||
tcx.sess.span_fatal(span, "compilation successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the `main` function which will initialize the rust runtime and call
|
||||
/// users main function.
|
||||
fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
||||
@ -885,59 +872,10 @@ fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
|
||||
}
|
||||
}
|
||||
|
||||
/// The context provided lists a set of reachable ids as calculated by
|
||||
/// middle::reachable, but this contains far more ids and symbols than we're
|
||||
/// actually exposing from the object file. This function will filter the set in
|
||||
/// the context to the set of ids which correspond to symbols that are exposed
|
||||
/// from the object file being generated.
|
||||
///
|
||||
/// This list is later used by linkers to determine the set of symbols needed to
|
||||
/// be exposed from a dynamic library and it's also encoded into the metadata.
|
||||
pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
|
||||
tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
|
||||
// Next, we want to ignore some FFI functions that are not exposed from
|
||||
// this crate. Reachable FFI functions can be lumped into two
|
||||
// categories:
|
||||
//
|
||||
// 1. Those that are included statically via a static library
|
||||
// 2. Those included otherwise (e.g. dynamically or via a framework)
|
||||
//
|
||||
// Although our LLVM module is not literally emitting code for the
|
||||
// statically included symbols, it's an export of our library which
|
||||
// needs to be passed on to the linker and encoded in the metadata.
|
||||
//
|
||||
// As a result, if this id is an FFI item (foreign item) then we only
|
||||
// let it through if it's included statically.
|
||||
match tcx.hir.get(id) {
|
||||
hir_map::NodeForeignItem(..) => {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
tcx.is_statically_included_foreign_item(def_id)
|
||||
}
|
||||
|
||||
// Only consider nodes that actually have exported symbols.
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemStatic(..), .. }) |
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemFn(..), .. }) |
|
||||
hir_map::NodeImplItem(&hir::ImplItem {
|
||||
node: hir::ImplItemKind::Method(..), .. }) => {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
(generics.parent_types == 0 && generics.types.is_empty()) &&
|
||||
// Functions marked with #[inline] are only ever translated
|
||||
// with "internal" linkage and are never exported.
|
||||
!attr::requests_inline(&attributes)
|
||||
}
|
||||
|
||||
_ => false
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>)
|
||||
-> OngoingCrateTranslation {
|
||||
|
||||
check_for_rustc_errors_attr(tcx);
|
||||
|
||||
|
||||
|
@ -50,6 +50,7 @@ extern crate rustc_incremental;
|
||||
extern crate rustc_llvm as llvm;
|
||||
extern crate rustc_platform_intrinsics as intrinsics;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate rustc_demangle;
|
||||
extern crate jobserver;
|
||||
extern crate num_cpus;
|
||||
@ -137,6 +138,63 @@ mod type_;
|
||||
mod type_of;
|
||||
mod value;
|
||||
|
||||
use std::sync::mpsc;
|
||||
use std::any::Any;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::OutputFilenames;
|
||||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
|
||||
pub struct LlvmTransCrate(());
|
||||
|
||||
impl LlvmTransCrate {
|
||||
pub fn new() -> Self {
|
||||
LlvmTransCrate(())
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate {
|
||||
type MetadataLoader = metadata::LlvmMetadataLoader;
|
||||
type OngoingCrateTranslation = back::write::OngoingCrateTranslation;
|
||||
type TranslatedCrate = CrateTranslation;
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoader> {
|
||||
box metadata::LlvmMetadataLoader
|
||||
}
|
||||
|
||||
fn provide_local(providers: &mut ty::maps::Providers) {
|
||||
provide_local(providers);
|
||||
}
|
||||
|
||||
fn provide_extern(providers: &mut ty::maps::Providers) {
|
||||
provide_extern(providers);
|
||||
}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
base::trans_crate(tcx, rx)
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
sess: &Session,
|
||||
dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate {
|
||||
trans.join(sess, dep_graph)
|
||||
}
|
||||
|
||||
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
|
||||
back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str());
|
||||
}
|
||||
|
||||
fn dump_incremental_data(trans: &Self::TranslatedCrate) {
|
||||
back::write::dump_incremental_data(trans);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleTranslation {
|
||||
/// The name of the module. When the crate may be saved between
|
||||
/// compilations, incremental compilation requires that name be
|
||||
|
@ -10,6 +10,12 @@ crate-type = ["dylib"]
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
rustc = { path = "../librustc" }
|
||||
ar = "0.3.0"
|
||||
flate2 = "0.2"
|
||||
owning_ref = "0.3.3"
|
||||
log = "0.3"
|
||||
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
|
@ -29,8 +29,89 @@
|
||||
|
||||
#![cfg_attr(stage0, feature(const_fn))]
|
||||
|
||||
extern crate ar;
|
||||
extern crate flate2;
|
||||
extern crate owning_ref;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::util::nodemap::NodeSet;
|
||||
|
||||
use syntax::attr;
|
||||
|
||||
pub mod link;
|
||||
pub mod trans_crate;
|
||||
|
||||
/// check for the #[rustc_error] annotation, which forces an
|
||||
/// error in trans. This is used to write compile-fail tests
|
||||
/// that actually test that compilation succeeds without
|
||||
/// reporting an error.
|
||||
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
|
||||
if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
|
||||
let main_def_id = tcx.hir.local_def_id(id);
|
||||
|
||||
if tcx.has_attr(main_def_id, "rustc_error") {
|
||||
tcx.sess.span_fatal(span, "compilation successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The context provided lists a set of reachable ids as calculated by
|
||||
/// middle::reachable, but this contains far more ids and symbols than we're
|
||||
/// actually exposing from the object file. This function will filter the set in
|
||||
/// the context to the set of ids which correspond to symbols that are exposed
|
||||
/// from the object file being generated.
|
||||
///
|
||||
/// This list is later used by linkers to determine the set of symbols needed to
|
||||
/// be exposed from a dynamic library and it's also encoded into the metadata.
|
||||
pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
|
||||
tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
|
||||
// Next, we want to ignore some FFI functions that are not exposed from
|
||||
// this crate. Reachable FFI functions can be lumped into two
|
||||
// categories:
|
||||
//
|
||||
// 1. Those that are included statically via a static library
|
||||
// 2. Those included otherwise (e.g. dynamically or via a framework)
|
||||
//
|
||||
// Although our LLVM module is not literally emitting code for the
|
||||
// statically included symbols, it's an export of our library which
|
||||
// needs to be passed on to the linker and encoded in the metadata.
|
||||
//
|
||||
// As a result, if this id is an FFI item (foreign item) then we only
|
||||
// let it through if it's included statically.
|
||||
match tcx.hir.get(id) {
|
||||
hir_map::NodeForeignItem(..) => {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
tcx.is_statically_included_foreign_item(def_id)
|
||||
}
|
||||
|
||||
// Only consider nodes that actually have exported symbols.
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemStatic(..), .. }) |
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemFn(..), .. }) |
|
||||
hir_map::NodeImplItem(&hir::ImplItem {
|
||||
node: hir::ImplItemKind::Method(..), .. }) => {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
(generics.parent_types == 0 && generics.types.is_empty()) &&
|
||||
// Functions marked with #[inline] are only ever translated
|
||||
// with "internal" linkage and are never exported.
|
||||
!attr::requests_inline(&attributes)
|
||||
}
|
||||
|
||||
_ => false
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
@ -8,13 +8,56 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::ich::Fingerprint;
|
||||
use rustc::session::config::{self, OutputFilenames, Input, OutputType};
|
||||
use rustc::session::Session;
|
||||
use rustc::middle::cstore;
|
||||
use std::path::PathBuf;
|
||||
use rustc::middle::cstore::{self, LinkMeta};
|
||||
use rustc::hir::svh::Svh;
|
||||
use std::path::{Path, PathBuf};
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
pub fn out_filename(sess: &Session,
|
||||
crate_type: config::CrateType,
|
||||
outputs: &OutputFilenames,
|
||||
crate_name: &str)
|
||||
-> PathBuf {
|
||||
let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
|
||||
let out_filename = outputs.outputs.get(&OutputType::Exe)
|
||||
.and_then(|s| s.to_owned())
|
||||
.or_else(|| outputs.single_output_file.clone())
|
||||
.unwrap_or(default_filename);
|
||||
|
||||
check_file_is_writeable(&out_filename, sess);
|
||||
|
||||
out_filename
|
||||
}
|
||||
|
||||
// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers
|
||||
// check this already -- however, the Linux linker will happily overwrite a
|
||||
// read-only file. We should be consistent.
|
||||
pub fn check_file_is_writeable(file: &Path, sess: &Session) {
|
||||
if !is_writeable(file) {
|
||||
sess.fatal(&format!("output file {} is not writeable -- check its \
|
||||
permissions", file.display()));
|
||||
}
|
||||
}
|
||||
|
||||
fn is_writeable(p: &Path) -> bool {
|
||||
match p.metadata() {
|
||||
Err(..) => true,
|
||||
Ok(m) => !m.permissions().readonly()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta {
|
||||
let r = LinkMeta {
|
||||
crate_hash: Svh::new(crate_hash.to_smaller_hash()),
|
||||
};
|
||||
info!("{:?}", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
pub fn find_crate_name(sess: Option<&Session>,
|
||||
attrs: &[ast::Attribute],
|
||||
input: &Input) -> String {
|
||||
|
249
src/librustc_trans_utils/trans_crate.rs
Normal file
249
src/librustc_trans_utils/trans_crate.rs
Normal file
@ -0,0 +1,249 @@
|
||||
// Copyright 2014-2015 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.
|
||||
|
||||
//! The Rust compiler.
|
||||
//!
|
||||
//! # Note
|
||||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::any::Any;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, Cursor};
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use ar::{Archive, Builder, Header};
|
||||
use flate2::Compression;
|
||||
use flate2::write::DeflateEncoder;
|
||||
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::session::Session;
|
||||
use rustc::session::config::{CrateType, OutputFilenames};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
|
||||
use rustc::dep_graph::{DepGraph, DepNode, DepKind};
|
||||
use rustc_back::target::Target;
|
||||
use link::{build_link_meta, out_filename};
|
||||
|
||||
pub trait TransCrate {
|
||||
type MetadataLoader: MetadataLoaderTrait;
|
||||
type OngoingCrateTranslation;
|
||||
type TranslatedCrate;
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait>;
|
||||
fn provide_local(_providers: &mut Providers);
|
||||
fn provide_extern(_providers: &mut Providers);
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation;
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
sess: &Session,
|
||||
dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate;
|
||||
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
|
||||
fn dump_incremental_data(trans: &Self::TranslatedCrate);
|
||||
}
|
||||
|
||||
pub struct DummyTransCrate;
|
||||
|
||||
impl TransCrate for DummyTransCrate {
|
||||
type MetadataLoader = DummyMetadataLoader;
|
||||
type OngoingCrateTranslation = ();
|
||||
type TranslatedCrate = ();
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait> {
|
||||
box DummyMetadataLoader(())
|
||||
}
|
||||
|
||||
fn provide_local(_providers: &mut Providers) {
|
||||
bug!("DummyTransCrate::provide_local");
|
||||
}
|
||||
|
||||
fn provide_extern(_providers: &mut Providers) {
|
||||
bug!("DummyTransCrate::provide_extern");
|
||||
}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
bug!("DummyTransCrate::trans_crate");
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
_trans: Self::OngoingCrateTranslation,
|
||||
_sess: &Session,
|
||||
_dep_graph: &DepGraph
|
||||
) -> Self::TranslatedCrate {
|
||||
bug!("DummyTransCrate::join_trans");
|
||||
}
|
||||
|
||||
fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
|
||||
bug!("DummyTransCrate::link_binary");
|
||||
}
|
||||
|
||||
fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
|
||||
bug!("DummyTransCrate::dump_incremental_data");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DummyMetadataLoader(());
|
||||
|
||||
impl MetadataLoaderTrait for DummyMetadataLoader {
|
||||
fn get_rlib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
bug!("DummyMetadataLoader::get_rlib_metadata");
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
bug!("DummyMetadataLoader::get_dylib_metadata");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoLlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoaderTrait for NoLlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
let file = File::open(filename)
|
||||
.map_err(|e| format!("metadata file open err: {:?}", e))?;
|
||||
let mut archive = Archive::new(file);
|
||||
|
||||
while let Some(entry_result) = archive.next_entry() {
|
||||
let mut entry = entry_result
|
||||
.map_err(|e| format!("metadata section read err: {:?}", e))?;
|
||||
if entry.header().identifier() == "rust.metadata.bin" {
|
||||
let mut buf = Vec::new();
|
||||
io::copy(&mut entry, &mut buf).unwrap();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
return Ok(buf.map_owner_box().erase_owner());
|
||||
}
|
||||
}
|
||||
|
||||
Err("Couldnt find metadata section".to_string())
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(
|
||||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path,
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
// FIXME: Support reading dylibs from llvm enabled rustc
|
||||
self.get_rlib_metadata(_target, _filename)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MetadataOnlyTransCrate;
|
||||
pub struct OngoingCrateTranslation {
|
||||
metadata: EncodedMetadata,
|
||||
metadata_version: Vec<u8>,
|
||||
crate_name: Symbol,
|
||||
}
|
||||
pub struct TranslatedCrate(OngoingCrateTranslation);
|
||||
|
||||
impl MetadataOnlyTransCrate {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
MetadataOnlyTransCrate
|
||||
}
|
||||
}
|
||||
|
||||
impl TransCrate for MetadataOnlyTransCrate {
|
||||
type MetadataLoader = NoLlvmMetadataLoader;
|
||||
type OngoingCrateTranslation = OngoingCrateTranslation;
|
||||
type TranslatedCrate = TranslatedCrate;
|
||||
|
||||
fn metadata_loader() -> Box<MetadataLoaderTrait> {
|
||||
box NoLlvmMetadataLoader
|
||||
}
|
||||
|
||||
fn provide_local(_providers: &mut Providers) {}
|
||||
fn provide_extern(_providers: &mut Providers) {}
|
||||
|
||||
fn trans_crate<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_rx: mpsc::Receiver<Box<Any + Send>>
|
||||
) -> Self::OngoingCrateTranslation {
|
||||
::check_for_rustc_errors_attr(tcx);
|
||||
let _ = tcx.link_args(LOCAL_CRATE);
|
||||
let _ = tcx.native_libraries(LOCAL_CRATE);
|
||||
tcx.sess.abort_if_errors();
|
||||
|
||||
let crate_hash = tcx.dep_graph
|
||||
.fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
|
||||
let link_meta = build_link_meta(crate_hash);
|
||||
let exported_symbols = ::find_exported_symbols(tcx);
|
||||
let (metadata, _hashes) = tcx.encode_metadata(&link_meta, &exported_symbols);
|
||||
|
||||
OngoingCrateTranslation {
|
||||
metadata: metadata,
|
||||
metadata_version: tcx.metadata_encoding_version().to_vec(),
|
||||
crate_name: tcx.crate_name(LOCAL_CRATE),
|
||||
}
|
||||
}
|
||||
|
||||
fn join_trans(
|
||||
trans: Self::OngoingCrateTranslation,
|
||||
_sess: &Session,
|
||||
_dep_graph: &DepGraph,
|
||||
) -> Self::TranslatedCrate {
|
||||
TranslatedCrate(trans)
|
||||
}
|
||||
|
||||
fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
|
||||
for &crate_type in sess.opts.crate_types.iter() {
|
||||
if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
|
||||
continue;
|
||||
}
|
||||
let output_name =
|
||||
out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
|
||||
let mut compressed = trans.0.metadata_version.clone();
|
||||
let metadata = if crate_type == CrateType::CrateTypeDylib {
|
||||
DeflateEncoder::new(&mut compressed, Compression::Fast)
|
||||
.write_all(&trans.0.metadata.raw_data)
|
||||
.unwrap();
|
||||
&compressed
|
||||
} else {
|
||||
&trans.0.metadata.raw_data
|
||||
};
|
||||
let mut builder = Builder::new(File::create(&output_name).unwrap());
|
||||
let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
|
||||
builder.append(&header, Cursor::new(metadata)).unwrap();
|
||||
}
|
||||
|
||||
if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
|
||||
&& !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
|
||||
sess.fatal("Executables are not supported by the metadata-only backend.");
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
|
||||
}
|
Loading…
Reference in New Issue
Block a user