(index<- ) ./librustc/lib.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
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
13 The Rust compiler.
14
15 # Note
16
17 This API is completely unstable and subject to change.
18
19 */
20
21 #![crate_id = "rustc#0.11-pre"]
22 #![comment = "The Rust compiler"]
23 #![license = "MIT/ASL2"]
24 #![crate_type = "dylib"]
25 #![crate_type = "rlib"]
26 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
27 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
28 html_root_url = "http://static.rust-lang.org/doc/master")]
29
30 #![allow(deprecated)]
31 #![feature(macro_rules, globs, struct_variant, managed_boxes, quote,
32 default_type_params, phase)]
33
34 extern crate flate;
35 extern crate arena;
36 extern crate syntax;
37 extern crate serialize;
38 extern crate sync;
39 extern crate getopts;
40 extern crate collections;
41 extern crate time;
42 extern crate libc;
43
44 #[phase(syntax, link)]
45 extern crate log;
46
47 use back::link;
48 use driver::session;
49 use middle::lint;
50
51 use d = driver::driver;
52
53 use std::any::AnyRefExt;
54 use std::cmp;
55 use std::io;
56 use std::os;
57 use std::str;
58 use std::task::TaskBuilder;
59 use syntax::ast;
60 use syntax::diagnostic::Emitter;
61 use syntax::diagnostic;
62 use syntax::parse;
63
64 pub mod middle {
65 pub mod trans;
66 pub mod ty;
67 pub mod ty_fold;
68 pub mod subst;
69 pub mod resolve;
70 pub mod resolve_lifetime;
71 pub mod typeck;
72 pub mod check_loop;
73 pub mod check_match;
74 pub mod check_const;
75 pub mod check_static;
76 pub mod lint;
77 pub mod borrowck;
78 pub mod dataflow;
79 pub mod mem_categorization;
80 pub mod liveness;
81 pub mod kind;
82 pub mod freevars;
83 pub mod pat_util;
84 pub mod region;
85 pub mod const_eval;
86 pub mod astencode;
87 pub mod lang_items;
88 pub mod privacy;
89 pub mod entry;
90 pub mod effect;
91 pub mod reachable;
92 pub mod graph;
93 pub mod cfg;
94 pub mod dead;
95 pub mod expr_use_visitor;
96 pub mod dependency_format;
97 }
98
99 pub mod front {
100 pub mod config;
101 pub mod test;
102 pub mod std_inject;
103 pub mod assign_node_ids_and_map;
104 pub mod feature_gate;
105 pub mod show_span;
106 }
107
108 pub mod back {
109 pub mod abi;
110 pub mod archive;
111 pub mod arm;
112 pub mod link;
113 pub mod lto;
114 pub mod mips;
115 pub mod rpath;
116 pub mod svh;
117 pub mod target_strs;
118 pub mod x86;
119 pub mod x86_64;
120 }
121
122 pub mod metadata;
123
124 pub mod driver;
125
126 pub mod util {
127 pub mod common;
128 pub mod ppaux;
129 pub mod sha2;
130 pub mod nodemap;
131 pub mod fs;
132 }
133
134 pub mod lib {
135 pub mod llvm;
136 pub mod llvmdeps;
137 }
138
139 static BUG_REPORT_URL: &'static str =
140 "http://static.rust-lang.org/doc/master/complement-bugreport.html";
141
142 pub fn version(argv0: &str) {
143 let vers = match option_env!("CFG_VERSION") {
144 Some(vers) => vers,
145 None => "unknown version"
146 };
147 println!("{} {}", argv0, vers);
148 println!("host: {}", d::host_triple());
149 }
150
151 pub fn usage(argv0: &str) {
152 let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
153 println!("{}\n\
154 Additional help:
155 -C help Print codegen options
156 -W help Print 'lint' options and default settings
157 -Z help Print internal options for debugging rustc\n",
158 getopts::usage(message, d::optgroups().as_slice()));
159 }
160
161 pub fn describe_warnings() {
162 println!("
163 Available lint options:
164 -W <foo> Warn about <foo>
165 -A <foo> Allow <foo>
166 -D <foo> Deny <foo>
167 -F <foo> Forbid <foo> (deny, and deny all overrides)
168 ");
169
170 let lint_dict = lint::get_lint_dict();
171 let mut lint_dict = lint_dict.move_iter()
172 .map(|(k, v)| (v, k))
173 .collect::<Vec<(lint::LintSpec, &'static str)> >();
174 lint_dict.as_mut_slice().sort();
175
176 let mut max_key = 0;
177 for &(_, name) in lint_dict.iter() {
178 max_key = cmp::max(name.len(), max_key);
179 }
180 fn padded(max: uint, s: &str) -> ~str {
181 " ".repeat(max - s.len()) + s
182 }
183 println!("\nAvailable lint checks:\n");
184 println!(" {} {:7.7s} {}",
185 padded(max_key, "name"), "default", "meaning");
186 println!(" {} {:7.7s} {}\n",
187 padded(max_key, "----"), "-------", "-------");
188 for (spec, name) in lint_dict.move_iter() {
189 let name = name.replace("_", "-");
190 println!(" {} {:7.7s} {}",
191 padded(max_key, name),
192 lint::level_to_str(spec.default),
193 spec.desc);
194 }
195 println!("");
196 }
197
198 pub fn describe_debug_flags() {
199 println!("\nAvailable debug options:\n");
200 let r = session::debugging_opts_map();
201 for tuple in r.iter() {
202 match *tuple {
203 (ref name, ref desc, _) => {
204 println!(" -Z {:>20s} -- {}", *name, *desc);
205 }
206 }
207 }
208 }
209
210 pub fn describe_codegen_flags() {
211 println!("\nAvailable codegen options:\n");
212 let mut cg = session::basic_codegen_options();
213 for &(name, parser, desc) in session::CG_OPTIONS.iter() {
214 // we invoke the parser function on `None` to see if this option needs
215 // an argument or not.
216 let (width, extra) = if parser(&mut cg, None) {
217 (25, "")
218 } else {
219 (21, "=val")
220 };
221 println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
222 extra, desc, width=width);
223 }
224 }
225
226 pub fn run_compiler(args: &[~str]) {
227 let mut args = Vec::from_slice(args);
228 let binary = args.shift().unwrap();
229
230 if args.is_empty() { usage(binary); return; }
231
232 let matches =
233 &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
234 Ok(m) => m,
235 Err(f) => {
236 d::early_error(f.to_err_msg());
237 }
238 };
239
240 if matches.opt_present("h") || matches.opt_present("help") {
241 usage(binary);
242 return;
243 }
244
245 let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
246 matches.opt_strs("warn").as_slice());
247 if lint_flags.iter().any(|x| x == &"help".to_owned()) {
248 describe_warnings();
249 return;
250 }
251
252 let r = matches.opt_strs("Z");
253 if r.iter().any(|x| x == &"help".to_owned()) {
254 describe_debug_flags();
255 return;
256 }
257
258 let cg_flags = matches.opt_strs("C");
259 if cg_flags.iter().any(|x| x == &"help".to_owned()) {
260 describe_codegen_flags();
261 return;
262 }
263
264 if cg_flags.contains(&"passes=list".to_owned()) {
265 unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
266 return;
267 }
268
269 if matches.opt_present("v") || matches.opt_present("version") {
270 version(binary);
271 return;
272 }
273 let (input, input_file_path) = match matches.free.len() {
274 0u => d::early_error("no input filename given"),
275 1u => {
276 let ifile = matches.free.get(0).as_slice();
277 if ifile == "-" {
278 let contents = io::stdin().read_to_end().unwrap();
279 let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
280 (d::StrInput(src), None)
281 } else {
282 (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
283 }
284 }
285 _ => d::early_error("multiple input filenames provided")
286 };
287
288 let sopts = d::build_session_options(matches);
289 let sess = d::build_session(sopts, input_file_path);
290 let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
291 let ofile = matches.opt_str("o").map(|o| Path::new(o));
292 let cfg = d::build_configuration(&sess);
293 let pretty = matches.opt_default("pretty", "normal").map(|a| {
294 d::parse_pretty(&sess, a)
295 });
296 match pretty {
297 Some::<d::PpMode>(ppm) => {
298 d::pretty_print_input(sess, cfg, &input, ppm, ofile);
299 return;
300 }
301 None::<d::PpMode> => {/* continue */ }
302 }
303
304 if r.contains(&("ls".to_owned())) {
305 match input {
306 d::FileInput(ref ifile) => {
307 let mut stdout = io::stdout();
308 d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
309 }
310 d::StrInput(_) => {
311 d::early_error("can not list metadata for stdin");
312 }
313 }
314 return;
315 }
316 let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
317 // these nasty nested conditions are to avoid doing extra work
318 if crate_id || crate_name || crate_file_name {
319 let attrs = parse_crate_attrs(&sess, &input);
320 let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
321 attrs.as_slice(), &sess);
322 let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
323
324 if crate_id {
325 println!("{}", id.to_str());
326 }
327 if crate_name {
328 println!("{}", id.name);
329 }
330 if crate_file_name {
331 let crate_types = session::collect_crate_types(&sess,
332 attrs.as_slice());
333 for &style in crate_types.iter() {
334 let fname = link::filename_for_input(&sess, style, &id,
335 &t_outputs.with_extension(""));
336 println!("{}", fname.filename_display());
337 }
338 }
339
340 return;
341 }
342
343 d::compile_input(sess, cfg, &input, &odir, &ofile);
344 }
345
346 fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
347 Vec<ast::Attribute> {
348 let result = match *input {
349 d::FileInput(ref ifile) => {
350 parse::parse_crate_attrs_from_file(ifile,
351 Vec::new(),
352 &sess.parse_sess)
353 }
354 d::StrInput(ref src) => {
355 parse::parse_crate_attrs_from_source_str(
356 d::anon_src().to_strbuf(),
357 src.to_strbuf(),
358 Vec::new(),
359 &sess.parse_sess)
360 }
361 };
362 result.move_iter().collect()
363 }
364
365 /// Run a procedure which will detect failures in the compiler and print nicer
366 /// error messages rather than just failing the test.
367 ///
368 /// The diagnostic emitter yielded to the procedure should be used for reporting
369 /// errors of the compiler.
370 pub fn monitor(f: proc():Send) {
371 // FIXME: This is a hack for newsched since it doesn't support split stacks.
372 // rustc needs a lot of stack! When optimizations are disabled, it needs
373 // even *more* stack than usual as well.
374 #[cfg(rtopt)]
375 static STACK_SIZE: uint = 6000000; // 6MB
376 #[cfg(not(rtopt))]
377 static STACK_SIZE: uint = 20000000; // 20MB
378
379 let mut task_builder = TaskBuilder::new().named("rustc");
380
381 // FIXME: Hacks on hacks. If the env is trying to override the stack size
382 // then *don't* set it explicitly.
383 if os::getenv("RUST_MIN_STACK").is_none() {
384 task_builder.opts.stack_size = Some(STACK_SIZE);
385 }
386
387 let (tx, rx) = channel();
388 let w = io::ChanWriter::new(tx);
389 let mut r = io::ChanReader::new(rx);
390
391 match task_builder.try(proc() {
392 io::stdio::set_stderr(box w);
393 f()
394 }) {
395 Ok(()) => { /* fallthrough */ }
396 Err(value) => {
397 // Task failed without emitting a fatal diagnostic
398 if !value.is::<diagnostic::FatalError>() {
399 let mut emitter = diagnostic::EmitterWriter::stderr();
400
401 // a .span_bug or .bug call has already printed what
402 // it wants to print.
403 if !value.is::<diagnostic::ExplicitBug>() {
404 emitter.emit(
405 None,
406 "unexpected failure",
407 diagnostic::Bug);
408 }
409
410 let xs = [
411 "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
412 "we would appreciate a bug report: " + BUG_REPORT_URL,
413 "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
414 ];
415 for note in xs.iter() {
416 emitter.emit(None, *note, diagnostic::Note)
417 }
418
419 match r.read_to_str() {
420 Ok(s) => println!("{}", s),
421 Err(e) => emitter.emit(None,
422 format!("failed to read internal stderr: {}", e),
423 diagnostic::Error),
424 }
425 }
426
427 // Fail so the process returns a failure code, but don't pollute the
428 // output with some unnecessary failure messages, we've already
429 // printed everything that we needed to.
430 io::stdio::set_stderr(box io::util::NullWriter);
431 fail!();
432 }
433 }
434 }
435
436 pub fn main() {
437 std::os::set_exit_status(main_args(std::os::args().as_slice()));
438 }
439
440 pub fn main_args(args: &[~str]) -> int {
441 let owned_args = args.to_owned();
442 monitor(proc() run_compiler(owned_args));
443 0
444 }