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

D
Daniel Micay 已提交
21
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
22 23
#[allow(unrecognized_lint)]; // NOTE: remove after the next snapshot
#[allow(cstack)]; // NOTE: remove after the next snapshot.
24

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

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

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

51
pub mod middle {
52
    pub mod trans;
53
    pub mod ty;
54
    pub mod ty_fold;
55
    pub mod subst;
56
    pub mod resolve;
57
    pub mod resolve_lifetime;
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 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 92 93 94 95
pub mod back {
    pub mod link;
    pub mod abi;
    pub mod upcall;
    pub mod arm;
J
Jyun-Yan You 已提交
96
    pub mod mips;
97 98 99 100
    pub mod x86;
    pub mod x86_64;
    pub mod rpath;
    pub mod target_strs;
101 102
}

103
pub mod metadata;
104

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

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

112 113
pub mod lib {
    pub mod llvm;
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 137
    println!("{} {}", argv0, vers);
    println!("host: {}", 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",
146
              groups::usage(message, optgroups()));
B
Brian Anderson 已提交
147 148
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        let _finally = finally { ch: ch };

A
Alex Crichton 已提交
366 367 368 369 370
        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()
371
    }) {
B
Brian Anderson 已提交
372 373 374
        result::Ok(_) => { /* fallthrough */ }
        result::Err(_) => {
            // Task failed without emitting a fatal diagnostic
B
Brian Anderson 已提交
375
            if p.recv() == done {
376
                diagnostic::DefaultEmitter.emit(
B
Brian Anderson 已提交
377
                    None,
378
                    diagnostic::ice_msg("unexpected failure"),
B
Brian Anderson 已提交
379 380
                    diagnostic::error);

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

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

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