lib.rs 12.8 KB
Newer Older
S
sevrak 已提交
1
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

B
Brian Anderson 已提交
11
#[crate_id = "rustc#0.9"];
12
#[comment = "The Rust compiler"];
13
#[license = "MIT/ASL2"];
14
#[crate_type = "dylib"];
15
#[crate_type = "rlib"];
B
Brian Anderson 已提交
16

D
Daniel Micay 已提交
17
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
18

19
extern mod extra;
20
extern mod syntax;
21

A
Alex Crichton 已提交
22
use back::link;
23 24 25
use driver::session;
use middle::lint;

A
Alex Crichton 已提交
26 27
use d = driver::driver;

A
Alex Crichton 已提交
28
use std::cast;
29
use std::comm;
A
Alex Crichton 已提交
30 31
use std::io;
use std::io::Reader;
32
use std::num;
33 34 35 36 37
use std::os;
use std::result;
use std::str;
use std::task;
use std::vec;
38
use extra::getopts::groups;
39
use extra::getopts;
A
Alex Crichton 已提交
40 41
use syntax::ast;
use syntax::attr;
42
use syntax::codemap;
43
use syntax::diagnostic::Emitter;
44
use syntax::diagnostic;
A
Alex Crichton 已提交
45
use syntax::parse;
46

47
pub mod middle {
48
    pub mod trans;
49
    pub mod ty;
50
    pub mod ty_fold;
51
    pub mod subst;
52
    pub mod resolve;
53
    pub mod resolve_lifetime;
B
Brian Anderson 已提交
54
    pub mod typeck;
55 56 57 58
    pub mod check_loop;
    pub mod check_match;
    pub mod check_const;
    pub mod lint;
59
    pub mod borrowck;
N
Niko Matsakis 已提交
60
    pub mod dataflow;
61 62 63 64 65 66 67 68 69 70
    pub mod mem_categorization;
    pub mod liveness;
    pub mod kind;
    pub mod freevars;
    pub mod pat_util;
    pub mod region;
    pub mod const_eval;
    pub mod astencode;
    pub mod lang_items;
    pub mod privacy;
71
    pub mod moves;
72
    pub mod entry;
73
    pub mod effect;
74
    pub mod reachable;
75
    pub mod graph;
76
    pub mod cfg;
K
Kiet Tran 已提交
77
    pub mod dead;
78 79
}

80 81 82
pub mod front {
    pub mod config;
    pub mod test;
83
    pub mod std_inject;
E
Eduard Burtescu 已提交
84
    pub mod assign_node_ids_and_map;
85
    pub mod feature_gate;
G
Graydon Hoare 已提交
86 87
}

88
pub mod back {
89
    pub mod archive;
90 91 92
    pub mod link;
    pub mod abi;
    pub mod arm;
J
Jyun-Yan You 已提交
93
    pub mod mips;
94 95 96 97
    pub mod x86;
    pub mod x86_64;
    pub mod rpath;
    pub mod target_strs;
A
Alex Crichton 已提交
98
    pub mod lto;
99 100
}

101
pub mod metadata;
102

103
pub mod driver;
G
Graydon Hoare 已提交
104

105 106 107
pub mod util {
    pub mod common;
    pub mod ppaux;
108
    pub mod sha2;
G
Graydon Hoare 已提交
109 110
}

111 112
pub mod lib {
    pub mod llvm;
113
    pub mod llvmdeps;
G
Graydon Hoare 已提交
114 115
}

116 117
// A curious inner module that allows ::std::foo to be available in here for
// macros.
118
/*
119
mod std {
120
    pub use std::clone;
121 122 123 124 125 126
    pub use std::cmp;
    pub use std::os;
    pub use std::str;
    pub use std::sys;
    pub use std::to_bytes;
    pub use std::unstable;
127 128
    pub use extra::serialize;
}
129
*/
130

S
Steven Fackler 已提交
131 132 133 134 135
pub fn version(argv0: &str) {
    let vers = match option_env!("CFG_VERSION") {
        Some(vers) => vers,
        None => "unknown version"
    };
136
    println!("{} {}", argv0, vers);
A
Alex Crichton 已提交
137
    println!("host: {}", d::host_triple());
S
Steven Fackler 已提交
138 139
}

140
pub fn usage(argv0: &str) {
A
Alex Crichton 已提交
141
    let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
142
    println!("{}\n\
B
Brian Anderson 已提交
143 144 145
Additional help:
    -W help             Print 'lint' options and default settings
    -Z help             Print internal options for debugging rustc\n",
A
Alex Crichton 已提交
146
              groups::usage(message, d::optgroups()));
B
Brian Anderson 已提交
147 148
}

149
pub fn describe_warnings() {
D
Do Nhat Minh 已提交
150
    println("
B
Brian Anderson 已提交
151 152 153 154 155
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> (deny, and deny all overrides)
156
");
B
Brian Anderson 已提交
157 158

    let lint_dict = lint::get_lint_dict();
159
    let mut lint_dict = lint_dict.move_iter()
160
                                 .map(|(k, v)| (v, k))
161
                                 .collect::<~[(lint::LintSpec, &'static str)]>();
162
    lint_dict.sort();
163

B
Brian Anderson 已提交
164
    let mut max_key = 0;
D
Daniel Micay 已提交
165
    for &(_, name) in lint_dict.iter() {
166 167
        max_key = num::max(name.len(), max_key);
    }
B
Brian Anderson 已提交
168
    fn padded(max: uint, s: &str) -> ~str {
H
Huon Wilson 已提交
169
        " ".repeat(max - s.len()) + s
B
Brian Anderson 已提交
170
    }
D
Do Nhat Minh 已提交
171
    println("\nAvailable lint checks:\n");
172 173 174 175
    println!("    {}  {:7.7s}  {}",
             padded(max_key, "name"), "default", "meaning");
    println!("    {}  {:7.7s}  {}\n",
             padded(max_key, "----"), "-------", "-------");
176
    for (spec, name) in lint_dict.move_iter() {
177
        let name = name.replace("_", "-");
178 179 180 181
        println!("    {}  {:7.7s}  {}",
                 padded(max_key, name),
                 lint::level_to_str(spec.default),
                 spec.desc);
B
Brian Anderson 已提交
182
    }
A
Alex Crichton 已提交
183
    println("");
B
Brian Anderson 已提交
184 185
}

186
pub fn describe_debug_flags() {
D
Do Nhat Minh 已提交
187
    println("\nAvailable debug options:\n");
188
    let r = session::debugging_opts_map();
D
Daniel Micay 已提交
189
    for tuple in r.iter() {
190 191
        match *tuple {
            (ref name, ref desc, _) => {
192
                println!("    -Z {:>20s} -- {}", *name, *desc);
193 194
            }
        }
B
Brian Anderson 已提交
195 196 197
    }
}

198
pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
199
    let mut args = args.to_owned();
K
klutzy 已提交
200
    let binary = args.shift();
B
Brian Anderson 已提交
201

202
    if args.is_empty() { usage(binary); return; }
B
Brian Anderson 已提交
203 204

    let matches =
A
Alex Crichton 已提交
205
        &match getopts::groups::getopts(args, d::optgroups()) {
206 207
          Ok(m) => m,
          Err(f) => {
A
Alex Crichton 已提交
208
            d::early_error(demitter, f.to_err_msg());
B
Brian Anderson 已提交
209 210 211
          }
        };

212
    if matches.opt_present("h") || matches.opt_present("help") {
213
        usage(binary);
B
Brian Anderson 已提交
214 215 216
        return;
    }

L
Lenny222 已提交
217
    // Display the available lint options if "-W help" or only "-W" is given.
218 219
    let lint_flags = vec::append(matches.opt_strs("W"),
                                 matches.opt_strs("warn"));
L
Lenny222 已提交
220

221
    let show_lint_options = lint_flags.iter().any(|x| x == &~"help") ||
222
        (matches.opt_present("W") && lint_flags.is_empty());
L
Lenny222 已提交
223 224

    if show_lint_options {
B
Brian Anderson 已提交
225 226 227 228
        describe_warnings();
        return;
    }

229
    let r = matches.opt_strs("Z");
230
    if r.iter().any(|x| x == &~"help") {
B
Brian Anderson 已提交
231 232 233 234
        describe_debug_flags();
        return;
    }

235
    if matches.opt_str("passes") == Some(~"list") {
236
        unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
237 238 239
        return;
    }

240
    if matches.opt_present("v") || matches.opt_present("version") {
241
        version(binary);
B
Brian Anderson 已提交
242 243
        return;
    }
244
    let input = match matches.free.len() {
A
Alex Crichton 已提交
245
      0u => d::early_error(demitter, "no input filename given"),
B
Brian Anderson 已提交
246
      1u => {
247 248
        let ifile = matches.free[0].as_slice();
        if "-" == ifile {
H
Huon Wilson 已提交
249
            let src = str::from_utf8_owned(io::stdin().read_to_end());
A
Alex Crichton 已提交
250
            d::str_input(src.to_managed())
B
Brian Anderson 已提交
251
        } else {
A
Alex Crichton 已提交
252
            d::file_input(Path::new(ifile))
B
Brian Anderson 已提交
253 254
        }
      }
A
Alex Crichton 已提交
255
      _ => d::early_error(demitter, "multiple input filenames provided")
B
Brian Anderson 已提交
256 257
    };

A
Alex Crichton 已提交
258 259
    let sopts = d::build_session_options(binary, matches, demitter);
    let sess = d::build_session(sopts, demitter);
260 261
    let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
    let ofile = matches.opt_str("o").map(|o| Path::new(o));
A
Alex Crichton 已提交
262
    let cfg = d::build_configuration(sess);
263
    let pretty = matches.opt_default("pretty", "normal").map(|a| {
A
Alex Crichton 已提交
264
        d::parse_pretty(sess, a)
265
    });
B
Brian Anderson 已提交
266
    match pretty {
A
Alex Crichton 已提交
267 268
      Some::<d::PpMode>(ppm) => {
        d::pretty_print_input(sess, cfg, &input, ppm);
B
Brian Anderson 已提交
269 270
        return;
      }
A
Alex Crichton 已提交
271
      None::<d::PpMode> => {/* continue */ }
B
Brian Anderson 已提交
272
    }
273
    let ls = matches.opt_present("ls");
B
Brian Anderson 已提交
274 275
    if ls {
        match input {
A
Alex Crichton 已提交
276
          d::file_input(ref ifile) => {
277
            let mut stdout = io::stdout();
A
Alex Crichton 已提交
278
            d::list_metadata(sess, &(*ifile),
279
                                  &mut stdout as &mut io::Writer);
B
Brian Anderson 已提交
280
          }
A
Alex Crichton 已提交
281 282
          d::str_input(_) => {
            d::early_error(demitter, "can not list metadata for stdin");
B
Brian Anderson 已提交
283 284 285 286
          }
        }
        return;
    }
A
Alex Crichton 已提交
287 288 289 290 291 292 293
    let (crate_id, crate_name, crate_file_name) = sopts.print_metas;
    // these nasty nested conditions are to avoid doing extra work
    if crate_id || crate_name || crate_file_name {
        let attrs = parse_crate_attrs(sess, &input);
        let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
                                                  attrs, sess);
        if crate_id || crate_name {
L
Luis de Bethencourt 已提交
294 295
            let crateid = match attr::find_crateid(attrs) {
                Some(crateid) => crateid,
A
Alex Crichton 已提交
296 297 298 299 300 301
                None => {
                    sess.fatal("No crate_id and --crate-id or \
                                --crate-name requested")
                }
            };
            if crate_id {
L
Luis de Bethencourt 已提交
302
                println(crateid.to_str());
A
Alex Crichton 已提交
303 304
            }
            if crate_name {
L
Luis de Bethencourt 已提交
305
                println(crateid.name);
A
Alex Crichton 已提交
306 307
            }
        }
B
Brian Anderson 已提交
308

A
Alex Crichton 已提交
309 310 311
        if crate_file_name {
            let lm = link::build_link_meta(sess, attrs, &t_outputs.obj_filename,
                                           &mut ::util::sha2::Sha256::new());
312
            let outputs = session::collect_outputs(&sess, attrs);
A
Alex Crichton 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
            for &style in outputs.iter() {
                let fname = link::filename_for_input(&sess, style, &lm,
                                                     &t_outputs.out_filename);
                println!("{}", fname.filename_display());
            }
        }

        return;
    }

    d::compile_input(sess, cfg, &input, &odir, &ofile);
}

fn parse_crate_attrs(sess: session::Session,
                     input: &d::input) -> ~[ast::Attribute] {
    match *input {
        d::file_input(ref ifile) => {
            parse::parse_crate_attrs_from_file(ifile, ~[], sess.parse_sess)
        }
        d::str_input(src) => {
            parse::parse_crate_attrs_from_source_str(
                d::anon_src(), src, ~[], sess.parse_sess)
        }
    }
B
Brian Anderson 已提交
337 338
}

339
#[deriving(Eq)]
340
pub enum monitor_msg {
B
Brian Anderson 已提交
341 342 343 344
    fatal,
    done,
}

345 346 347 348 349 350
struct RustcEmitter {
    ch_capture: comm::SharedChan<monitor_msg>
}

impl diagnostic::Emitter for RustcEmitter {
    fn emit(&self,
351
            cmsp: Option<(&codemap::CodeMap, codemap::Span)>,
352 353 354
            msg: &str,
            lvl: diagnostic::level) {
        if lvl == diagnostic::fatal {
A
Alex Crichton 已提交
355 356
            let this = unsafe { cast::transmute_mut(self) };
            this.ch_capture.send(fatal)
357 358 359 360 361 362
        }

        diagnostic::DefaultEmitter.emit(cmsp, msg, lvl)
    }
}

B
Brian Anderson 已提交
363 364 365 366 367 368 369 370 371 372 373 374
/*
This is a sanity check that any failure of the compiler is performed
through the diagnostic module and reported properly - we shouldn't be calling
plain-old-fail on any execution path that might be taken. Since we have
console logging off by default, hitting a plain fail statement would make the
compiler silently exit, which would be terrible.

This method wraps the compiler in a subtask and injects a function into the
diagnostic emitter which records when we hit a fatal error. If the task
fails without recording a fatal error then we've encountered a compiler
bug and need to present an error.
*/
375
pub fn monitor(f: proc(@diagnostic::Emitter)) {
376
    use std::comm::*;
377 378

    // XXX: This is a hack for newsched since it doesn't support split stacks.
379 380 381 382 383 384
    // rustc needs a lot of stack! When optimizations are disabled, it needs
    // even *more* stack than usual as well.
    #[cfg(rtopt)]
    static STACK_SIZE: uint = 6000000;  // 6MB
    #[cfg(not(rtopt))]
    static STACK_SIZE: uint = 20000000; // 20MB
385

A
Alex Crichton 已提交
386
    let (p, ch) = SharedChan::new();
B
Brian Anderson 已提交
387
    let ch_capture = ch.clone();
388
    let mut task_builder = task::task();
B
Brian Anderson 已提交
389
    task_builder.name("rustc");
390 391 392 393 394 395 396

    // XXX: Hacks on hacks. If the env is trying to override the stack size
    // then *don't* set it explicitly.
    if os::getenv("RUST_MIN_STACK").is_none() {
        task_builder.opts.stack_size = Some(STACK_SIZE);
    }

397
    match task_builder.try(proc() {
B
Brian Anderson 已提交
398
        let ch = ch_capture.clone();
B
Brian Anderson 已提交
399 400
        // The 'diagnostics emitter'. Every error, warning, etc. should
        // go through this function.
401 402 403
        let demitter = @RustcEmitter {
            ch_capture: ch.clone(),
        } as @diagnostic::Emitter;
B
Brian Anderson 已提交
404 405

        struct finally {
B
Brian Anderson 已提交
406
            ch: SharedChan<monitor_msg>,
407 408 409
        }

        impl Drop for finally {
D
Daniel Micay 已提交
410
            fn drop(&mut self) { self.ch.send(done); }
B
Brian Anderson 已提交
411 412 413 414
        }

        let _finally = finally { ch: ch };

A
Alex Crichton 已提交
415
        f(demitter);
416
    }) {
B
Brian Anderson 已提交
417 418 419
        result::Ok(_) => { /* fallthrough */ }
        result::Err(_) => {
            // Task failed without emitting a fatal diagnostic
B
Brian Anderson 已提交
420
            if p.recv() == done {
421
                diagnostic::DefaultEmitter.emit(
B
Brian Anderson 已提交
422
                    None,
423
                    diagnostic::ice_msg("unexpected failure"),
B
Brian Anderson 已提交
424 425
                    diagnostic::error);

426
                let xs = [
B
Brian Anderson 已提交
427 428
                    ~"the compiler hit an unexpected failure path. \
                     this is a bug",
429
                    ~"try running with RUST_LOG=rustc=1 \
B
Brian Anderson 已提交
430 431
                     to get further details and report the results \
                     to github.com/mozilla/rust/issues"
432
                ];
D
Daniel Micay 已提交
433
                for note in xs.iter() {
434 435 436
                    diagnostic::DefaultEmitter.emit(None,
                                                    *note,
                                                    diagnostic::note)
B
Brian Anderson 已提交
437 438 439
                }
            }
            // Fail so the process returns a failure code
440
            fail!();
B
Brian Anderson 已提交
441 442 443 444
        }
    }
}

445
pub fn main() {
B
Brian Anderson 已提交
446
    std::os::set_exit_status(main_args(std::os::args()));
447 448
}

B
Brian Anderson 已提交
449
pub fn main_args(args: &[~str]) -> int {
450
    let owned_args = args.to_owned();
451
    monitor(proc(demitter) run_compiler(owned_args, demitter));
452
    0
B
Brian Anderson 已提交
453
}