]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 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 | ||
11 | use llvm; | |
32a655c1 | 12 | use llvm::{ContextRef, ModuleRef, ValueRef}; |
8bb4bdeb XL |
13 | use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap, |
14 | DepTrackingMapConfig, WorkProduct}; | |
92a42be0 | 15 | use middle::cstore::LinkMeta; |
32a655c1 | 16 | use rustc::hir; |
54a0048b SL |
17 | use rustc::hir::def::ExportMap; |
18 | use rustc::hir::def_id::DefId; | |
19 | use rustc::traits; | |
54a0048b | 20 | use debuginfo; |
32a655c1 SL |
21 | use callee::Callee; |
22 | use base; | |
54a0048b SL |
23 | use declare; |
24 | use glue::DropGlueKind; | |
54a0048b SL |
25 | use monomorphize::Instance; |
26 | ||
a7813a04 | 27 | use partitioning::CodegenUnit; |
a7813a04 | 28 | use trans_item::TransItem; |
476ff2be SL |
29 | use type_::Type; |
30 | use rustc_data_structures::base_n; | |
9e0c209e | 31 | use rustc::ty::subst::Substs; |
54a0048b | 32 | use rustc::ty::{self, Ty, TyCtxt}; |
1a4d82fc JJ |
33 | use session::config::NoDebugInfo; |
34 | use session::Session; | |
5bcae85e SL |
35 | use session::config; |
36 | use symbol_map::SymbolMap; | |
476ff2be | 37 | use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet}; |
1a4d82fc | 38 | |
54a0048b | 39 | use std::ffi::{CStr, CString}; |
1a4d82fc | 40 | use std::cell::{Cell, RefCell}; |
7453a54e | 41 | use std::marker::PhantomData; |
1a4d82fc | 42 | use std::ptr; |
32a655c1 | 43 | use std::iter; |
1a4d82fc | 44 | use std::rc::Rc; |
54a0048b | 45 | use std::str; |
1a4d82fc | 46 | use syntax::ast; |
476ff2be | 47 | use syntax::symbol::InternedString; |
32a655c1 SL |
48 | use syntax_pos::DUMMY_SP; |
49 | use abi::{Abi, FnType}; | |
1a4d82fc JJ |
50 | |
51 | pub struct Stats { | |
c34b1796 AL |
52 | pub n_glues_created: Cell<usize>, |
53 | pub n_null_glues: Cell<usize>, | |
54 | pub n_real_glues: Cell<usize>, | |
55 | pub n_fns: Cell<usize>, | |
c34b1796 AL |
56 | pub n_inlines: Cell<usize>, |
57 | pub n_closures: Cell<usize>, | |
58 | pub n_llvm_insns: Cell<usize>, | |
476ff2be | 59 | pub llvm_insns: RefCell<FxHashMap<String, usize>>, |
1a4d82fc | 60 | // (ident, llvm-instructions) |
c34b1796 | 61 | pub fn_stats: RefCell<Vec<(String, usize)> >, |
1a4d82fc JJ |
62 | } |
63 | ||
64 | /// The shared portion of a `CrateContext`. There is one `SharedCrateContext` | |
65 | /// per crate. The data here is shared between all compilation units of the | |
66 | /// crate, so it must not contain references to any LLVM data structures | |
67 | /// (aside from metadata-related ones). | |
62682a34 | 68 | pub struct SharedCrateContext<'a, 'tcx: 'a> { |
1a4d82fc JJ |
69 | metadata_llmod: ModuleRef, |
70 | metadata_llcx: ContextRef, | |
71 | ||
72 | export_map: ExportMap, | |
476ff2be | 73 | exported_symbols: NodeSet, |
1a4d82fc | 74 | link_meta: LinkMeta, |
a7813a04 | 75 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
32a655c1 | 76 | empty_param_env: ty::ParameterEnvironment<'tcx>, |
1a4d82fc | 77 | stats: Stats, |
c34b1796 | 78 | check_overflow: bool, |
1a4d82fc | 79 | |
62682a34 | 80 | use_dll_storage_attrs: bool, |
7453a54e | 81 | |
476ff2be | 82 | translation_items: RefCell<FxHashSet<TransItem<'tcx>>>, |
a7813a04 | 83 | trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>, |
9e0c209e | 84 | project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>, |
1a4d82fc JJ |
85 | } |
86 | ||
87 | /// The local portion of a `CrateContext`. There is one `LocalCrateContext` | |
88 | /// per compilation unit. Each one has its own LLVM `ContextRef` so that | |
89 | /// several compilation units may be optimized in parallel. All other LLVM | |
90 | /// data structures in the `LocalCrateContext` are tied to that `ContextRef`. | |
91 | pub struct LocalCrateContext<'tcx> { | |
92 | llmod: ModuleRef, | |
93 | llcx: ContextRef, | |
5bcae85e | 94 | previous_work_product: Option<WorkProduct>, |
a7813a04 | 95 | codegen_unit: CodegenUnit<'tcx>, |
476ff2be SL |
96 | needs_unwind_cleanup_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>, |
97 | fn_pointer_shims: RefCell<FxHashMap<Ty<'tcx>, ValueRef>>, | |
98 | drop_glues: RefCell<FxHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>, | |
54a0048b | 99 | /// Cache instances of monomorphic and polymorphic items |
476ff2be | 100 | instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>, |
1a4d82fc | 101 | /// Cache generated vtables |
476ff2be SL |
102 | vtables: RefCell<FxHashMap<(ty::Ty<'tcx>, |
103 | Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>, | |
1a4d82fc | 104 | /// Cache of constant strings, |
476ff2be | 105 | const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>, |
1a4d82fc JJ |
106 | |
107 | /// Reverse-direction for const ptrs cast from globals. | |
85aaf69f | 108 | /// Key is a ValueRef holding a *T, |
1a4d82fc JJ |
109 | /// Val is a ValueRef holding a *[T]. |
110 | /// | |
111 | /// Needed because LLVM loses pointer->pointee association | |
112 | /// when we ptrcast, and we have to ptrcast during translation | |
85aaf69f SL |
113 | /// of a [T] const because we form a slice, a (*T,usize) pair, not |
114 | /// a pointer to an LLVM array type. Similar for trait objects. | |
476ff2be | 115 | const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>, |
85aaf69f SL |
116 | |
117 | /// Cache of emitted const globals (value -> global) | |
476ff2be | 118 | const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>, |
1a4d82fc JJ |
119 | |
120 | /// Cache of emitted const values | |
476ff2be | 121 | const_values: RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>), ValueRef>>, |
1a4d82fc | 122 | |
1a4d82fc JJ |
123 | /// Cache of external const values |
124 | extern_const_values: RefCell<DefIdMap<ValueRef>>, | |
125 | ||
a7813a04 | 126 | /// Mapping from static definitions to their DefId's. |
476ff2be | 127 | statics: RefCell<FxHashMap<ValueRef, DefId>>, |
a7813a04 | 128 | |
476ff2be | 129 | impl_method_cache: RefCell<FxHashMap<(DefId, ast::Name), DefId>>, |
1a4d82fc JJ |
130 | |
131 | /// Cache of closure wrappers for bare fn's. | |
476ff2be | 132 | closure_bare_wrapper_cache: RefCell<FxHashMap<ValueRef, ValueRef>>, |
1a4d82fc | 133 | |
c1a9b12d SL |
134 | /// List of globals for static variables which need to be passed to the |
135 | /// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete. | |
136 | /// (We have to make sure we don't invalidate any ValueRefs referring | |
137 | /// to constants.) | |
138 | statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>, | |
139 | ||
476ff2be SL |
140 | lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>, |
141 | llsizingtypes: RefCell<FxHashMap<Ty<'tcx>, Type>>, | |
142 | type_hashcodes: RefCell<FxHashMap<Ty<'tcx>, String>>, | |
1a4d82fc JJ |
143 | int_type: Type, |
144 | opaque_vec_type: Type, | |
476ff2be | 145 | str_slice_type: Type, |
1a4d82fc JJ |
146 | |
147 | /// Holds the LLVM values for closure IDs. | |
476ff2be | 148 | closure_vals: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>, |
1a4d82fc JJ |
149 | |
150 | dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>, | |
151 | ||
54a0048b SL |
152 | eh_personality: Cell<Option<ValueRef>>, |
153 | eh_unwind_resume: Cell<Option<ValueRef>>, | |
154 | rust_try_fn: Cell<Option<ValueRef>>, | |
1a4d82fc | 155 | |
476ff2be | 156 | intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>, |
1a4d82fc | 157 | |
92a42be0 SL |
158 | /// Depth of the current type-of computation - used to bail out |
159 | type_of_depth: Cell<usize>, | |
5bcae85e SL |
160 | |
161 | symbol_map: Rc<SymbolMap<'tcx>>, | |
c30ab7b3 SL |
162 | |
163 | /// A counter that is used for generating local symbol names | |
164 | local_gen_sym_counter: Cell<usize>, | |
7453a54e SL |
165 | } |
166 | ||
167 | // Implement DepTrackingMapConfig for `trait_cache` | |
168 | pub struct TraitSelectionCache<'tcx> { | |
169 | data: PhantomData<&'tcx ()> | |
170 | } | |
171 | ||
172 | impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { | |
173 | type Key = ty::PolyTraitRef<'tcx>; | |
174 | type Value = traits::Vtable<'tcx, ()>; | |
54a0048b | 175 | fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> { |
a7813a04 XL |
176 | key.to_poly_trait_predicate().dep_node() |
177 | } | |
178 | } | |
179 | ||
9e0c209e SL |
180 | // # Global Cache |
181 | ||
182 | pub struct ProjectionCache<'gcx> { | |
183 | data: PhantomData<&'gcx ()> | |
184 | } | |
185 | ||
186 | impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { | |
187 | type Key = Ty<'gcx>; | |
188 | type Value = Ty<'gcx>; | |
189 | fn to_dep_node(key: &Self::Key) -> DepNode<DefId> { | |
190 | // Ideally, we'd just put `key` into the dep-node, but we | |
191 | // can't put full types in there. So just collect up all the | |
192 | // def-ids of structs/enums as well as any traits that we | |
193 | // project out of. It doesn't matter so much what we do here, | |
194 | // except that if we are too coarse, we'll create overly | |
195 | // coarse edges between impls and the trans. For example, if | |
196 | // we just used the def-id of things we are projecting out of, | |
197 | // then the key for `<Foo as SomeTrait>::T` and `<Bar as | |
198 | // SomeTrait>::T` would both share a dep-node | |
199 | // (`TraitSelect(SomeTrait)`), and hence the impls for both | |
200 | // `Foo` and `Bar` would be considered inputs. So a change to | |
201 | // `Bar` would affect things that just normalized `Foo`. | |
202 | // Anyway, this heuristic is not ideal, but better than | |
203 | // nothing. | |
204 | let def_ids: Vec<DefId> = | |
205 | key.walk() | |
206 | .filter_map(|t| match t.sty { | |
207 | ty::TyAdt(adt_def, _) => Some(adt_def.did), | |
208 | ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), | |
209 | _ => None, | |
210 | }) | |
211 | .collect(); | |
8bb4bdeb XL |
212 | |
213 | DepNode::ProjectionCache { def_ids: def_ids } | |
9e0c209e SL |
214 | } |
215 | } | |
216 | ||
a7813a04 XL |
217 | /// This list owns a number of LocalCrateContexts and binds them to their common |
218 | /// SharedCrateContext. This type just exists as a convenience, something to | |
219 | /// pass around all LocalCrateContexts with and get an iterator over them. | |
220 | pub struct CrateContextList<'a, 'tcx: 'a> { | |
221 | shared: &'a SharedCrateContext<'a, 'tcx>, | |
222 | local_ccxs: Vec<LocalCrateContext<'tcx>>, | |
223 | } | |
224 | ||
225 | impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> { | |
a7813a04 | 226 | pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>, |
5bcae85e SL |
227 | codegen_units: Vec<CodegenUnit<'tcx>>, |
228 | previous_work_products: Vec<Option<WorkProduct>>, | |
229 | symbol_map: Rc<SymbolMap<'tcx>>) | |
a7813a04 XL |
230 | -> CrateContextList<'a, 'tcx> { |
231 | CrateContextList { | |
232 | shared: shared_ccx, | |
5bcae85e SL |
233 | local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| { |
234 | LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone()) | |
a7813a04 XL |
235 | }).collect() |
236 | } | |
237 | } | |
238 | ||
5bcae85e SL |
239 | /// Iterate over all crate contexts, whether or not they need |
240 | /// translation. That is, whether or not a `.o` file is available | |
241 | /// for re-use from a previous incr. comp.). | |
242 | pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> { | |
a7813a04 XL |
243 | CrateContextIterator { |
244 | shared: self.shared, | |
245 | index: 0, | |
5bcae85e SL |
246 | local_ccxs: &self.local_ccxs[..], |
247 | filter_to_previous_work_product_unavail: false, | |
a7813a04 XL |
248 | } |
249 | } | |
250 | ||
5bcae85e SL |
251 | /// Iterator over all CCX that need translation (cannot reuse results from |
252 | /// previous incr. comp.). | |
253 | pub fn iter_need_trans<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> { | |
254 | CrateContextIterator { | |
a7813a04 | 255 | shared: self.shared, |
5bcae85e | 256 | index: 0, |
a7813a04 | 257 | local_ccxs: &self.local_ccxs[..], |
5bcae85e | 258 | filter_to_previous_work_product_unavail: true, |
a7813a04 XL |
259 | } |
260 | } | |
261 | ||
262 | pub fn shared(&self) -> &'a SharedCrateContext<'a, 'tcx> { | |
263 | self.shared | |
7453a54e | 264 | } |
1a4d82fc JJ |
265 | } |
266 | ||
a7813a04 XL |
267 | /// A CrateContext value binds together one LocalCrateContext with the |
268 | /// SharedCrateContext. It exists as a convenience wrapper, so we don't have to | |
269 | /// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans. | |
1a4d82fc | 270 | pub struct CrateContext<'a, 'tcx: 'a> { |
62682a34 | 271 | shared: &'a SharedCrateContext<'a, 'tcx>, |
a7813a04 XL |
272 | local_ccxs: &'a [LocalCrateContext<'tcx>], |
273 | /// The index of `local` in `local_ccxs`. This is used in | |
1a4d82fc | 274 | /// `maybe_iter(true)` to identify the original `LocalCrateContext`. |
c34b1796 | 275 | index: usize, |
1a4d82fc JJ |
276 | } |
277 | ||
8bb4bdeb XL |
278 | impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> { |
279 | } | |
280 | ||
1a4d82fc | 281 | pub struct CrateContextIterator<'a, 'tcx: 'a> { |
62682a34 | 282 | shared: &'a SharedCrateContext<'a, 'tcx>, |
a7813a04 | 283 | local_ccxs: &'a [LocalCrateContext<'tcx>], |
c34b1796 | 284 | index: usize, |
5bcae85e SL |
285 | |
286 | /// if true, only return results where `previous_work_product` is none | |
287 | filter_to_previous_work_product_unavail: bool, | |
1a4d82fc JJ |
288 | } |
289 | ||
290 | impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { | |
291 | type Item = CrateContext<'a, 'tcx>; | |
292 | ||
293 | fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> { | |
5bcae85e SL |
294 | loop { |
295 | if self.index >= self.local_ccxs.len() { | |
296 | return None; | |
297 | } | |
1a4d82fc | 298 | |
5bcae85e SL |
299 | let index = self.index; |
300 | self.index += 1; | |
1a4d82fc | 301 | |
5bcae85e SL |
302 | let ccx = CrateContext { |
303 | shared: self.shared, | |
304 | index: index, | |
305 | local_ccxs: self.local_ccxs, | |
306 | }; | |
307 | ||
308 | if | |
309 | self.filter_to_previous_work_product_unavail && | |
310 | ccx.previous_work_product().is_some() | |
311 | { | |
312 | continue; | |
313 | } | |
314 | ||
315 | return Some(ccx); | |
316 | } | |
1a4d82fc JJ |
317 | } |
318 | } | |
319 | ||
5bcae85e SL |
320 | pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode { |
321 | let reloc_model_arg = match sess.opts.cg.relocation_model { | |
322 | Some(ref s) => &s[..], | |
323 | None => &sess.target.target.options.relocation_model[..], | |
324 | }; | |
325 | ||
326 | match ::back::write::RELOC_MODEL_ARGS.iter().find( | |
327 | |&&arg| arg.0 == reloc_model_arg) { | |
328 | Some(x) => x.1, | |
329 | _ => { | |
330 | sess.err(&format!("{:?} is not a valid relocation mode", | |
331 | sess.opts | |
332 | .cg | |
333 | .code_model)); | |
334 | sess.abort_if_errors(); | |
335 | bug!(); | |
336 | } | |
337 | } | |
338 | } | |
339 | ||
340 | fn is_any_library(sess: &Session) -> bool { | |
341 | sess.crate_types.borrow().iter().any(|ty| { | |
342 | *ty != config::CrateTypeExecutable | |
343 | }) | |
344 | } | |
345 | ||
346 | pub fn is_pie_binary(sess: &Session) -> bool { | |
347 | !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC | |
348 | } | |
349 | ||
1a4d82fc JJ |
350 | unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { |
351 | let llcx = llvm::LLVMContextCreate(); | |
85aaf69f | 352 | let mod_name = CString::new(mod_name).unwrap(); |
1a4d82fc JJ |
353 | let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); |
354 | ||
54a0048b SL |
355 | // Ensure the data-layout values hardcoded remain the defaults. |
356 | if sess.target.target.options.is_builtin { | |
c1a9b12d SL |
357 | let tm = ::back::write::create_target_machine(sess); |
358 | llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm); | |
359 | llvm::LLVMRustDisposeTargetMachine(tm); | |
54a0048b SL |
360 | |
361 | let data_layout = llvm::LLVMGetDataLayout(llmod); | |
362 | let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes()) | |
363 | .ok().expect("got a non-UTF8 data-layout from LLVM"); | |
364 | ||
5bcae85e SL |
365 | // Unfortunately LLVM target specs change over time, and right now we |
366 | // don't have proper support to work with any more than one | |
367 | // `data_layout` than the one that is in the rust-lang/rust repo. If | |
368 | // this compiler is configured against a custom LLVM, we may have a | |
369 | // differing data layout, even though we should update our own to use | |
370 | // that one. | |
371 | // | |
372 | // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we | |
373 | // disable this check entirely as we may be configured with something | |
374 | // that has a different target layout. | |
375 | // | |
376 | // Unsure if this will actually cause breakage when rustc is configured | |
377 | // as such. | |
378 | // | |
379 | // FIXME(#34960) | |
380 | let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or(""); | |
381 | let custom_llvm_used = cfg_llvm_root.trim() != ""; | |
382 | ||
383 | if !custom_llvm_used && sess.target.target.data_layout != data_layout { | |
54a0048b SL |
384 | bug!("data-layout for builtin `{}` target, `{}`, \ |
385 | differs from LLVM default, `{}`", | |
386 | sess.target.target.llvm_target, | |
387 | sess.target.target.data_layout, | |
388 | data_layout); | |
389 | } | |
c1a9b12d | 390 | } |
1a4d82fc | 391 | |
54a0048b SL |
392 | let data_layout = CString::new(&sess.target.target.data_layout[..]).unwrap(); |
393 | llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); | |
394 | ||
85aaf69f SL |
395 | let llvm_target = sess.target.target.llvm_target.as_bytes(); |
396 | let llvm_target = CString::new(llvm_target).unwrap(); | |
1a4d82fc | 397 | llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); |
5bcae85e SL |
398 | |
399 | if is_pie_binary(sess) { | |
400 | llvm::LLVMRustSetModulePIELevel(llmod); | |
401 | } | |
402 | ||
1a4d82fc JJ |
403 | (llcx, llmod) |
404 | } | |
405 | ||
62682a34 | 406 | impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { |
a7813a04 | 407 | pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>, |
1a4d82fc | 408 | export_map: ExportMap, |
1a4d82fc | 409 | link_meta: LinkMeta, |
476ff2be | 410 | exported_symbols: NodeSet, |
9e0c209e | 411 | check_overflow: bool) |
62682a34 | 412 | -> SharedCrateContext<'b, 'tcx> { |
1a4d82fc JJ |
413 | let (metadata_llcx, metadata_llmod) = unsafe { |
414 | create_context_and_module(&tcx.sess, "metadata") | |
415 | }; | |
416 | ||
62682a34 SL |
417 | // An interesting part of Windows which MSVC forces our hand on (and |
418 | // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` | |
419 | // attributes in LLVM IR as well as native dependencies (in C these | |
420 | // correspond to `__declspec(dllimport)`). | |
421 | // | |
422 | // Whenever a dynamic library is built by MSVC it must have its public | |
423 | // interface specified by functions tagged with `dllexport` or otherwise | |
424 | // they're not available to be linked against. This poses a few problems | |
425 | // for the compiler, some of which are somewhat fundamental, but we use | |
426 | // the `use_dll_storage_attrs` variable below to attach the `dllexport` | |
476ff2be | 427 | // attribute to all LLVM functions that are exported e.g. they're |
62682a34 SL |
428 | // already tagged with external linkage). This is suboptimal for a few |
429 | // reasons: | |
430 | // | |
431 | // * If an object file will never be included in a dynamic library, | |
432 | // there's no need to attach the dllexport attribute. Most object | |
433 | // files in Rust are not destined to become part of a dll as binaries | |
434 | // are statically linked by default. | |
435 | // * If the compiler is emitting both an rlib and a dylib, the same | |
436 | // source object file is currently used but with MSVC this may be less | |
437 | // feasible. The compiler may be able to get around this, but it may | |
438 | // involve some invasive changes to deal with this. | |
439 | // | |
440 | // The flipside of this situation is that whenever you link to a dll and | |
441 | // you import a function from it, the import should be tagged with | |
442 | // `dllimport`. At this time, however, the compiler does not emit | |
443 | // `dllimport` for any declarations other than constants (where it is | |
444 | // required), which is again suboptimal for even more reasons! | |
445 | // | |
446 | // * Calling a function imported from another dll without using | |
447 | // `dllimport` causes the linker/compiler to have extra overhead (one | |
448 | // `jmp` instruction on x86) when calling the function. | |
449 | // * The same object file may be used in different circumstances, so a | |
450 | // function may be imported from a dll if the object is linked into a | |
451 | // dll, but it may be just linked against if linked into an rlib. | |
452 | // * The compiler has no knowledge about whether native functions should | |
453 | // be tagged dllimport or not. | |
454 | // | |
455 | // For now the compiler takes the perf hit (I do not have any numbers to | |
456 | // this effect) by marking very little as `dllimport` and praying the | |
457 | // linker will take care of everything. Fixing this problem will likely | |
458 | // require adding a few attributes to Rust itself (feature gated at the | |
459 | // start) and then strongly recommending static linkage on MSVC! | |
460 | let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc; | |
461 | ||
a7813a04 | 462 | SharedCrateContext { |
1a4d82fc JJ |
463 | metadata_llmod: metadata_llmod, |
464 | metadata_llcx: metadata_llcx, | |
465 | export_map: export_map, | |
476ff2be | 466 | exported_symbols: exported_symbols, |
1a4d82fc | 467 | link_meta: link_meta, |
32a655c1 | 468 | empty_param_env: tcx.empty_parameter_environment(), |
1a4d82fc JJ |
469 | tcx: tcx, |
470 | stats: Stats { | |
85aaf69f SL |
471 | n_glues_created: Cell::new(0), |
472 | n_null_glues: Cell::new(0), | |
473 | n_real_glues: Cell::new(0), | |
474 | n_fns: Cell::new(0), | |
85aaf69f SL |
475 | n_inlines: Cell::new(0), |
476 | n_closures: Cell::new(0), | |
477 | n_llvm_insns: Cell::new(0), | |
476ff2be | 478 | llvm_insns: RefCell::new(FxHashMap()), |
1a4d82fc JJ |
479 | fn_stats: RefCell::new(Vec::new()), |
480 | }, | |
c34b1796 | 481 | check_overflow: check_overflow, |
62682a34 | 482 | use_dll_storage_attrs: use_dll_storage_attrs, |
476ff2be | 483 | translation_items: RefCell::new(FxHashSet()), |
a7813a04 | 484 | trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), |
9e0c209e | 485 | project_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())), |
1a4d82fc JJ |
486 | } |
487 | } | |
488 | ||
32a655c1 SL |
489 | pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { |
490 | self.tcx.type_needs_drop_given_env(ty, &self.empty_param_env) | |
491 | } | |
492 | ||
493 | pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { | |
494 | ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP) | |
495 | } | |
496 | ||
1a4d82fc JJ |
497 | pub fn metadata_llmod(&self) -> ModuleRef { |
498 | self.metadata_llmod | |
499 | } | |
500 | ||
501 | pub fn metadata_llcx(&self) -> ContextRef { | |
502 | self.metadata_llcx | |
503 | } | |
504 | ||
505 | pub fn export_map<'a>(&'a self) -> &'a ExportMap { | |
506 | &self.export_map | |
507 | } | |
508 | ||
476ff2be SL |
509 | pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { |
510 | &self.exported_symbols | |
1a4d82fc JJ |
511 | } |
512 | ||
a7813a04 XL |
513 | pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>> { |
514 | &self.trait_cache | |
515 | } | |
516 | ||
9e0c209e SL |
517 | pub fn project_cache(&self) -> &RefCell<DepTrackingMap<ProjectionCache<'tcx>>> { |
518 | &self.project_cache | |
519 | } | |
520 | ||
1a4d82fc JJ |
521 | pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { |
522 | &self.link_meta | |
523 | } | |
524 | ||
a7813a04 | 525 | pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { |
1a4d82fc JJ |
526 | self.tcx |
527 | } | |
528 | ||
529 | pub fn sess<'a>(&'a self) -> &'a Session { | |
530 | &self.tcx.sess | |
531 | } | |
532 | ||
476ff2be SL |
533 | pub fn dep_graph<'a>(&'a self) -> &'a DepGraph { |
534 | &self.tcx.dep_graph | |
535 | } | |
536 | ||
1a4d82fc JJ |
537 | pub fn stats<'a>(&'a self) -> &'a Stats { |
538 | &self.stats | |
539 | } | |
62682a34 SL |
540 | |
541 | pub fn use_dll_storage_attrs(&self) -> bool { | |
542 | self.use_dll_storage_attrs | |
543 | } | |
a7813a04 | 544 | |
476ff2be | 545 | pub fn translation_items(&self) -> &RefCell<FxHashSet<TransItem<'tcx>>> { |
a7813a04 XL |
546 | &self.translation_items |
547 | } | |
548 | ||
549 | /// Given the def-id of some item that has no type parameters, make | |
550 | /// a suitable "empty substs" for it. | |
551 | pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { | |
9e0c209e SL |
552 | Substs::for_item(self.tcx(), item_def_id, |
553 | |_, _| self.tcx().mk_region(ty::ReErased), | |
554 | |_, _| { | |
555 | bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) | |
556 | }) | |
3157f602 XL |
557 | } |
558 | ||
a7813a04 XL |
559 | pub fn metadata_symbol_name(&self) -> String { |
560 | format!("rust_metadata_{}_{}", | |
561 | self.link_meta().crate_name, | |
562 | self.link_meta().crate_hash) | |
563 | } | |
1a4d82fc JJ |
564 | } |
565 | ||
566 | impl<'tcx> LocalCrateContext<'tcx> { | |
62682a34 | 567 | fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>, |
5bcae85e SL |
568 | codegen_unit: CodegenUnit<'tcx>, |
569 | previous_work_product: Option<WorkProduct>, | |
570 | symbol_map: Rc<SymbolMap<'tcx>>) | |
1a4d82fc JJ |
571 | -> LocalCrateContext<'tcx> { |
572 | unsafe { | |
a7813a04 XL |
573 | // Append ".rs" to LLVM module identifier. |
574 | // | |
575 | // LLVM code generator emits a ".file filename" directive | |
576 | // for ELF backends. Value of the "filename" is set as the | |
577 | // LLVM module identifier. Due to a LLVM MC bug[1], LLVM | |
578 | // crashes if the module identifier is same as other symbols | |
579 | // such as a function name in the module. | |
580 | // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 | |
5bcae85e | 581 | let llmod_id = format!("{}.rs", codegen_unit.name()); |
a7813a04 XL |
582 | |
583 | let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, | |
584 | &llmod_id[..]); | |
1a4d82fc | 585 | |
1a4d82fc | 586 | let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo { |
5bcae85e SL |
587 | let dctx = debuginfo::CrateDebugContext::new(llmod); |
588 | debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess); | |
589 | Some(dctx) | |
1a4d82fc JJ |
590 | } else { |
591 | None | |
592 | }; | |
593 | ||
a7813a04 | 594 | let local_ccx = LocalCrateContext { |
1a4d82fc JJ |
595 | llmod: llmod, |
596 | llcx: llcx, | |
5bcae85e | 597 | previous_work_product: previous_work_product, |
a7813a04 | 598 | codegen_unit: codegen_unit, |
476ff2be SL |
599 | needs_unwind_cleanup_cache: RefCell::new(FxHashMap()), |
600 | fn_pointer_shims: RefCell::new(FxHashMap()), | |
601 | drop_glues: RefCell::new(FxHashMap()), | |
602 | instances: RefCell::new(FxHashMap()), | |
603 | vtables: RefCell::new(FxHashMap()), | |
604 | const_cstr_cache: RefCell::new(FxHashMap()), | |
605 | const_unsized: RefCell::new(FxHashMap()), | |
606 | const_globals: RefCell::new(FxHashMap()), | |
607 | const_values: RefCell::new(FxHashMap()), | |
85aaf69f | 608 | extern_const_values: RefCell::new(DefIdMap()), |
476ff2be SL |
609 | statics: RefCell::new(FxHashMap()), |
610 | impl_method_cache: RefCell::new(FxHashMap()), | |
611 | closure_bare_wrapper_cache: RefCell::new(FxHashMap()), | |
c1a9b12d | 612 | statics_to_rauw: RefCell::new(Vec::new()), |
476ff2be SL |
613 | lltypes: RefCell::new(FxHashMap()), |
614 | llsizingtypes: RefCell::new(FxHashMap()), | |
615 | type_hashcodes: RefCell::new(FxHashMap()), | |
1a4d82fc JJ |
616 | int_type: Type::from_ref(ptr::null_mut()), |
617 | opaque_vec_type: Type::from_ref(ptr::null_mut()), | |
476ff2be | 618 | str_slice_type: Type::from_ref(ptr::null_mut()), |
476ff2be | 619 | closure_vals: RefCell::new(FxHashMap()), |
1a4d82fc | 620 | dbg_cx: dbg_cx, |
54a0048b SL |
621 | eh_personality: Cell::new(None), |
622 | eh_unwind_resume: Cell::new(None), | |
623 | rust_try_fn: Cell::new(None), | |
476ff2be | 624 | intrinsics: RefCell::new(FxHashMap()), |
92a42be0 | 625 | type_of_depth: Cell::new(0), |
5bcae85e | 626 | symbol_map: symbol_map, |
c30ab7b3 | 627 | local_gen_sym_counter: Cell::new(0), |
1a4d82fc JJ |
628 | }; |
629 | ||
a7813a04 XL |
630 | let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = { |
631 | // Do a little dance to create a dummy CrateContext, so we can | |
632 | // create some things in the LLVM module of this codegen unit | |
633 | let mut local_ccxs = vec![local_ccx]; | |
634 | let (int_type, opaque_vec_type, str_slice_ty) = { | |
635 | let dummy_ccx = LocalCrateContext::dummy_ccx(shared, | |
636 | local_ccxs.as_mut_slice()); | |
637 | let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice"); | |
638 | str_slice_ty.set_struct_body(&[Type::i8p(&dummy_ccx), | |
639 | Type::int(&dummy_ccx)], | |
640 | false); | |
641 | (Type::int(&dummy_ccx), Type::opaque_vec(&dummy_ccx), str_slice_ty) | |
642 | }; | |
643 | (int_type, opaque_vec_type, str_slice_ty, local_ccxs.pop().unwrap()) | |
644 | }; | |
1a4d82fc | 645 | |
a7813a04 XL |
646 | local_ccx.int_type = int_type; |
647 | local_ccx.opaque_vec_type = opaque_vec_type; | |
476ff2be | 648 | local_ccx.str_slice_type = str_slice_ty; |
1a4d82fc | 649 | |
1a4d82fc JJ |
650 | local_ccx |
651 | } | |
652 | } | |
653 | ||
654 | /// Create a dummy `CrateContext` from `self` and the provided | |
655 | /// `SharedCrateContext`. This is somewhat dangerous because `self` may | |
a7813a04 | 656 | /// not be fully initialized. |
1a4d82fc JJ |
657 | /// |
658 | /// This is used in the `LocalCrateContext` constructor to allow calling | |
659 | /// functions that expect a complete `CrateContext`, even before the local | |
660 | /// portion is fully initialized and attached to the `SharedCrateContext`. | |
a7813a04 XL |
661 | fn dummy_ccx<'a>(shared: &'a SharedCrateContext<'a, 'tcx>, |
662 | local_ccxs: &'a [LocalCrateContext<'tcx>]) | |
1a4d82fc | 663 | -> CrateContext<'a, 'tcx> { |
a7813a04 | 664 | assert!(local_ccxs.len() == 1); |
1a4d82fc JJ |
665 | CrateContext { |
666 | shared: shared, | |
a7813a04 XL |
667 | index: 0, |
668 | local_ccxs: local_ccxs | |
1a4d82fc JJ |
669 | } |
670 | } | |
671 | } | |
672 | ||
673 | impl<'b, 'tcx> CrateContext<'b, 'tcx> { | |
62682a34 | 674 | pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> { |
1a4d82fc JJ |
675 | self.shared |
676 | } | |
677 | ||
32a655c1 | 678 | fn local(&self) -> &'b LocalCrateContext<'tcx> { |
a7813a04 | 679 | &self.local_ccxs[self.index] |
1a4d82fc JJ |
680 | } |
681 | ||
a7813a04 | 682 | pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { |
62682a34 | 683 | self.shared.tcx |
1a4d82fc JJ |
684 | } |
685 | ||
686 | pub fn sess<'a>(&'a self) -> &'a Session { | |
687 | &self.shared.tcx.sess | |
688 | } | |
689 | ||
e9174d1e | 690 | pub fn get_intrinsic(&self, key: &str) -> ValueRef { |
1a4d82fc JJ |
691 | if let Some(v) = self.intrinsics().borrow().get(key).cloned() { |
692 | return v; | |
693 | } | |
694 | match declare_intrinsic(self, key) { | |
695 | Some(v) => return v, | |
54a0048b | 696 | None => bug!("unknown intrinsic '{}'", key) |
1a4d82fc JJ |
697 | } |
698 | } | |
699 | ||
1a4d82fc | 700 | pub fn llmod(&self) -> ModuleRef { |
a7813a04 | 701 | self.local().llmod |
1a4d82fc JJ |
702 | } |
703 | ||
704 | pub fn llcx(&self) -> ContextRef { | |
a7813a04 XL |
705 | self.local().llcx |
706 | } | |
707 | ||
5bcae85e SL |
708 | pub fn previous_work_product(&self) -> Option<&WorkProduct> { |
709 | self.local().previous_work_product.as_ref() | |
710 | } | |
711 | ||
a7813a04 XL |
712 | pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> { |
713 | &self.local().codegen_unit | |
1a4d82fc JJ |
714 | } |
715 | ||
c1a9b12d SL |
716 | pub fn td(&self) -> llvm::TargetDataRef { |
717 | unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) } | |
1a4d82fc JJ |
718 | } |
719 | ||
1a4d82fc JJ |
720 | pub fn export_map<'a>(&'a self) -> &'a ExportMap { |
721 | &self.shared.export_map | |
722 | } | |
723 | ||
476ff2be SL |
724 | pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { |
725 | &self.shared.exported_symbols | |
1a4d82fc JJ |
726 | } |
727 | ||
1a4d82fc JJ |
728 | pub fn link_meta<'a>(&'a self) -> &'a LinkMeta { |
729 | &self.shared.link_meta | |
730 | } | |
731 | ||
476ff2be | 732 | pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FxHashMap<Ty<'tcx>, bool>> { |
a7813a04 | 733 | &self.local().needs_unwind_cleanup_cache |
1a4d82fc JJ |
734 | } |
735 | ||
476ff2be | 736 | pub fn fn_pointer_shims(&self) -> &RefCell<FxHashMap<Ty<'tcx>, ValueRef>> { |
a7813a04 | 737 | &self.local().fn_pointer_shims |
1a4d82fc JJ |
738 | } |
739 | ||
5bcae85e | 740 | pub fn drop_glues<'a>(&'a self) |
476ff2be | 741 | -> &'a RefCell<FxHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> { |
a7813a04 | 742 | &self.local().drop_glues |
1a4d82fc JJ |
743 | } |
744 | ||
476ff2be | 745 | pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> { |
a7813a04 | 746 | &self.local().instances |
1a4d82fc JJ |
747 | } |
748 | ||
476ff2be SL |
749 | pub fn vtables<'a>(&'a self) |
750 | -> &'a RefCell<FxHashMap<(ty::Ty<'tcx>, | |
751 | Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> { | |
a7813a04 | 752 | &self.local().vtables |
1a4d82fc JJ |
753 | } |
754 | ||
476ff2be | 755 | pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<InternedString, ValueRef>> { |
a7813a04 | 756 | &self.local().const_cstr_cache |
1a4d82fc JJ |
757 | } |
758 | ||
476ff2be | 759 | pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> { |
a7813a04 | 760 | &self.local().const_unsized |
85aaf69f SL |
761 | } |
762 | ||
476ff2be | 763 | pub fn const_globals<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> { |
a7813a04 | 764 | &self.local().const_globals |
1a4d82fc JJ |
765 | } |
766 | ||
476ff2be SL |
767 | pub fn const_values<'a>(&'a self) -> &'a RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>), |
768 | ValueRef>> { | |
a7813a04 | 769 | &self.local().const_values |
1a4d82fc JJ |
770 | } |
771 | ||
1a4d82fc | 772 | pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> { |
a7813a04 XL |
773 | &self.local().extern_const_values |
774 | } | |
775 | ||
476ff2be | 776 | pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> { |
a7813a04 | 777 | &self.local().statics |
1a4d82fc JJ |
778 | } |
779 | ||
780 | pub fn impl_method_cache<'a>(&'a self) | |
476ff2be | 781 | -> &'a RefCell<FxHashMap<(DefId, ast::Name), DefId>> { |
a7813a04 | 782 | &self.local().impl_method_cache |
1a4d82fc JJ |
783 | } |
784 | ||
476ff2be | 785 | pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> { |
a7813a04 | 786 | &self.local().closure_bare_wrapper_cache |
1a4d82fc JJ |
787 | } |
788 | ||
c1a9b12d | 789 | pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> { |
a7813a04 | 790 | &self.local().statics_to_rauw |
c1a9b12d SL |
791 | } |
792 | ||
476ff2be | 793 | pub fn lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> { |
a7813a04 | 794 | &self.local().lltypes |
1a4d82fc JJ |
795 | } |
796 | ||
476ff2be | 797 | pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> { |
a7813a04 | 798 | &self.local().llsizingtypes |
1a4d82fc JJ |
799 | } |
800 | ||
476ff2be | 801 | pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, String>> { |
a7813a04 | 802 | &self.local().type_hashcodes |
1a4d82fc JJ |
803 | } |
804 | ||
1a4d82fc JJ |
805 | pub fn stats<'a>(&'a self) -> &'a Stats { |
806 | &self.shared.stats | |
807 | } | |
808 | ||
1a4d82fc | 809 | pub fn int_type(&self) -> Type { |
a7813a04 | 810 | self.local().int_type |
1a4d82fc JJ |
811 | } |
812 | ||
813 | pub fn opaque_vec_type(&self) -> Type { | |
a7813a04 | 814 | self.local().opaque_vec_type |
1a4d82fc JJ |
815 | } |
816 | ||
476ff2be SL |
817 | pub fn str_slice_type(&self) -> Type { |
818 | self.local().str_slice_type | |
819 | } | |
820 | ||
821 | pub fn closure_vals<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> { | |
a7813a04 | 822 | &self.local().closure_vals |
1a4d82fc JJ |
823 | } |
824 | ||
825 | pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> { | |
a7813a04 | 826 | &self.local().dbg_cx |
1a4d82fc JJ |
827 | } |
828 | ||
54a0048b | 829 | pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> { |
a7813a04 | 830 | &self.local().rust_try_fn |
c1a9b12d SL |
831 | } |
832 | ||
476ff2be | 833 | fn intrinsics<'a>(&'a self) -> &'a RefCell<FxHashMap<&'static str, ValueRef>> { |
a7813a04 | 834 | &self.local().intrinsics |
1a4d82fc JJ |
835 | } |
836 | ||
1a4d82fc | 837 | pub fn obj_size_bound(&self) -> u64 { |
54a0048b | 838 | self.tcx().data_layout.obj_size_bound() |
1a4d82fc JJ |
839 | } |
840 | ||
841 | pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! { | |
842 | self.sess().fatal( | |
62682a34 SL |
843 | &format!("the type `{:?}` is too big for the current architecture", |
844 | obj)) | |
c34b1796 AL |
845 | } |
846 | ||
92a42be0 | 847 | pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> { |
a7813a04 | 848 | let current_depth = self.local().type_of_depth.get(); |
92a42be0 SL |
849 | debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth); |
850 | if current_depth > self.sess().recursion_limit.get() { | |
851 | self.sess().fatal( | |
852 | &format!("overflow representing the type `{}`", ty)) | |
853 | } | |
a7813a04 XL |
854 | self.local().type_of_depth.set(current_depth + 1); |
855 | TypeOfDepthLock(self.local()) | |
92a42be0 SL |
856 | } |
857 | ||
9e0c209e | 858 | pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout { |
32a655c1 | 859 | self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { |
9e0c209e SL |
860 | ty.layout(&infcx).unwrap_or_else(|e| { |
861 | match e { | |
862 | ty::layout::LayoutError::SizeOverflow(_) => | |
863 | self.sess().fatal(&e.to_string()), | |
864 | _ => bug!("failed to get layout for `{}`: {}", ty, e) | |
865 | } | |
866 | }) | |
867 | }) | |
c34b1796 AL |
868 | } |
869 | ||
9e0c209e SL |
870 | pub fn check_overflow(&self) -> bool { |
871 | self.shared.check_overflow | |
1a4d82fc | 872 | } |
62682a34 SL |
873 | |
874 | pub fn use_dll_storage_attrs(&self) -> bool { | |
875 | self.shared.use_dll_storage_attrs() | |
876 | } | |
92a42be0 | 877 | |
5bcae85e SL |
878 | pub fn symbol_map(&self) -> &SymbolMap<'tcx> { |
879 | &*self.local().symbol_map | |
7453a54e SL |
880 | } |
881 | ||
476ff2be | 882 | pub fn translation_items(&self) -> &RefCell<FxHashSet<TransItem<'tcx>>> { |
5bcae85e | 883 | &self.shared.translation_items |
7453a54e | 884 | } |
54a0048b SL |
885 | |
886 | /// Given the def-id of some item that has no type parameters, make | |
887 | /// a suitable "empty substs" for it. | |
888 | pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { | |
a7813a04 | 889 | self.shared().empty_substs_for_def_id(item_def_id) |
54a0048b | 890 | } |
c30ab7b3 SL |
891 | |
892 | /// Generate a new symbol name with the given prefix. This symbol name must | |
893 | /// only be used for definitions with `internal` or `private` linkage. | |
894 | pub fn generate_local_symbol_name(&self, prefix: &str) -> String { | |
895 | let idx = self.local().local_gen_sym_counter.get(); | |
896 | self.local().local_gen_sym_counter.set(idx + 1); | |
897 | // Include a '.' character, so there can be no accidental conflicts with | |
898 | // user defined names | |
476ff2be SL |
899 | let mut name = String::with_capacity(prefix.len() + 6); |
900 | name.push_str(prefix); | |
901 | name.push_str("."); | |
902 | base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name); | |
903 | name | |
c30ab7b3 | 904 | } |
32a655c1 SL |
905 | |
906 | pub fn eh_personality(&self) -> ValueRef { | |
907 | // The exception handling personality function. | |
908 | // | |
909 | // If our compilation unit has the `eh_personality` lang item somewhere | |
910 | // within it, then we just need to translate that. Otherwise, we're | |
911 | // building an rlib which will depend on some upstream implementation of | |
912 | // this function, so we just codegen a generic reference to it. We don't | |
913 | // specify any of the types for the function, we just make it a symbol | |
914 | // that LLVM can later use. | |
915 | // | |
916 | // Note that MSVC is a little special here in that we don't use the | |
917 | // `eh_personality` lang item at all. Currently LLVM has support for | |
918 | // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the | |
919 | // *name of the personality function* to decide what kind of unwind side | |
920 | // tables/landing pads to emit. It looks like Dwarf is used by default, | |
921 | // injecting a dependency on the `_Unwind_Resume` symbol for resuming | |
922 | // an "exception", but for MSVC we want to force SEH. This means that we | |
923 | // can't actually have the personality function be our standard | |
924 | // `rust_eh_personality` function, but rather we wired it up to the | |
925 | // CRT's custom personality function, which forces LLVM to consider | |
926 | // landing pads as "landing pads for SEH". | |
927 | if let Some(llpersonality) = self.local().eh_personality.get() { | |
928 | return llpersonality | |
929 | } | |
930 | let tcx = self.tcx(); | |
931 | let llfn = match tcx.lang_items.eh_personality() { | |
932 | Some(def_id) if !base::wants_msvc_seh(self.sess()) => { | |
933 | Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self) | |
934 | } | |
935 | _ => { | |
936 | let name = if base::wants_msvc_seh(self.sess()) { | |
937 | "__CxxFrameHandler3" | |
938 | } else { | |
939 | "rust_eh_personality" | |
940 | }; | |
941 | let fty = Type::variadic_func(&[], &Type::i32(self)); | |
942 | declare::declare_cfn(self, name, fty) | |
943 | } | |
944 | }; | |
945 | self.local().eh_personality.set(Some(llfn)); | |
946 | llfn | |
947 | } | |
948 | ||
949 | // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined, | |
950 | // otherwise declares it as an external function. | |
951 | pub fn eh_unwind_resume(&self) -> ValueRef { | |
952 | use attributes; | |
953 | let unwresume = &self.local().eh_unwind_resume; | |
954 | if let Some(llfn) = unwresume.get() { | |
955 | return llfn; | |
956 | } | |
957 | ||
958 | let tcx = self.tcx(); | |
959 | assert!(self.sess().target.target.options.custom_unwind_resume); | |
960 | if let Some(def_id) = tcx.lang_items.eh_unwind_resume() { | |
961 | let llfn = Callee::def(self, def_id, tcx.intern_substs(&[])).reify(self); | |
962 | unwresume.set(Some(llfn)); | |
963 | return llfn; | |
964 | } | |
965 | ||
8bb4bdeb XL |
966 | let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig( |
967 | iter::once(tcx.mk_mut_ptr(tcx.types.u8)), | |
968 | tcx.types.never, | |
969 | false, | |
970 | hir::Unsafety::Unsafe, | |
971 | Abi::C | |
972 | ))); | |
32a655c1 SL |
973 | |
974 | let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty); | |
975 | attributes::unwind(llfn, true); | |
976 | unwresume.set(Some(llfn)); | |
977 | llfn | |
978 | } | |
92a42be0 SL |
979 | } |
980 | ||
981 | pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>); | |
982 | ||
983 | impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> { | |
984 | fn drop(&mut self) { | |
985 | self.0.type_of_depth.set(self.0.type_of_depth.get() - 1); | |
986 | } | |
1a4d82fc JJ |
987 | } |
988 | ||
d9579d0f | 989 | /// Declare any llvm intrinsics that you might need |
e9174d1e | 990 | fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> { |
1a4d82fc JJ |
991 | macro_rules! ifn { |
992 | ($name:expr, fn() -> $ret:expr) => ( | |
e9174d1e | 993 | if key == $name { |
54a0048b | 994 | let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret)); |
e9174d1e | 995 | llvm::SetUnnamedAddr(f, false); |
1a4d82fc JJ |
996 | ccx.intrinsics().borrow_mut().insert($name, f.clone()); |
997 | return Some(f); | |
998 | } | |
999 | ); | |
7453a54e SL |
1000 | ($name:expr, fn(...) -> $ret:expr) => ( |
1001 | if key == $name { | |
54a0048b | 1002 | let f = declare::declare_cfn(ccx, $name, Type::variadic_func(&[], &$ret)); |
7453a54e SL |
1003 | llvm::SetUnnamedAddr(f, false); |
1004 | ccx.intrinsics().borrow_mut().insert($name, f.clone()); | |
1005 | return Some(f); | |
1006 | } | |
1007 | ); | |
1a4d82fc | 1008 | ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( |
e9174d1e | 1009 | if key == $name { |
54a0048b | 1010 | let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret)); |
e9174d1e | 1011 | llvm::SetUnnamedAddr(f, false); |
1a4d82fc JJ |
1012 | ccx.intrinsics().borrow_mut().insert($name, f.clone()); |
1013 | return Some(f); | |
1014 | } | |
7453a54e | 1015 | ); |
1a4d82fc JJ |
1016 | } |
1017 | macro_rules! mk_struct { | |
1018 | ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false)) | |
1019 | } | |
1020 | ||
1021 | let i8p = Type::i8p(ccx); | |
1022 | let void = Type::void(ccx); | |
1023 | let i1 = Type::i1(ccx); | |
1024 | let t_i8 = Type::i8(ccx); | |
1025 | let t_i16 = Type::i16(ccx); | |
1026 | let t_i32 = Type::i32(ccx); | |
1027 | let t_i64 = Type::i64(ccx); | |
32a655c1 | 1028 | let t_i128 = Type::i128(ccx); |
1a4d82fc JJ |
1029 | let t_f32 = Type::f32(ccx); |
1030 | let t_f64 = Type::f64(ccx); | |
1031 | ||
e9174d1e | 1032 | ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); |
1a4d82fc JJ |
1033 | ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); |
1034 | ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void); | |
e9174d1e | 1035 | ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); |
1a4d82fc JJ |
1036 | ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); |
1037 | ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void); | |
e9174d1e | 1038 | ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void); |
1a4d82fc JJ |
1039 | ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void); |
1040 | ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void); | |
1041 | ||
1042 | ifn!("llvm.trap", fn() -> void); | |
1043 | ifn!("llvm.debugtrap", fn() -> void); | |
7453a54e | 1044 | ifn!("llvm.frameaddress", fn(t_i32) -> i8p); |
1a4d82fc JJ |
1045 | |
1046 | ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); | |
1047 | ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); | |
1048 | ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32); | |
1049 | ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64); | |
1050 | ||
1051 | ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32); | |
1052 | ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64); | |
1053 | ifn!("llvm.sin.f32", fn(t_f32) -> t_f32); | |
1054 | ifn!("llvm.sin.f64", fn(t_f64) -> t_f64); | |
1055 | ifn!("llvm.cos.f32", fn(t_f32) -> t_f32); | |
1056 | ifn!("llvm.cos.f64", fn(t_f64) -> t_f64); | |
1057 | ifn!("llvm.exp.f32", fn(t_f32) -> t_f32); | |
1058 | ifn!("llvm.exp.f64", fn(t_f64) -> t_f64); | |
1059 | ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32); | |
1060 | ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64); | |
1061 | ifn!("llvm.log.f32", fn(t_f32) -> t_f32); | |
1062 | ifn!("llvm.log.f64", fn(t_f64) -> t_f64); | |
1063 | ifn!("llvm.log10.f32", fn(t_f32) -> t_f32); | |
1064 | ifn!("llvm.log10.f64", fn(t_f64) -> t_f64); | |
1065 | ifn!("llvm.log2.f32", fn(t_f32) -> t_f32); | |
1066 | ifn!("llvm.log2.f64", fn(t_f64) -> t_f64); | |
1067 | ||
1068 | ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32); | |
1069 | ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); | |
1070 | ||
1071 | ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); | |
1072 | ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); | |
1073 | ||
1074 | ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); | |
1075 | ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); | |
1076 | ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32); | |
1077 | ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64); | |
1078 | ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32); | |
1079 | ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64); | |
1080 | ||
62682a34 SL |
1081 | ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32); |
1082 | ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64); | |
1083 | ifn!("llvm.round.f32", fn(t_f32) -> t_f32); | |
1084 | ifn!("llvm.round.f64", fn(t_f64) -> t_f64); | |
1085 | ||
1a4d82fc JJ |
1086 | ifn!("llvm.rint.f32", fn(t_f32) -> t_f32); |
1087 | ifn!("llvm.rint.f64", fn(t_f64) -> t_f64); | |
1088 | ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32); | |
1089 | ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64); | |
1090 | ||
1091 | ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8); | |
1092 | ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16); | |
1093 | ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32); | |
1094 | ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64); | |
32a655c1 | 1095 | ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128); |
1a4d82fc JJ |
1096 | |
1097 | ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8); | |
1098 | ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16); | |
1099 | ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32); | |
1100 | ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64); | |
32a655c1 | 1101 | ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128); |
1a4d82fc JJ |
1102 | |
1103 | ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8); | |
1104 | ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16); | |
1105 | ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32); | |
1106 | ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64); | |
32a655c1 | 1107 | ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128); |
1a4d82fc JJ |
1108 | |
1109 | ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16); | |
1110 | ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32); | |
1111 | ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64); | |
32a655c1 | 1112 | ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128); |
1a4d82fc JJ |
1113 | |
1114 | ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1115 | ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1116 | ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1117 | ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1118 | ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1119 | |
1120 | ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1121 | ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1122 | ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1123 | ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1124 | ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1125 | |
1126 | ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1127 | ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1128 | ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1129 | ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1130 | ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1131 | |
1132 | ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1133 | ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1134 | ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1135 | ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1136 | ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1137 | |
1138 | ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1139 | ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1140 | ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1141 | ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1142 | ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1143 | |
1144 | ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); | |
1145 | ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); | |
1146 | ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); | |
1147 | ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1}); | |
32a655c1 | 1148 | ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1}); |
1a4d82fc JJ |
1149 | |
1150 | ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void); | |
1151 | ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void); | |
1152 | ||
1153 | ifn!("llvm.expect.i1", fn(i1, i1) -> i1); | |
c1a9b12d | 1154 | ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32); |
7453a54e SL |
1155 | ifn!("llvm.localescape", fn(...) -> void); |
1156 | ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p); | |
1157 | ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p); | |
1a4d82fc | 1158 | |
3157f602 | 1159 | ifn!("llvm.assume", fn(i1) -> void); |
1a4d82fc JJ |
1160 | |
1161 | if ccx.sess().opts.debuginfo != NoDebugInfo { | |
1162 | ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void); | |
1163 | ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void); | |
1164 | } | |
1165 | return None; | |
1166 | } |