]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
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::sync::mpsc; | |
30 | ||
0531ce1d XL |
31 | use rustc_data_structures::owning_ref::OwningRef; |
32 | use rustc_data_structures::sync::Lrc; | |
ea8adc8c XL |
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; | |
2c00a5a8 XL |
39 | use rustc::session::{Session, CompileIncomplete}; |
40 | use rustc::session::config::{CrateType, OutputFilenames, PrintRequest}; | |
ea8adc8c XL |
41 | use rustc::ty::TyCtxt; |
42 | use rustc::ty::maps::Providers; | |
43 | use rustc::middle::cstore::EncodedMetadata; | |
2c00a5a8 | 44 | use rustc::middle::cstore::MetadataLoader; |
ff7c6d11 | 45 | use rustc::dep_graph::DepGraph; |
83c7162d XL |
46 | use rustc_target::spec::Target; |
47 | use rustc_data_structures::fx::FxHashMap; | |
2c00a5a8 | 48 | use rustc_mir::monomorphize::collector; |
ea8adc8c XL |
49 | use link::{build_link_meta, out_filename}; |
50 | ||
0531ce1d XL |
51 | pub use rustc_data_structures::sync::MetadataRef; |
52 | ||
ea8adc8c | 53 | pub trait TransCrate { |
2c00a5a8 XL |
54 | fn init(&self, _sess: &Session) {} |
55 | fn print(&self, _req: PrintRequest, _sess: &Session) {} | |
56 | fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] } | |
57 | fn print_passes(&self) {} | |
58 | fn print_version(&self) {} | |
59 | fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] } | |
60 | ||
0531ce1d | 61 | fn metadata_loader(&self) -> Box<MetadataLoader + Sync>; |
2c00a5a8 XL |
62 | fn provide(&self, _providers: &mut Providers); |
63 | fn provide_extern(&self, _providers: &mut Providers); | |
ea8adc8c | 64 | fn trans_crate<'a, 'tcx>( |
2c00a5a8 | 65 | &self, |
ea8adc8c XL |
66 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
67 | rx: mpsc::Receiver<Box<Any + Send>> | |
2c00a5a8 XL |
68 | ) -> Box<Any>; |
69 | ||
70 | /// This is called on the returned `Box<Any>` from `trans_crate` | |
71 | /// | |
72 | /// # Panics | |
73 | /// | |
74 | /// Panics when the passed `Box<Any>` was not returned by `trans_crate`. | |
75 | fn join_trans_and_link( | |
76 | &self, | |
77 | trans: Box<Any>, | |
ea8adc8c | 78 | sess: &Session, |
2c00a5a8 XL |
79 | dep_graph: &DepGraph, |
80 | outputs: &OutputFilenames, | |
81 | ) -> Result<(), CompileIncomplete>; | |
ea8adc8c XL |
82 | } |
83 | ||
84 | pub struct DummyTransCrate; | |
85 | ||
86 | impl TransCrate for DummyTransCrate { | |
0531ce1d | 87 | fn metadata_loader(&self) -> Box<MetadataLoader + Sync> { |
ea8adc8c XL |
88 | box DummyMetadataLoader(()) |
89 | } | |
90 | ||
2c00a5a8 | 91 | fn provide(&self, _providers: &mut Providers) { |
abe05a73 | 92 | bug!("DummyTransCrate::provide"); |
ea8adc8c XL |
93 | } |
94 | ||
2c00a5a8 | 95 | fn provide_extern(&self, _providers: &mut Providers) { |
ea8adc8c XL |
96 | bug!("DummyTransCrate::provide_extern"); |
97 | } | |
98 | ||
99 | fn trans_crate<'a, 'tcx>( | |
2c00a5a8 | 100 | &self, |
ea8adc8c XL |
101 | _tcx: TyCtxt<'a, 'tcx, 'tcx>, |
102 | _rx: mpsc::Receiver<Box<Any + Send>> | |
2c00a5a8 | 103 | ) -> Box<Any> { |
ea8adc8c XL |
104 | bug!("DummyTransCrate::trans_crate"); |
105 | } | |
106 | ||
2c00a5a8 XL |
107 | fn join_trans_and_link( |
108 | &self, | |
109 | _trans: Box<Any>, | |
ea8adc8c | 110 | _sess: &Session, |
2c00a5a8 XL |
111 | _dep_graph: &DepGraph, |
112 | _outputs: &OutputFilenames, | |
113 | ) -> Result<(), CompileIncomplete> { | |
114 | bug!("DummyTransCrate::join_trans_and_link"); | |
ea8adc8c XL |
115 | } |
116 | } | |
117 | ||
118 | pub struct DummyMetadataLoader(()); | |
119 | ||
2c00a5a8 | 120 | impl MetadataLoader for DummyMetadataLoader { |
ea8adc8c XL |
121 | fn get_rlib_metadata( |
122 | &self, | |
123 | _target: &Target, | |
124 | _filename: &Path | |
0531ce1d | 125 | ) -> Result<MetadataRef, String> { |
ea8adc8c XL |
126 | bug!("DummyMetadataLoader::get_rlib_metadata"); |
127 | } | |
128 | ||
129 | fn get_dylib_metadata( | |
130 | &self, | |
131 | _target: &Target, | |
132 | _filename: &Path | |
0531ce1d | 133 | ) -> Result<MetadataRef, String> { |
ea8adc8c XL |
134 | bug!("DummyMetadataLoader::get_dylib_metadata"); |
135 | } | |
136 | } | |
137 | ||
138 | pub struct NoLlvmMetadataLoader; | |
139 | ||
2c00a5a8 | 140 | impl MetadataLoader for NoLlvmMetadataLoader { |
0531ce1d | 141 | fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> { |
ea8adc8c XL |
142 | let file = File::open(filename) |
143 | .map_err(|e| format!("metadata file open err: {:?}", e))?; | |
144 | let mut archive = Archive::new(file); | |
145 | ||
146 | while let Some(entry_result) = archive.next_entry() { | |
147 | let mut entry = entry_result | |
148 | .map_err(|e| format!("metadata section read err: {:?}", e))?; | |
149 | if entry.header().identifier() == "rust.metadata.bin" { | |
150 | let mut buf = Vec::new(); | |
151 | io::copy(&mut entry, &mut buf).unwrap(); | |
152 | let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into(); | |
0531ce1d | 153 | return Ok(rustc_erase_owner!(buf.map_owner_box())); |
ea8adc8c XL |
154 | } |
155 | } | |
156 | ||
0531ce1d | 157 | Err("Couldn't find metadata section".to_string()) |
ea8adc8c XL |
158 | } |
159 | ||
160 | fn get_dylib_metadata( | |
161 | &self, | |
162 | _target: &Target, | |
163 | _filename: &Path, | |
0531ce1d | 164 | ) -> Result<MetadataRef, String> { |
ea8adc8c XL |
165 | // FIXME: Support reading dylibs from llvm enabled rustc |
166 | self.get_rlib_metadata(_target, _filename) | |
167 | } | |
168 | } | |
169 | ||
2c00a5a8 | 170 | pub struct MetadataOnlyTransCrate(()); |
ea8adc8c XL |
171 | pub struct OngoingCrateTranslation { |
172 | metadata: EncodedMetadata, | |
173 | metadata_version: Vec<u8>, | |
174 | crate_name: Symbol, | |
175 | } | |
ea8adc8c XL |
176 | |
177 | impl MetadataOnlyTransCrate { | |
2c00a5a8 XL |
178 | pub fn new() -> Box<TransCrate> { |
179 | box MetadataOnlyTransCrate(()) | |
ea8adc8c XL |
180 | } |
181 | } | |
182 | ||
183 | impl TransCrate for MetadataOnlyTransCrate { | |
2c00a5a8 XL |
184 | fn init(&self, sess: &Session) { |
185 | for cty in sess.opts.crate_types.iter() { | |
186 | match *cty { | |
187 | CrateType::CrateTypeRlib | CrateType::CrateTypeDylib | | |
188 | CrateType::CrateTypeExecutable => {}, | |
189 | _ => { | |
190 | sess.parse_sess.span_diagnostic.warn( | |
191 | &format!("LLVM unsupported, so output type {} is not supported", cty) | |
192 | ); | |
193 | }, | |
194 | } | |
195 | } | |
196 | } | |
ea8adc8c | 197 | |
0531ce1d | 198 | fn metadata_loader(&self) -> Box<MetadataLoader + Sync> { |
ea8adc8c XL |
199 | box NoLlvmMetadataLoader |
200 | } | |
201 | ||
2c00a5a8 XL |
202 | fn provide(&self, providers: &mut Providers) { |
203 | ::symbol_names::provide(providers); | |
0531ce1d XL |
204 | |
205 | providers.target_features_whitelist = |_tcx, _cnum| { | |
83c7162d | 206 | Lrc::new(FxHashMap()) // Just a dummy |
2c00a5a8 XL |
207 | }; |
208 | } | |
209 | fn provide_extern(&self, _providers: &mut Providers) {} | |
ea8adc8c XL |
210 | |
211 | fn trans_crate<'a, 'tcx>( | |
2c00a5a8 | 212 | &self, |
ea8adc8c XL |
213 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
214 | _rx: mpsc::Receiver<Box<Any + Send>> | |
2c00a5a8 XL |
215 | ) -> Box<Any> { |
216 | use rustc_mir::monomorphize::item::MonoItem; | |
217 | ||
ea8adc8c | 218 | ::check_for_rustc_errors_attr(tcx); |
2c00a5a8 XL |
219 | ::symbol_names_test::report_symbol_names(tcx); |
220 | ::rustc_incremental::assert_dep_graph(tcx); | |
221 | ::rustc_incremental::assert_module_sources::assert_module_sources(tcx); | |
222 | ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, | |
223 | collector::collect_crate_mono_items( | |
224 | tcx, | |
225 | collector::MonoItemCollectionMode::Eager | |
226 | ).0.iter() | |
227 | ); | |
228 | ::rustc::middle::dependency_format::calculate(tcx); | |
ea8adc8c XL |
229 | let _ = tcx.link_args(LOCAL_CRATE); |
230 | let _ = tcx.native_libraries(LOCAL_CRATE); | |
2c00a5a8 XL |
231 | for trans_item in |
232 | collector::collect_crate_mono_items( | |
233 | tcx, | |
234 | collector::MonoItemCollectionMode::Eager | |
235 | ).0 { | |
236 | match trans_item { | |
237 | MonoItem::Fn(inst) => { | |
238 | let def_id = inst.def_id(); | |
239 | if def_id.is_local() { | |
2c00a5a8 | 240 | let _ = inst.def.is_inline(tcx); |
0531ce1d | 241 | let _ = tcx.trans_fn_attrs(def_id); |
2c00a5a8 XL |
242 | } |
243 | } | |
244 | _ => {} | |
245 | } | |
246 | } | |
ea8adc8c XL |
247 | tcx.sess.abort_if_errors(); |
248 | ||
ff7c6d11 | 249 | let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE)); |
0531ce1d | 250 | let metadata = tcx.encode_metadata(&link_meta); |
ea8adc8c | 251 | |
2c00a5a8 | 252 | box OngoingCrateTranslation { |
ea8adc8c XL |
253 | metadata: metadata, |
254 | metadata_version: tcx.metadata_encoding_version().to_vec(), | |
255 | crate_name: tcx.crate_name(LOCAL_CRATE), | |
256 | } | |
257 | } | |
258 | ||
2c00a5a8 XL |
259 | fn join_trans_and_link( |
260 | &self, | |
261 | trans: Box<Any>, | |
262 | sess: &Session, | |
ea8adc8c | 263 | _dep_graph: &DepGraph, |
2c00a5a8 XL |
264 | outputs: &OutputFilenames, |
265 | ) -> Result<(), CompileIncomplete> { | |
266 | let trans = trans.downcast::<OngoingCrateTranslation>() | |
267 | .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>"); | |
ea8adc8c XL |
268 | for &crate_type in sess.opts.crate_types.iter() { |
269 | if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib { | |
270 | continue; | |
271 | } | |
272 | let output_name = | |
2c00a5a8 XL |
273 | out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str()); |
274 | let mut compressed = trans.metadata_version.clone(); | |
ea8adc8c | 275 | let metadata = if crate_type == CrateType::CrateTypeDylib { |
ff7c6d11 | 276 | DeflateEncoder::new(&mut compressed, Compression::fast()) |
2c00a5a8 | 277 | .write_all(&trans.metadata.raw_data) |
ea8adc8c XL |
278 | .unwrap(); |
279 | &compressed | |
280 | } else { | |
2c00a5a8 | 281 | &trans.metadata.raw_data |
ea8adc8c XL |
282 | }; |
283 | let mut builder = Builder::new(File::create(&output_name).unwrap()); | |
284 | let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64); | |
285 | builder.append(&header, Cursor::new(metadata)).unwrap(); | |
286 | } | |
287 | ||
2c00a5a8 | 288 | sess.abort_if_errors(); |
ea8adc8c | 289 | if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib) |
2c00a5a8 XL |
290 | && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) |
291 | { | |
ea8adc8c XL |
292 | sess.fatal("Executables are not supported by the metadata-only backend."); |
293 | } | |
2c00a5a8 | 294 | Ok(()) |
ea8adc8c | 295 | } |
ea8adc8c | 296 | } |