lib.rs 11.1 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"];
B
Brian Anderson 已提交
20

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

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

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

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

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

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

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

102
pub mod metadata;
103

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

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

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

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

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

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

148
pub fn describe_warnings() {
149
    use extra::sort::Sort;
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 162 163
                                 .collect::<~[(lint::LintSpec, &'static str)]>();
    lint_dict.qsort();

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();
200
    let binary = args.shift().to_managed();
B
Brian Anderson 已提交
201

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

    let matches =
205
        &match getopts::groups::getopts(args, optgroups()) {
206 207
          Ok(m) => m,
          Err(f) => {
208
            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() {
245
      0u => 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());
250
            str_input(src.to_managed())
B
Brian Anderson 已提交
251
        } else {
252
            file_input(Path::new(ifile))
B
Brian Anderson 已提交
253 254
        }
      }
255
      _ => early_error(demitter, "multiple input filenames provided")
B
Brian Anderson 已提交
256 257
    };

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

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

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

295 296 297 298 299 300
struct RustcEmitter {
    ch_capture: comm::SharedChan<monitor_msg>
}

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

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

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

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

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

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

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

        struct finally {
B
Brian Anderson 已提交
356
            ch: SharedChan<monitor_msg>,
357 358 359
        }

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

        let _finally = finally { ch: ch };

A
Alex Crichton 已提交
365
        f(demitter);
366
    }) {
B
Brian Anderson 已提交
367 368 369
        result::Ok(_) => { /* fallthrough */ }
        result::Err(_) => {
            // Task failed without emitting a fatal diagnostic
B
Brian Anderson 已提交
370
            if p.recv() == done {
371
                diagnostic::DefaultEmitter.emit(
B
Brian Anderson 已提交
372
                    None,
373
                    diagnostic::ice_msg("unexpected failure"),
B
Brian Anderson 已提交
374 375
                    diagnostic::error);

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

395
pub fn main() {
B
Brian Anderson 已提交
396
    std::os::set_exit_status(main_args(std::os::args()));
397 398
}

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