]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/context.rs
rustc_trans: Apply dllexport attributes for MSVC
[rust.git] / src / librustc_trans / trans / context.rs
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;
12 use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
13 use llvm::TargetData;
14 use llvm::mk_target_data;
15 use metadata::common::LinkMeta;
16 use middle::def::ExportMap;
17 use middle::traits;
18 use trans::adt;
19 use trans::base;
20 use trans::builder::Builder;
21 use trans::common::{ExternMap,BuilderRef_res};
22 use trans::debuginfo;
23 use trans::declare;
24 use trans::glue::DropGlueKind;
25 use trans::monomorphize::MonoId;
26 use trans::type_::{Type, TypeNames};
27 use middle::subst::Substs;
28 use middle::ty::{self, Ty};
29 use session::config::NoDebugInfo;
30 use session::Session;
31 use util::ppaux::Repr;
32 use util::sha2::Sha256;
33 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
34
35 use std::ffi::CString;
36 use std::cell::{Cell, RefCell};
37 use std::ptr;
38 use std::rc::Rc;
39 use syntax::ast;
40 use syntax::parse::token::InternedString;
41
42 pub struct Stats {
43     pub n_glues_created: Cell<usize>,
44     pub n_null_glues: Cell<usize>,
45     pub n_real_glues: Cell<usize>,
46     pub n_fns: Cell<usize>,
47     pub n_monos: Cell<usize>,
48     pub n_inlines: Cell<usize>,
49     pub n_closures: Cell<usize>,
50     pub n_llvm_insns: Cell<usize>,
51     pub llvm_insns: RefCell<FnvHashMap<String, usize>>,
52     // (ident, llvm-instructions)
53     pub fn_stats: RefCell<Vec<(String, usize)> >,
54 }
55
56 /// The shared portion of a `CrateContext`.  There is one `SharedCrateContext`
57 /// per crate.  The data here is shared between all compilation units of the
58 /// crate, so it must not contain references to any LLVM data structures
59 /// (aside from metadata-related ones).
60 pub struct SharedCrateContext<'tcx> {
61     local_ccxs: Vec<LocalCrateContext<'tcx>>,
62
63     metadata_llmod: ModuleRef,
64     metadata_llcx: ContextRef,
65
66     export_map: ExportMap,
67     reachable: NodeSet,
68     item_symbols: RefCell<NodeMap<String>>,
69     link_meta: LinkMeta,
70     symbol_hasher: RefCell<Sha256>,
71     tcx: ty::ctxt<'tcx>,
72     stats: Stats,
73     check_overflow: bool,
74     check_drop_flag_for_sanity: bool,
75
76     available_monomorphizations: RefCell<FnvHashSet<String>>,
77     available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
78     use_dll_storage_attrs: bool,
79 }
80
81 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
82 /// per compilation unit.  Each one has its own LLVM `ContextRef` so that
83 /// several compilation units may be optimized in parallel.  All other LLVM
84 /// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
85 pub struct LocalCrateContext<'tcx> {
86     llmod: ModuleRef,
87     llcx: ContextRef,
88     td: TargetData,
89     tn: TypeNames,
90     externs: RefCell<ExternMap>,
91     item_vals: RefCell<NodeMap<ValueRef>>,
92     needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
93     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
94     drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
95     /// Track mapping of external ids to local items imported for inlining
96     external: RefCell<DefIdMap<Option<ast::NodeId>>>,
97     /// Backwards version of the `external` map (inlined items to where they
98     /// came from)
99     external_srcs: RefCell<NodeMap<ast::DefId>>,
100     /// Cache instances of monomorphized functions
101     monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
102     monomorphizing: RefCell<DefIdMap<usize>>,
103     /// Cache generated vtables
104     vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
105     /// Cache of constant strings,
106     const_cstr_cache: RefCell<FnvHashMap<InternedString, ValueRef>>,
107
108     /// Reverse-direction for const ptrs cast from globals.
109     /// Key is a ValueRef holding a *T,
110     /// Val is a ValueRef holding a *[T].
111     ///
112     /// Needed because LLVM loses pointer->pointee association
113     /// when we ptrcast, and we have to ptrcast during translation
114     /// of a [T] const because we form a slice, a (*T,usize) pair, not
115     /// a pointer to an LLVM array type. Similar for trait objects.
116     const_unsized: RefCell<FnvHashMap<ValueRef, ValueRef>>,
117
118     /// Cache of emitted const globals (value -> global)
119     const_globals: RefCell<FnvHashMap<ValueRef, ValueRef>>,
120
121     /// Cache of emitted const values
122     const_values: RefCell<FnvHashMap<(ast::NodeId, &'tcx Substs<'tcx>), ValueRef>>,
123
124     /// Cache of emitted static values
125     static_values: RefCell<NodeMap<ValueRef>>,
126
127     /// Cache of external const values
128     extern_const_values: RefCell<DefIdMap<ValueRef>>,
129
130     impl_method_cache: RefCell<FnvHashMap<(ast::DefId, ast::Name), ast::DefId>>,
131
132     /// Cache of closure wrappers for bare fn's.
133     closure_bare_wrapper_cache: RefCell<FnvHashMap<ValueRef, ValueRef>>,
134
135     lltypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
136     llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
137     adt_reprs: RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>>,
138     type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>,
139     int_type: Type,
140     opaque_vec_type: Type,
141     builder: BuilderRef_res,
142
143     /// Holds the LLVM values for closure IDs.
144     closure_vals: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
145
146     dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
147
148     eh_personality: RefCell<Option<ValueRef>>,
149
150     intrinsics: RefCell<FnvHashMap<&'static str, ValueRef>>,
151
152     /// Number of LLVM instructions translated into this `LocalCrateContext`.
153     /// This is used to perform some basic load-balancing to keep all LLVM
154     /// contexts around the same size.
155     n_llvm_insns: Cell<usize>,
156
157     trait_cache: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
158                                     traits::Vtable<'tcx, ()>>>,
159 }
160
161 pub struct CrateContext<'a, 'tcx: 'a> {
162     shared: &'a SharedCrateContext<'tcx>,
163     local: &'a LocalCrateContext<'tcx>,
164     /// The index of `local` in `shared.local_ccxs`.  This is used in
165     /// `maybe_iter(true)` to identify the original `LocalCrateContext`.
166     index: usize,
167 }
168
169 pub struct CrateContextIterator<'a, 'tcx: 'a> {
170     shared: &'a SharedCrateContext<'tcx>,
171     index: usize,
172 }
173
174 impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
175     type Item = CrateContext<'a, 'tcx>;
176
177     fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
178         if self.index >= self.shared.local_ccxs.len() {
179             return None;
180         }
181
182         let index = self.index;
183         self.index += 1;
184
185         Some(CrateContext {
186             shared: self.shared,
187             local: &self.shared.local_ccxs[index],
188             index: index,
189         })
190     }
191 }
192
193 /// The iterator produced by `CrateContext::maybe_iter`.
194 pub struct CrateContextMaybeIterator<'a, 'tcx: 'a> {
195     shared: &'a SharedCrateContext<'tcx>,
196     index: usize,
197     single: bool,
198     origin: usize,
199 }
200
201 impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> {
202     type Item = (CrateContext<'a, 'tcx>, bool);
203
204     fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> {
205         if self.index >= self.shared.local_ccxs.len() {
206             return None;
207         }
208
209         let index = self.index;
210         self.index += 1;
211         if self.single {
212             self.index = self.shared.local_ccxs.len();
213         }
214
215         let ccx = CrateContext {
216             shared: self.shared,
217             local: &self.shared.local_ccxs[index],
218             index: index,
219         };
220         Some((ccx, index == self.origin))
221     }
222 }
223
224
225 unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
226     let llcx = llvm::LLVMContextCreate();
227     let mod_name = CString::new(mod_name).unwrap();
228     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
229
230     let data_layout = sess.target.target.data_layout.as_bytes();
231     let data_layout = CString::new(data_layout).unwrap();
232     llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
233
234     let llvm_target = sess.target.target.llvm_target.as_bytes();
235     let llvm_target = CString::new(llvm_target).unwrap();
236     llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
237     (llcx, llmod)
238 }
239
240 impl<'tcx> SharedCrateContext<'tcx> {
241     pub fn new(crate_name: &str,
242                local_count: usize,
243                tcx: ty::ctxt<'tcx>,
244                export_map: ExportMap,
245                symbol_hasher: Sha256,
246                link_meta: LinkMeta,
247                reachable: NodeSet,
248                check_overflow: bool,
249                check_drop_flag_for_sanity: bool)
250                -> SharedCrateContext<'tcx> {
251         let (metadata_llcx, metadata_llmod) = unsafe {
252             create_context_and_module(&tcx.sess, "metadata")
253         };
254
255         // An interesting part of Windows which MSVC forces our hand on (and
256         // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
257         // attributes in LLVM IR as well as native dependencies (in C these
258         // correspond to `__declspec(dllimport)`).
259         //
260         // Whenever a dynamic library is built by MSVC it must have its public
261         // interface specified by functions tagged with `dllexport` or otherwise
262         // they're not available to be linked against. This poses a few problems
263         // for the compiler, some of which are somewhat fundamental, but we use
264         // the `use_dll_storage_attrs` variable below to attach the `dllexport`
265         // attribute to all LLVM functions that are reachable (e.g. they're
266         // already tagged with external linkage). This is suboptimal for a few
267         // reasons:
268         //
269         // * If an object file will never be included in a dynamic library,
270         //   there's no need to attach the dllexport attribute. Most object
271         //   files in Rust are not destined to become part of a dll as binaries
272         //   are statically linked by default.
273         // * If the compiler is emitting both an rlib and a dylib, the same
274         //   source object file is currently used but with MSVC this may be less
275         //   feasible. The compiler may be able to get around this, but it may
276         //   involve some invasive changes to deal with this.
277         //
278         // The flipside of this situation is that whenever you link to a dll and
279         // you import a function from it, the import should be tagged with
280         // `dllimport`. At this time, however, the compiler does not emit
281         // `dllimport` for any declarations other than constants (where it is
282         // required), which is again suboptimal for even more reasons!
283         //
284         // * Calling a function imported from another dll without using
285         //   `dllimport` causes the linker/compiler to have extra overhead (one
286         //   `jmp` instruction on x86) when calling the function.
287         // * The same object file may be used in different circumstances, so a
288         //   function may be imported from a dll if the object is linked into a
289         //   dll, but it may be just linked against if linked into an rlib.
290         // * The compiler has no knowledge about whether native functions should
291         //   be tagged dllimport or not.
292         //
293         // For now the compiler takes the perf hit (I do not have any numbers to
294         // this effect) by marking very little as `dllimport` and praying the
295         // linker will take care of everything. Fixing this problem will likely
296         // require adding a few attributes to Rust itself (feature gated at the
297         // start) and then strongly recommending static linkage on MSVC!
298         let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
299
300         let mut shared_ccx = SharedCrateContext {
301             local_ccxs: Vec::with_capacity(local_count),
302             metadata_llmod: metadata_llmod,
303             metadata_llcx: metadata_llcx,
304             export_map: export_map,
305             reachable: reachable,
306             item_symbols: RefCell::new(NodeMap()),
307             link_meta: link_meta,
308             symbol_hasher: RefCell::new(symbol_hasher),
309             tcx: tcx,
310             stats: Stats {
311                 n_glues_created: Cell::new(0),
312                 n_null_glues: Cell::new(0),
313                 n_real_glues: Cell::new(0),
314                 n_fns: Cell::new(0),
315                 n_monos: Cell::new(0),
316                 n_inlines: Cell::new(0),
317                 n_closures: Cell::new(0),
318                 n_llvm_insns: Cell::new(0),
319                 llvm_insns: RefCell::new(FnvHashMap()),
320                 fn_stats: RefCell::new(Vec::new()),
321             },
322             check_overflow: check_overflow,
323             check_drop_flag_for_sanity: check_drop_flag_for_sanity,
324             available_monomorphizations: RefCell::new(FnvHashSet()),
325             available_drop_glues: RefCell::new(FnvHashMap()),
326             use_dll_storage_attrs: use_dll_storage_attrs,
327         };
328
329         for i in 0..local_count {
330             // Append ".rs" to crate name as LLVM module identifier.
331             //
332             // LLVM code generator emits a ".file filename" directive
333             // for ELF backends. Value of the "filename" is set as the
334             // LLVM module identifier.  Due to a LLVM MC bug[1], LLVM
335             // crashes if the module identifier is same as other symbols
336             // such as a function name in the module.
337             // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
338             let llmod_id = format!("{}.{}.rs", crate_name, i);
339             let local_ccx = LocalCrateContext::new(&shared_ccx, &llmod_id[..]);
340             shared_ccx.local_ccxs.push(local_ccx);
341         }
342
343         shared_ccx
344     }
345
346     pub fn iter<'a>(&'a self) -> CrateContextIterator<'a, 'tcx> {
347         CrateContextIterator {
348             shared: self,
349             index: 0,
350         }
351     }
352
353     pub fn get_ccx<'a>(&'a self, index: usize) -> CrateContext<'a, 'tcx> {
354         CrateContext {
355             shared: self,
356             local: &self.local_ccxs[index],
357             index: index,
358         }
359     }
360
361     fn get_smallest_ccx<'a>(&'a self) -> CrateContext<'a, 'tcx> {
362         let (local_ccx, index) =
363             self.local_ccxs
364                 .iter()
365                 .zip(0..self.local_ccxs.len())
366                 .min_by(|&(local_ccx, _idx)| local_ccx.n_llvm_insns.get())
367                 .unwrap();
368         CrateContext {
369             shared: self,
370             local: local_ccx,
371             index: index,
372         }
373     }
374
375
376     pub fn metadata_llmod(&self) -> ModuleRef {
377         self.metadata_llmod
378     }
379
380     pub fn metadata_llcx(&self) -> ContextRef {
381         self.metadata_llcx
382     }
383
384     pub fn export_map<'a>(&'a self) -> &'a ExportMap {
385         &self.export_map
386     }
387
388     pub fn reachable<'a>(&'a self) -> &'a NodeSet {
389         &self.reachable
390     }
391
392     pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
393         &self.item_symbols
394     }
395
396     pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
397         &self.link_meta
398     }
399
400     pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
401         &self.tcx
402     }
403
404     pub fn take_tcx(self) -> ty::ctxt<'tcx> {
405         self.tcx
406     }
407
408     pub fn sess<'a>(&'a self) -> &'a Session {
409         &self.tcx.sess
410     }
411
412     pub fn stats<'a>(&'a self) -> &'a Stats {
413         &self.stats
414     }
415
416     pub fn use_dll_storage_attrs(&self) -> bool {
417         self.use_dll_storage_attrs
418     }
419 }
420
421 impl<'tcx> LocalCrateContext<'tcx> {
422     fn new(shared: &SharedCrateContext<'tcx>,
423            name: &str)
424            -> LocalCrateContext<'tcx> {
425         unsafe {
426             let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, name);
427
428             let td = mk_target_data(&shared.tcx
429                                           .sess
430                                           .target
431                                           .target
432                                           .data_layout
433                                           );
434
435             let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
436                 Some(debuginfo::CrateDebugContext::new(llmod))
437             } else {
438                 None
439             };
440
441             let mut local_ccx = LocalCrateContext {
442                 llmod: llmod,
443                 llcx: llcx,
444                 td: td,
445                 tn: TypeNames::new(),
446                 externs: RefCell::new(FnvHashMap()),
447                 item_vals: RefCell::new(NodeMap()),
448                 needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
449                 fn_pointer_shims: RefCell::new(FnvHashMap()),
450                 drop_glues: RefCell::new(FnvHashMap()),
451                 external: RefCell::new(DefIdMap()),
452                 external_srcs: RefCell::new(NodeMap()),
453                 monomorphized: RefCell::new(FnvHashMap()),
454                 monomorphizing: RefCell::new(DefIdMap()),
455                 vtables: RefCell::new(FnvHashMap()),
456                 const_cstr_cache: RefCell::new(FnvHashMap()),
457                 const_unsized: RefCell::new(FnvHashMap()),
458                 const_globals: RefCell::new(FnvHashMap()),
459                 const_values: RefCell::new(FnvHashMap()),
460                 static_values: RefCell::new(NodeMap()),
461                 extern_const_values: RefCell::new(DefIdMap()),
462                 impl_method_cache: RefCell::new(FnvHashMap()),
463                 closure_bare_wrapper_cache: RefCell::new(FnvHashMap()),
464                 lltypes: RefCell::new(FnvHashMap()),
465                 llsizingtypes: RefCell::new(FnvHashMap()),
466                 adt_reprs: RefCell::new(FnvHashMap()),
467                 type_hashcodes: RefCell::new(FnvHashMap()),
468                 int_type: Type::from_ref(ptr::null_mut()),
469                 opaque_vec_type: Type::from_ref(ptr::null_mut()),
470                 builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
471                 closure_vals: RefCell::new(FnvHashMap()),
472                 dbg_cx: dbg_cx,
473                 eh_personality: RefCell::new(None),
474                 intrinsics: RefCell::new(FnvHashMap()),
475                 n_llvm_insns: Cell::new(0),
476                 trait_cache: RefCell::new(FnvHashMap()),
477             };
478
479             local_ccx.int_type = Type::int(&local_ccx.dummy_ccx(shared));
480             local_ccx.opaque_vec_type = Type::opaque_vec(&local_ccx.dummy_ccx(shared));
481
482             // Done mutating local_ccx directly.  (The rest of the
483             // initialization goes through RefCell.)
484             {
485                 let ccx = local_ccx.dummy_ccx(shared);
486
487                 let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
488                 str_slice_ty.set_struct_body(&[Type::i8p(&ccx), ccx.int_type()], false);
489                 ccx.tn().associate_type("str_slice", &str_slice_ty);
490
491                 if ccx.sess().count_llvm_insns() {
492                     base::init_insn_ctxt()
493                 }
494             }
495
496             local_ccx
497         }
498     }
499
500     /// Create a dummy `CrateContext` from `self` and  the provided
501     /// `SharedCrateContext`.  This is somewhat dangerous because `self` may
502     /// not actually be an element of `shared.local_ccxs`, which can cause some
503     /// operations to panic unexpectedly.
504     ///
505     /// This is used in the `LocalCrateContext` constructor to allow calling
506     /// functions that expect a complete `CrateContext`, even before the local
507     /// portion is fully initialized and attached to the `SharedCrateContext`.
508     fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext<'tcx>)
509                      -> CrateContext<'a, 'tcx> {
510         CrateContext {
511             shared: shared,
512             local: self,
513             index: !0 as usize,
514         }
515     }
516 }
517
518 impl<'b, 'tcx> CrateContext<'b, 'tcx> {
519     pub fn shared(&self) -> &'b SharedCrateContext<'tcx> {
520         self.shared
521     }
522
523     pub fn local(&self) -> &'b LocalCrateContext<'tcx> {
524         self.local
525     }
526
527
528     /// Get a (possibly) different `CrateContext` from the same
529     /// `SharedCrateContext`.
530     pub fn rotate(&self) -> CrateContext<'b, 'tcx> {
531         self.shared.get_smallest_ccx()
532     }
533
534     /// Either iterate over only `self`, or iterate over all `CrateContext`s in
535     /// the `SharedCrateContext`.  The iterator produces `(ccx, is_origin)`
536     /// pairs, where `is_origin` is `true` if `ccx` is `self` and `false`
537     /// otherwise.  This method is useful for avoiding code duplication in
538     /// cases where it may or may not be necessary to translate code into every
539     /// context.
540     pub fn maybe_iter(&self, iter_all: bool) -> CrateContextMaybeIterator<'b, 'tcx> {
541         CrateContextMaybeIterator {
542             shared: self.shared,
543             index: if iter_all { 0 } else { self.index },
544             single: !iter_all,
545             origin: self.index,
546         }
547     }
548
549
550     pub fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
551         &self.shared.tcx
552     }
553
554     pub fn sess<'a>(&'a self) -> &'a Session {
555         &self.shared.tcx.sess
556     }
557
558     pub fn builder<'a>(&'a self) -> Builder<'a, 'tcx> {
559         Builder::new(self)
560     }
561
562     pub fn raw_builder<'a>(&'a self) -> BuilderRef {
563         self.local.builder.b
564     }
565
566     pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef {
567         if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
568             return v;
569         }
570         match declare_intrinsic(self, key) {
571             Some(v) => return v,
572             None => panic!()
573         }
574     }
575
576     pub fn is_split_stack_supported(&self) -> bool {
577         self.sess().target.target.options.morestack
578     }
579
580
581     pub fn llmod(&self) -> ModuleRef {
582         self.local.llmod
583     }
584
585     pub fn llcx(&self) -> ContextRef {
586         self.local.llcx
587     }
588
589     pub fn td<'a>(&'a self) -> &'a TargetData {
590         &self.local.td
591     }
592
593     pub fn tn<'a>(&'a self) -> &'a TypeNames {
594         &self.local.tn
595     }
596
597     pub fn externs<'a>(&'a self) -> &'a RefCell<ExternMap> {
598         &self.local.externs
599     }
600
601     pub fn item_vals<'a>(&'a self) -> &'a RefCell<NodeMap<ValueRef>> {
602         &self.local.item_vals
603     }
604
605     pub fn export_map<'a>(&'a self) -> &'a ExportMap {
606         &self.shared.export_map
607     }
608
609     pub fn reachable<'a>(&'a self) -> &'a NodeSet {
610         &self.shared.reachable
611     }
612
613     pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
614         &self.shared.item_symbols
615     }
616
617     pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
618         &self.shared.link_meta
619     }
620
621     pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, bool>> {
622         &self.local.needs_unwind_cleanup_cache
623     }
624
625     pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
626         &self.local.fn_pointer_shims
627     }
628
629     pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
630         &self.local.drop_glues
631     }
632
633     pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
634         &self.local.external
635     }
636
637     pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<ast::DefId>> {
638         &self.local.external_srcs
639     }
640
641     pub fn monomorphized<'a>(&'a self) -> &'a RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>> {
642         &self.local.monomorphized
643     }
644
645     pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<usize>> {
646         &self.local.monomorphizing
647     }
648
649     pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
650         &self.local.vtables
651     }
652
653     pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FnvHashMap<InternedString, ValueRef>> {
654         &self.local.const_cstr_cache
655     }
656
657     pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
658         &self.local.const_unsized
659     }
660
661     pub fn const_globals<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
662         &self.local.const_globals
663     }
664
665     pub fn const_values<'a>(&'a self) -> &'a RefCell<FnvHashMap<(ast::NodeId, &'tcx Substs<'tcx>),
666                                                                 ValueRef>> {
667         &self.local.const_values
668     }
669
670     pub fn static_values<'a>(&'a self) -> &'a RefCell<NodeMap<ValueRef>> {
671         &self.local.static_values
672     }
673
674     pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
675         &self.local.extern_const_values
676     }
677
678     pub fn impl_method_cache<'a>(&'a self)
679             -> &'a RefCell<FnvHashMap<(ast::DefId, ast::Name), ast::DefId>> {
680         &self.local.impl_method_cache
681     }
682
683     pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
684         &self.local.closure_bare_wrapper_cache
685     }
686
687     pub fn lltypes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Type>> {
688         &self.local.lltypes
689     }
690
691     pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Type>> {
692         &self.local.llsizingtypes
693     }
694
695     pub fn adt_reprs<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>> {
696         &self.local.adt_reprs
697     }
698
699     pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> {
700         &self.shared.symbol_hasher
701     }
702
703     pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, String>> {
704         &self.local.type_hashcodes
705     }
706
707     pub fn stats<'a>(&'a self) -> &'a Stats {
708         &self.shared.stats
709     }
710
711     pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
712         &self.shared.available_monomorphizations
713     }
714
715     pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
716         &self.shared.available_drop_glues
717     }
718
719     pub fn int_type(&self) -> Type {
720         self.local.int_type
721     }
722
723     pub fn opaque_vec_type(&self) -> Type {
724         self.local.opaque_vec_type
725     }
726
727     pub fn closure_vals<'a>(&'a self) -> &'a RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>> {
728         &self.local.closure_vals
729     }
730
731     pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
732         &self.local.dbg_cx
733     }
734
735     pub fn eh_personality<'a>(&'a self) -> &'a RefCell<Option<ValueRef>> {
736         &self.local.eh_personality
737     }
738
739     fn intrinsics<'a>(&'a self) -> &'a RefCell<FnvHashMap<&'static str, ValueRef>> {
740         &self.local.intrinsics
741     }
742
743     pub fn count_llvm_insn(&self) {
744         self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1);
745     }
746
747     pub fn trait_cache(&self) -> &RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
748                                                      traits::Vtable<'tcx, ()>>> {
749         &self.local.trait_cache
750     }
751
752     /// Return exclusive upper bound on object size.
753     ///
754     /// The theoretical maximum object size is defined as the maximum positive `int` value. This
755     /// ensures that the `offset` semantics remain well-defined by allowing it to correctly index
756     /// every address within an object along with one byte past the end, along with allowing `int`
757     /// to store the difference between any two pointers into an object.
758     ///
759     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer to
760     /// represent object size in bits. It would need to be 1 << 61 to account for this, but is
761     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
762     /// address space on 64-bit ARMv8 and x86_64.
763     pub fn obj_size_bound(&self) -> u64 {
764         match &self.sess().target.target.target_pointer_width[..] {
765             "32" => 1 << 31,
766             "64" => 1 << 47,
767             _ => unreachable!() // error handled by config::build_target_config
768         }
769     }
770
771     pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! {
772         self.sess().fatal(
773             &format!("the type `{}` is too big for the current architecture",
774                     obj.repr(self.tcx())))
775     }
776
777     pub fn check_overflow(&self) -> bool {
778         self.shared.check_overflow
779     }
780
781     pub fn check_drop_flag_for_sanity(&self) -> bool {
782         // This controls whether we emit a conditional llvm.debugtrap
783         // guarded on whether the dropflag is one of its (two) valid
784         // values.
785         self.shared.check_drop_flag_for_sanity
786     }
787
788     pub fn use_dll_storage_attrs(&self) -> bool {
789         self.shared.use_dll_storage_attrs()
790     }
791 }
792
793 /// Declare any llvm intrinsics that you might need
794 fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
795     macro_rules! ifn {
796         ($name:expr, fn() -> $ret:expr) => (
797             if *key == $name {
798                 let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
799                                              ty::mk_nil(ccx.tcx()));
800                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
801                 return Some(f);
802             }
803         );
804         ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
805             if *key == $name {
806                 let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
807                                              ty::mk_nil(ccx.tcx()));
808                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
809                 return Some(f);
810             }
811         )
812     }
813     macro_rules! mk_struct {
814         ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
815     }
816
817     let i8p = Type::i8p(ccx);
818     let void = Type::void(ccx);
819     let i1 = Type::i1(ccx);
820     let t_i8 = Type::i8(ccx);
821     let t_i16 = Type::i16(ccx);
822     let t_i32 = Type::i32(ccx);
823     let t_i64 = Type::i64(ccx);
824     let t_f32 = Type::f32(ccx);
825     let t_f64 = Type::f64(ccx);
826
827     ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
828     ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
829     ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
830     ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
831     ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
832     ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);
833
834     ifn!("llvm.trap", fn() -> void);
835     ifn!("llvm.debugtrap", fn() -> void);
836     ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
837
838     ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
839     ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
840     ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
841     ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
842
843     ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
844     ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
845     ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
846     ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
847     ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
848     ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
849     ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
850     ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
851     ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
852     ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
853     ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
854     ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
855     ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
856     ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
857     ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
858     ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
859
860     ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
861     ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
862
863     ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
864     ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
865
866     ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
867     ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
868     ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
869     ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
870     ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
871     ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
872
873     ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
874     ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
875     ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
876     ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
877
878     ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
879     ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
880     ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
881     ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
882
883     ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8);
884     ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
885     ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
886     ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
887
888     ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8);
889     ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
890     ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
891     ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
892
893     ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
894     ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
895     ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
896
897     ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
898     ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
899     ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
900     ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
901
902     ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
903     ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
904     ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
905     ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
906
907     ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
908     ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
909     ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
910     ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
911
912     ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
913     ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
914     ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
915     ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
916
917     ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
918     ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
919     ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
920     ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
921
922     ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
923     ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
924     ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
925     ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
926
927     ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void);
928     ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);
929
930     ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
931     ifn!("llvm.assume", fn(i1) -> void);
932
933     // Some intrinsics were introduced in later versions of LLVM, but they have
934     // fallbacks in libc or libm and such. Currently, all of these intrinsics
935     // were introduced in LLVM 3.4, so we case on that.
936     macro_rules! compatible_ifn {
937         ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
938             ifn!($name, fn($($arg),*) -> $ret);
939         )
940     }
941
942     compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32);
943     compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64);
944     compatible_ifn!("llvm.round.f32", roundf(t_f32) -> t_f32);
945     compatible_ifn!("llvm.round.f64", round(t_f64) -> t_f64);
946
947
948     if ccx.sess().opts.debuginfo != NoDebugInfo {
949         ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
950         ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);
951     }
952     return None;
953 }