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.

C
Corey Richardson 已提交
11
#[crate_id = "rustc#0.9-pre"];
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;
84
    pub mod assign_node_ids;
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 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
        if crate_file_name {
            let lm = link::build_link_meta(sess, attrs, &t_outputs.obj_filename,
                                           &mut ::util::sha2::Sha256::new());
            let outputs = session::collect_outputs(sopts, attrs);
            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
}