1 // Copyright 2012-2013 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
12 use back::link;
13 use back::{arm, x86, x86_64, mips};
14 use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
15 FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
16 use driver::session::{Session, No, Less, Default};
17 use driver::session;
18 use front;
19 use lib::llvm::llvm;
20 use lib::llvm::{ContextRef, ModuleRef};
21 use metadata::common::LinkMeta;
22 use metadata::{creader, filesearch};
23 use metadata::cstore::CStore;
24 use metadata::creader::Loader;
25 use metadata;
26 use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
27 use middle::dependency_format;
28 use middle;
29 use util::common::time;
30 use util::ppaux;
31 use util::nodemap::{NodeMap, NodeSet};
32
33 use serialize::{json, Encodable};
34
35 use std::cell::{Cell, RefCell};
36 use std::io;
37 use std::io::fs;
38 use std::io::MemReader;
39 use std::os;
40 use getopts::{optopt, optmulti, optflag, optflagopt};
41 use getopts;
42 use syntax::ast;
43 use syntax::abi;
44 use syntax::attr;
45 use syntax::attr::{AttrMetaMethods};
46 use syntax::codemap;
47 use syntax::crateid::CrateId;
48 use syntax::diagnostic;
49 use syntax::diagnostic::Emitter;
50 use syntax::ext::base::CrateLoader;
51 use syntax::parse;
52 use syntax::parse::token::InternedString;
53 use syntax::parse::token;
54 use syntax::print::{pp, pprust};
55 use syntax;
56
57 pub enum PpMode {
58 PpmNormal,
59 PpmExpanded,
60 PpmTyped,
61 PpmIdentified,
62 PpmExpandedIdentified
63 }
64
65 /**
66 * The name used for source code that doesn't originate in a file
67 * (e.g. source from stdin or a string)
68 */
69 pub fn anon_src() -> ~str {
70 "<anon>".to_str()
71 }
72
73 pub fn source_name(input: &Input) -> ~str {
74 match *input {
75 // FIXME (#9639): This needs to handle non-utf8 paths
76 FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
77 StrInput(_) => anon_src()
78 }
79 }
80
81 pub fn default_configuration(sess: &Session) ->
82 ast::CrateConfig {
83 let tos = match sess.targ_cfg.os {
84 abi::OsWin32 => InternedString::new("win32"),
85 abi::OsMacos => InternedString::new("macos"),
86 abi::OsLinux => InternedString::new("linux"),
87 abi::OsAndroid => InternedString::new("android"),
88 abi::OsFreebsd => InternedString::new("freebsd"),
89 };
90
91 // ARM is bi-endian, however using NDK seems to default
92 // to little-endian unless a flag is provided.
93 let (end,arch,wordsz) = match sess.targ_cfg.arch {
94 abi::X86 => ("little", "x86", "32"),
95 abi::X86_64 => ("little", "x86_64", "64"),
96 abi::Arm => ("little", "arm", "32"),
97 abi::Mips => ("big", "mips", "32")
98 };
99
100 let fam = match sess.targ_cfg.os {
101 abi::OsWin32 => InternedString::new("windows"),
102 _ => InternedString::new("unix")
103 };
104
105 let mk = attr::mk_name_value_item_str;
106 return vec!(// Target bindings.
107 attr::mk_word_item(fam.clone()),
108 mk(InternedString::new("target_os"), tos),
109 mk(InternedString::new("target_family"), fam),
110 mk(InternedString::new("target_arch"), InternedString::new(arch)),
111 mk(InternedString::new("target_endian"), InternedString::new(end)),
112 mk(InternedString::new("target_word_size"),
113 InternedString::new(wordsz))
114 );
115 }
116
117 pub fn append_configuration(cfg: &mut ast::CrateConfig,
118 name: InternedString) {
119 if !cfg.iter().any(|mi| mi.name() == name) {
120 cfg.push(attr::mk_word_item(name))
121 }
122 }
123
124 pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
125 // Combine the configuration requested by the session (command line) with
126 // some default and generated configuration items
127 let default_cfg = default_configuration(sess);
128 let mut user_cfg = sess.opts.cfg.clone();
129 // If the user wants a test runner, then add the test cfg
130 if sess.opts.test {
131 append_configuration(&mut user_cfg, InternedString::new("test"))
132 }
133 // If the user requested GC, then add the GC cfg
134 append_configuration(&mut user_cfg, if sess.opts.gc {
135 InternedString::new("gc")
136 } else {
137 InternedString::new("nogc")
138 });
139 user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
140 }
141
142 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
143 fn parse_cfgspecs(cfgspecs: Vec<~str> )
144 -> ast::CrateConfig {
145 cfgspecs.move_iter().map(|s| {
146 parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
147 s.to_strbuf(),
148 Vec::new(),
149 &parse::new_parse_sess())
150 }).collect::<ast::CrateConfig>()
151 }
152
153 pub enum Input {
154 /// Load source from file
155 FileInput(Path),
156 /// The string is the source
157 StrInput(~str)
158 }
159
160 impl Input {
161 fn filestem(&self) -> ~str {
162 match *self {
163 FileInput(ref ifile) => ifile.filestem_str().unwrap().to_str(),
164 StrInput(_) => "rust_out".to_owned(),
165 }
166 }
167 }
168
169
170 pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
171 -> ast::Crate {
172 let krate = time(sess.time_passes(), "parsing", (), |_| {
173 match *input {
174 FileInput(ref file) => {
175 parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess)
176 }
177 StrInput(ref src) => {
178 parse::parse_crate_from_source_str(anon_src().to_strbuf(),
179 src.to_strbuf(),
180 cfg.clone(),
181 &sess.parse_sess)
182 }
183 }
184 });
185
186 if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
187 let mut stdout = io::BufferedWriter::new(io::stdout());
188 let mut json = json::PrettyEncoder::new(&mut stdout);
189 // unwrapping so IoError isn't ignored
190 krate.encode(&mut json).unwrap();
191 }
192
193 if sess.show_span() {
194 front::show_span::run(sess, &krate);
195 }
196
197 krate
198 }
199
200 // For continuing compilation after a parsed crate has been
201 // modified
202
203 /// Run the "early phases" of the compiler: initial `cfg` processing,
204 /// syntax expansion, secondary `cfg` expansion, synthesis of a test
205 /// harness if one is to be provided and injection of a dependency on the
206 /// standard library and prelude.
207 pub fn phase_2_configure_and_expand(sess: &Session,
208 loader: &mut CrateLoader,
209 mut krate: ast::Crate,
210 crate_id: &CrateId)
211 -> (ast::Crate, syntax::ast_map::Map) {
212 let time_passes = sess.time_passes();
213
214 *sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
215
216 time(time_passes, "gated feature checking", (), |_|
217 front::feature_gate::check_crate(sess, &krate));
218
219 krate = time(time_passes, "crate injection", krate, |krate|
220 front::std_inject::maybe_inject_crates_ref(sess, krate));
221
222 // strip before expansion to allow macros to depend on
223 // configuration variables e.g/ in
224 //
225 // #[macro_escape] #[cfg(foo)]
226 // mod bar { macro_rules! baz!(() => {{}}) }
227 //
228 // baz! should not use this definition unless foo is enabled.
229
230 krate = time(time_passes, "configuration 1", krate, |krate|
231 front::config::strip_unconfigured_items(krate));
232
233 krate = time(time_passes, "expansion", krate, |krate| {
234 // Windows dlls do not have rpaths, so they don't know how to find their
235 // dependencies. It's up to use to tell the system where to find all the
236 // dependent dlls. Note that this uses cfg!(windows) as opposed to
237 // targ_cfg because syntax extensions are always loaded for the host
238 // compiler, not for the target.
239 if cfg!(windows) {
240 sess.host_filesearch().add_dylib_search_paths();
241 }
242 let cfg = syntax::ext::expand::ExpansionConfig {
243 loader: loader,
244 deriving_hash_type_parameter: sess.features.default_type_params.get(),
245 crate_id: crate_id.clone(),
246 };
247 syntax::ext::expand::expand_crate(&sess.parse_sess,
248 cfg,
249 krate)
250 });
251
252 // strip again, in case expansion added anything with a #[cfg].
253 krate = time(time_passes, "configuration 2", krate, |krate|
254 front::config::strip_unconfigured_items(krate));
255
256 krate = time(time_passes, "maybe building test harness", krate, |krate|
257 front::test::modify_for_testing(sess, krate));
258
259 krate = time(time_passes, "prelude injection", krate, |krate|
260 front::std_inject::maybe_inject_prelude(sess, krate));
261
262 let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
263 front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
264
265 if sess.opts.debugging_opts & session::AST_JSON != 0 {
266 let mut stdout = io::BufferedWriter::new(io::stdout());
267 let mut json = json::PrettyEncoder::new(&mut stdout);
268 // unwrapping so IoError isn't ignored
269 krate.encode(&mut json).unwrap();
270 }
271
272 (krate, map)
273 }
274
275 pub struct CrateAnalysis {
276 pub exp_map2: middle::resolve::ExportMap2,
277 pub exported_items: middle::privacy::ExportedItems,
278 pub public_items: middle::privacy::PublicItems,
279 pub ty_cx: ty::ctxt,
280 pub reachable: NodeSet,
281 }
282
283 /// Run the resolution, typechecking, region checking and other
284 /// miscellaneous analysis passes on the crate. Return various
285 /// structures carrying the results of the analysis.
286 pub fn phase_3_run_analysis_passes(sess: Session,
287 krate: &ast::Crate,
288 ast_map: syntax::ast_map::Map) -> CrateAnalysis {
289
290 let time_passes = sess.time_passes();
291
292 time(time_passes, "external crate/lib resolution", (), |_|
293 creader::read_crates(&sess, krate));
294
295 let lang_items = time(time_passes, "language item collection", (), |_|
296 middle::lang_items::collect_language_items(krate, &sess));
297
298 let middle::resolve::CrateMap {
299 def_map: def_map,
300 exp_map2: exp_map2,
301 trait_map: trait_map,
302 external_exports: external_exports,
303 last_private_map: last_private_map
304 } =
305 time(time_passes, "resolution", (), |_|
306 middle::resolve::resolve_crate(&sess, &lang_items, krate));
307
308 // Discard MTWT tables that aren't required past resolution.
309 syntax::ext::mtwt::clear_tables();
310
311 let named_region_map = time(time_passes, "lifetime resolution", (),
312 |_| middle::resolve_lifetime::krate(&sess, krate));
313
314 time(time_passes, "looking for entry point", (),
315 |_| middle::entry::find_entry_point(&sess, krate, &ast_map));
316
317 sess.macro_registrar_fn.set(
318 time(time_passes, "looking for macro registrar", (), |_|
319 syntax::ext::registrar::find_macro_registrar(
320 sess.diagnostic(), krate)));
321
322 let freevars = time(time_passes, "freevar finding", (), |_|
323 freevars::annotate_freevars(&def_map, krate));
324
325 let region_map = time(time_passes, "region resolution", (), |_|
326 middle::region::resolve_crate(&sess, krate));
327
328 time(time_passes, "loop checking", (), |_|
329 middle::check_loop::check_crate(&sess, krate));
330
331 let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
332 freevars, region_map, lang_items);
333
334 // passes are timed inside typeck
335 typeck::check_crate(&ty_cx, trait_map, krate);
336
337 time(time_passes, "check static items", (), |_|
338 middle::check_static::check_crate(&ty_cx, krate));
339
340 // These next two const passes can probably be merged
341 time(time_passes, "const marking", (), |_|
342 middle::const_eval::process_crate(krate, &ty_cx));
343
344 time(time_passes, "const checking", (), |_|
345 middle::check_const::check_crate(krate, &ty_cx));
346
347 let maps = (external_exports, last_private_map);
348 let (exported_items, public_items) =
349 time(time_passes, "privacy checking", maps, |(a, b)|
350 middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate));
351
352 time(time_passes, "effect checking", (), |_|
353 middle::effect::check_crate(&ty_cx, krate));
354
355 time(time_passes, "match checking", (), |_|
356 middle::check_match::check_crate(&ty_cx, krate));
357
358 time(time_passes, "liveness checking", (), |_|
359 middle::liveness::check_crate(&ty_cx, krate));
360
361 time(time_passes, "borrow checking", (), |_|
362 middle::borrowck::check_crate(&ty_cx, krate));
363
364 time(time_passes, "kind checking", (), |_|
365 kind::check_crate(&ty_cx, krate));
366
367 let reachable_map =
368 time(time_passes, "reachability checking", (), |_|
369 reachable::find_reachable(&ty_cx, &exported_items));
370
371 time(time_passes, "death checking", (), |_| {
372 middle::dead::check_crate(&ty_cx,
373 &exported_items,
374 &reachable_map,
375 krate)
376 });
377
378 time(time_passes, "lint checking", (), |_|
379 lint::check_crate(&ty_cx, &exported_items, krate));
380
381 CrateAnalysis {
382 exp_map2: exp_map2,
383 ty_cx: ty_cx,
384 exported_items: exported_items,
385 public_items: public_items,
386 reachable: reachable_map,
387 }
388 }
389
390 pub struct CrateTranslation {
391 pub context: ContextRef,
392 pub module: ModuleRef,
393 pub metadata_module: ModuleRef,
394 pub link: LinkMeta,
395 pub metadata: Vec<u8>,
396 pub reachable: Vec<~str>,
397 pub crate_formats: dependency_format::Dependencies,
398 }
399
400 /// Run the translation phase to LLVM, after which the AST and analysis can
401 /// be discarded.
402 pub fn phase_4_translate_to_llvm(krate: ast::Crate,
403 analysis: CrateAnalysis,
404 outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
405 let time_passes = analysis.ty_cx.sess.time_passes();
406
407 time(time_passes, "resolving dependency formats", (), |_|
408 dependency_format::calculate(&analysis.ty_cx));
409
410 // Option dance to work around the lack of stack once closures.
411 time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
412 trans::base::trans_crate(krate, analysis, outputs))
413 }
414
415 /// Run LLVM itself, producing a bitcode file, assembly file or object file
416 /// as a side effect.
417 pub fn phase_5_run_llvm_passes(sess: &Session,
418 trans: &CrateTranslation,
419 outputs: &OutputFilenames) {
420 if sess.opts.cg.no_integrated_as {
421 let output_type = link::OutputTypeAssembly;
422
423 time(sess.time_passes(), "LLVM passes", (), |_|
424 link::write::run_passes(sess, trans, [output_type], outputs));
425
426 link::write::run_assembler(sess, outputs);
427
428 // Remove assembly source, unless --save-temps was specified
429 if !sess.opts.cg.save_temps {
430 fs::unlink(&outputs.temp_path(link::OutputTypeAssembly)).unwrap();
431 }
432 } else {
433 time(sess.time_passes(), "LLVM passes", (), |_|
434 link::write::run_passes(sess,
435 trans,
436 sess.opts.output_types.as_slice(),
437 outputs));
438 }
439 }
440
441 /// Run the linker on any artifacts that resulted from the LLVM run.
442 /// This should produce either a finished executable or library.
443 pub fn phase_6_link_output(sess: &Session,
444 trans: &CrateTranslation,
445 outputs: &OutputFilenames) {
446 time(sess.time_passes(), "linking", (), |_|
447 link::link_binary(sess,
448 trans,
449 outputs,
450 &trans.link.crateid));
451 }
452
453 pub fn stop_after_phase_3(sess: &Session) -> bool {
454 if sess.opts.no_trans {
455 debug!("invoked with --no-trans, returning early from compile_input");
456 return true;
457 }
458 return false;
459 }
460
461 pub fn stop_after_phase_1(sess: &Session) -> bool {
462 if sess.opts.parse_only {
463 debug!("invoked with --parse-only, returning early from compile_input");
464 return true;
465 }
466 if sess.show_span() {
467 return true;
468 }
469 return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
470 }
471
472 pub fn stop_after_phase_2(sess: &Session) -> bool {
473 if sess.opts.no_analysis {
474 debug!("invoked with --no-analysis, returning early from compile_input");
475 return true;
476 }
477 return sess.opts.debugging_opts & session::AST_JSON != 0;
478 }
479
480 pub fn stop_after_phase_5(sess: &Session) -> bool {
481 if !sess.opts.output_types.iter().any(|&i| i == link::OutputTypeExe) {
482 debug!("not building executable, returning early from compile_input");
483 return true;
484 }
485 return false;
486 }
487
488 fn write_out_deps(sess: &Session,
489 input: &Input,
490 outputs: &OutputFilenames,
491 krate: &ast::Crate) {
492 let id = link::find_crate_id(krate.attrs.as_slice(), outputs.out_filestem);
493
494 let mut out_filenames = Vec::new();
495 for output_type in sess.opts.output_types.iter() {
496 let file = outputs.path(*output_type);
497 match *output_type {
498 link::OutputTypeExe => {
499 for output in sess.crate_types.borrow().iter() {
500 let p = link::filename_for_input(sess, *output, &id, &file);
501 out_filenames.push(p);
502 }
503 }
504 _ => { out_filenames.push(file); }
505 }
506 }
507
508 // Write out dependency rules to the dep-info file if requested with
509 // --dep-info
510 let deps_filename = match sess.opts.write_dependency_info {
511 // Use filename from --dep-file argument if given
512 (true, Some(ref filename)) => filename.clone(),
513 // Use default filename: crate source filename with extension replaced
514 // by ".d"
515 (true, None) => match *input {
516 FileInput(..) => outputs.with_extension("d"),
517 StrInput(..) => {
518 sess.warn("can not write --dep-info without a filename \
519 when compiling stdin.");
520 return
521 },
522 },
523 _ => return,
524 };
525
526 let result = (|| {
527 // Build a list of files used to compile the output and
528 // write Makefile-compatible dependency rules
529 let files: Vec<~str> = sess.codemap().files.borrow()
530 .iter().filter(|fmap| fmap.is_real_file())
531 .map(|fmap| fmap.name.to_owned())
532 .collect();
533 let mut file = try!(io::File::create(&deps_filename));
534 for path in out_filenames.iter() {
535 try!(write!(&mut file as &mut Writer,
536 "{}: {}\n\n", path.display(), files.connect(" ")));
537 }
538 Ok(())
539 })();
540
541 match result {
542 Ok(()) => {}
543 Err(e) => {
544 sess.fatal(format!("error writing dependencies to `{}`: {}",
545 deps_filename.display(), e));
546 }
547 }
548 }
549
550 pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
551 outdir: &Option<Path>, output: &Option<Path>) {
552 // We need nested scopes here, because the intermediate results can keep
553 // large chunks of memory alive and we want to free them as soon as
554 // possible to keep the peak memory usage low
555 let (outputs, trans, sess) = {
556 let (outputs, expanded_crate, ast_map) = {
557 let krate = phase_1_parse_input(&sess, cfg, input);
558 if stop_after_phase_1(&sess) { return; }
559 let outputs = build_output_filenames(input,
560 outdir,
561 output,
562 krate.attrs.as_slice(),
563 &sess);
564 let loader = &mut Loader::new(&sess);
565 let id = link::find_crate_id(krate.attrs.as_slice(),
566 outputs.out_filestem);
567 let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
568 krate, &id);
569 (outputs, expanded_crate, ast_map)
570 };
571 write_out_deps(&sess, input, &outputs, &expanded_crate);
572
573 if stop_after_phase_2(&sess) { return; }
574
575 let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
576 if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
577 let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
578 analysis, &outputs);
579
580 // Discard interned strings as they are no longer required.
581 token::get_ident_interner().clear();
582
583 (outputs, trans, tcx.sess)
584 };
585 phase_5_run_llvm_passes(&sess, &trans, &outputs);
586 if stop_after_phase_5(&sess) { return; }
587 phase_6_link_output(&sess, &trans, &outputs);
588 }
589
590 struct IdentifiedAnnotation;
591
592 impl pprust::PpAnn for IdentifiedAnnotation {
593 fn pre(&self,
594 s: &mut pprust::State,
595 node: pprust::AnnNode) -> io::IoResult<()> {
596 match node {
597 pprust::NodeExpr(_) => s.popen(),
598 _ => Ok(())
599 }
600 }
601 fn post(&self,
602 s: &mut pprust::State,
603 node: pprust::AnnNode) -> io::IoResult<()> {
604 match node {
605 pprust::NodeItem(item) => {
606 try!(pp::space(&mut s.s));
607 s.synth_comment(item.id.to_str().to_strbuf())
608 }
609 pprust::NodeBlock(blk) => {
610 try!(pp::space(&mut s.s));
611 s.synth_comment((format!("block {}", blk.id)).to_strbuf())
612 }
613 pprust::NodeExpr(expr) => {
614 try!(pp::space(&mut s.s));
615 try!(s.synth_comment(expr.id.to_str().to_strbuf()));
616 s.pclose()
617 }
618 pprust::NodePat(pat) => {
619 try!(pp::space(&mut s.s));
620 s.synth_comment((format!("pat {}", pat.id)).to_strbuf())
621 }
622 }
623 }
624 }
625
626 struct TypedAnnotation {
627 analysis: CrateAnalysis,
628 }
629
630 impl pprust::PpAnn for TypedAnnotation {
631 fn pre(&self,
632 s: &mut pprust::State,
633 node: pprust::AnnNode) -> io::IoResult<()> {
634 match node {
635 pprust::NodeExpr(_) => s.popen(),
636 _ => Ok(())
637 }
638 }
639 fn post(&self,
640 s: &mut pprust::State,
641 node: pprust::AnnNode) -> io::IoResult<()> {
642 let tcx = &self.analysis.ty_cx;
643 match node {
644 pprust::NodeExpr(expr) => {
645 try!(pp::space(&mut s.s));
646 try!(pp::word(&mut s.s, "as"));
647 try!(pp::space(&mut s.s));
648 try!(pp::word(&mut s.s,
649 ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))));
650 s.pclose()
651 }
652 _ => Ok(())
653 }
654 }
655 }
656
657 pub fn pretty_print_input(sess: Session,
658 cfg: ast::CrateConfig,
659 input: &Input,
660 ppm: PpMode,
661 ofile: Option<Path>) {
662 let krate = phase_1_parse_input(&sess, cfg, input);
663 let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
664
665 let (krate, ast_map, is_expanded) = match ppm {
666 PpmExpanded | PpmExpandedIdentified | PpmTyped => {
667 let loader = &mut Loader::new(&sess);
668 let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader,
669 krate, &id);
670 (krate, Some(ast_map), true)
671 }
672 _ => (krate, None, false)
673 };
674
675 let src_name = source_name(input);
676 let src = Vec::from_slice(sess.codemap().get_filemap(src_name).src.as_bytes());
677 let mut rdr = MemReader::new(src);
678
679 let out = match ofile {
680 None => box io::stdout() as Box<Writer>,
681 Some(p) => {
682 let r = io::File::create(&p);
683 match r {
684 Ok(w) => box w as Box<Writer>,
685 Err(e) => fail!("print-print failed to open {} due to {}",
686 p.display(), e),
687 }
688 }
689 };
690 match ppm {
691 PpmIdentified | PpmExpandedIdentified => {
692 pprust::print_crate(sess.codemap(),
693 sess.diagnostic(),
694 &krate,
695 src_name.to_strbuf(),
696 &mut rdr,
697 out,
698 &IdentifiedAnnotation,
699 is_expanded)
700 }
701 PpmTyped => {
702 let ast_map = ast_map.expect("--pretty=typed missing ast_map");
703 let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
704 let annotation = TypedAnnotation {
705 analysis: analysis
706 };
707 pprust::print_crate(annotation.analysis.ty_cx.sess.codemap(),
708 annotation.analysis.ty_cx.sess.diagnostic(),
709 &krate,
710 src_name.to_strbuf(),
711 &mut rdr,
712 out,
713 &annotation,
714 is_expanded)
715 }
716 _ => {
717 pprust::print_crate(sess.codemap(),
718 sess.diagnostic(),
719 &krate,
720 src_name.to_strbuf(),
721 &mut rdr,
722 out,
723 &pprust::NoAnn,
724 is_expanded)
725 }
726 }.unwrap()
727
728 }
729
730 pub fn get_os(triple: &str) -> Option<abi::Os> {
731 for &(name, os) in os_names.iter() {
732 if triple.contains(name) { return Some(os) }
733 }
734 None
735 }
736 static os_names : &'static [(&'static str, abi::Os)] = &'static [
737 ("mingw32", abi::OsWin32),
738 ("win32", abi::OsWin32),
739 ("darwin", abi::OsMacos),
740 ("android", abi::OsAndroid),
741 ("linux", abi::OsLinux),
742 ("freebsd", abi::OsFreebsd)];
743
744 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
745 for &(arch, abi) in architecture_abis.iter() {
746 if triple.contains(arch) { return Some(abi) }
747 }
748 None
749 }
750 static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
751 ("i386", abi::X86),
752 ("i486", abi::X86),
753 ("i586", abi::X86),
754 ("i686", abi::X86),
755 ("i786", abi::X86),
756
757 ("x86_64", abi::X86_64),
758
759 ("arm", abi::Arm),
760 ("xscale", abi::Arm),
761 ("thumb", abi::Arm),
762
763 ("mips", abi::Mips)];
764
765 pub fn build_target_config(sopts: &session::Options) -> session::Config {
766 let os = match get_os(sopts.target_triple) {
767 Some(os) => os,
768 None => early_error("unknown operating system")
769 };
770 let arch = match get_arch(sopts.target_triple) {
771 Some(arch) => arch,
772 None => early_error("unknown architecture: " + sopts.target_triple)
773 };
774 let (int_type, uint_type) = match arch {
775 abi::X86 => (ast::TyI32, ast::TyU32),
776 abi::X86_64 => (ast::TyI64, ast::TyU64),
777 abi::Arm => (ast::TyI32, ast::TyU32),
778 abi::Mips => (ast::TyI32, ast::TyU32)
779 };
780 let target_triple = sopts.target_triple.clone();
781 let target_strs = match arch {
782 abi::X86 => x86::get_target_strs(target_triple, os),
783 abi::X86_64 => x86_64::get_target_strs(target_triple, os),
784 abi::Arm => arm::get_target_strs(target_triple, os),
785 abi::Mips => mips::get_target_strs(target_triple, os)
786 };
787 session::Config {
788 os: os,
789 arch: arch,
790 target_strs: target_strs,
791 int_type: int_type,
792 uint_type: uint_type,
793 }
794 }
795
796 pub fn host_triple() -> &'static str {
797 // Get the host triple out of the build environment. This ensures that our
798 // idea of the host triple is the same as for the set of libraries we've
799 // actually built. We can't just take LLVM's host triple because they
800 // normalize all ix86 architectures to i386.
801 //
802 // Instead of grabbing the host triple (for the current host), we grab (at
803 // compile time) the target triple that this rustc is built with and
804 // calling that (at runtime) the host triple.
805 (option_env!("CFG_COMPILER_HOST_TRIPLE")).
806 expect("CFG_COMPILER_HOST_TRIPLE")
807 }
808
809 pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
810 let mut crate_types: Vec<CrateType> = Vec::new();
811 let unparsed_crate_types = matches.opt_strs("crate-type");
812 for unparsed_crate_type in unparsed_crate_types.iter() {
813 for part in unparsed_crate_type.split(',') {
814 let new_part = match part {
815 "lib" => session::default_lib_output(),
816 "rlib" => session::CrateTypeRlib,
817 "staticlib" => session::CrateTypeStaticlib,
818 "dylib" => session::CrateTypeDylib,
819 "bin" => session::CrateTypeExecutable,
820 _ => early_error(format!("unknown crate type: `{}`", part))
821 };
822 crate_types.push(new_part)
823 }
824 }
825
826 let parse_only = matches.opt_present("parse-only");
827 let no_trans = matches.opt_present("no-trans");
828 let no_analysis = matches.opt_present("no-analysis");
829
830 let lint_levels = [lint::allow, lint::warn,
831 lint::deny, lint::forbid];
832 let mut lint_opts = Vec::new();
833 let lint_dict = lint::get_lint_dict();
834 for level in lint_levels.iter() {
835 let level_name = lint::level_to_str(*level);
836
837 let level_short = level_name.slice_chars(0, 1);
838 let level_short = level_short.to_ascii().to_upper().into_str();
839 let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
840 matches.opt_strs(level_name).as_slice());
841 for lint_name in flags.iter() {
842 let lint_name = lint_name.replace("-", "_");
843 match lint_dict.find_equiv(&lint_name) {
844 None => {
845 early_error(format!("unknown {} flag: {}",
846 level_name, lint_name));
847 }
848 Some(lint) => {
849 lint_opts.push((lint.lint, *level));
850 }
851 }
852 }
853 }
854
855 let mut debugging_opts = 0;
856 let debug_flags = matches.opt_strs("Z");
857 let debug_map = session::debugging_opts_map();
858 for debug_flag in debug_flags.iter() {
859 let mut this_bit = 0;
860 for tuple in debug_map.iter() {
861 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
862 if *name == *debug_flag { this_bit = bit; break; }
863 }
864 if this_bit == 0 {
865 early_error(format!("unknown debug flag: {}", *debug_flag))
866 }
867 debugging_opts |= this_bit;
868 }
869
870 if debugging_opts & session::DEBUG_LLVM != 0 {
871 unsafe { llvm::LLVMSetDebug(1); }
872 }
873
874 let mut output_types = Vec::new();
875 if !parse_only && !no_trans {
876 let unparsed_output_types = matches.opt_strs("emit");
877 for unparsed_output_type in unparsed_output_types.iter() {
878 for part in unparsed_output_type.split(',') {
879 let output_type = match part.as_slice() {
880 "asm" => link::OutputTypeAssembly,
881 "ir" => link::OutputTypeLlvmAssembly,
882 "bc" => link::OutputTypeBitcode,
883 "obj" => link::OutputTypeObject,
884 "link" => link::OutputTypeExe,
885 _ => early_error(format!("unknown emission type: `{}`", part))
886 };
887 output_types.push(output_type)
888 }
889 }
890 };
891 output_types.as_mut_slice().sort();
892 output_types.dedup();
893 if output_types.len() == 0 {
894 output_types.push(link::OutputTypeExe);
895 }
896
897 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
898 let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
899 let opt_level = {
900 if (debugging_opts & session::NO_OPT) != 0 {
901 No
902 } else if matches.opt_present("O") {
903 if matches.opt_present("opt-level") {
904 early_error("-O and --opt-level both provided");
905 }
906 Default
907 } else if matches.opt_present("opt-level") {
908 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
909 None |
910 Some("0") => No,
911 Some("1") => Less,
912 Some("2") => Default,
913 Some("3") => Aggressive,
914 Some(arg) => {
915 early_error(format!("optimization level needs to be between 0-3 \
916 (instead was `{}`)", arg));
917 }
918 }
919 } else {
920 No
921 }
922 };
923 let gc = debugging_opts & session::GC != 0;
924 let debuginfo = if matches.opt_present("g") {
925 if matches.opt_present("debuginfo") {
926 early_error("-g and --debuginfo both provided");
927 }
928 FullDebugInfo
929 } else if matches.opt_present("debuginfo") {
930 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
931 Some("0") => NoDebugInfo,
932 Some("1") => LimitedDebugInfo,
933 None |
934 Some("2") => FullDebugInfo,
935 Some(arg) => {
936 early_error(format!("optimization level needs to be between 0-3 \
937 (instead was `{}`)", arg));
938 }
939 }
940 } else {
941 NoDebugInfo
942 };
943
944 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
945 Path::new(s.as_slice())
946 }).collect();
947
948 let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
949 let test = matches.opt_present("test");
950 let write_dependency_info = (matches.opt_present("dep-info"),
951 matches.opt_str("dep-info").map(|p| Path::new(p)));
952
953 let print_metas = (matches.opt_present("crate-id"),
954 matches.opt_present("crate-name"),
955 matches.opt_present("crate-file-name"));
956 let cg = build_codegen_options(matches);
957
958 session::Options {
959 crate_types: crate_types,
960 gc: gc,
961 optimize: opt_level,
962 debuginfo: debuginfo,
963 lint_opts: lint_opts,
964 output_types: output_types,
965 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
966 maybe_sysroot: sysroot_opt,
967 target_triple: target,
968 cfg: cfg,
969 test: test,
970 parse_only: parse_only,
971 no_trans: no_trans,
972 no_analysis: no_analysis,
973 debugging_opts: debugging_opts,
974 write_dependency_info: write_dependency_info,
975 print_metas: print_metas,
976 cg: cg,
977 }
978 }
979
980 pub fn build_codegen_options(matches: &getopts::Matches)
981 -> session::CodegenOptions
982 {
983 let mut cg = session::basic_codegen_options();
984 for option in matches.opt_strs("C").move_iter() {
985 let mut iter = option.splitn('=', 1);
986 let key = iter.next().unwrap();
987 let value = iter.next();
988 let option_to_lookup = key.replace("-", "_");
989 let mut found = false;
990 for &(candidate, setter, _) in session::CG_OPTIONS.iter() {
991 if option_to_lookup.as_slice() != candidate { continue }
992 if !setter(&mut cg, value) {
993 match value {
994 Some(..) => early_error(format!("codegen option `{}` takes \
995 no value", key)),
996 None => early_error(format!("codegen option `{0}` requires \
997 a value (-C {0}=<value>)",
998 key))
999 }
1000 }
1001 found = true;
1002 break;
1003 }
1004 if !found {
1005 early_error(format!("unknown codegen option: `{}`", key));
1006 }
1007 }
1008 return cg;
1009 }
1010
1011 pub fn build_session(sopts: session::Options,
1012 local_crate_source_file: Option<Path>)
1013 -> Session {
1014 let codemap = codemap::CodeMap::new();
1015 let diagnostic_handler =
1016 diagnostic::default_handler();
1017 let span_diagnostic_handler =
1018 diagnostic::mk_span_handler(diagnostic_handler, codemap);
1019
1020 build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
1021 }
1022
1023 pub fn build_session_(sopts: session::Options,
1024 local_crate_source_file: Option<Path>,
1025 span_diagnostic: diagnostic::SpanHandler)
1026 -> Session {
1027 let target_cfg = build_target_config(&sopts);
1028 let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
1029 let default_sysroot = match sopts.maybe_sysroot {
1030 Some(_) => None,
1031 None => Some(filesearch::get_or_default_sysroot())
1032 };
1033
1034 // Make the path absolute, if necessary
1035 let local_crate_source_file = local_crate_source_file.map(|path|
1036 if path.is_absolute() {
1037 path.clone()
1038 } else {
1039 os::getcwd().join(path.clone())
1040 }
1041 );
1042
1043 Session {
1044 targ_cfg: target_cfg,
1045 opts: sopts,
1046 cstore: CStore::new(token::get_ident_interner()),
1047 parse_sess: p_s,
1048 // For a library crate, this is always none
1049 entry_fn: RefCell::new(None),
1050 entry_type: Cell::new(None),
1051 macro_registrar_fn: Cell::new(None),
1052 default_sysroot: default_sysroot,
1053 local_crate_source_file: local_crate_source_file,
1054 working_dir: os::getcwd(),
1055 lints: RefCell::new(NodeMap::new()),
1056 node_id: Cell::new(1),
1057 crate_types: RefCell::new(Vec::new()),
1058 features: front::feature_gate::Features::new(),
1059 recursion_limit: Cell::new(64),
1060 }
1061 }
1062
1063 pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
1064 match name {
1065 "normal" => PpmNormal,
1066 "expanded" => PpmExpanded,
1067 "typed" => PpmTyped,
1068 "expanded,identified" => PpmExpandedIdentified,
1069 "identified" => PpmIdentified,
1070 _ => {
1071 sess.fatal("argument to `pretty` must be one of `normal`, \
1072 `expanded`, `typed`, `identified`, \
1073 or `expanded,identified`");
1074 }
1075 }
1076 }
1077
1078 // rustc command line options
1079 pub fn optgroups() -> Vec<getopts::OptGroup> {
1080 vec!(
1081 optflag("h", "help", "Display this message"),
1082 optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
1083 optmulti("L", "", "Add a directory to the library search path", "PATH"),
1084 optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
1085 "[bin|lib|rlib|dylib|staticlib]"),
1086 optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
1087 "[asm|bc|ir|obj|link]"),
1088 optflag("", "crate-id", "Output the crate id and exit"),
1089 optflag("", "crate-name", "Output the crate name and exit"),
1090 optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
1091 continued and exit"),
1092 optflag("g", "", "Equivalent to --debuginfo=2"),
1093 optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
1094 0 = no debug info,
1095 1 = line-tables only (for stacktraces and breakpoints),
1096 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
1097 optflag("", "no-trans", "Run all passes except translation; no output"),
1098 optflag("", "no-analysis",
1099 "Parse and expand the source, but run no analysis and produce no output"),
1100 optflag("O", "", "Equivalent to --opt-level=2"),
1101 optopt("o", "", "Write output to <filename>", "FILENAME"),
1102 optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
1103 optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
1104 optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
1105 optflagopt("", "pretty",
1106 "Pretty-print the input instead of compiling;
1107 valid types are: normal (un-annotated source),
1108 expanded (crates expanded),
1109 typed (crates expanded, with type annotations),
1110 or identified (fully parenthesized,
1111 AST nodes and blocks with IDs)", "TYPE"),
1112 optflagopt("", "dep-info",
1113 "Output dependency info to <filename> after compiling, \
1114 in a format suitable for use by Makefiles", "FILENAME"),
1115 optopt("", "sysroot", "Override the system root", "PATH"),
1116 optflag("", "test", "Build a test harness"),
1117 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
1118 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
1119 for details)", "TRIPLE"),
1120 optmulti("W", "warn", "Set lint warnings", "OPT"),
1121 optmulti("A", "allow", "Set lint allowed", "OPT"),
1122 optmulti("D", "deny", "Set lint denied", "OPT"),
1123 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
1124 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
1125 optmulti("Z", "", "Set internal debugging options", "FLAG"),
1126 optflag( "v", "version", "Print version info and exit"))
1127 }
1128
1129 pub struct OutputFilenames {
1130 pub out_directory: Path,
1131 pub out_filestem: ~str,
1132 pub single_output_file: Option<Path>,
1133 }
1134
1135 impl OutputFilenames {
1136 pub fn path(&self, flavor: link::OutputType) -> Path {
1137 match self.single_output_file {
1138 Some(ref path) => return path.clone(),
1139 None => {}
1140 }
1141 self.temp_path(flavor)
1142 }
1143
1144 pub fn temp_path(&self, flavor: link::OutputType) -> Path {
1145 let base = self.out_directory.join(self.out_filestem.as_slice());
1146 match flavor {
1147 link::OutputTypeBitcode => base.with_extension("bc"),
1148 link::OutputTypeAssembly => base.with_extension("s"),
1149 link::OutputTypeLlvmAssembly => base.with_extension("ll"),
1150 link::OutputTypeObject => base.with_extension("o"),
1151 link::OutputTypeExe => base,
1152 }
1153 }
1154
1155 pub fn with_extension(&self, extension: &str) -> Path {
1156 let stem = self.out_filestem.as_slice();
1157 self.out_directory.join(stem).with_extension(extension)
1158 }
1159 }
1160
1161 pub fn build_output_filenames(input: &Input,
1162 odir: &Option<Path>,
1163 ofile: &Option<Path>,
1164 attrs: &[ast::Attribute],
1165 sess: &Session)
1166 -> OutputFilenames {
1167 match *ofile {
1168 None => {
1169 // "-" as input file will cause the parser to read from stdin so we
1170 // have to make up a name
1171 // We want to toss everything after the final '.'
1172 let dirpath = match *odir {
1173 Some(ref d) => d.clone(),
1174 None => Path::new(".")
1175 };
1176
1177 let mut stem = input.filestem();
1178
1179 // If a crateid is present, we use it as the link name
1180 let crateid = attr::find_crateid(attrs);
1181 match crateid {
1182 None => {}
1183 Some(crateid) => stem = crateid.name.to_str(),
1184 }
1185 OutputFilenames {
1186 out_directory: dirpath,
1187 out_filestem: stem,
1188 single_output_file: None,
1189 }
1190 }
1191
1192 Some(ref out_file) => {
1193 let ofile = if sess.opts.output_types.len() > 1 {
1194 sess.warn("ignoring specified output filename because multiple \
1195 outputs were requested");
1196 None
1197 } else {
1198 Some(out_file.clone())
1199 };
1200 if *odir != None {
1201 sess.warn("ignoring --out-dir flag due to -o flag.");
1202 }
1203 OutputFilenames {
1204 out_directory: out_file.dir_path(),
1205 out_filestem: out_file.filestem_str().unwrap().to_str(),
1206 single_output_file: ofile,
1207 }
1208 }
1209 }
1210 }
1211
1212 pub fn early_error(msg: &str) -> ! {
1213 let mut emitter = diagnostic::EmitterWriter::stderr();
1214 emitter.emit(None, msg, diagnostic::Fatal);
1215 fail!(diagnostic::FatalError);
1216 }
1217
1218 pub fn list_metadata(sess: &Session, path: &Path,
1219 out: &mut io::Writer) -> io::IoResult<()> {
1220 metadata::loader::list_file_metadata(
1221 session::sess_os_to_meta_os(sess.targ_cfg.os), path, out)
1222 }
1223
1224 #[cfg(test)]
1225 mod test {
1226
1227 use driver::driver::{build_configuration, build_session};
1228 use driver::driver::{build_session_options, optgroups};
1229
1230 use getopts::getopts;
1231 use syntax::attr;
1232 use syntax::attr::AttrMetaMethods;
1233
1234 // When the user supplies --test we should implicitly supply --cfg test
1235 #[test]
1236 fn test_switch_implies_cfg_test() {
1237 let matches =
1238 &match getopts(["--test".to_owned()], optgroups().as_slice()) {
1239 Ok(m) => m,
1240 Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
1241 };
1242 let sessopts = build_session_options(matches);
1243 let sess = build_session(sessopts, None);
1244 let cfg = build_configuration(&sess);
1245 assert!((attr::contains_name(cfg.as_slice(), "test")));
1246 }
1247
1248 // When the user supplies --test and --cfg test, don't implicitly add
1249 // another --cfg test
1250 #[test]
1251 fn test_switch_implies_cfg_test_unless_cfg_test() {
1252 let matches =
1253 &match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
1254 optgroups().as_slice()) {
1255 Ok(m) => m,
1256 Err(f) => {
1257 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
1258 f.to_err_msg());
1259 }
1260 };
1261 let sessopts = build_session_options(matches);
1262 let sess = build_session(sessopts, None);
1263 let cfg = build_configuration(&sess);
1264 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
1265 assert!(test_items.next().is_some());
1266 assert!(test_items.next().is_none());
1267 }
1268 }
librustc/driver/driver.rs:56:1-56:1 -enum- definition:
pub enum PpMode {
PpmNormal,
PpmExpanded,
references:- 41063: pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
1064: match name {
librustc/lib.rs:
296: match pretty {
297: Some::<d::PpMode>(ppm) => {
298: d::pretty_print_input(sess, cfg, &input, ppm, ofile);
--
300: }
301: None::<d::PpMode> => {/* continue */ }
302: }
librustc/driver/driver.rs:729:1-729:1 -fn- definition:
pub fn get_os(triple: &str) -> Option<abi::Os> {
for &(name, os) in os_names.iter() {
if triple.contains(name) { return Some(os) }
references:- 2765: pub fn build_target_config(sopts: &session::Options) -> session::Config {
766: let os = match get_os(sopts.target_triple) {
767: Some(os) => os,
librustc/metadata/creader.rs:
389: let id_hash = link::crate_id_hash(&info.crate_id);
390: let os = driver::get_os(driver::host_triple()).unwrap();
391: let mut load_ctxt = loader::Context {
librustc/driver/driver.rs:169:1-169:1 -fn- definition:
pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
-> ast::Crate {
let krate = time(sess.time_passes(), "parsing", (), |_| {
references:- 2661: ofile: Option<Path>) {
662: let krate = phase_1_parse_input(&sess, cfg, input);
663: let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
librustc/driver/driver.rs:795:1-795:1 -fn- definition:
pub fn host_triple() -> &'static str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
references:- 8897: let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
898: let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
899: let opt_level = {
librustc/driver/session.rs:
335: self.sysroot(),
336: host_triple(),
337: &self.opts.addl_lib_search_paths)
--
351: maybe_sysroot: None,
352: target_triple: host_triple().to_owned(),
353: cfg: Vec::new(),
librustc/metadata/creader.rs:
398: filesearch: self.env.sess.host_filesearch(),
399: triple: driver::host_triple(),
400: os: session::sess_os_to_meta_os(os),
--
416: only a version for triple `{}` could be found (need {})",
417: info.ident, target_triple, driver::host_triple());
418: self.env.sess.span_err(krate.span, message);
librustc/lib.rs:
147: println!("{} {}", argv0, vers);
148: println!("host: {}", d::host_triple());
149: }
librustc/driver/driver.rs:116:1-116:1 -fn- definition:
pub fn append_configuration(cfg: &mut ast::CrateConfig,
name: InternedString) {
if !cfg.iter().any(|mi| mi.name() == name) {
references:- 2130: if sess.opts.test {
131: append_configuration(&mut user_cfg, InternedString::new("test"))
132: }
133: // If the user requested GC, then add the GC cfg
134: append_configuration(&mut user_cfg, if sess.opts.gc {
135: InternedString::new("gc")
librustc/driver/driver.rs:1128:1-1128:1 -struct- definition:
pub struct OutputFilenames {
pub out_directory: Path,
pub out_filestem: ~str,
references:- 131202: }
1203: OutputFilenames {
1204: out_directory: out_file.dir_path(),
librustc/middle/trans/base.rs:
2137: analysis: CrateAnalysis,
2138: output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139: let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
librustc/back/link.rs:
128: output_types: &[OutputType],
129: output: &OutputFilenames) {
130: let llmod = trans.module;
--
798: trans: &CrateTranslation,
799: outputs: &OutputFilenames,
800: id: &CrateId) -> Vec<Path> {
--
852: crate_type: session::CrateType,
853: outputs: &OutputFilenames,
854: id: &CrateId) -> Path {
librustc/driver/driver.rs:
1184: }
1185: OutputFilenames {
1186: out_directory: dirpath,
librustc/driver/driver.rs:68:4-68:4 -fn- definition:
*/
pub fn anon_src() -> ~str {
"<anon>".to_str()
references:- 376: FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
77: StrInput(_) => anon_src()
78: }
librustc/lib.rs:
355: parse::parse_crate_attrs_from_source_str(
356: d::anon_src().to_strbuf(),
357: src.to_strbuf(),
librustc/driver/driver.rs:
177: StrInput(ref src) => {
178: parse::parse_crate_from_source_str(anon_src().to_strbuf(),
179: src.to_strbuf(),
librustc/driver/driver.rs:285:53-285:53 -fn- definition:
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes(sess: Session,
krate: &ast::Crate,
references:- 2575: let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
576: if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
--
702: let ast_map = ast_map.expect("--pretty=typed missing ast_map");
703: let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
704: let annotation = TypedAnnotation {
librustc/driver/driver.rs:1160:1-1160:1 -fn- definition:
pub fn build_output_filenames(input: &Input,
odir: &Option<Path>,
ofile: &Option<Path>,
references:- 2558: if stop_after_phase_1(&sess) { return; }
559: let outputs = build_output_filenames(input,
560: outdir,
librustc/lib.rs:
319: let attrs = parse_crate_attrs(&sess, &input);
320: let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
321: attrs.as_slice(), &sess);
librustc/driver/driver.rs:1211:1-1211:1 -fn- definition:
pub fn early_error(msg: &str) -> ! {
let mut emitter = diagnostic::EmitterWriter::stderr();
emitter.emit(None, msg, diagnostic::Fatal);
references:- 17844: None => {
845: early_error(format!("unknown {} flag: {}",
846: level_name, lint_name));
--
864: if this_bit == 0 {
865: early_error(format!("unknown debug flag: {}", *debug_flag))
866: }
--
993: match value {
994: Some(..) => early_error(format!("codegen option `{}` takes \
995: no value", key)),
996: None => early_error(format!("codegen option `{0}` requires \
997: a value (-C {0}=<value>)",
librustc/lib.rs:
235: Err(f) => {
236: d::early_error(f.to_err_msg());
237: }
--
284: }
285: _ => d::early_error("multiple input filenames provided")
286: };
--
310: d::StrInput(_) => {
311: d::early_error("can not list metadata for stdin");
312: }
librustc/driver/driver.rs:
1004: if !found {
1005: early_error(format!("unknown codegen option: `{}`", key));
1006: }
librustc/driver/driver.rs:625:1-625:1 -struct- definition:
struct TypedAnnotation {
analysis: CrateAnalysis,
}
references:- 2703: let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
704: let annotation = TypedAnnotation {
705: analysis: analysis
librustc/driver/driver.rs:1078:30-1078:30 -fn- definition:
// rustc command line options
pub fn optgroups() -> Vec<getopts::OptGroup> {
vec!(
references:- 2librustc/lib.rs:
232: let matches =
233: &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
234: Ok(m) => m,
librustc/driver/driver.rs:206:34-206:34 -fn- definition:
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: &Session,
loader: &mut CrateLoader,
references:- 2566: outputs.out_filestem);
567: let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
568: krate, &id);
--
667: let loader = &mut Loader::new(&sess);
668: let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader,
669: krate, &id);
librustc/driver/driver.rs:152:1-152:1 -enum- definition:
pub enum Input {
/// Load source from file
FileInput(Path),
references:- 81161: pub fn build_output_filenames(input: &Input,
1162: odir: &Option<Path>,
librustc/lib.rs:
346: fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
347: Vec<ast::Attribute> {
librustc/driver/driver.rs:
658: cfg: ast::CrateConfig,
659: input: &Input,
660: ppm: PpMode,
librustc/driver/driver.rs:389:1-389:1 -struct- definition:
pub struct CrateTranslation {
pub context: ContextRef,
pub module: ModuleRef,
references:- 12librustc/middle/trans/base.rs:
2239: (ccx.tcx, CrateTranslation {
2240: context: llcx,
librustc/driver/driver.rs:
417: pub fn phase_5_run_llvm_passes(sess: &Session,
418: trans: &CrateTranslation,
419: outputs: &OutputFilenames) {
--
443: pub fn phase_6_link_output(sess: &Session,
444: trans: &CrateTranslation,
445: outputs: &OutputFilenames) {
librustc/middle/trans/base.rs:
2137: analysis: CrateAnalysis,
2138: output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139: let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
librustc/back/link.rs:
850: fn link_binary_output(sess: &Session,
851: trans: &CrateTranslation,
852: crate_type: session::CrateType,
--
1039: // links to all upstream files as well.
1040: fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
1041: obj_filename: &Path, out_filename: &Path) {
--
1094: tmpdir: &Path,
1095: trans: &CrateTranslation,
1096: obj_filename: &Path,
--
1365: dylib: bool, tmpdir: &Path,
1366: trans: &CrateTranslation) {
1367: // All of the heavy lifting has previously been accomplished by the
librustc/driver/driver.rs:274:1-274:1 -struct- definition:
pub struct CrateAnalysis {
pub exp_map2: middle::resolve::ExportMap2,
pub exported_items: middle::privacy::ExportedItems,
references:- 6381: CrateAnalysis {
382: exp_map2: exp_map2,
--
626: struct TypedAnnotation {
627: analysis: CrateAnalysis,
628: }
librustc/middle/trans/base.rs:
2138: output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
2139: let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;