]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
a7813a04 | 11 | use dep_graph::DepGraph; |
3157f602 XL |
12 | use hir::def_id::DefIndex; |
13 | use hir::svh::Svh; | |
1a4d82fc | 14 | use lint; |
92a42be0 | 15 | use middle::cstore::CrateStore; |
e9174d1e | 16 | use middle::dependency_format; |
1a4d82fc | 17 | use session::search_paths::PathKind; |
3157f602 | 18 | use session::config::{DebugInfoLevel, PanicStrategy}; |
54a0048b | 19 | use ty::tls; |
e9174d1e | 20 | use util::nodemap::{NodeMap, FnvHashMap}; |
54a0048b | 21 | use mir::transform as mir_pass; |
1a4d82fc | 22 | |
3157f602 XL |
23 | use syntax::ast::{NodeId, Name}; |
24 | use errors::{self, DiagnosticBuilder}; | |
5bcae85e | 25 | use errors::emitter::{Emitter, EmitterWriter}; |
3157f602 | 26 | use syntax::json::JsonEmitter; |
1a4d82fc JJ |
27 | use syntax::feature_gate; |
28 | use syntax::parse; | |
1a4d82fc | 29 | use syntax::parse::ParseSess; |
54a0048b | 30 | use syntax::parse::token; |
1a4d82fc | 31 | use syntax::{ast, codemap}; |
62682a34 | 32 | use syntax::feature_gate::AttributeType; |
3157f602 | 33 | use syntax_pos::{Span, MultiSpan}; |
1a4d82fc | 34 | |
85aaf69f | 35 | use rustc_back::target::Target; |
a7813a04 | 36 | use llvm; |
85aaf69f | 37 | |
c34b1796 | 38 | use std::path::{Path, PathBuf}; |
1a4d82fc | 39 | use std::cell::{Cell, RefCell}; |
7453a54e | 40 | use std::collections::{HashMap, HashSet}; |
c34b1796 | 41 | use std::env; |
a7813a04 | 42 | use std::ffi::CString; |
92a42be0 | 43 | use std::rc::Rc; |
54a0048b | 44 | use std::fmt; |
a7813a04 | 45 | use libc::c_int; |
1a4d82fc JJ |
46 | |
47 | pub mod config; | |
92a42be0 | 48 | pub mod filesearch; |
1a4d82fc JJ |
49 | pub mod search_paths; |
50 | ||
51 | // Represents the data associated with a compilation | |
52 | // session for a single crate. | |
53 | pub struct Session { | |
a7813a04 | 54 | pub dep_graph: DepGraph, |
1a4d82fc | 55 | pub target: config::Config, |
85aaf69f | 56 | pub host: Target, |
1a4d82fc | 57 | pub opts: config::Options, |
92a42be0 | 58 | pub cstore: Rc<for<'a> CrateStore<'a>>, |
1a4d82fc JJ |
59 | pub parse_sess: ParseSess, |
60 | // For a library crate, this is always none | |
7453a54e | 61 | pub entry_fn: RefCell<Option<(NodeId, Span)>>, |
1a4d82fc JJ |
62 | pub entry_type: Cell<Option<config::EntryFnType>>, |
63 | pub plugin_registrar_fn: Cell<Option<ast::NodeId>>, | |
c34b1796 | 64 | pub default_sysroot: Option<PathBuf>, |
d9579d0f AL |
65 | // The name of the root source file of the crate, in the local file system. |
66 | // The path is always expected to be absolute. `None` means that there is no | |
67 | // source file. | |
c34b1796 AL |
68 | pub local_crate_source_file: Option<PathBuf>, |
69 | pub working_dir: PathBuf, | |
1a4d82fc | 70 | pub lint_store: RefCell<lint::LintStore>, |
7453a54e | 71 | pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>, |
9346a6ac | 72 | pub plugin_llvm_passes: RefCell<Vec<String>>, |
54a0048b | 73 | pub mir_passes: RefCell<mir_pass::Passes>, |
62682a34 | 74 | pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>, |
1a4d82fc | 75 | pub crate_types: RefCell<Vec<config::CrateType>>, |
e9174d1e | 76 | pub dependency_formats: RefCell<dependency_format::Dependencies>, |
54a0048b SL |
77 | // The crate_disambiguator is constructed out of all the `-C metadata` |
78 | // arguments passed to the compiler. Its value together with the crate-name | |
79 | // forms a unique global identifier for the crate. It is used to allow | |
80 | // multiple crates with the same name to coexist. See the | |
81 | // trans::back::symbol_names module for more information. | |
5bcae85e | 82 | pub crate_disambiguator: RefCell<token::InternedString>, |
1a4d82fc JJ |
83 | pub features: RefCell<feature_gate::Features>, |
84 | ||
85 | /// The maximum recursion limit for potentially infinitely recursive | |
86 | /// operations such as auto-dereference and monomorphization. | |
c34b1796 | 87 | pub recursion_limit: Cell<usize>, |
1a4d82fc | 88 | |
a7813a04 XL |
89 | /// The metadata::creader module may inject an allocator/panic_runtime |
90 | /// dependency if it didn't already find one, and this tracks what was | |
91 | /// injected. | |
e9174d1e | 92 | pub injected_allocator: Cell<Option<ast::CrateNum>>, |
a7813a04 | 93 | pub injected_panic_runtime: Cell<Option<ast::CrateNum>>, |
e9174d1e | 94 | |
92a42be0 SL |
95 | /// Names of all bang-style macros and syntax extensions |
96 | /// available in this crate | |
97 | pub available_macros: RefCell<HashSet<Name>>, | |
98 | ||
7453a54e SL |
99 | /// Map from imported macro spans (which consist of |
100 | /// the localized span for the macro body) to the | |
101 | /// macro name and defintion span in the source crate. | |
102 | pub imported_macro_spans: RefCell<HashMap<Span, (String, Span)>>, | |
103 | ||
e9174d1e | 104 | next_node_id: Cell<ast::NodeId>, |
1a4d82fc JJ |
105 | } |
106 | ||
107 | impl Session { | |
5bcae85e SL |
108 | pub fn local_crate_disambiguator(&self) -> token::InternedString { |
109 | self.crate_disambiguator.borrow().clone() | |
110 | } | |
7453a54e SL |
111 | pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self, |
112 | sp: S, | |
113 | msg: &str) | |
114 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
115 | self.diagnostic().struct_span_warn(sp, msg) |
116 | } | |
7453a54e SL |
117 | pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self, |
118 | sp: S, | |
119 | msg: &str, | |
120 | code: &str) | |
121 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
122 | self.diagnostic().struct_span_warn_with_code(sp, msg, code) |
123 | } | |
124 | pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
125 | self.diagnostic().struct_warn(msg) | |
126 | } | |
7453a54e SL |
127 | pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, |
128 | sp: S, | |
129 | msg: &str) | |
130 | -> DiagnosticBuilder<'a> { | |
5bcae85e | 131 | self.diagnostic().struct_span_err(sp, msg) |
9cc50fc6 | 132 | } |
7453a54e SL |
133 | pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, |
134 | sp: S, | |
135 | msg: &str, | |
136 | code: &str) | |
137 | -> DiagnosticBuilder<'a> { | |
5bcae85e | 138 | self.diagnostic().struct_span_err_with_code(sp, msg, code) |
9cc50fc6 SL |
139 | } |
140 | pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
141 | self.diagnostic().struct_err(msg) | |
142 | } | |
7453a54e SL |
143 | pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self, |
144 | sp: S, | |
145 | msg: &str) | |
146 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
147 | self.diagnostic().struct_span_fatal(sp, msg) |
148 | } | |
7453a54e SL |
149 | pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self, |
150 | sp: S, | |
151 | msg: &str, | |
152 | code: &str) | |
153 | -> DiagnosticBuilder<'a> { | |
9cc50fc6 SL |
154 | self.diagnostic().struct_span_fatal_with_code(sp, msg, code) |
155 | } | |
156 | pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> { | |
157 | self.diagnostic().struct_fatal(msg) | |
158 | } | |
159 | ||
7453a54e | 160 | pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
9346a6ac | 161 | panic!(self.diagnostic().span_fatal(sp, msg)) |
1a4d82fc | 162 | } |
7453a54e | 163 | pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) -> ! { |
9346a6ac | 164 | panic!(self.diagnostic().span_fatal_with_code(sp, msg, code)) |
85aaf69f | 165 | } |
1a4d82fc | 166 | pub fn fatal(&self, msg: &str) -> ! { |
9cc50fc6 | 167 | panic!(self.diagnostic().fatal(msg)) |
1a4d82fc | 168 | } |
7453a54e | 169 | pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg: &str) { |
e9174d1e SL |
170 | if is_warning { |
171 | self.span_warn(sp, msg); | |
172 | } else { | |
173 | self.span_err(sp, msg); | |
174 | } | |
175 | } | |
7453a54e | 176 | pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
5bcae85e | 177 | self.diagnostic().span_err(sp, msg) |
1a4d82fc | 178 | } |
7453a54e | 179 | pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
5bcae85e | 180 | self.diagnostic().span_err_with_code(sp, &msg, code) |
1a4d82fc JJ |
181 | } |
182 | pub fn err(&self, msg: &str) { | |
9cc50fc6 | 183 | self.diagnostic().err(msg) |
1a4d82fc | 184 | } |
c34b1796 | 185 | pub fn err_count(&self) -> usize { |
9cc50fc6 | 186 | self.diagnostic().err_count() |
1a4d82fc JJ |
187 | } |
188 | pub fn has_errors(&self) -> bool { | |
9cc50fc6 | 189 | self.diagnostic().has_errors() |
1a4d82fc JJ |
190 | } |
191 | pub fn abort_if_errors(&self) { | |
9cc50fc6 SL |
192 | self.diagnostic().abort_if_errors(); |
193 | } | |
7453a54e SL |
194 | pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize> |
195 | where F: FnOnce() -> T | |
9cc50fc6 | 196 | { |
7453a54e SL |
197 | let old_count = self.err_count(); |
198 | let result = f(); | |
199 | let errors = self.err_count() - old_count; | |
200 | if errors == 0 { | |
201 | Ok(result) | |
202 | } else { | |
203 | Err(errors) | |
d9579d0f | 204 | } |
1a4d82fc | 205 | } |
7453a54e | 206 | pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 207 | self.diagnostic().span_warn(sp, msg) |
1a4d82fc | 208 | } |
7453a54e | 209 | pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) { |
9cc50fc6 | 210 | self.diagnostic().span_warn_with_code(sp, msg, code) |
1a4d82fc JJ |
211 | } |
212 | pub fn warn(&self, msg: &str) { | |
9cc50fc6 | 213 | self.diagnostic().warn(msg) |
1a4d82fc | 214 | } |
7453a54e | 215 | pub fn opt_span_warn<S: Into<MultiSpan>>(&self, opt_sp: Option<S>, msg: &str) { |
1a4d82fc JJ |
216 | match opt_sp { |
217 | Some(sp) => self.span_warn(sp, msg), | |
218 | None => self.warn(msg), | |
219 | } | |
220 | } | |
d9579d0f | 221 | /// Delay a span_bug() call until abort_if_errors() |
7453a54e | 222 | pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 223 | self.diagnostic().delay_span_bug(sp, msg) |
d9579d0f | 224 | } |
9cc50fc6 SL |
225 | pub fn note_without_error(&self, msg: &str) { |
226 | self.diagnostic().note_without_error(msg) | |
227 | } | |
7453a54e | 228 | pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { |
9cc50fc6 | 229 | self.diagnostic().span_note_without_error(sp, msg) |
1a4d82fc | 230 | } |
7453a54e | 231 | pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! { |
1a4d82fc JJ |
232 | self.diagnostic().span_unimpl(sp, msg) |
233 | } | |
234 | pub fn unimpl(&self, msg: &str) -> ! { | |
9cc50fc6 | 235 | self.diagnostic().unimpl(msg) |
1a4d82fc JJ |
236 | } |
237 | pub fn add_lint(&self, | |
238 | lint: &'static lint::Lint, | |
239 | id: ast::NodeId, | |
240 | sp: Span, | |
241 | msg: String) { | |
242 | let lint_id = lint::LintId::of(lint); | |
243 | let mut lints = self.lints.borrow_mut(); | |
3157f602 XL |
244 | if let Some(arr) = lints.get_mut(&id) { |
245 | let tuple = (lint_id, sp, msg); | |
246 | if !arr.contains(&tuple) { | |
247 | arr.push(tuple); | |
54a0048b | 248 | } |
3157f602 | 249 | return; |
1a4d82fc JJ |
250 | } |
251 | lints.insert(id, vec!((lint_id, sp, msg))); | |
252 | } | |
1a4d82fc | 253 | pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId { |
62682a34 SL |
254 | let id = self.next_node_id.get(); |
255 | ||
256 | match id.checked_add(count) { | |
257 | Some(next) => self.next_node_id.set(next), | |
54a0048b | 258 | None => bug!("Input too large, ran out of node ids!") |
62682a34 SL |
259 | } |
260 | ||
261 | id | |
1a4d82fc | 262 | } |
3157f602 XL |
263 | pub fn next_node_id(&self) -> NodeId { |
264 | self.reserve_node_ids(1) | |
265 | } | |
9cc50fc6 | 266 | pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler { |
1a4d82fc JJ |
267 | &self.parse_sess.span_diagnostic |
268 | } | |
269 | pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap { | |
62682a34 | 270 | self.parse_sess.codemap() |
1a4d82fc | 271 | } |
1a4d82fc JJ |
272 | pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } |
273 | pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } | |
274 | pub fn count_llvm_insns(&self) -> bool { | |
275 | self.opts.debugging_opts.count_llvm_insns | |
276 | } | |
1a4d82fc JJ |
277 | pub fn time_llvm_passes(&self) -> bool { |
278 | self.opts.debugging_opts.time_llvm_passes | |
279 | } | |
280 | pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats } | |
281 | pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats } | |
282 | pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments } | |
283 | pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify } | |
284 | pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats } | |
285 | pub fn print_llvm_passes(&self) -> bool { | |
286 | self.opts.debugging_opts.print_llvm_passes | |
287 | } | |
288 | pub fn lto(&self) -> bool { | |
289 | self.opts.cg.lto | |
290 | } | |
291 | pub fn no_landing_pads(&self) -> bool { | |
a7813a04 XL |
292 | self.opts.debugging_opts.no_landing_pads || |
293 | self.opts.cg.panic == PanicStrategy::Abort | |
1a4d82fc JJ |
294 | } |
295 | pub fn unstable_options(&self) -> bool { | |
296 | self.opts.debugging_opts.unstable_options | |
297 | } | |
c1a9b12d SL |
298 | pub fn nonzeroing_move_hints(&self) -> bool { |
299 | self.opts.debugging_opts.enable_nonzeroing_move_hints | |
300 | } | |
3157f602 XL |
301 | |
302 | pub fn must_not_eliminate_frame_pointers(&self) -> bool { | |
303 | self.opts.debuginfo != DebugInfoLevel::NoDebugInfo || | |
304 | !self.target.target.options.eliminate_frame_pointer | |
305 | } | |
306 | ||
307 | /// Returns the symbol name for the registrar function, | |
308 | /// given the crate Svh and the function DefIndex. | |
309 | pub fn generate_plugin_registrar_symbol(&self, svh: &Svh, index: DefIndex) | |
310 | -> String { | |
311 | format!("__rustc_plugin_registrar__{}_{}", svh, index.as_usize()) | |
312 | } | |
313 | ||
1a4d82fc JJ |
314 | pub fn sysroot<'a>(&'a self) -> &'a Path { |
315 | match self.opts.maybe_sysroot { | |
316 | Some (ref sysroot) => sysroot, | |
317 | None => self.default_sysroot.as_ref() | |
318 | .expect("missing sysroot and default_sysroot in Session") | |
319 | } | |
320 | } | |
321 | pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { | |
322 | filesearch::FileSearch::new(self.sysroot(), | |
c34b1796 | 323 | &self.opts.target_triple, |
1a4d82fc JJ |
324 | &self.opts.search_paths, |
325 | kind) | |
326 | } | |
327 | pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch { | |
328 | filesearch::FileSearch::new( | |
329 | self.sysroot(), | |
330 | config::host_triple(), | |
331 | &self.opts.search_paths, | |
332 | kind) | |
333 | } | |
334 | } | |
335 | ||
336 | pub fn build_session(sopts: config::Options, | |
a7813a04 | 337 | dep_graph: &DepGraph, |
c34b1796 | 338 | local_crate_source_file: Option<PathBuf>, |
3157f602 | 339 | registry: errors::registry::Registry, |
92a42be0 | 340 | cstore: Rc<for<'a> CrateStore<'a>>) |
1a4d82fc | 341 | -> Session { |
a7813a04 XL |
342 | build_session_with_codemap(sopts, |
343 | dep_graph, | |
344 | local_crate_source_file, | |
345 | registry, | |
346 | cstore, | |
347 | Rc::new(codemap::CodeMap::new())) | |
348 | } | |
349 | ||
350 | pub fn build_session_with_codemap(sopts: config::Options, | |
351 | dep_graph: &DepGraph, | |
352 | local_crate_source_file: Option<PathBuf>, | |
3157f602 | 353 | registry: errors::registry::Registry, |
a7813a04 XL |
354 | cstore: Rc<for<'a> CrateStore<'a>>, |
355 | codemap: Rc<codemap::CodeMap>) | |
356 | -> Session { | |
85aaf69f SL |
357 | // FIXME: This is not general enough to make the warning lint completely override |
358 | // normal diagnostic warnings, since the warning lint can also be denied and changed | |
359 | // later via the source code. | |
360 | let can_print_warnings = sopts.lint_opts | |
361 | .iter() | |
362 | .filter(|&&(ref key, _)| *key == "warnings") | |
363 | .map(|&(_, ref level)| *level != lint::Allow) | |
364 | .last() | |
365 | .unwrap_or(true); | |
5bcae85e | 366 | let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug; |
9cc50fc6 | 367 | |
9cc50fc6 SL |
368 | let emitter: Box<Emitter> = match sopts.error_format { |
369 | config::ErrorOutputType::HumanReadable(color_config) => { | |
3157f602 | 370 | Box::new(EmitterWriter::stderr(color_config, |
5bcae85e | 371 | Some(codemap.clone()))) |
9cc50fc6 SL |
372 | } |
373 | config::ErrorOutputType::Json => { | |
374 | Box::new(JsonEmitter::stderr(Some(registry), codemap.clone())) | |
375 | } | |
376 | }; | |
85aaf69f | 377 | |
1a4d82fc | 378 | let diagnostic_handler = |
9cc50fc6 SL |
379 | errors::Handler::with_emitter(can_print_warnings, |
380 | treat_err_as_bug, | |
381 | emitter); | |
1a4d82fc | 382 | |
a7813a04 XL |
383 | build_session_(sopts, |
384 | dep_graph, | |
385 | local_crate_source_file, | |
386 | diagnostic_handler, | |
387 | codemap, | |
388 | cstore) | |
1a4d82fc JJ |
389 | } |
390 | ||
391 | pub fn build_session_(sopts: config::Options, | |
a7813a04 | 392 | dep_graph: &DepGraph, |
c34b1796 | 393 | local_crate_source_file: Option<PathBuf>, |
9cc50fc6 SL |
394 | span_diagnostic: errors::Handler, |
395 | codemap: Rc<codemap::CodeMap>, | |
92a42be0 | 396 | cstore: Rc<for<'a> CrateStore<'a>>) |
1a4d82fc | 397 | -> Session { |
85aaf69f SL |
398 | let host = match Target::search(config::host_triple()) { |
399 | Ok(t) => t, | |
400 | Err(e) => { | |
9cc50fc6 | 401 | panic!(span_diagnostic.fatal(&format!("Error loading host specification: {}", e))); |
85aaf69f SL |
402 | } |
403 | }; | |
1a4d82fc | 404 | let target_cfg = config::build_target_config(&sopts, &span_diagnostic); |
9cc50fc6 | 405 | let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap); |
1a4d82fc JJ |
406 | let default_sysroot = match sopts.maybe_sysroot { |
407 | Some(_) => None, | |
408 | None => Some(filesearch::get_or_default_sysroot()) | |
409 | }; | |
410 | ||
411 | // Make the path absolute, if necessary | |
412 | let local_crate_source_file = local_crate_source_file.map(|path| | |
413 | if path.is_absolute() { | |
414 | path.clone() | |
415 | } else { | |
85aaf69f | 416 | env::current_dir().unwrap().join(&path) |
1a4d82fc JJ |
417 | } |
418 | ); | |
419 | ||
1a4d82fc | 420 | let sess = Session { |
a7813a04 | 421 | dep_graph: dep_graph.clone(), |
1a4d82fc | 422 | target: target_cfg, |
85aaf69f | 423 | host: host, |
1a4d82fc | 424 | opts: sopts, |
92a42be0 | 425 | cstore: cstore, |
1a4d82fc JJ |
426 | parse_sess: p_s, |
427 | // For a library crate, this is always none | |
428 | entry_fn: RefCell::new(None), | |
429 | entry_type: Cell::new(None), | |
430 | plugin_registrar_fn: Cell::new(None), | |
431 | default_sysroot: default_sysroot, | |
432 | local_crate_source_file: local_crate_source_file, | |
85aaf69f | 433 | working_dir: env::current_dir().unwrap(), |
1a4d82fc | 434 | lint_store: RefCell::new(lint::LintStore::new()), |
85aaf69f | 435 | lints: RefCell::new(NodeMap()), |
9346a6ac | 436 | plugin_llvm_passes: RefCell::new(Vec::new()), |
54a0048b | 437 | mir_passes: RefCell::new(mir_pass::Passes::new()), |
62682a34 | 438 | plugin_attributes: RefCell::new(Vec::new()), |
1a4d82fc | 439 | crate_types: RefCell::new(Vec::new()), |
e9174d1e | 440 | dependency_formats: RefCell::new(FnvHashMap()), |
5bcae85e | 441 | crate_disambiguator: RefCell::new(token::intern("").as_str()), |
1a4d82fc JJ |
442 | features: RefCell::new(feature_gate::Features::new()), |
443 | recursion_limit: Cell::new(64), | |
e9174d1e SL |
444 | next_node_id: Cell::new(1), |
445 | injected_allocator: Cell::new(None), | |
a7813a04 | 446 | injected_panic_runtime: Cell::new(None), |
92a42be0 | 447 | available_macros: RefCell::new(HashSet::new()), |
7453a54e | 448 | imported_macro_spans: RefCell::new(HashMap::new()), |
1a4d82fc JJ |
449 | }; |
450 | ||
a7813a04 XL |
451 | init_llvm(&sess); |
452 | ||
1a4d82fc JJ |
453 | sess |
454 | } | |
455 | ||
a7813a04 XL |
456 | fn init_llvm(sess: &Session) { |
457 | unsafe { | |
458 | // Before we touch LLVM, make sure that multithreading is enabled. | |
459 | use std::sync::Once; | |
460 | static INIT: Once = Once::new(); | |
461 | static mut POISONED: bool = false; | |
462 | INIT.call_once(|| { | |
463 | if llvm::LLVMStartMultithreaded() != 1 { | |
464 | // use an extra bool to make sure that all future usage of LLVM | |
465 | // cannot proceed despite the Once not running more than once. | |
466 | POISONED = true; | |
467 | } | |
468 | ||
469 | configure_llvm(sess); | |
470 | }); | |
471 | ||
472 | if POISONED { | |
473 | bug!("couldn't enable multi-threaded LLVM"); | |
474 | } | |
475 | } | |
476 | } | |
477 | ||
478 | unsafe fn configure_llvm(sess: &Session) { | |
479 | let mut llvm_c_strs = Vec::new(); | |
480 | let mut llvm_args = Vec::new(); | |
481 | ||
482 | { | |
483 | let mut add = |arg: &str| { | |
484 | let s = CString::new(arg).unwrap(); | |
485 | llvm_args.push(s.as_ptr()); | |
486 | llvm_c_strs.push(s); | |
487 | }; | |
488 | add("rustc"); // fake program name | |
489 | if sess.time_llvm_passes() { add("-time-passes"); } | |
490 | if sess.print_llvm_passes() { add("-debug-pass=Structure"); } | |
491 | ||
492 | for arg in &sess.opts.cg.llvm_args { | |
493 | add(&(*arg)); | |
494 | } | |
495 | } | |
496 | ||
497 | llvm::LLVMInitializePasses(); | |
498 | ||
499 | llvm::initialize_available_targets(); | |
500 | ||
501 | llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, | |
502 | llvm_args.as_ptr()); | |
503 | } | |
504 | ||
9cc50fc6 | 505 | pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { |
5bcae85e | 506 | let emitter: Box<Emitter> = match output { |
9cc50fc6 | 507 | config::ErrorOutputType::HumanReadable(color_config) => { |
5bcae85e SL |
508 | Box::new(EmitterWriter::stderr(color_config, |
509 | None)) | |
9cc50fc6 SL |
510 | } |
511 | config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), | |
512 | }; | |
5bcae85e SL |
513 | let handler = errors::Handler::with_emitter(true, false, emitter); |
514 | handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal); | |
9cc50fc6 | 515 | panic!(errors::FatalError); |
1a4d82fc JJ |
516 | } |
517 | ||
9cc50fc6 | 518 | pub fn early_warn(output: config::ErrorOutputType, msg: &str) { |
5bcae85e | 519 | let emitter: Box<Emitter> = match output { |
9cc50fc6 | 520 | config::ErrorOutputType::HumanReadable(color_config) => { |
5bcae85e SL |
521 | Box::new(EmitterWriter::stderr(color_config, |
522 | None)) | |
9cc50fc6 SL |
523 | } |
524 | config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()), | |
525 | }; | |
5bcae85e SL |
526 | let handler = errors::Handler::with_emitter(true, false, emitter); |
527 | handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); | |
1a4d82fc | 528 | } |
7453a54e SL |
529 | |
530 | // Err(0) means compilation was stopped, but no errors were found. | |
531 | // This would be better as a dedicated enum, but using try! is so convenient. | |
532 | pub type CompileResult = Result<(), usize>; | |
533 | ||
534 | pub fn compile_result_from_err_count(err_count: usize) -> CompileResult { | |
535 | if err_count == 0 { | |
536 | Ok(()) | |
537 | } else { | |
538 | Err(err_count) | |
539 | } | |
540 | } | |
54a0048b SL |
541 | |
542 | #[cold] | |
543 | #[inline(never)] | |
544 | pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! { | |
545 | // this wrapper mostly exists so I don't have to write a fully | |
546 | // qualified path of None::<Span> inside the bug!() macro defintion | |
547 | opt_span_bug_fmt(file, line, None::<Span>, args); | |
548 | } | |
549 | ||
550 | #[cold] | |
551 | #[inline(never)] | |
552 | pub fn span_bug_fmt<S: Into<MultiSpan>>(file: &'static str, | |
553 | line: u32, | |
554 | span: S, | |
555 | args: fmt::Arguments) -> ! { | |
556 | opt_span_bug_fmt(file, line, Some(span), args); | |
557 | } | |
558 | ||
559 | fn opt_span_bug_fmt<S: Into<MultiSpan>>(file: &'static str, | |
a7813a04 XL |
560 | line: u32, |
561 | span: Option<S>, | |
562 | args: fmt::Arguments) -> ! { | |
54a0048b SL |
563 | tls::with_opt(move |tcx| { |
564 | let msg = format!("{}:{}: {}", file, line, args); | |
565 | match (tcx, span) { | |
566 | (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg), | |
567 | (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), | |
568 | (None, _) => panic!(msg) | |
569 | } | |
570 | }); | |
571 | unreachable!(); | |
572 | } |