| |
| use syntax::{ast, codemap}; |
| use syntax::ast::node_id; |
| use codemap::span; |
| use syntax::ast::{int_ty, uint_ty, float_ty}; |
| use syntax::parse::parse_sess; |
| use metadata::filesearch; |
| use back::target_strs; |
| use back::link; |
| use middle::lint; |
| |
| |
| enum os { os_win32, os_macos, os_linux, os_freebsd, } |
| |
| impl os : cmp::Eq { |
| pure fn eq(other: &os) -> bool { |
| (self as uint) == ((*other) as uint) |
| } |
| pure fn ne(other: &os) -> bool { !self.eq(other) } |
| } |
| |
| enum arch { arch_x86, arch_x86_64, arch_arm, } |
| |
| impl arch : cmp::Eq { |
| pure fn eq(other: &arch) -> bool { |
| (self as uint) == ((*other) as uint) |
| } |
| pure fn ne(other: &arch) -> bool { !self.eq(other) } |
| } |
| |
| enum crate_type { bin_crate, lib_crate, unknown_crate, } |
| |
| type config = |
| {os: os, |
| arch: arch, |
| target_strs: target_strs::t, |
| int_type: int_ty, |
| uint_type: uint_ty, |
| float_type: float_ty}; |
| |
| const verbose: uint = 1 << 0; |
| const time_passes: uint = 1 << 1; |
| const count_llvm_insns: uint = 1 << 2; |
| const time_llvm_passes: uint = 1 << 3; |
| const trans_stats: uint = 1 << 4; |
| const no_asm_comments: uint = 1 << 5; |
| const no_verify: uint = 1 << 6; |
| const trace: uint = 1 << 7; |
| const coherence: uint = 1 << 8; |
| const borrowck_stats: uint = 1 << 9; |
| const borrowck_note_pure: uint = 1 << 10; |
| const borrowck_note_loan: uint = 1 << 11; |
| const no_landing_pads: uint = 1 << 12; |
| const debug_llvm: uint = 1 << 13; |
| const count_type_sizes: uint = 1 << 14; |
| const meta_stats: uint = 1 << 15; |
| const no_opt: uint = 1 << 16; |
| |
| fn debugging_opts_map() -> ~[(~str, ~str, uint)] { |
| ~[(~"verbose", ~"in general, enable more debug printouts", verbose), |
| (~"time-passes", ~"measure time of each rustc pass", time_passes), |
| (~"count-llvm-insns", ~"count where LLVM \ |
| instrs originate", count_llvm_insns), |
| (~"time-llvm-passes", ~"measure time of each LLVM pass", |
| time_llvm_passes), |
| (~"trans-stats", ~"gather trans statistics", trans_stats), |
| (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments), |
| (~"no-verify", ~"skip LLVM verification", no_verify), |
| (~"trace", ~"emit trace logs", trace), |
| (~"coherence", ~"perform coherence checking", coherence), |
| (~"borrowck-stats", ~"gather borrowck statistics", borrowck_stats), |
| (~"borrowck-note-pure", ~"note where purity is req'd", |
| borrowck_note_pure), |
| (~"borrowck-note-loan", ~"note where loans are req'd", |
| borrowck_note_loan), |
| (~"no-landing-pads", ~"omit landing pads for unwinding", |
| no_landing_pads), |
| (~"debug-llvm", ~"enable debug output from LLVM", debug_llvm), |
| (~"count-type-sizes", ~"count the sizes of aggregate types", |
| count_type_sizes), |
| (~"meta-stats", ~"gather metadata statistics", meta_stats), |
| (~"no-opt", ~"do not optimize, even if -O is passed", no_opt), |
| ] |
| } |
| |
| enum OptLevel { |
| No, // -O0 |
| Less, // -O1 |
| Default, // -O2 |
| Aggressive // -O3 |
| } |
| |
| impl OptLevel : cmp::Eq { |
| pure fn eq(other: &OptLevel) -> bool { |
| (self as uint) == ((*other) as uint) |
| } |
| pure fn ne(other: &OptLevel) -> bool { !self.eq(other) } |
| } |
| |
| type options = |
| // The crate config requested for the session, which may be combined |
| // with additional crate configurations during the compile process |
| {crate_type: crate_type, |
| static: bool, |
| gc: bool, |
| optimize: OptLevel, |
| debuginfo: bool, |
| extra_debuginfo: bool, |
| lint_opts: ~[(lint::lint, lint::level)], |
| save_temps: bool, |
| jit: bool, |
| output_type: back::link::output_type, |
| addl_lib_search_paths: ~[Path], |
| maybe_sysroot: Option<Path>, |
| target_triple: ~str, |
| // User-specified cfg meta items. The compiler itself will add additional |
| // items to the crate config, and during parsing the entire crate config |
| // will be added to the crate AST node. This should not be used for |
| // anything except building the full crate config prior to parsing. |
| cfg: ast::crate_cfg, |
| binary: ~str, |
| test: bool, |
| parse_only: bool, |
| no_trans: bool, |
| debugging_opts: uint, |
| }; |
| |
| type crate_metadata = {name: ~str, data: ~[u8]}; |
| |
| type session_ = {targ_cfg: @config, |
| opts: @options, |
| cstore: metadata::cstore::cstore, |
| parse_sess: parse_sess, |
| codemap: codemap::codemap, |
| // For a library crate, this is always none |
| mut main_fn: Option<(node_id, codemap::span)>, |
| span_diagnostic: diagnostic::span_handler, |
| filesearch: filesearch::filesearch, |
| mut building_library: bool, |
| working_dir: Path, |
| lint_settings: lint::lint_settings}; |
| |
| enum session { |
| session_(@session_) |
| } |
| |
| impl session { |
| fn span_fatal(sp: span, msg: ~str) -> ! { |
| self.span_diagnostic.span_fatal(sp, msg) |
| } |
| fn fatal(msg: ~str) -> ! { |
| self.span_diagnostic.handler().fatal(msg) |
| } |
| fn span_err(sp: span, msg: ~str) { |
| self.span_diagnostic.span_err(sp, msg) |
| } |
| fn err(msg: ~str) { |
| self.span_diagnostic.handler().err(msg) |
| } |
| fn has_errors() -> bool { |
| self.span_diagnostic.handler().has_errors() |
| } |
| fn abort_if_errors() { |
| self.span_diagnostic.handler().abort_if_errors() |
| } |
| fn span_warn(sp: span, msg: ~str) { |
| self.span_diagnostic.span_warn(sp, msg) |
| } |
| fn warn(msg: ~str) { |
| self.span_diagnostic.handler().warn(msg) |
| } |
| fn span_note(sp: span, msg: ~str) { |
| self.span_diagnostic.span_note(sp, msg) |
| } |
| fn note(msg: ~str) { |
| self.span_diagnostic.handler().note(msg) |
| } |
| fn span_bug(sp: span, msg: ~str) -> ! { |
| self.span_diagnostic.span_bug(sp, msg) |
| } |
| fn bug(msg: ~str) -> ! { |
| self.span_diagnostic.handler().bug(msg) |
| } |
| fn span_unimpl(sp: span, msg: ~str) -> ! { |
| self.span_diagnostic.span_unimpl(sp, msg) |
| } |
| fn unimpl(msg: ~str) -> ! { |
| self.span_diagnostic.handler().unimpl(msg) |
| } |
| fn span_lint_level(level: lint::level, |
| sp: span, msg: ~str) { |
| match level { |
| lint::allow => { }, |
| lint::warn => self.span_warn(sp, msg), |
| lint::deny | lint::forbid => { |
| self.span_err(sp, msg); |
| } |
| } |
| } |
| fn span_lint(lint_mode: lint::lint, |
| expr_id: ast::node_id, item_id: ast::node_id, |
| span: span, msg: ~str) { |
| let level = lint::get_lint_settings_level( |
| self.lint_settings, lint_mode, expr_id, item_id); |
| self.span_lint_level(level, span, msg); |
| } |
| fn next_node_id() -> ast::node_id { |
| return syntax::parse::next_node_id(self.parse_sess); |
| } |
| fn diagnostic() -> diagnostic::span_handler { |
| self.span_diagnostic |
| } |
| fn debugging_opt(opt: uint) -> bool { |
| (self.opts.debugging_opts & opt) != 0u |
| } |
| // This exists to help with refactoring to eliminate impossible |
| // cases later on |
| fn impossible_case(sp: span, msg: &str) -> ! { |
| self.span_bug(sp, #fmt("Impossible case reached: %s", msg)); |
| } |
| fn verbose() -> bool { self.debugging_opt(verbose) } |
| fn time_passes() -> bool { self.debugging_opt(time_passes) } |
| fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) } |
| fn count_type_sizes() -> bool { self.debugging_opt(count_type_sizes) } |
| fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) } |
| fn trans_stats() -> bool { self.debugging_opt(trans_stats) } |
| fn meta_stats() -> bool { self.debugging_opt(meta_stats) } |
| fn no_asm_comments() -> bool { self.debugging_opt(no_asm_comments) } |
| fn no_verify() -> bool { self.debugging_opt(no_verify) } |
| fn trace() -> bool { self.debugging_opt(trace) } |
| fn coherence() -> bool { self.debugging_opt(coherence) } |
| fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) } |
| fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) } |
| fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) } |
| |
| fn str_of(id: ast::ident) -> ~str { |
| *self.parse_sess.interner.get(id) |
| } |
| fn ident_of(st: ~str) -> ast::ident { |
| self.parse_sess.interner.intern(@st) |
| } |
| fn intr() -> @syntax::parse::token::ident_interner { |
| self.parse_sess.interner |
| } |
| } |
| |
| /// Some reasonable defaults |
| fn basic_options() -> @options { |
| @{ |
| crate_type: session::lib_crate, |
| static: false, |
| gc: false, |
| optimize: No, |
| debuginfo: false, |
| extra_debuginfo: false, |
| lint_opts: ~[], |
| save_temps: false, |
| jit: false, |
| output_type: link::output_type_exe, |
| addl_lib_search_paths: ~[], |
| maybe_sysroot: None, |
| target_triple: driver::host_triple(), |
| cfg: ~[], |
| binary: ~"rustc", |
| test: false, |
| parse_only: false, |
| no_trans: false, |
| debugging_opts: 0u |
| } |
| } |
| |
| // Seems out of place, but it uses session, so I'm putting it here |
| fn expect<T: Copy>(sess: session, opt: Option<T>, msg: fn() -> ~str) -> T { |
| diagnostic::expect(sess.diagnostic(), opt, msg) |
| } |
| |
| fn building_library(req_crate_type: crate_type, crate: @ast::crate, |
| testing: bool) -> bool { |
| match req_crate_type { |
| bin_crate => false, |
| lib_crate => true, |
| unknown_crate => { |
| if testing { |
| false |
| } else { |
| match syntax::attr::first_attr_value_str_by_name( |
| crate.node.attrs, |
| ~"crate_type") { |
| option::Some(~"lib") => true, |
| _ => false |
| } |
| } |
| } |
| } |
| } |
| |
| fn sess_os_to_meta_os(os: os) -> metadata::loader::os { |
| use metadata::loader; |
| |
| match os { |
| os_win32 => loader::os_win32, |
| os_linux => loader::os_linux, |
| os_macos => loader::os_macos, |
| os_freebsd => loader::os_freebsd |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| #[legacy_exports]; |
| use syntax::ast_util; |
| |
| fn make_crate_type_attr(t: ~str) -> ast::attribute { |
| ast_util::respan(ast_util::dummy_sp(), { |
| style: ast::attr_outer, |
| value: ast_util::respan(ast_util::dummy_sp(), |
| ast::meta_name_value( |
| ~"crate_type", |
| ast_util::respan(ast_util::dummy_sp(), |
| ast::lit_str(@t)))), |
| is_sugared_doc: false |
| }) |
| } |
| |
| fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate { |
| let mut attrs = ~[]; |
| if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; } |
| if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; } |
| @ast_util::respan(ast_util::dummy_sp(), { |
| directives: ~[], |
| module: {view_items: ~[], items: ~[]}, |
| attrs: attrs, |
| config: ~[] |
| }) |
| } |
| |
| #[test] |
| fn bin_crate_type_attr_results_in_bin_output() { |
| let crate = make_crate(true, false); |
| assert !building_library(unknown_crate, crate, false); |
| } |
| |
| #[test] |
| fn lib_crate_type_attr_results_in_lib_output() { |
| let crate = make_crate(false, true); |
| assert building_library(unknown_crate, crate, false); |
| } |
| |
| #[test] |
| fn bin_option_overrides_lib_crate_type() { |
| let crate = make_crate(false, true); |
| assert !building_library(bin_crate, crate, false); |
| } |
| |
| #[test] |
| fn lib_option_overrides_bin_crate_type() { |
| let crate = make_crate(true, false); |
| assert building_library(lib_crate, crate, false); |
| } |
| |
| #[test] |
| fn bin_crate_type_is_default() { |
| let crate = make_crate(false, false); |
| assert !building_library(unknown_crate, crate, false); |
| } |
| |
| #[test] |
| fn test_option_overrides_lib_crate_type() { |
| let crate = make_crate(false, true); |
| assert !building_library(unknown_crate, crate, true); |
| } |
| |
| #[test] |
| fn test_option_does_not_override_requested_lib_type() { |
| let crate = make_crate(false, false); |
| assert building_library(lib_crate, crate, true); |
| } |
| } |
| |
| // Local Variables: |
| // fill-column: 78; |
| // indent-tabs-mode: nil |
| // c-basic-offset: 4 |
| // buffer-file-coding-system: utf-8-unix |
| // End: |