5 //! This API is completely unstable and subject to change.
7 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
8 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
9 html_root_url = "https://doc.rust-lang.org/nightly/")]
12 #![feature(box_syntax)]
18 use std::sync::{mpsc, Arc};
20 use rustc_data_structures::owning_ref::OwningRef;
21 use flate2::Compression;
22 use flate2::write::DeflateEncoder;
24 use syntax::symbol::Symbol;
25 use rustc::hir::def_id::LOCAL_CRATE;
26 use rustc::session::{Session, CompileIncomplete};
27 use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
28 use rustc::ty::TyCtxt;
29 use rustc::ty::query::Providers;
30 use rustc::middle::cstore::EncodedMetadata;
31 use rustc::middle::cstore::MetadataLoader;
32 use rustc::dep_graph::DepGraph;
33 use rustc_target::spec::Target;
34 use link::out_filename;
36 pub use rustc_data_structures::sync::MetadataRef;
38 pub trait CodegenBackend {
39 fn init(&self, _sess: &Session) {}
40 fn print(&self, _req: PrintRequest, _sess: &Session) {}
41 fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
42 fn print_passes(&self) {}
43 fn print_version(&self) {}
44 fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
46 fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync>;
47 fn provide(&self, _providers: &mut Providers);
48 fn provide_extern(&self, _providers: &mut Providers);
49 fn codegen_crate<'a, 'tcx>(
51 tcx: TyCtxt<'a, 'tcx, 'tcx>,
52 rx: mpsc::Receiver<Box<dyn Any + Send>>
55 /// This is called on the returned `Box<dyn Any>` from `codegen_backend`
59 /// Panics when the passed `Box<dyn Any>` was not returned by `codegen_backend`.
60 fn join_codegen_and_link(
62 ongoing_codegen: Box<dyn Any>,
65 outputs: &OutputFilenames,
66 ) -> Result<(), CompileIncomplete>;
69 pub struct NoLlvmMetadataLoader;
71 impl MetadataLoader for NoLlvmMetadataLoader {
72 fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
73 let buf = fs::read(filename).map_err(|e| format!("metadata file open err: {:?}", e))?;
74 let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
75 Ok(rustc_erase_owner!(buf.map_owner_box()))
78 fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String> {
79 self.get_rlib_metadata(target, filename)
83 pub struct MetadataOnlyCodegenBackend(());
84 pub struct OngoingCodegen {
85 metadata: EncodedMetadata,
86 metadata_version: Vec<u8>,
90 impl MetadataOnlyCodegenBackend {
91 pub fn boxed() -> Box<dyn CodegenBackend> {
92 box MetadataOnlyCodegenBackend(())
96 impl CodegenBackend for MetadataOnlyCodegenBackend {
97 fn init(&self, sess: &Session) {
98 for cty in sess.opts.crate_types.iter() {
100 CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {},
102 sess.diagnostic().warn(
103 &format!("LLVM unsupported, so output type {} is not supported", cty)
110 fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
111 box NoLlvmMetadataLoader
114 fn provide(&self, providers: &mut Providers) {
115 ::symbol_names::provide(providers);
117 providers.target_features_whitelist = |_tcx, _cnum| {
118 Default::default() // Just a dummy
120 providers.is_reachable_non_generic = |_tcx, _defid| true;
121 providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
123 fn provide_extern(&self, providers: &mut Providers) {
124 providers.is_reachable_non_generic = |_tcx, _defid| true;
127 fn codegen_crate<'a, 'tcx>(
129 tcx: TyCtxt<'a, 'tcx, 'tcx>,
130 _rx: mpsc::Receiver<Box<dyn Any + Send>>
132 use rustc_mir::monomorphize::item::MonoItem;
134 ::check_for_rustc_errors_attr(tcx);
135 ::symbol_names_test::report_symbol_names(tcx);
136 ::rustc_incremental::assert_dep_graph(tcx);
137 ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
139 // ::rustc::middle::dependency_format::calculate(tcx);
140 let _ = tcx.link_args(LOCAL_CRATE);
141 let _ = tcx.native_libraries(LOCAL_CRATE);
142 let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
143 for (mono_item, _) in cgus.iter().flat_map(|cgu| cgu.items().iter()) {
144 if let MonoItem::Fn(inst) = mono_item {
145 let def_id = inst.def_id();
146 if def_id.is_local() {
147 let _ = tcx.codegen_fn_attrs(def_id);
151 tcx.sess.abort_if_errors();
153 let metadata = tcx.encode_metadata();
157 metadata_version: tcx.metadata_encoding_version().to_vec(),
158 crate_name: tcx.crate_name(LOCAL_CRATE),
162 fn join_codegen_and_link(
164 ongoing_codegen: Box<dyn Any>,
166 _dep_graph: &DepGraph,
167 outputs: &OutputFilenames,
168 ) -> Result<(), CompileIncomplete> {
169 let ongoing_codegen = ongoing_codegen.downcast::<OngoingCodegen>()
170 .expect("Expected MetadataOnlyCodegenBackend's OngoingCodegen, found Box<dyn Any>");
171 for &crate_type in sess.opts.crate_types.iter() {
172 if crate_type != CrateType::Rlib &&
173 crate_type != CrateType::Dylib {
177 out_filename(sess, crate_type, &outputs, &ongoing_codegen.crate_name.as_str());
178 let mut compressed = ongoing_codegen.metadata_version.clone();
179 let metadata = if crate_type == CrateType::Dylib {
180 DeflateEncoder::new(&mut compressed, Compression::fast())
181 .write_all(&ongoing_codegen.metadata.raw_data)
185 &ongoing_codegen.metadata.raw_data
187 fs::write(&output_name, metadata).unwrap();
190 sess.abort_if_errors();
191 if !sess.opts.crate_types.contains(&CrateType::Rlib)
192 && !sess.opts.crate_types.contains(&CrateType::Dylib)
194 sess.fatal("Executables are not supported by the metadata-only backend.");