]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans_utils/trans_crate.rs
Rollup merge of #47529 - nikomatsakis:impl-trait-issue-38064, r=cramertj
[rust.git] / src / librustc_trans_utils / trans_crate.rs
1 // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The Rust compiler.
12 //!
13 //! # Note
14 //!
15 //! This API is completely unstable and subject to change.
16
17 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
18       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
19       html_root_url = "https://doc.rust-lang.org/nightly/")]
20 #![deny(warnings)]
21
22 #![feature(box_syntax)]
23
24 use std::any::Any;
25 use std::io::prelude::*;
26 use std::io::{self, Cursor};
27 use std::fs::File;
28 use std::path::Path;
29 use std::rc::Rc;
30 use std::sync::mpsc;
31
32 use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
33 use ar::{Archive, Builder, Header};
34 use flate2::Compression;
35 use flate2::write::DeflateEncoder;
36
37 use syntax::symbol::Symbol;
38 use rustc::hir::def_id::LOCAL_CRATE;
39 use rustc::session::{Session, CompileIncomplete};
40 use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
41 use rustc::ty::TyCtxt;
42 use rustc::ty::maps::Providers;
43 use rustc::middle::cstore::EncodedMetadata;
44 use rustc::middle::cstore::MetadataLoader;
45 use rustc::dep_graph::DepGraph;
46 use rustc_back::target::Target;
47 use rustc_mir::monomorphize::collector;
48 use link::{build_link_meta, out_filename};
49
50 pub trait TransCrate {
51     fn print(&self, _req: PrintRequest, _sess: &Session) {}
52     fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
53
54     fn metadata_loader(&self) -> Box<MetadataLoader>;
55     fn provide(&self, _providers: &mut Providers);
56     fn provide_extern(&self, _providers: &mut Providers);
57     fn trans_crate<'a, 'tcx>(
58         &self,
59         tcx: TyCtxt<'a, 'tcx, 'tcx>,
60         rx: mpsc::Receiver<Box<Any + Send>>
61     ) -> Box<Any>;
62
63     /// This is called on the returned `Box<Any>` from `trans_crate`
64     ///
65     /// # Panics
66     ///
67     /// Panics when the passed `Box<Any>` was not returned by `trans_crate`.
68     fn join_trans_and_link(
69         &self,
70         trans: Box<Any>,
71         sess: &Session,
72         dep_graph: &DepGraph,
73         outputs: &OutputFilenames,
74     ) -> Result<(), CompileIncomplete>;
75 }
76
77 pub struct DummyTransCrate;
78
79 impl TransCrate for DummyTransCrate {
80     fn metadata_loader(&self) -> Box<MetadataLoader> {
81         box DummyMetadataLoader(())
82     }
83
84     fn provide(&self, _providers: &mut Providers) {
85         bug!("DummyTransCrate::provide");
86     }
87
88     fn provide_extern(&self, _providers: &mut Providers) {
89         bug!("DummyTransCrate::provide_extern");
90     }
91
92     fn trans_crate<'a, 'tcx>(
93         &self,
94         _tcx: TyCtxt<'a, 'tcx, 'tcx>,
95         _rx: mpsc::Receiver<Box<Any + Send>>
96     ) -> Box<Any> {
97         bug!("DummyTransCrate::trans_crate");
98     }
99
100     fn join_trans_and_link(
101         &self,
102         _trans: Box<Any>,
103         _sess: &Session,
104         _dep_graph: &DepGraph,
105         _outputs: &OutputFilenames,
106     ) -> Result<(), CompileIncomplete> {
107         bug!("DummyTransCrate::join_trans_and_link");
108     }
109 }
110
111 pub struct DummyMetadataLoader(());
112
113 impl MetadataLoader for DummyMetadataLoader {
114     fn get_rlib_metadata(
115         &self,
116         _target: &Target,
117         _filename: &Path
118     ) -> Result<ErasedBoxRef<[u8]>, String> {
119         bug!("DummyMetadataLoader::get_rlib_metadata");
120     }
121
122     fn get_dylib_metadata(
123         &self,
124         _target: &Target,
125         _filename: &Path
126     ) -> Result<ErasedBoxRef<[u8]>, String> {
127         bug!("DummyMetadataLoader::get_dylib_metadata");
128     }
129 }
130
131 pub struct NoLlvmMetadataLoader;
132
133 impl MetadataLoader for NoLlvmMetadataLoader {
134     fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
135         let file = File::open(filename)
136             .map_err(|e| format!("metadata file open err: {:?}", e))?;
137         let mut archive = Archive::new(file);
138
139         while let Some(entry_result) = archive.next_entry() {
140             let mut entry = entry_result
141                 .map_err(|e| format!("metadata section read err: {:?}", e))?;
142             if entry.header().identifier() == "rust.metadata.bin" {
143                 let mut buf = Vec::new();
144                 io::copy(&mut entry, &mut buf).unwrap();
145                 let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
146                 return Ok(buf.map_owner_box().erase_owner());
147             }
148         }
149
150         Err("Couldnt find metadata section".to_string())
151     }
152
153     fn get_dylib_metadata(
154         &self,
155         _target: &Target,
156         _filename: &Path,
157     ) -> Result<ErasedBoxRef<[u8]>, String> {
158         // FIXME: Support reading dylibs from llvm enabled rustc
159         self.get_rlib_metadata(_target, _filename)
160     }
161 }
162
163 pub struct MetadataOnlyTransCrate(());
164 pub struct OngoingCrateTranslation {
165     metadata: EncodedMetadata,
166     metadata_version: Vec<u8>,
167     crate_name: Symbol,
168 }
169
170 impl MetadataOnlyTransCrate {
171     pub fn new(sess: &Session) -> Box<TransCrate> {
172         for cty in sess.opts.crate_types.iter() {
173             match *cty {
174                 CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
175                 CrateType::CrateTypeExecutable => {},
176                 _ => {
177                     sess.parse_sess.span_diagnostic.warn(
178                         &format!("LLVM unsupported, so output type {} is not supported", cty)
179                     );
180                 },
181             }
182         }
183
184         box MetadataOnlyTransCrate(())
185     }
186 }
187
188 impl TransCrate for MetadataOnlyTransCrate {
189     fn metadata_loader(&self) -> Box<MetadataLoader> {
190         box NoLlvmMetadataLoader
191     }
192
193     fn provide(&self, providers: &mut Providers) {
194         ::symbol_names::provide(providers);
195         providers.target_features_enabled = |_tcx, _id| {
196             Rc::new(Vec::new()) // Just a dummy
197         };
198     }
199     fn provide_extern(&self, _providers: &mut Providers) {}
200
201     fn trans_crate<'a, 'tcx>(
202         &self,
203         tcx: TyCtxt<'a, 'tcx, 'tcx>,
204         _rx: mpsc::Receiver<Box<Any + Send>>
205     ) -> Box<Any> {
206         use rustc_mir::monomorphize::item::MonoItem;
207
208         ::check_for_rustc_errors_attr(tcx);
209         ::symbol_names_test::report_symbol_names(tcx);
210         ::rustc_incremental::assert_dep_graph(tcx);
211         ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
212         ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx,
213             collector::collect_crate_mono_items(
214                 tcx,
215                 collector::MonoItemCollectionMode::Eager
216             ).0.iter()
217         );
218         ::rustc::middle::dependency_format::calculate(tcx);
219         let _ = tcx.link_args(LOCAL_CRATE);
220         let _ = tcx.native_libraries(LOCAL_CRATE);
221         for trans_item in
222             collector::collect_crate_mono_items(
223                 tcx,
224                 collector::MonoItemCollectionMode::Eager
225             ).0 {
226             match trans_item {
227                 MonoItem::Fn(inst) => {
228                     let def_id = inst.def_id();
229                     if def_id.is_local()  {
230                         let _ = tcx.export_name(def_id);
231                         let _ = tcx.contains_extern_indicator(def_id);
232                         let _ = inst.def.is_inline(tcx);
233                         let attrs = inst.def.attrs(tcx);
234                         let _ =
235                             ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
236                     }
237                 }
238                 _ => {}
239             }
240         }
241         tcx.sess.abort_if_errors();
242
243         let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
244         let exported_symbols = ::find_exported_symbols(tcx);
245         let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
246
247         box OngoingCrateTranslation {
248             metadata: metadata,
249             metadata_version: tcx.metadata_encoding_version().to_vec(),
250             crate_name: tcx.crate_name(LOCAL_CRATE),
251         }
252     }
253
254     fn join_trans_and_link(
255         &self,
256         trans: Box<Any>,
257         sess: &Session,
258         _dep_graph: &DepGraph,
259         outputs: &OutputFilenames,
260     ) -> Result<(), CompileIncomplete> {
261         let trans = trans.downcast::<OngoingCrateTranslation>()
262             .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
263         for &crate_type in sess.opts.crate_types.iter() {
264             if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
265                 continue;
266             }
267             let output_name =
268                 out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
269             let mut compressed = trans.metadata_version.clone();
270             let metadata = if crate_type == CrateType::CrateTypeDylib {
271                 DeflateEncoder::new(&mut compressed, Compression::fast())
272                     .write_all(&trans.metadata.raw_data)
273                     .unwrap();
274                 &compressed
275             } else {
276                 &trans.metadata.raw_data
277             };
278             let mut builder = Builder::new(File::create(&output_name).unwrap());
279             let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
280             builder.append(&header, Cursor::new(metadata)).unwrap();
281         }
282
283         sess.abort_if_errors();
284         if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
285             && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
286         {
287             sess.fatal("Executables are not supported by the metadata-only backend.");
288         }
289         Ok(())
290     }
291 }