lib.rs 11.5 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.

11
#[link(name = "rustc",
12
       vers = "0.9-pre",
13
       uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf",
14
       url = "https://github.com/mozilla/rust/tree/master/src/rustc")];
15

16
#[comment = "The Rust compiler"];
17
#[license = "MIT/ASL2"];
18
#[crate_type = "lib"];
B
Brian Anderson 已提交
19

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

22 23 24 25 26
// Rustc tasks always run on a fixed_stack_segment, so code in this
// module can call C functions (in particular, LLVM functions) with
// impunity.
#[allow(cstack)];

27
extern mod extra;
28
extern mod syntax;
29 30 31 32

use driver::driver::{host_triple, optgroups, early_error};
use driver::driver::{str_input, file_input, build_session_options};
use driver::driver::{build_session, build_configuration, parse_pretty};
33
use driver::driver::{PpMode, pretty_print_input, list_metadata};
34 35 36 37
use driver::driver::{compile_input};
use driver::session;
use middle::lint;

38
use std::comm;
A
Alex Crichton 已提交
39
use std::rt::io;
40
use std::rt::io::Reader;
41
use std::num;
42 43 44 45 46
use std::os;
use std::result;
use std::str;
use std::task;
use std::vec;
47
use extra::getopts::groups;
48
use extra::getopts;
49
use syntax::codemap;
50
use syntax::diagnostic::Emitter;
51 52
use syntax::diagnostic;

53
pub mod middle {
54
    pub mod trans;
55
    pub mod ty;
56
    pub mod subst;
57
    pub mod resolve;
B
Brian Anderson 已提交
58
    pub mod typeck;
59 60 61 62
    pub mod check_loop;
    pub mod check_match;
    pub mod check_const;
    pub mod lint;
63
    pub mod borrowck;
N
Niko Matsakis 已提交
64
    pub mod dataflow;
65 66 67 68 69 70 71 72 73 74
    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;
75
    pub mod moves;
76
    pub mod entry;
77
    pub mod effect;
78
    pub mod reachable;
79
    pub mod graph;
80
    pub mod cfg;
81
    pub mod stack_check;
82 83
}

84 85 86
pub mod front {
    pub mod config;
    pub mod test;
87
    pub mod std_inject;
88
    pub mod assign_node_ids;
89
    pub mod feature_gate;
G
Graydon Hoare 已提交
90 91
}

92 93 94 95 96
pub mod back {
    pub mod link;
    pub mod abi;
    pub mod upcall;
    pub mod arm;
J
Jyun-Yan You 已提交
97
    pub mod mips;
98 99 100 101
    pub mod x86;
    pub mod x86_64;
    pub mod rpath;
    pub mod target_strs;
102 103
}

104
pub mod metadata;
105

106
pub mod driver;
G
Graydon Hoare 已提交
107

108 109 110
pub mod util {
    pub mod common;
    pub mod ppaux;
G
Graydon Hoare 已提交
111 112
}

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

117 118
// A curious inner module that allows ::std::foo to be available in here for
// macros.
119
/*
120
mod std {
121
    pub use std::clone;
122 123 124 125 126 127
    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;
128 129
    pub use extra::serialize;
}
130
*/
131

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

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

150
pub fn describe_warnings() {
151
    use extra::sort::Sort;
D
Do Nhat Minh 已提交
152
    println("
B
Brian Anderson 已提交
153 154 155 156 157
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)
158
");
B
Brian Anderson 已提交
159 160

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

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

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

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

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

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

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

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

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

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

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

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

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

T
Tim Chevalier 已提交
260
    let sopts = build_session_options(binary, matches, demitter);
B
Brian Anderson 已提交
261
    let sess = build_session(sopts, demitter);
262 263
    let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
    let ofile = matches.opt_str("o").map(|o| Path::new(o));
264
    let cfg = build_configuration(sess);
265
    let pretty = do matches.opt_default("pretty", "normal").map |a| {
266 267
        parse_pretty(sess, a)
    };
B
Brian Anderson 已提交
268
    match pretty {
269
      Some::<PpMode>(ppm) => {
270
        pretty_print_input(sess, cfg, &input, ppm);
B
Brian Anderson 已提交
271 272
        return;
      }
273
      None::<PpMode> => {/* continue */ }
B
Brian Anderson 已提交
274
    }
275
    let ls = matches.opt_present("ls");
B
Brian Anderson 已提交
276 277
    if ls {
        match input {
278
          file_input(ref ifile) => {
A
Alex Crichton 已提交
279
            list_metadata(sess, &(*ifile), @mut io::stdout() as @mut io::Writer);
B
Brian Anderson 已提交
280 281
          }
          str_input(_) => {
282
            early_error(demitter, "can not list metadata for stdin");
B
Brian Anderson 已提交
283 284 285 286 287
          }
        }
        return;
    }

288
    compile_input(sess, cfg, &input, &odir, &ofile);
B
Brian Anderson 已提交
289 290
}

291
#[deriving(Eq)]
292
pub enum monitor_msg {
B
Brian Anderson 已提交
293 294 295 296
    fatal,
    done,
}

297 298 299 300 301 302
struct RustcEmitter {
    ch_capture: comm::SharedChan<monitor_msg>
}

impl diagnostic::Emitter for RustcEmitter {
    fn emit(&self,
303
            cmsp: Option<(@codemap::CodeMap, codemap::Span)>,
304 305 306 307 308 309 310 311 312 313
            msg: &str,
            lvl: diagnostic::level) {
        if lvl == diagnostic::fatal {
            self.ch_capture.send(fatal)
        }

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

B
Brian Anderson 已提交
314 315 316 317 318 319 320 321 322 323 324 325
/*
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.
*/
326
pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
327
    use std::comm::*;
328 329

    // XXX: This is a hack for newsched since it doesn't support split stacks.
330 331 332 333 334 335
    // 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
336

B
Brian Anderson 已提交
337
    let (p, ch) = stream();
338
    let ch = SharedChan::new(ch);
B
Brian Anderson 已提交
339
    let ch_capture = ch.clone();
340
    let mut task_builder = task::task();
B
Brian Anderson 已提交
341
    task_builder.name("rustc");
342
    task_builder.supervised();
343 344 345 346 347 348 349

    // 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);
    }

350
    match do task_builder.try {
B
Brian Anderson 已提交
351
        let ch = ch_capture.clone();
B
Brian Anderson 已提交
352 353
        // The 'diagnostics emitter'. Every error, warning, etc. should
        // go through this function.
354 355 356
        let demitter = @RustcEmitter {
            ch_capture: ch.clone(),
        } as @diagnostic::Emitter;
B
Brian Anderson 已提交
357 358

        struct finally {
B
Brian Anderson 已提交
359
            ch: SharedChan<monitor_msg>,
360 361 362
        }

        impl Drop for finally {
D
Daniel Micay 已提交
363
            fn drop(&mut self) { self.ch.send(done); }
B
Brian Anderson 已提交
364 365 366 367
        }

        let _finally = finally { ch: ch };

A
Alex Crichton 已提交
368 369 370 371 372
        f(demitter);

        // Due reasons explain in #7732, if there was a jit execution context it
        // must be consumed and passed along to our parent task.
        back::link::jit::consume_engine()
B
Brian Anderson 已提交
373 374 375 376
    } {
        result::Ok(_) => { /* fallthrough */ }
        result::Err(_) => {
            // Task failed without emitting a fatal diagnostic
B
Brian Anderson 已提交
377
            if p.recv() == done {
378
                diagnostic::DefaultEmitter.emit(
B
Brian Anderson 已提交
379
                    None,
380
                    diagnostic::ice_msg("unexpected failure"),
B
Brian Anderson 已提交
381 382
                    diagnostic::error);

383
                let xs = [
B
Brian Anderson 已提交
384 385
                    ~"the compiler hit an unexpected failure path. \
                     this is a bug",
386
                    ~"try running with RUST_LOG=rustc=1 \
B
Brian Anderson 已提交
387 388
                     to get further details and report the results \
                     to github.com/mozilla/rust/issues"
389
                ];
D
Daniel Micay 已提交
390
                for note in xs.iter() {
391 392 393
                    diagnostic::DefaultEmitter.emit(None,
                                                    *note,
                                                    diagnostic::note)
B
Brian Anderson 已提交
394 395 396
                }
            }
            // Fail so the process returns a failure code
397
            fail!();
B
Brian Anderson 已提交
398 399 400 401
        }
    }
}

402
pub fn main() {
B
Brian Anderson 已提交
403
    std::os::set_exit_status(main_args(std::os::args()));
404 405
}

B
Brian Anderson 已提交
406
pub fn main_args(args: &[~str]) -> int {
407
    let owned_args = args.to_owned();
L
Luqman Aden 已提交
408
    do monitor |demitter| {
409
        run_compiler(owned_args, demitter);
B
Brian Anderson 已提交
410
    }
B
Brian Anderson 已提交
411 412

    return 0;
B
Brian Anderson 已提交
413
}