lib.rs 11.2 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
       package_id = "rustc",
13
       vers = "0.9-pre",
14
       uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf",
15
       url = "https://github.com/mozilla/rust/tree/master/src/rustc")];
16

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

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

24
extern mod extra;
25
extern mod syntax;
26 27 28 29

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};
30
use driver::driver::{PpMode, pretty_print_input, list_metadata};
31 32 33 34
use driver::driver::{compile_input};
use driver::session;
use middle::lint;

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

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

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

91
pub mod back {
92
    pub mod archive;
93 94 95 96
    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;
115
    pub mod llvmdeps;
G
Graydon Hoare 已提交
116 117
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

B
Brian Anderson 已提交
338
    let (p, ch) = stream();
339
    let ch = SharedChan::new(ch);
B
Brian Anderson 已提交
340
    let ch_capture = ch.clone();
341
    let mut task_builder = task::task();
B
Brian Anderson 已提交
342
    task_builder.name("rustc");
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 task_builder.try(proc() {
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
        f(demitter);
369
    }) {
B
Brian Anderson 已提交
370 371 372
        result::Ok(_) => { /* fallthrough */ }
        result::Err(_) => {
            // Task failed without emitting a fatal diagnostic
B
Brian Anderson 已提交
373
            if p.recv() == done {
374
                diagnostic::DefaultEmitter.emit(
B
Brian Anderson 已提交
375
                    None,
376
                    diagnostic::ice_msg("unexpected failure"),
B
Brian Anderson 已提交
377 378
                    diagnostic::error);

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

398
pub fn main() {
B
Brian Anderson 已提交
399
    std::os::set_exit_status(main_args(std::os::args()));
400 401
}

B
Brian Anderson 已提交
402
pub fn main_args(args: &[~str]) -> int {
403
    let owned_args = args.to_owned();
404
    monitor(proc(demitter) run_compiler(owned_args, demitter));
405
    0
B
Brian Anderson 已提交
406
}