]> git.proxmox.com Git - rustc.git/blame - src/librustc_driver/driver.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc_driver / driver.rs
CommitLineData
85aaf69f 1// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
1a4d82fc
JJ
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
54a0048b 11use rustc::hir;
a7813a04
XL
12use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
13use rustc::hir::def::DefMap;
3157f602 14use rustc::hir::lowering::lower_crate;
e9174d1e 15use rustc_mir as mir;
7453a54e
SL
16use rustc::mir::mir_map::MirMap;
17use rustc::session::{Session, CompileResult, compile_result_from_err_count};
5bcae85e
SL
18use rustc::session::config::{self, Input, OutputFilenames, OutputType,
19 OutputTypes};
1a4d82fc
JJ
20use rustc::session::search_paths::PathKind;
21use rustc::lint;
54a0048b 22use rustc::middle::{self, dependency_format, stability, reachable};
7453a54e 23use rustc::middle::privacy::AccessLevels;
54a0048b 24use rustc::ty::{self, TyCtxt};
1a4d82fc 25use rustc::util::common::time;
7453a54e 26use rustc::util::nodemap::NodeSet;
54a0048b 27use rustc_back::sha2::{Sha256, Digest};
1a4d82fc 28use rustc_borrowck as borrowck;
9e0c209e 29use rustc_incremental::{self, IncrementalHashesMap};
3157f602 30use rustc_resolve::{MakeGlobMap, Resolver};
9e0c209e 31use rustc_metadata::creader::CrateLoader;
92a42be0 32use rustc_metadata::cstore::CStore;
3157f602 33use rustc_trans::back::{link, write};
54a0048b 34use rustc_trans as trans;
1a4d82fc 35use rustc_typeck as typeck;
85aaf69f 36use rustc_privacy;
92a42be0
SL
37use rustc_plugin::registry::Registry;
38use rustc_plugin as plugin;
3157f602 39use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, static_recursion};
54a0048b 40use rustc_const_eval::check_match;
85aaf69f 41use super::Compilation;
1a4d82fc
JJ
42
43use serialize::json;
44
85aaf69f 45use std::env;
9e0c209e 46use std::mem;
62682a34 47use std::ffi::{OsString, OsStr};
c34b1796
AL
48use std::fs;
49use std::io::{self, Write};
50use std::path::{Path, PathBuf};
3157f602 51use syntax::{ast, diagnostics, visit};
9e0c209e
SL
52use syntax::attr;
53use syntax::ext::base::ExtCtxt;
54a0048b 54use syntax::parse::{self, PResult, token};
92a42be0 55use syntax::util::node_count::NodeCounter;
1a4d82fc 56use syntax;
9cc50fc6 57use syntax_ext;
1a4d82fc 58
9e0c209e
SL
59use derive_registrar;
60
a7813a04
XL
61#[derive(Clone)]
62pub struct Resolutions {
3157f602 63 pub def_map: DefMap,
a7813a04
XL
64 pub freevars: FreevarMap,
65 pub trait_map: TraitMap,
66 pub maybe_unused_trait_imports: NodeSet,
67}
68
7453a54e 69pub fn compile_input(sess: &Session,
92a42be0 70 cstore: &CStore,
1a4d82fc
JJ
71 cfg: ast::CrateConfig,
72 input: &Input,
c34b1796
AL
73 outdir: &Option<PathBuf>,
74 output: &Option<PathBuf>,
85aaf69f 75 addl_plugins: Option<Vec<String>>,
7453a54e
SL
76 control: &CompileController) -> CompileResult {
77 macro_rules! controller_entry_point {
78 ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
a7813a04 79 let state = &mut $make_state;
7453a54e
SL
80 let phase_result: &CompileResult = &$phase_result;
81 if phase_result.is_ok() || control.$point.run_callback_on_error {
82 (control.$point.callback)(state);
83 }
84
85 if control.$point.stop == Compilation::Stop {
86 return compile_result_from_err_count($tsess.err_count());
87 }
88 }}
89 }
85aaf69f 90
1a4d82fc
JJ
91 // We need nested scopes here, because the intermediate results can keep
92 // large chunks of memory alive and we want to free them as soon as
93 // possible to keep the peak memory usage low
9e0c209e 94 let (outputs, trans) = {
3157f602
XL
95 let krate = match phase_1_parse_input(sess, cfg, input) {
96 Ok(krate) => krate,
97 Err(mut parse_error) => {
98 parse_error.emit();
99 return Err(1);
100 }
101 };
85aaf69f 102
9e0c209e 103 let (krate, registry) = {
a7813a04
XL
104 let mut compile_state = CompileState::state_after_parse(input,
105 sess,
106 outdir,
107 output,
108 krate,
109 &cstore);
85aaf69f 110 controller_entry_point!(after_parse,
d9579d0f 111 sess,
a7813a04 112 compile_state,
7453a54e 113 Ok(()));
1a4d82fc 114
9e0c209e 115 (compile_state.krate.unwrap(), compile_state.registry)
1a4d82fc
JJ
116 };
117
3157f602 118 let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
5bcae85e 119 let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
3157f602
XL
120 let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
121 phase_2_configure_and_expand(
9e0c209e 122 sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map,
3157f602
XL
123 |expanded_crate| {
124 let mut state = CompileState::state_after_expand(
5bcae85e 125 input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
3157f602
XL
126 );
127 controller_entry_point!(after_expand, sess, state, Ok(()));
128 Ok(())
129 }
130 )?
a7813a04 131 };
92a42be0 132
5bcae85e 133 write_out_deps(sess, &outputs, &crate_name);
92a42be0 134
85aaf69f 135 let arenas = ty::CtxtArenas::new();
1a4d82fc 136
a7813a04 137 // Construct the HIR map
a7813a04
XL
138 let hir_map = time(sess.time_passes(),
139 "indexing hir",
3157f602 140 || hir_map::map_crate(&mut hir_forest, defs));
85aaf69f 141
7453a54e
SL
142 {
143 let _ignore = hir_map.dep_graph.in_ignore();
a7813a04 144 controller_entry_point!(after_hir_lowering,
7453a54e 145 sess,
a7813a04
XL
146 CompileState::state_after_hir_lowering(input,
147 sess,
148 outdir,
149 output,
150 &arenas,
151 &cstore,
152 &hir_map,
153 &analysis,
154 &resolutions,
155 &expanded_crate,
156 &hir_map.krate(),
5bcae85e 157 &crate_name),
7453a54e
SL
158 Ok(()));
159 }
85aaf69f 160
b039eaaf 161 time(sess.time_passes(), "attribute checking", || {
54a0048b 162 hir::check_attr::check_crate(sess, &expanded_crate);
b039eaaf
SL
163 });
164
a7813a04 165 let opt_crate = if keep_ast(sess) {
9cc50fc6
SL
166 Some(&expanded_crate)
167 } else {
168 drop(expanded_crate);
169 None
170 };
171
54a0048b 172 phase_3_run_analysis_passes(sess,
54a0048b 173 hir_map,
a7813a04
XL
174 analysis,
175 resolutions,
54a0048b 176 &arenas,
5bcae85e 177 &crate_name,
9e0c209e 178 |tcx, mir_map, analysis, incremental_hashes_map, result| {
7453a54e
SL
179 {
180 // Eventually, we will want to track plugins.
181 let _ignore = tcx.dep_graph.in_ignore();
182
a7813a04
XL
183 let mut state = CompileState::state_after_analysis(input,
184 sess,
185 outdir,
186 output,
187 opt_crate,
188 tcx.map.krate(),
189 &analysis,
190 mir_map.as_ref(),
191 tcx,
5bcae85e 192 &crate_name);
a7813a04 193 (control.after_analysis.callback)(&mut state);
7453a54e
SL
194
195 if control.after_analysis.stop == Compilation::Stop {
a7813a04 196 return result.and_then(|_| Err(0usize));
7453a54e
SL
197 }
198 }
62682a34 199
54a0048b 200 result?;
7453a54e
SL
201
202 if log_enabled!(::log::INFO) {
203 println!("Pre-trans");
204 tcx.print_debug_stats();
205 }
206 let trans = phase_4_translate_to_llvm(tcx,
207 mir_map.unwrap(),
9e0c209e
SL
208 analysis,
209 &incremental_hashes_map);
7453a54e
SL
210
211 if log_enabled!(::log::INFO) {
212 println!("Post-trans");
213 tcx.print_debug_stats();
214 }
215
216 // Discard interned strings as they are no longer required.
5bcae85e 217 token::clear_ident_interner();
7453a54e 218
9e0c209e 219 Ok((outputs, trans))
54a0048b 220 })??
62682a34
SL
221 };
222
9e0c209e 223 let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
85aaf69f
SL
224
225 controller_entry_point!(after_llvm,
d9579d0f 226 sess,
a7813a04 227 CompileState::state_after_llvm(input, sess, outdir, output, &trans),
7453a54e 228 phase5_result);
54a0048b 229 phase5_result?;
7453a54e 230
3157f602
XL
231 write::cleanup_llvm(&trans);
232
7453a54e 233 phase_6_link_output(sess, &trans, &outputs);
85aaf69f 234
9e0c209e
SL
235 // Now that we won't touch anything in the incremental compilation directory
236 // any more, we can finalize it (which involves renaming it)
237 rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
238
239 if sess.opts.debugging_opts.perf_stats {
240 sess.print_perf_stats();
241 }
242
3157f602
XL
243 controller_entry_point!(compilation_done,
244 sess,
245 CompileState::state_when_compilation_done(input, sess, outdir, output),
246 Ok(()));
247
7453a54e 248 Ok(())
1a4d82fc
JJ
249}
250
5bcae85e
SL
251fn keep_hygiene_data(sess: &Session) -> bool {
252 sess.opts.debugging_opts.keep_hygiene_data
a7813a04
XL
253}
254
255fn keep_ast(sess: &Session) -> bool {
256 sess.opts.debugging_opts.keep_ast ||
257 sess.opts.debugging_opts.save_analysis ||
9e0c209e
SL
258 sess.opts.debugging_opts.save_analysis_csv ||
259 sess.opts.debugging_opts.save_analysis_api
a7813a04
XL
260}
261
1a4d82fc
JJ
262/// The name used for source code that doesn't originate in a file
263/// (e.g. source from stdin or a string)
264pub fn anon_src() -> String {
265 "<anon>".to_string()
266}
267
268pub fn source_name(input: &Input) -> String {
269 match *input {
270 // FIXME (#9639): This needs to handle non-utf8 paths
c34b1796 271 Input::File(ref ifile) => ifile.to_str().unwrap().to_string(),
54a0048b 272 Input::Str { ref name, .. } => name.clone(),
1a4d82fc
JJ
273 }
274}
275
85aaf69f
SL
276/// CompileController is used to customise compilation, it allows compilation to
277/// be stopped and/or to call arbitrary code at various points in compilation.
278/// It also allows for various flags to be set to influence what information gets
279/// collected during compilation.
280///
281/// This is a somewhat higher level controller than a Session - the Session
282/// controls what happens in each phase, whereas the CompileController controls
283/// whether a phase is run at all and whether other code (from outside the
284/// the compiler) is run between phases.
285///
286/// Note that if compilation is set to stop and a callback is provided for a
287/// given entry point, the callback is called before compilation is stopped.
288///
289/// Expect more entry points to be added in the future.
290pub struct CompileController<'a> {
291 pub after_parse: PhaseController<'a>,
292 pub after_expand: PhaseController<'a>,
a7813a04 293 pub after_hir_lowering: PhaseController<'a>,
85aaf69f
SL
294 pub after_analysis: PhaseController<'a>,
295 pub after_llvm: PhaseController<'a>,
3157f602 296 pub compilation_done: PhaseController<'a>,
85aaf69f 297
3157f602 298 pub make_glob_map: MakeGlobMap,
85aaf69f
SL
299}
300
301impl<'a> CompileController<'a> {
302 pub fn basic() -> CompileController<'a> {
303 CompileController {
304 after_parse: PhaseController::basic(),
305 after_expand: PhaseController::basic(),
a7813a04 306 after_hir_lowering: PhaseController::basic(),
85aaf69f
SL
307 after_analysis: PhaseController::basic(),
308 after_llvm: PhaseController::basic(),
3157f602
XL
309 compilation_done: PhaseController::basic(),
310 make_glob_map: MakeGlobMap::No,
85aaf69f
SL
311 }
312 }
313}
314
315pub struct PhaseController<'a> {
316 pub stop: Compilation,
7453a54e
SL
317 // If true then the compiler will try to run the callback even if the phase
318 // ends with an error. Note that this is not always possible.
319 pub run_callback_on_error: bool,
a7813a04 320 pub callback: Box<Fn(&mut CompileState) + 'a>,
85aaf69f
SL
321}
322
323impl<'a> PhaseController<'a> {
324 pub fn basic() -> PhaseController<'a> {
325 PhaseController {
326 stop: Compilation::Continue,
7453a54e 327 run_callback_on_error: false,
85aaf69f
SL
328 callback: box |_| {},
329 }
330 }
331}
332
333/// State that is passed to a callback. What state is available depends on when
334/// during compilation the callback is made. See the various constructor methods
335/// (`state_*`) in the impl to see which data is provided for any given entry point.
a7813a04 336pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
85aaf69f 337 pub input: &'a Input,
a7813a04
XL
338 pub session: &'ast Session,
339 pub krate: Option<ast::Crate>,
9e0c209e 340 pub registry: Option<Registry<'a>>,
a7813a04 341 pub cstore: Option<&'a CStore>,
85aaf69f
SL
342 pub crate_name: Option<&'a str>,
343 pub output_filenames: Option<&'a OutputFilenames>,
344 pub out_dir: Option<&'a Path>,
a7813a04
XL
345 pub out_file: Option<&'a Path>,
346 pub arenas: Option<&'ast ty::CtxtArenas<'ast>>,
85aaf69f 347 pub expanded_crate: Option<&'a ast::Crate>,
e9174d1e
SL
348 pub hir_crate: Option<&'a hir::Crate>,
349 pub ast_map: Option<&'a hir_map::Map<'ast>>,
a7813a04
XL
350 pub resolutions: Option<&'a Resolutions>,
351 pub mir_map: Option<&'b MirMap<'tcx>>,
b039eaaf 352 pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
a7813a04 353 pub tcx: Option<TyCtxt<'b, 'tcx, 'tcx>>,
85aaf69f
SL
354 pub trans: Option<&'a trans::CrateTranslation>,
355}
356
a7813a04 357impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
85aaf69f 358 fn empty(input: &'a Input,
a7813a04 359 session: &'ast Session,
c34b1796 360 out_dir: &'a Option<PathBuf>)
a7813a04 361 -> CompileState<'a, 'b, 'ast, 'tcx> {
85aaf69f
SL
362 CompileState {
363 input: input,
364 session: session,
c34b1796 365 out_dir: out_dir.as_ref().map(|s| &**s),
a7813a04
XL
366 out_file: None,
367 arenas: None,
85aaf69f 368 krate: None,
9e0c209e 369 registry: None,
a7813a04 370 cstore: None,
85aaf69f
SL
371 crate_name: None,
372 output_filenames: None,
373 expanded_crate: None,
e9174d1e 374 hir_crate: None,
85aaf69f 375 ast_map: None,
a7813a04 376 resolutions: None,
85aaf69f 377 analysis: None,
92a42be0 378 mir_map: None,
85aaf69f
SL
379 tcx: None,
380 trans: None,
381 }
382 }
383
384 fn state_after_parse(input: &'a Input,
a7813a04 385 session: &'ast Session,
c34b1796 386 out_dir: &'a Option<PathBuf>,
a7813a04
XL
387 out_file: &'a Option<PathBuf>,
388 krate: ast::Crate,
389 cstore: &'a CStore)
390 -> CompileState<'a, 'b, 'ast, 'tcx> {
391 CompileState {
9e0c209e
SL
392 // Initialize the registry before moving `krate`
393 registry: Some(Registry::new(&session, krate.span)),
a7813a04
XL
394 krate: Some(krate),
395 cstore: Some(cstore),
396 out_file: out_file.as_ref().map(|s| &**s),
397 ..CompileState::empty(input, session, out_dir)
398 }
85aaf69f
SL
399 }
400
401 fn state_after_expand(input: &'a Input,
a7813a04 402 session: &'ast Session,
c34b1796 403 out_dir: &'a Option<PathBuf>,
a7813a04
XL
404 out_file: &'a Option<PathBuf>,
405 cstore: &'a CStore,
85aaf69f
SL
406 expanded_crate: &'a ast::Crate,
407 crate_name: &'a str)
a7813a04 408 -> CompileState<'a, 'b, 'ast, 'tcx> {
85aaf69f
SL
409 CompileState {
410 crate_name: Some(crate_name),
a7813a04 411 cstore: Some(cstore),
85aaf69f 412 expanded_crate: Some(expanded_crate),
a7813a04 413 out_file: out_file.as_ref().map(|s| &**s),
92a42be0 414 ..CompileState::empty(input, session, out_dir)
85aaf69f
SL
415 }
416 }
417
a7813a04
XL
418 fn state_after_hir_lowering(input: &'a Input,
419 session: &'ast Session,
420 out_dir: &'a Option<PathBuf>,
421 out_file: &'a Option<PathBuf>,
422 arenas: &'ast ty::CtxtArenas<'ast>,
423 cstore: &'a CStore,
424 hir_map: &'a hir_map::Map<'ast>,
425 analysis: &'a ty::CrateAnalysis,
426 resolutions: &'a Resolutions,
427 krate: &'a ast::Crate,
428 hir_crate: &'a hir::Crate,
429 crate_name: &'a str)
430 -> CompileState<'a, 'b, 'ast, 'tcx> {
85aaf69f
SL
431 CompileState {
432 crate_name: Some(crate_name),
a7813a04
XL
433 arenas: Some(arenas),
434 cstore: Some(cstore),
9cc50fc6 435 ast_map: Some(hir_map),
a7813a04
XL
436 analysis: Some(analysis),
437 resolutions: Some(resolutions),
438 expanded_crate: Some(krate),
e9174d1e 439 hir_crate: Some(hir_crate),
a7813a04 440 out_file: out_file.as_ref().map(|s| &**s),
92a42be0 441 ..CompileState::empty(input, session, out_dir)
85aaf69f
SL
442 }
443 }
444
445 fn state_after_analysis(input: &'a Input,
a7813a04 446 session: &'ast Session,
c34b1796 447 out_dir: &'a Option<PathBuf>,
a7813a04 448 out_file: &'a Option<PathBuf>,
9cc50fc6 449 krate: Option<&'a ast::Crate>,
e9174d1e 450 hir_crate: &'a hir::Crate,
a7813a04
XL
451 analysis: &'a ty::CrateAnalysis<'a>,
452 mir_map: Option<&'b MirMap<'tcx>>,
453 tcx: TyCtxt<'b, 'tcx, 'tcx>,
b039eaaf 454 crate_name: &'a str)
a7813a04 455 -> CompileState<'a, 'b, 'ast, 'tcx> {
85aaf69f
SL
456 CompileState {
457 analysis: Some(analysis),
7453a54e 458 mir_map: mir_map,
85aaf69f 459 tcx: Some(tcx),
a7813a04 460 expanded_crate: krate,
e9174d1e 461 hir_crate: Some(hir_crate),
b039eaaf 462 crate_name: Some(crate_name),
a7813a04 463 out_file: out_file.as_ref().map(|s| &**s),
92a42be0 464 ..CompileState::empty(input, session, out_dir)
85aaf69f
SL
465 }
466 }
467
468
469 fn state_after_llvm(input: &'a Input,
a7813a04 470 session: &'ast Session,
c34b1796 471 out_dir: &'a Option<PathBuf>,
a7813a04 472 out_file: &'a Option<PathBuf>,
85aaf69f 473 trans: &'a trans::CrateTranslation)
a7813a04
XL
474 -> CompileState<'a, 'b, 'ast, 'tcx> {
475 CompileState {
476 trans: Some(trans),
477 out_file: out_file.as_ref().map(|s| &**s),
478 ..CompileState::empty(input, session, out_dir)
479 }
85aaf69f 480 }
3157f602
XL
481
482 fn state_when_compilation_done(input: &'a Input,
483 session: &'ast Session,
484 out_dir: &'a Option<PathBuf>,
485 out_file: &'a Option<PathBuf>)
486 -> CompileState<'a, 'b, 'ast, 'tcx> {
487 CompileState {
488 out_file: out_file.as_ref().map(|s| &**s),
489 ..CompileState::empty(input, session, out_dir)
490 }
491 }
85aaf69f
SL
492}
493
54a0048b
SL
494pub fn phase_1_parse_input<'a>(sess: &'a Session,
495 cfg: ast::CrateConfig,
496 input: &Input)
497 -> PResult<'a, ast::Crate> {
5bcae85e 498 let continue_after_error = sess.opts.debugging_opts.continue_parse_after_error;
7453a54e 499 sess.diagnostic().set_continue_after_error(continue_after_error);
1a4d82fc 500
e9174d1e 501 let krate = time(sess.time_passes(), "parsing", || {
1a4d82fc
JJ
502 match *input {
503 Input::File(ref file) => {
54a0048b 504 parse::parse_crate_from_file(file, cfg.clone(), &sess.parse_sess)
1a4d82fc 505 }
54a0048b
SL
506 Input::Str { ref input, ref name } => {
507 parse::parse_crate_from_source_str(name.clone(),
508 input.clone(),
1a4d82fc
JJ
509 cfg.clone(),
510 &sess.parse_sess)
511 }
512 }
54a0048b 513 })?;
1a4d82fc 514
7453a54e
SL
515 sess.diagnostic().set_continue_after_error(true);
516
1a4d82fc
JJ
517 if sess.opts.debugging_opts.ast_json_noexpand {
518 println!("{}", json::as_json(&krate));
519 }
520
92a42be0
SL
521 if sess.opts.debugging_opts.input_stats {
522 println!("Lines of code: {}", sess.codemap().count_lines());
523 println!("Pre-expansion node count: {}", count_nodes(&krate));
524 }
525
9cc50fc6 526 if let Some(ref s) = sess.opts.debugging_opts.show_span {
85aaf69f 527 syntax::show_span::run(sess.diagnostic(), s, &krate);
1a4d82fc
JJ
528 }
529
54a0048b 530 Ok(krate)
1a4d82fc
JJ
531}
532
92a42be0
SL
533fn count_nodes(krate: &ast::Crate) -> usize {
534 let mut counter = NodeCounter::new();
535 visit::walk_crate(&mut counter, krate);
536 counter.count
537}
538
1a4d82fc
JJ
539// For continuing compilation after a parsed crate has been
540// modified
541
3157f602
XL
542pub struct ExpansionResult<'a> {
543 pub expanded_crate: ast::Crate,
544 pub defs: hir_map::Definitions,
545 pub analysis: ty::CrateAnalysis<'a>,
546 pub resolutions: Resolutions,
547 pub hir_forest: hir_map::Forest,
548}
549
1a4d82fc
JJ
550/// Run the "early phases" of the compiler: initial `cfg` processing,
551/// loading compiler plugins (including those from `addl_plugins`),
552/// syntax expansion, secondary `cfg` expansion, synthesis of a test
3157f602
XL
553/// harness if one is to be provided, injection of a dependency on the
554/// standard library and prelude, and name resolution.
1a4d82fc
JJ
555///
556/// Returns `None` if we're aborting after handling -W help.
3157f602
XL
557pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
558 cstore: &CStore,
9e0c209e
SL
559 krate: ast::Crate,
560 registry: Option<Registry>,
3157f602
XL
561 crate_name: &'a str,
562 addl_plugins: Option<Vec<String>>,
563 make_glob_map: MakeGlobMap,
564 after_expand: F)
565 -> Result<ExpansionResult<'a>, usize>
566 where F: FnOnce(&ast::Crate) -> CompileResult,
567{
1a4d82fc
JJ
568 let time_passes = sess.time_passes();
569
9e0c209e
SL
570 let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test);
571 // these need to be set "early" so that expansion sees `quote` if enabled.
572 *sess.features.borrow_mut() = features;
9346a6ac 573
92a42be0 574 *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
5bcae85e
SL
575 *sess.crate_disambiguator.borrow_mut() =
576 token::intern(&compute_crate_disambiguator(sess)).as_str();
d9579d0f 577
e9174d1e 578 time(time_passes, "recursion limit", || {
d9579d0f
AL
579 middle::recursion_limit::update_recursion_limit(sess, &krate);
580 });
581
92a42be0 582 krate = time(time_passes, "crate injection", || {
3157f602
XL
583 let alt_std_name = sess.opts.alt_std_name.clone();
584 syntax::std_inject::maybe_inject_crates_ref(&sess.parse_sess, krate, alt_std_name)
92a42be0 585 });
1a4d82fc
JJ
586
587 let mut addl_plugins = Some(addl_plugins);
92a42be0 588 let registrars = time(time_passes, "plugin loading", || {
54a0048b
SL
589 plugin::load::load_plugins(sess,
590 &cstore,
591 &krate,
592 crate_name,
593 addl_plugins.take().unwrap())
92a42be0 594 });
1a4d82fc 595
9e0c209e 596 let mut registry = registry.unwrap_or(Registry::new(sess, krate.span));
1a4d82fc 597
e9174d1e 598 time(time_passes, "plugin registration", || {
1a4d82fc
JJ
599 if sess.features.borrow().rustc_diagnostic_macros {
600 registry.register_macro("__diagnostic_used",
92a42be0 601 diagnostics::plugin::expand_diagnostic_used);
1a4d82fc 602 registry.register_macro("__register_diagnostic",
92a42be0 603 diagnostics::plugin::expand_register_diagnostic);
1a4d82fc 604 registry.register_macro("__build_diagnostic_array",
92a42be0 605 diagnostics::plugin::expand_build_diagnostic_array);
1a4d82fc
JJ
606 }
607
85aaf69f 608 for registrar in registrars {
1a4d82fc
JJ
609 registry.args_hidden = Some(registrar.args);
610 (registrar.fun)(&mut registry);
611 }
612 });
613
b039eaaf 614 let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
7453a54e 615 llvm_passes, attributes, mir_passes, .. } = registry;
1a4d82fc 616
54a0048b 617 sess.track_errors(|| {
1a4d82fc 618 let mut ls = sess.lint_store.borrow_mut();
b039eaaf
SL
619 for pass in early_lint_passes {
620 ls.register_early_pass(Some(sess), true, pass);
621 }
622 for pass in late_lint_passes {
623 ls.register_late_pass(Some(sess), true, pass);
1a4d82fc
JJ
624 }
625
85aaf69f 626 for (name, to) in lint_groups {
1a4d82fc
JJ
627 ls.register_group(Some(sess), true, name, to);
628 }
9346a6ac
AL
629
630 *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
54a0048b 631 sess.mir_passes.borrow_mut().extend(mir_passes);
62682a34 632 *sess.plugin_attributes.borrow_mut() = attributes.clone();
54a0048b 633 })?;
1a4d82fc
JJ
634
635 // Lint plugins are registered; now we can process command line flags.
636 if sess.opts.describe_lints {
7453a54e
SL
637 super::describe_lints(&sess.lint_store.borrow(), true);
638 return Err(0);
1a4d82fc 639 }
54a0048b 640 sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?;
1a4d82fc 641
9e0c209e
SL
642 let mut crate_loader = CrateLoader::new(sess, &cstore, &krate, crate_name);
643 let resolver_arenas = Resolver::arenas();
644 let mut resolver =
645 Resolver::new(sess, &krate, make_glob_map, &mut crate_loader, &resolver_arenas);
646 syntax_ext::register_builtins(&mut resolver, sess.features.borrow().quote);
647
e9174d1e
SL
648 krate = time(time_passes, "expansion", || {
649 // Windows dlls do not have rpaths, so they don't know how to find their
650 // dependencies. It's up to us to tell the system where to find all the
651 // dependent dlls. Note that this uses cfg!(windows) as opposed to
652 // targ_cfg because syntax extensions are always loaded for the host
653 // compiler, not for the target.
3157f602
XL
654 //
655 // This is somewhat of an inherently racy operation, however, as
656 // multiple threads calling this function could possibly continue
657 // extending PATH far beyond what it should. To solve this for now we
658 // just don't add any new elements to PATH which are already there
659 // within PATH. This is basically a targeted fix at #17360 for rustdoc
660 // which runs rustc in parallel but has been seen (#33844) to cause
661 // problems with PATH becoming too long.
662 let mut old_path = OsString::new();
e9174d1e 663 if cfg!(windows) {
3157f602 664 old_path = env::var_os("PATH").unwrap_or(old_path);
e9174d1e
SL
665 let mut new_path = sess.host_filesearch(PathKind::All)
666 .get_dylib_search_paths();
3157f602
XL
667 for path in env::split_paths(&old_path) {
668 if !new_path.contains(&path) {
669 new_path.push(path);
670 }
671 }
e9174d1e 672 env::set_var("PATH", &env::join_paths(new_path).unwrap());
1a4d82fc 673 }
e9174d1e
SL
674 let features = sess.features.borrow();
675 let cfg = syntax::ext::expand::ExpansionConfig {
e9174d1e
SL
676 features: Some(&features),
677 recursion_limit: sess.recursion_limit.get(),
678 trace_mac: sess.opts.debugging_opts.trace_macros,
3157f602 679 should_test: sess.opts.test,
9e0c209e 680 ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string())
e9174d1e 681 };
9e0c209e 682 let mut ecx = ExtCtxt::new(&sess.parse_sess, krate.config.clone(), cfg, &mut resolver);
5bcae85e 683 let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate);
e9174d1e 684 if cfg!(windows) {
3157f602 685 env::set_var("PATH", &old_path);
e9174d1e
SL
686 }
687 ret
688 });
1a4d82fc 689
9e0c209e
SL
690 krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new());
691
92a42be0 692 krate = time(time_passes, "maybe building test harness", || {
3157f602 693 syntax::test::modify_for_testing(&sess.parse_sess,
9e0c209e 694 &mut resolver,
3157f602
XL
695 sess.opts.test,
696 krate,
697 sess.diagnostic())
92a42be0 698 });
1a4d82fc 699
9e0c209e
SL
700 krate = time(time_passes, "maybe creating a macro crate", || {
701 let crate_types = sess.crate_types.borrow();
702 let is_rustc_macro_crate = crate_types.contains(&config::CrateTypeRustcMacro);
703 let num_crate_types = crate_types.len();
704 syntax_ext::rustc_macro_registrar::modify(&sess.parse_sess,
705 &mut resolver,
706 krate,
707 is_rustc_macro_crate,
708 num_crate_types,
709 sess.diagnostic(),
710 &sess.features.borrow())
711 });
5bcae85e
SL
712
713 if sess.opts.debugging_opts.input_stats {
714 println!("Post-expansion node count: {}", count_nodes(&krate));
715 }
716
717 if sess.opts.debugging_opts.ast_json {
718 println!("{}", json::as_json(&krate));
719 }
720
92a42be0
SL
721 time(time_passes,
722 "checking for inline asm in case the target doesn't support it",
7453a54e 723 || no_asm::check_crate(sess, &krate));
1a4d82fc 724
a7813a04
XL
725 // Needs to go *after* expansion to be able to check the results of macro expansion.
726 time(time_passes, "complete gated feature checking", || {
7453a54e 727 sess.track_errors(|| {
3157f602
XL
728 syntax::feature_gate::check_crate(&krate,
729 &sess.parse_sess,
730 &sess.features.borrow(),
731 &attributes,
732 sess.opts.unstable_features);
7453a54e 733 })
54a0048b 734 })?;
c34b1796 735
3157f602
XL
736 // Collect defintions for def ids.
737 time(sess.time_passes(), "collecting defs", || resolver.definitions.collect(&krate));
738
3157f602
XL
739 time(sess.time_passes(),
740 "early lint checks",
741 || lint::check_ast_crate(sess, &krate));
742
743 time(sess.time_passes(),
744 "AST validation",
745 || ast_validation::check_crate(sess, &krate));
746
747 time(sess.time_passes(), "name resolution", || -> CompileResult {
748 // Currently, we ignore the name resolution data structures for the purposes of dependency
749 // tracking. Instead we will run name resolution and include its output in the hash of each
750 // item, much like we do for macro expansion. In other words, the hash reflects not just
751 // its contents but the results of name resolution on those contents. Hopefully we'll push
752 // this back at some point.
753 let _ignore = sess.dep_graph.in_ignore();
754 resolver.build_reduced_graph(&krate);
755 resolver.resolve_imports();
756
757 // Since import resolution will eventually happen in expansion,
758 // don't perform `after_expand` until after import resolution.
759 after_expand(&krate)?;
760
761 resolver.resolve_crate(&krate);
762 Ok(())
763 })?;
764
765 // Lower ast -> hir.
766 let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
767 hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph)
768 });
769
5bcae85e
SL
770 // Discard hygiene data, which isn't required past lowering to HIR.
771 if !keep_hygiene_data(sess) {
772 syntax::ext::hygiene::reset_hygiene_data();
3157f602
XL
773 }
774
775 Ok(ExpansionResult {
776 expanded_crate: krate,
777 defs: resolver.definitions,
778 analysis: ty::CrateAnalysis {
779 export_map: resolver.export_map,
780 access_levels: AccessLevels::default(),
781 reachable: NodeSet(),
782 name: crate_name,
783 glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
784 },
785 resolutions: Resolutions {
786 def_map: resolver.def_map,
787 freevars: resolver.freevars,
788 trait_map: resolver.trait_map,
789 maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
790 },
791 hir_forest: hir_forest
792 })
1a4d82fc
JJ
793}
794
1a4d82fc
JJ
795/// Run the resolution, typechecking, region checking and other
796/// miscellaneous analysis passes on the crate. Return various
797/// structures carrying the results of the analysis.
b039eaaf 798pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
9cc50fc6 799 hir_map: hir_map::Map<'tcx>,
a7813a04
XL
800 mut analysis: ty::CrateAnalysis,
801 resolutions: Resolutions,
62682a34 802 arenas: &'tcx ty::CtxtArenas<'tcx>,
b039eaaf 803 name: &str,
62682a34 804 f: F)
7453a54e 805 -> Result<R, usize>
a7813a04
XL
806 where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
807 Option<MirMap<'tcx>>,
808 ty::CrateAnalysis,
9e0c209e 809 IncrementalHashesMap,
a7813a04 810 CompileResult) -> R
62682a34 811{
7453a54e 812 macro_rules! try_with_f {
9e0c209e 813 ($e: expr, ($t: expr, $m: expr, $a: expr, $h: expr)) => {
7453a54e
SL
814 match $e {
815 Ok(x) => x,
816 Err(x) => {
9e0c209e 817 f($t, $m, $a, $h, Err(x));
7453a54e
SL
818 return Err(x);
819 }
820 }
821 }
822 }
823
1a4d82fc 824 let time_passes = sess.time_passes();
1a4d82fc 825
54a0048b 826 let lang_items = time(time_passes, "language item collection", || {
7453a54e
SL
827 sess.track_errors(|| {
828 middle::lang_items::collect_language_items(&sess, &hir_map)
829 })
54a0048b 830 })?;
1a4d82fc 831
54a0048b
SL
832 let named_region_map = time(time_passes,
833 "lifetime resolution",
834 || middle::resolve_lifetime::krate(sess,
835 &hir_map,
3157f602 836 &resolutions.def_map))?;
1a4d82fc 837
92a42be0
SL
838 time(time_passes,
839 "looking for entry point",
9cc50fc6 840 || middle::entry::find_entry_point(sess, &hir_map));
1a4d82fc 841
92a42be0 842 sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || {
7453a54e 843 plugin::build::find_plugin_registrar(sess.diagnostic(), &hir_map)
92a42be0 844 }));
9e0c209e 845 sess.derive_registrar_fn.set(derive_registrar::find(&hir_map));
1a4d82fc 846
92a42be0
SL
847 let region_map = time(time_passes,
848 "region resolution",
7453a54e 849 || middle::region::resolve_crate(sess, &hir_map));
1a4d82fc 850
92a42be0
SL
851 time(time_passes,
852 "loop checking",
7453a54e 853 || loops::check_crate(sess, &hir_map));
1a4d82fc 854
54a0048b 855 time(time_passes,
7453a54e 856 "static item recursion checking",
3157f602 857 || static_recursion::check_crate(sess, &resolutions.def_map, &hir_map))?;
7453a54e
SL
858
859 let index = stability::Index::new(&hir_map);
1a4d82fc 860
54a0048b 861 TyCtxt::create_and_enter(sess,
a7813a04
XL
862 arenas,
863 resolutions.def_map,
5bcae85e 864 resolutions.trait_map,
a7813a04
XL
865 named_region_map,
866 hir_map,
867 resolutions.freevars,
868 resolutions.maybe_unused_trait_imports,
869 region_map,
870 lang_items,
871 index,
872 name,
873 |tcx| {
9e0c209e
SL
874 let incremental_hashes_map =
875 time(time_passes,
876 "compute_incremental_hashes_map",
877 || rustc_incremental::compute_incremental_hashes_map(tcx));
54a0048b
SL
878 time(time_passes,
879 "load_dep_graph",
9e0c209e 880 || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
54a0048b 881
7453a54e 882 // passes are timed inside typeck
9e0c209e 883 try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis, incremental_hashes_map));
7453a54e
SL
884
885 time(time_passes,
886 "const checking",
887 || consts::check_crate(tcx));
888
889 analysis.access_levels =
890 time(time_passes, "privacy checking", || {
54a0048b 891 rustc_privacy::check_crate(tcx, &analysis.export_map)
7453a54e
SL
892 });
893
894 // Do not move this check past lint
895 time(time_passes, "stability index", || {
896 tcx.stability.borrow_mut().build(tcx, &analysis.access_levels)
897 });
898
899 time(time_passes,
900 "intrinsic checking",
901 || middle::intrinsicck::check_crate(tcx));
902
903 time(time_passes,
904 "effect checking",
905 || middle::effect::check_crate(tcx));
906
907 time(time_passes,
908 "match checking",
54a0048b 909 || check_match::check_crate(tcx));
7453a54e
SL
910
911 // this must run before MIR dump, because
912 // "not all control paths return a value" is reported here.
913 //
914 // maybe move the check to a MIR pass?
915 time(time_passes,
916 "liveness checking",
917 || middle::liveness::check_crate(tcx));
918
919 time(time_passes,
920 "rvalue checking",
921 || rvalues::check_crate(tcx));
922
923 let mut mir_map =
924 time(time_passes,
925 "MIR dump",
926 || mir::mir_map::build_mir_for_crate(tcx));
927
54a0048b
SL
928 time(time_passes, "MIR passes", || {
929 let mut passes = sess.mir_passes.borrow_mut();
930 // Push all the built-in passes.
3157f602
XL
931 passes.push_hook(box mir::transform::dump_mir::DumpMir);
932 passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("initial"));
a7813a04 933 passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
54a0048b 934 passes.push_pass(box mir::transform::type_check::TypeckMir);
3157f602
XL
935 passes.push_pass(
936 box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
937 passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("qualify-consts"));
54a0048b
SL
938 // And run everything.
939 passes.run_passes(tcx, &mut mir_map);
940 });
7453a54e
SL
941
942 time(time_passes,
943 "borrow checking",
54a0048b 944 || borrowck::check_crate(tcx, &mir_map));
7453a54e
SL
945
946 // Avoid overwhelming user with errors if type checking failed.
947 // I'm not sure how helpful this is, to be honest, but it avoids
948 // a
949 // lot of annoying errors in the compile-fail tests (basically,
950 // lint warnings and so on -- kindck used to do this abort, but
951 // kindck is gone now). -nmatsakis
952 if sess.err_count() > 0 {
9e0c209e
SL
953 return Ok(f(tcx,
954 Some(mir_map),
955 analysis,
956 incremental_hashes_map,
957 Err(sess.err_count())));
7453a54e
SL
958 }
959
960 analysis.reachable =
961 time(time_passes,
962 "reachability checking",
963 || reachable::find_reachable(tcx, &analysis.access_levels));
964
965 time(time_passes, "death checking", || {
966 middle::dead::check_crate(tcx, &analysis.access_levels);
967 });
968
969 let ref lib_features_used =
970 time(time_passes,
971 "stability checking",
972 || stability::check_unstable_api_usage(tcx));
973
974 time(time_passes, "unused lib feature checking", || {
975 stability::check_unused_or_stable_features(&tcx.sess,
976 lib_features_used)
977 });
978
979 time(time_passes,
980 "lint checking",
981 || lint::check_crate(tcx, &analysis.access_levels));
982
983 // The above three passes generate errors w/o aborting
984 if sess.err_count() > 0 {
9e0c209e
SL
985 return Ok(f(tcx,
986 Some(mir_map),
987 analysis,
988 incremental_hashes_map,
989 Err(sess.err_count())));
7453a54e
SL
990 }
991
9e0c209e 992 Ok(f(tcx, Some(mir_map), analysis, incremental_hashes_map, Ok(())))
7453a54e 993 })
1a4d82fc
JJ
994}
995
1a4d82fc 996/// Run the translation phase to LLVM, after which the AST and analysis can
a7813a04
XL
997pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
998 mut mir_map: MirMap<'tcx>,
9e0c209e
SL
999 analysis: ty::CrateAnalysis,
1000 incremental_hashes_map: &IncrementalHashesMap)
a7813a04 1001 -> trans::CrateTranslation {
62682a34 1002 let time_passes = tcx.sess.time_passes();
1a4d82fc 1003
92a42be0
SL
1004 time(time_passes,
1005 "resolving dependency formats",
1006 || dependency_format::calculate(&tcx.sess));
1007
54a0048b
SL
1008 // Run the passes that transform the MIR into a more suitable for translation
1009 // to LLVM code.
1010 time(time_passes, "Prepare MIR codegen passes", || {
1011 let mut passes = ::rustc::mir::transform::Passes::new();
3157f602 1012 passes.push_hook(box mir::transform::dump_mir::DumpMir);
54a0048b 1013 passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
3157f602
XL
1014 passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("no-landing-pads"));
1015
9e0c209e 1016 // From here on out, regions are gone.
54a0048b 1017 passes.push_pass(box mir::transform::erase_regions::EraseRegions);
3157f602
XL
1018
1019 passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
1020 passes.push_pass(box borrowck::ElaborateDrops);
1021 passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads);
1022 passes.push_pass(box mir::transform::simplify_cfg::SimplifyCfg::new("elaborate-drops"));
1023
9e0c209e
SL
1024 // No lifetime analysis based on borrowing can be done from here on out.
1025 passes.push_pass(box mir::transform::instcombine::InstCombine::new());
5bcae85e 1026 passes.push_pass(box mir::transform::deaggregator::Deaggregator);
9e0c209e 1027 passes.push_pass(box mir::transform::copy_prop::CopyPropagation);
5bcae85e 1028
3157f602
XL
1029 passes.push_pass(box mir::transform::add_call_guards::AddCallGuards);
1030 passes.push_pass(box mir::transform::dump_mir::Marker("PreTrans"));
1031
54a0048b
SL
1032 passes.run_passes(tcx, &mut mir_map);
1033 });
1034
1035 let translation =
1036 time(time_passes,
1037 "translation",
9e0c209e 1038 move || trans::trans_crate(tcx, &mir_map, analysis, &incremental_hashes_map));
54a0048b 1039
92a42be0 1040 time(time_passes,
54a0048b 1041 "assert dep graph",
9e0c209e 1042 || rustc_incremental::assert_dep_graph(tcx));
1a4d82fc 1043
92a42be0 1044 time(time_passes,
54a0048b 1045 "serialize dep graph",
9e0c209e
SL
1046 || rustc_incremental::save_dep_graph(tcx,
1047 &incremental_hashes_map,
1048 translation.link.crate_hash));
54a0048b 1049 translation
1a4d82fc
JJ
1050}
1051
1052/// Run LLVM itself, producing a bitcode file, assembly file or object file
1053/// as a side effect.
1054pub fn phase_5_run_llvm_passes(sess: &Session,
1055 trans: &trans::CrateTranslation,
7453a54e 1056 outputs: &OutputFilenames) -> CompileResult {
1a4d82fc 1057 if sess.opts.cg.no_integrated_as {
5bcae85e 1058 let output_types = OutputTypes::new(&[(OutputType::Assembly, None)]);
92a42be0
SL
1059 time(sess.time_passes(),
1060 "LLVM passes",
5bcae85e 1061 || write::run_passes(sess, trans, &output_types, outputs));
1a4d82fc
JJ
1062
1063 write::run_assembler(sess, outputs);
1064
1065 // Remove assembly source, unless --save-temps was specified
1066 if !sess.opts.cg.save_temps {
5bcae85e 1067 fs::remove_file(&outputs.temp_path(OutputType::Assembly, None)).unwrap();
1a4d82fc
JJ
1068 }
1069 } else {
92a42be0
SL
1070 time(sess.time_passes(),
1071 "LLVM passes",
1072 || write::run_passes(sess, trans, &sess.opts.output_types, outputs));
1a4d82fc
JJ
1073 }
1074
5bcae85e
SL
1075 time(sess.time_passes(),
1076 "serialize work products",
9e0c209e 1077 move || rustc_incremental::save_work_products(sess));
5bcae85e 1078
7453a54e
SL
1079 if sess.err_count() > 0 {
1080 Err(sess.err_count())
1081 } else {
1082 Ok(())
1083 }
1a4d82fc
JJ
1084}
1085
1086/// Run the linker on any artifacts that resulted from the LLVM run.
1087/// This should produce either a finished executable or library.
1088pub fn phase_6_link_output(sess: &Session,
1089 trans: &trans::CrateTranslation,
1090 outputs: &OutputFilenames) {
92a42be0
SL
1091 time(sess.time_passes(),
1092 "linking",
1093 || link::link_binary(sess, trans, outputs, &trans.link.crate_name));
1a4d82fc
JJ
1094}
1095
1096fn escape_dep_filename(filename: &str) -> String {
1097 // Apparently clang and gcc *only* escape spaces:
1098 // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
1099 filename.replace(" ", "\\ ")
1100}
1101
5bcae85e 1102fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
1a4d82fc 1103 let mut out_filenames = Vec::new();
b039eaaf 1104 for output_type in sess.opts.output_types.keys() {
1a4d82fc
JJ
1105 let file = outputs.path(*output_type);
1106 match *output_type {
b039eaaf 1107 OutputType::Exe => {
62682a34 1108 for output in sess.crate_types.borrow().iter() {
5bcae85e 1109 let p = link::filename_for_input(sess, *output, crate_name, outputs);
1a4d82fc
JJ
1110 out_filenames.push(p);
1111 }
1112 }
92a42be0
SL
1113 _ => {
1114 out_filenames.push(file);
1115 }
1a4d82fc
JJ
1116 }
1117 }
1118
b039eaaf
SL
1119 // Write out dependency rules to the dep-info file if requested
1120 if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
92a42be0 1121 return;
b039eaaf
SL
1122 }
1123 let deps_filename = outputs.path(OutputType::DepInfo);
1a4d82fc 1124
92a42be0
SL
1125 let result =
1126 (|| -> io::Result<()> {
1127 // Build a list of files used to compile the output and
1128 // write Makefile-compatible dependency rules
1129 let files: Vec<String> = sess.codemap()
1130 .files
1131 .borrow()
1132 .iter()
1133 .filter(|fmap| fmap.is_real_file())
1134 .filter(|fmap| !fmap.is_imported())
1135 .map(|fmap| escape_dep_filename(&fmap.name))
1136 .collect();
54a0048b 1137 let mut file = fs::File::create(&deps_filename)?;
92a42be0 1138 for path in &out_filenames {
54a0048b 1139 write!(file, "{}: {}\n\n", path.display(), files.join(" "))?;
92a42be0 1140 }
b039eaaf 1141
92a42be0
SL
1142 // Emit a fake target for each input file to the compilation. This
1143 // prevents `make` from spitting out an error if a file is later
1144 // deleted. For more info see #28735
1145 for path in files {
54a0048b 1146 writeln!(file, "{}:", path)?;
92a42be0
SL
1147 }
1148 Ok(())
1149 })();
1a4d82fc
JJ
1150
1151 match result {
1152 Ok(()) => {}
1153 Err(e) => {
1154 sess.fatal(&format!("error writing dependencies to `{}`: {}",
92a42be0
SL
1155 deps_filename.display(),
1156 e));
1a4d82fc
JJ
1157 }
1158 }
1159}
1160
92a42be0 1161pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
1a4d82fc 1162 // Unconditionally collect crate types from attributes to make them used
92a42be0
SL
1163 let attr_types: Vec<config::CrateType> =
1164 attrs.iter()
1165 .filter_map(|a| {
1166 if a.check_name("crate_type") {
1167 match a.value_str() {
1168 Some(ref n) if *n == "rlib" => {
1169 Some(config::CrateTypeRlib)
1170 }
1171 Some(ref n) if *n == "dylib" => {
1172 Some(config::CrateTypeDylib)
1173 }
a7813a04
XL
1174 Some(ref n) if *n == "cdylib" => {
1175 Some(config::CrateTypeCdylib)
1176 }
92a42be0
SL
1177 Some(ref n) if *n == "lib" => {
1178 Some(config::default_lib_output())
1179 }
1180 Some(ref n) if *n == "staticlib" => {
1181 Some(config::CrateTypeStaticlib)
1182 }
9e0c209e
SL
1183 Some(ref n) if *n == "rustc-macro" => {
1184 Some(config::CrateTypeRustcMacro)
1185 }
92a42be0
SL
1186 Some(ref n) if *n == "bin" => Some(config::CrateTypeExecutable),
1187 Some(_) => {
1188 session.add_lint(lint::builtin::UNKNOWN_CRATE_TYPES,
1189 ast::CRATE_NODE_ID,
1190 a.span,
1191 "invalid `crate_type` value".to_string());
1192 None
1193 }
1194 _ => {
9cc50fc6
SL
1195 session.struct_span_err(a.span, "`crate_type` requires a value")
1196 .note("for example: `#![crate_type=\"lib\"]`")
1197 .emit();
92a42be0
SL
1198 None
1199 }
1200 }
1201 } else {
1202 None
1203 }
1204 })
1205 .collect();
1a4d82fc
JJ
1206
1207 // If we're generating a test executable, then ignore all other output
1208 // styles at all other locations
1209 if session.opts.test {
92a42be0 1210 return vec![config::CrateTypeExecutable];
1a4d82fc
JJ
1211 }
1212
1213 // Only check command line flags if present. If no types are specified by
1214 // command line, then reuse the empty `base` Vec to hold the types that
1215 // will be found in crate attributes.
1216 let mut base = session.opts.crate_types.clone();
9346a6ac 1217 if base.is_empty() {
62682a34 1218 base.extend(attr_types);
9346a6ac 1219 if base.is_empty() {
1a4d82fc
JJ
1220 base.push(link::default_output_for_target(session));
1221 }
1222 base.sort();
1223 base.dedup();
1224 }
1225
92a42be0
SL
1226 base.into_iter()
1227 .filter(|crate_type| {
1228 let res = !link::invalid_output_for_target(session, *crate_type);
1a4d82fc 1229
92a42be0
SL
1230 if !res {
1231 session.warn(&format!("dropping unsupported crate type `{}` for target `{}`",
1232 *crate_type,
1233 session.opts.target_triple));
1234 }
1a4d82fc 1235
92a42be0
SL
1236 res
1237 })
1238 .collect()
1a4d82fc
JJ
1239}
1240
54a0048b
SL
1241pub fn compute_crate_disambiguator(session: &Session) -> String {
1242 let mut hasher = Sha256::new();
1243
1244 let mut metadata = session.opts.cg.metadata.clone();
1245 // We don't want the crate_disambiguator to dependent on the order
1246 // -C metadata arguments, so sort them:
1247 metadata.sort();
1248 // Every distinct -C metadata value is only incorporated once:
1249 metadata.dedup();
1250
1251 hasher.input_str("metadata");
1252 for s in &metadata {
1253 // Also incorporate the length of a metadata string, so that we generate
1254 // different values for `-Cmetadata=ab -Cmetadata=c` and
1255 // `-Cmetadata=a -Cmetadata=bc`
1256 hasher.input_str(&format!("{}", s.len())[..]);
1257 hasher.input_str(&s[..]);
1258 }
1259
1260 let mut hash = hasher.result_str();
1261
1262 // If this is an executable, add a special suffix, so that we don't get
1263 // symbol conflicts when linking against a library of the same name.
1264 if session.crate_types.borrow().contains(&config::CrateTypeExecutable) {
1265 hash.push_str("-exe");
1266 }
1267
1268 hash
1a4d82fc
JJ
1269}
1270
1271pub fn build_output_filenames(input: &Input,
c34b1796
AL
1272 odir: &Option<PathBuf>,
1273 ofile: &Option<PathBuf>,
1a4d82fc
JJ
1274 attrs: &[ast::Attribute],
1275 sess: &Session)
92a42be0 1276 -> OutputFilenames {
1a4d82fc
JJ
1277 match *ofile {
1278 None => {
1279 // "-" as input file will cause the parser to read from stdin so we
1280 // have to make up a name
1281 // We want to toss everything after the final '.'
1282 let dirpath = match *odir {
1283 Some(ref d) => d.clone(),
92a42be0 1284 None => PathBuf::new(),
1a4d82fc
JJ
1285 };
1286
1287 // If a crate name is present, we use it as the link name
92a42be0
SL
1288 let stem = sess.opts
1289 .crate_name
1290 .clone()
1291 .or_else(|| attr::find_crate_name(attrs).map(|n| n.to_string()))
1292 .unwrap_or(input.filestem());
1a4d82fc
JJ
1293
1294 OutputFilenames {
1295 out_directory: dirpath,
1296 out_filestem: stem,
1297 single_output_file: None,
1298 extra: sess.opts.cg.extra_filename.clone(),
b039eaaf 1299 outputs: sess.opts.output_types.clone(),
1a4d82fc
JJ
1300 }
1301 }
1302
1303 Some(ref out_file) => {
92a42be0
SL
1304 let unnamed_output_types = sess.opts
1305 .output_types
1306 .values()
b039eaaf
SL
1307 .filter(|a| a.is_none())
1308 .count();
1309 let ofile = if unnamed_output_types > 1 {
92a42be0
SL
1310 sess.warn("ignoring specified output filename because multiple outputs were \
1311 requested");
1a4d82fc
JJ
1312 None
1313 } else {
1314 Some(out_file.clone())
1315 };
1316 if *odir != None {
1317 sess.warn("ignoring --out-dir flag due to -o flag.");
1318 }
c34b1796
AL
1319
1320 let cur_dir = Path::new("");
1321
1a4d82fc 1322 OutputFilenames {
c34b1796 1323 out_directory: out_file.parent().unwrap_or(cur_dir).to_path_buf(),
92a42be0
SL
1324 out_filestem: out_file.file_stem()
1325 .unwrap_or(OsStr::new(""))
1326 .to_str()
1327 .unwrap()
1328 .to_string(),
1a4d82fc
JJ
1329 single_output_file: ofile,
1330 extra: sess.opts.cg.extra_filename.clone(),
b039eaaf 1331 outputs: sess.opts.output_types.clone(),
1a4d82fc
JJ
1332 }
1333 }
1334 }
1335}
5bcae85e
SL
1336
1337// For use by the `rusti` project (https://github.com/murarth/rusti).
1338pub fn reset_thread_local_state() {
1339 // These may be left in an incoherent state after a previous compile.
1340 syntax::ext::hygiene::reset_hygiene_data();
1341 // `clear_ident_interner` can be used to free memory, but it does not restore the initial state.
1342 token::reset_ident_interner();
1343}