]> git.lizzy.rs Git - rust.git/blob - src/rustc/driver/session.rs
59c4e5697adcf276e8952d3a0d6feef758c20646
[rust.git] / src / rustc / driver / session.rs
1
2 import syntax::{ast, codemap};
3 import syntax::ast::node_id;
4 import codemap::span;
5 import syntax::ast::{int_ty, uint_ty, float_ty};
6 import syntax::parse::parse_sess;
7 import metadata::filesearch;
8 import back::target_strs;
9 import back::link;
10 import middle::lint;
11
12
13 enum os { os_win32, os_macos, os_linux, os_freebsd, }
14
15 impl os : cmp::Eq {
16     pure fn eq(&&other: os) -> bool {
17         (self as uint) == (other as uint)
18     }
19 }
20
21 enum arch { arch_x86, arch_x86_64, arch_arm, }
22
23 impl arch: cmp::Eq {
24     pure fn eq(&&other: arch) -> bool {
25         (self as uint) == (other as uint)
26     }
27 }
28
29 enum crate_type { bin_crate, lib_crate, unknown_crate, }
30
31 type config =
32     {os: os,
33      arch: arch,
34      target_strs: target_strs::t,
35      int_type: int_ty,
36      uint_type: uint_ty,
37      float_type: float_ty};
38
39 const ppregions: uint = 1u;
40 const time_passes: uint = 2u;
41 const count_llvm_insns: uint = 4u;
42 const time_llvm_passes: uint = 8u;
43 const trans_stats: uint = 16u;
44 const no_asm_comments: uint = 32u;
45 const no_verify: uint = 64u;
46 const trace: uint = 128u;
47 // FIXME (#2377): This exists to transition to a Rust crate runtime
48 // It should be removed
49 const no_rt: uint = 256u;
50 const coherence: uint = 512u;
51 const borrowck_stats: uint = 1024u;
52 const borrowck_note_pure: uint = 2048;
53 const borrowck_note_loan: uint = 4096;
54 const no_landing_pads: uint = 8192;
55 const debug_llvm: uint = 16384;
56 const count_type_sizes: uint = 32768;
57 const meta_stats: uint = 65536;
58
59 fn debugging_opts_map() -> ~[(~str, ~str, uint)] {
60     ~[(~"ppregions", ~"prettyprint regions with \
61                     internal repr details", ppregions),
62      (~"time-passes", ~"measure time of each rustc pass", time_passes),
63      (~"count-llvm-insns", ~"count where LLVM \
64                            instrs originate", count_llvm_insns),
65      (~"time-llvm-passes", ~"measure time of each LLVM pass",
66       time_llvm_passes),
67      (~"trans-stats", ~"gather trans statistics", trans_stats),
68      (~"no-asm-comments", ~"omit comments when using -S", no_asm_comments),
69      (~"no-verify", ~"skip LLVM verification", no_verify),
70      (~"trace", ~"emit trace logs", trace),
71      (~"no-rt", ~"do not link to the runtime", no_rt),
72      (~"coherence", ~"perform coherence checking", coherence),
73      (~"borrowck-stats", ~"gather borrowck statistics",  borrowck_stats),
74      (~"borrowck-note-pure", ~"note where purity is req'd",
75       borrowck_note_pure),
76      (~"borrowck-note-loan", ~"note where loans are req'd",
77       borrowck_note_loan),
78      (~"no-landing-pads", ~"omit landing pads for unwinding",
79       no_landing_pads),
80      (~"debug-llvm", ~"enable debug output from LLVM", debug_llvm),
81      (~"count-type-sizes", ~"count the sizes of aggregate types",
82       count_type_sizes),
83      (~"meta-stats", ~"gather metadata statistics", meta_stats)
84     ]
85 }
86
87 enum OptLevel {
88     No, // -O0
89     Less, // -O1
90     Default, // -O2
91     Aggressive // -O3
92 }
93
94 impl OptLevel : cmp::Eq {
95     pure fn eq(&&other: OptLevel) -> bool {
96         (self as uint) == (other as uint)
97     }
98 }
99
100 type options =
101     // The crate config requested for the session, which may be combined
102     // with additional crate configurations during the compile process
103     {crate_type: crate_type,
104      static: bool,
105      gc: bool,
106      optimize: OptLevel,
107      debuginfo: bool,
108      extra_debuginfo: bool,
109      lint_opts: ~[(lint::lint, lint::level)],
110      save_temps: bool,
111      output_type: back::link::output_type,
112      addl_lib_search_paths: ~[Path],
113      maybe_sysroot: Option<Path>,
114      target_triple: ~str,
115      cfg: ast::crate_cfg,
116      test: bool,
117      parse_only: bool,
118      no_trans: bool,
119      debugging_opts: uint,
120     };
121
122 type crate_metadata = {name: ~str, data: ~[u8]};
123
124 type session_ = {targ_cfg: @config,
125                  opts: @options,
126                  cstore: metadata::cstore::cstore,
127                  parse_sess: parse_sess,
128                  codemap: codemap::codemap,
129                  // For a library crate, this is always none
130                  mut main_fn: Option<(node_id, codemap::span)>,
131                  span_diagnostic: diagnostic::span_handler,
132                  filesearch: filesearch::filesearch,
133                  mut building_library: bool,
134                  working_dir: Path,
135                  lint_settings: lint::lint_settings};
136
137 enum session {
138     session_(@session_)
139 }
140
141 impl session {
142     fn span_fatal(sp: span, msg: ~str) -> ! {
143         self.span_diagnostic.span_fatal(sp, msg)
144     }
145     fn fatal(msg: ~str) -> ! {
146         self.span_diagnostic.handler().fatal(msg)
147     }
148     fn span_err(sp: span, msg: ~str) {
149         self.span_diagnostic.span_err(sp, msg)
150     }
151     fn err(msg: ~str) {
152         self.span_diagnostic.handler().err(msg)
153     }
154     fn has_errors() -> bool {
155         self.span_diagnostic.handler().has_errors()
156     }
157     fn abort_if_errors() {
158         self.span_diagnostic.handler().abort_if_errors()
159     }
160     fn span_warn(sp: span, msg: ~str) {
161         self.span_diagnostic.span_warn(sp, msg)
162     }
163     fn warn(msg: ~str) {
164         self.span_diagnostic.handler().warn(msg)
165     }
166     fn span_note(sp: span, msg: ~str) {
167         self.span_diagnostic.span_note(sp, msg)
168     }
169     fn note(msg: ~str) {
170         self.span_diagnostic.handler().note(msg)
171     }
172     fn span_bug(sp: span, msg: ~str) -> ! {
173         self.span_diagnostic.span_bug(sp, msg)
174     }
175     fn bug(msg: ~str) -> ! {
176         self.span_diagnostic.handler().bug(msg)
177     }
178     fn span_unimpl(sp: span, msg: ~str) -> ! {
179         self.span_diagnostic.span_unimpl(sp, msg)
180     }
181     fn unimpl(msg: ~str) -> ! {
182         self.span_diagnostic.handler().unimpl(msg)
183     }
184     fn span_lint_level(level: lint::level,
185                        sp: span, msg: ~str) {
186         match level {
187           lint::allow => { },
188           lint::warn => self.span_warn(sp, msg),
189           lint::deny | lint::forbid => {
190             self.span_err(sp, msg);
191           }
192         }
193     }
194     fn span_lint(lint_mode: lint::lint,
195                  expr_id: ast::node_id, item_id: ast::node_id,
196                  span: span, msg: ~str) {
197         let level = lint::get_lint_settings_level(
198             self.lint_settings, lint_mode, expr_id, item_id);
199         self.span_lint_level(level, span, msg);
200     }
201     fn next_node_id() -> ast::node_id {
202         return syntax::parse::next_node_id(self.parse_sess);
203     }
204     fn diagnostic() -> diagnostic::span_handler {
205         self.span_diagnostic
206     }
207     fn debugging_opt(opt: uint) -> bool {
208         (self.opts.debugging_opts & opt) != 0u
209     }
210     // This exists to help with refactoring to eliminate impossible
211     // cases later on
212     fn impossible_case(sp: span, msg: &str) -> ! {
213         self.span_bug(sp, #fmt("Impossible case reached: %s", msg));
214     }
215     fn ppregions() -> bool { self.debugging_opt(ppregions) }
216     fn time_passes() -> bool { self.debugging_opt(time_passes) }
217     fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
218     fn count_type_sizes() -> bool { self.debugging_opt(count_type_sizes) }
219     fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) }
220     fn trans_stats() -> bool { self.debugging_opt(trans_stats) }
221     fn meta_stats() -> bool { self.debugging_opt(meta_stats) }
222     fn no_asm_comments() -> bool { self.debugging_opt(no_asm_comments) }
223     fn no_verify() -> bool { self.debugging_opt(no_verify) }
224     fn trace() -> bool { self.debugging_opt(trace) }
225     fn coherence() -> bool { self.debugging_opt(coherence) }
226     fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
227     fn borrowck_note_pure() -> bool { self.debugging_opt(borrowck_note_pure) }
228     fn borrowck_note_loan() -> bool { self.debugging_opt(borrowck_note_loan) }
229
230     fn str_of(id: ast::ident) -> ~str {
231         *self.parse_sess.interner.get(id)
232     }
233     fn ident_of(st: ~str) -> ast::ident {
234         self.parse_sess.interner.intern(@st)
235     }
236     fn intr() -> syntax::parse::token::ident_interner {
237         self.parse_sess.interner
238     }
239 }
240
241 /// Some reasonable defaults
242 fn basic_options() -> @options {
243     @{
244         crate_type: session::lib_crate,
245         static: false,
246         gc: false,
247         optimize: No,
248         debuginfo: false,
249         extra_debuginfo: false,
250         lint_opts: ~[],
251         save_temps: false,
252         output_type: link::output_type_exe,
253         addl_lib_search_paths: ~[],
254         maybe_sysroot: None,
255         target_triple: driver::host_triple(),
256         cfg: ~[],
257         test: false,
258         parse_only: false,
259         no_trans: false,
260         debugging_opts: 0u
261     }
262 }
263
264 // Seems out of place, but it uses session, so I'm putting it here
265 fn expect<T: copy>(sess: session, opt: Option<T>, msg: fn() -> ~str) -> T {
266     diagnostic::expect(sess.diagnostic(), opt, msg)
267 }
268
269 fn building_library(req_crate_type: crate_type, crate: @ast::crate,
270                     testing: bool) -> bool {
271     match req_crate_type {
272       bin_crate => false,
273       lib_crate => true,
274       unknown_crate => {
275         if testing {
276             false
277         } else {
278             match syntax::attr::first_attr_value_str_by_name(
279                 crate.node.attrs,
280                 ~"crate_type") {
281               option::Some(~"lib") => true,
282               _ => false
283             }
284         }
285       }
286     }
287 }
288
289 fn sess_os_to_meta_os(os: os) -> metadata::loader::os {
290     import metadata::loader;
291
292     match os {
293       os_win32 => loader::os_win32,
294       os_linux => loader::os_linux,
295       os_macos => loader::os_macos,
296       os_freebsd => loader::os_freebsd
297     }
298 }
299
300 #[cfg(test)]
301 mod test {
302     import syntax::ast_util;
303
304     fn make_crate_type_attr(t: ~str) -> ast::attribute {
305         ast_util::respan(ast_util::dummy_sp(), {
306             style: ast::attr_outer,
307             value: ast_util::respan(ast_util::dummy_sp(),
308                 ast::meta_name_value(
309                     ~"crate_type",
310                     ast_util::respan(ast_util::dummy_sp(),
311                                      ast::lit_str(@t)))),
312             is_sugared_doc: false
313         })
314     }
315
316     fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate {
317         let mut attrs = ~[];
318         if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; }
319         if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; }
320         @ast_util::respan(ast_util::dummy_sp(), {
321             directives: ~[],
322             module: {view_items: ~[], items: ~[]},
323             attrs: attrs,
324             config: ~[]
325         })
326     }
327
328     #[test]
329     fn bin_crate_type_attr_results_in_bin_output() {
330         let crate = make_crate(true, false);
331         assert !building_library(unknown_crate, crate, false);
332     }
333
334     #[test]
335     fn lib_crate_type_attr_results_in_lib_output() {
336         let crate = make_crate(false, true);
337         assert building_library(unknown_crate, crate, false);
338     }
339
340     #[test]
341     fn bin_option_overrides_lib_crate_type() {
342         let crate = make_crate(false, true);
343         assert !building_library(bin_crate, crate, false);
344     }
345
346     #[test]
347     fn lib_option_overrides_bin_crate_type() {
348         let crate = make_crate(true, false);
349         assert building_library(lib_crate, crate, false);
350     }
351
352     #[test]
353     fn bin_crate_type_is_default() {
354         let crate = make_crate(false, false);
355         assert !building_library(unknown_crate, crate, false);
356     }
357
358     #[test]
359     fn test_option_overrides_lib_crate_type() {
360         let crate = make_crate(false, true);
361         assert !building_library(unknown_crate, crate, true);
362     }
363
364     #[test]
365     fn test_option_does_not_override_requested_lib_type() {
366         let crate = make_crate(false, false);
367         assert building_library(lib_crate, crate, true);
368     }
369 }
370
371 // Local Variables:
372 // fill-column: 78;
373 // indent-tabs-mode: nil
374 // c-basic-offset: 4
375 // buffer-file-coding-system: utf-8-unix
376 // End: