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.
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.
13 use llvm::{ContextRef, ModuleRef, ValueRef};
14 use rustc::dep_graph::{DepGraph, DepGraphSafe};
16 use rustc::hir::def_id::DefId;
17 use rustc::ich::StableHashingContext;
23 use monomorphize::Instance;
25 use partitioning::CodegenUnit;
27 use rustc_data_structures::base_n;
28 use rustc::middle::trans::Stats;
29 use rustc_data_structures::stable_hasher::StableHashingContextProvider;
30 use rustc::session::config::{self, NoDebugInfo};
31 use rustc::session::Session;
32 use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
33 use rustc::ty::{self, Ty, TyCtxt};
34 use rustc::util::nodemap::FxHashMap;
35 use rustc_trans_utils;
37 use std::ffi::{CStr, CString};
38 use std::cell::{Cell, RefCell};
43 use std::marker::PhantomData;
44 use syntax::symbol::InternedString;
47 /// The shared portion of a `CrateContext`. There is one `SharedCrateContext`
48 /// per crate. The data here is shared between all compilation units of the
49 /// crate, so it must not contain references to any LLVM data structures
50 /// (aside from metadata-related ones).
51 pub struct SharedCrateContext<'a, 'tcx: 'a> {
52 tcx: TyCtxt<'a, 'tcx, 'tcx>,
54 use_dll_storage_attrs: bool,
55 tls_model: llvm::ThreadLocalMode,
58 /// The local portion of a `CrateContext`. There is one `LocalCrateContext`
59 /// per compilation unit. Each one has its own LLVM `ContextRef` so that
60 /// several compilation units may be optimized in parallel. All other LLVM
61 /// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
62 pub struct LocalCrateContext<'a, 'tcx: 'a> {
65 stats: RefCell<Stats>,
66 codegen_unit: Arc<CodegenUnit<'tcx>>,
68 /// Cache instances of monomorphic and polymorphic items
69 instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
70 /// Cache generated vtables
71 vtables: RefCell<FxHashMap<(Ty<'tcx>,
72 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
73 /// Cache of constant strings,
74 const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
76 /// Reverse-direction for const ptrs cast from globals.
77 /// Key is a ValueRef holding a *T,
78 /// Val is a ValueRef holding a *[T].
80 /// Needed because LLVM loses pointer->pointee association
81 /// when we ptrcast, and we have to ptrcast during translation
82 /// of a [T] const because we form a slice, a (*T,usize) pair, not
83 /// a pointer to an LLVM array type. Similar for trait objects.
84 const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
86 /// Cache of emitted const globals (value -> global)
87 const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
89 /// Mapping from static definitions to their DefId's.
90 statics: RefCell<FxHashMap<ValueRef, DefId>>,
92 /// List of globals for static variables which need to be passed to the
93 /// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
94 /// (We have to make sure we don't invalidate any ValueRefs referring
96 statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
98 /// Statics that will be placed in the llvm.used variable
99 /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
100 used_statics: RefCell<Vec<ValueRef>>,
102 lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
104 opaque_vec_type: Type,
105 str_slice_type: Type,
107 dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
109 eh_personality: Cell<Option<ValueRef>>,
110 eh_unwind_resume: Cell<Option<ValueRef>>,
111 rust_try_fn: Cell<Option<ValueRef>>,
113 intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
115 /// A counter that is used for generating local symbol names
116 local_gen_sym_counter: Cell<usize>,
118 /// A placeholder so we can add lifetimes
119 placeholder: PhantomData<&'a ()>,
122 /// A CrateContext value binds together one LocalCrateContext with the
123 /// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
124 /// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
125 pub struct CrateContext<'a, 'tcx: 'a> {
126 shared: &'a SharedCrateContext<'a, 'tcx>,
127 local_ccx: &'a LocalCrateContext<'a, 'tcx>,
130 impl<'a, 'tcx> CrateContext<'a, 'tcx> {
131 pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
132 local_ccx: &'a LocalCrateContext<'a, 'tcx>)
134 CrateContext { shared, local_ccx }
138 impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
141 impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
144 impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
145 type ContextType = StableHashingContext<'tcx>;
147 fn create_stable_hashing_context(&self) -> Self::ContextType {
148 self.tcx.create_stable_hashing_context()
152 pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
153 let reloc_model_arg = match sess.opts.cg.relocation_model {
154 Some(ref s) => &s[..],
155 None => &sess.target.target.options.relocation_model[..],
158 match ::back::write::RELOC_MODEL_ARGS.iter().find(
159 |&&arg| arg.0 == reloc_model_arg) {
162 sess.err(&format!("{:?} is not a valid relocation mode",
164 sess.abort_if_errors();
170 fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
171 let tls_model_arg = match sess.opts.debugging_opts.tls_model {
172 Some(ref s) => &s[..],
173 None => &sess.target.target.options.tls_model[..],
176 match ::back::write::TLS_MODEL_ARGS.iter().find(
177 |&&arg| arg.0 == tls_model_arg) {
180 sess.err(&format!("{:?} is not a valid TLS model",
182 sess.abort_if_errors();
188 fn is_any_library(sess: &Session) -> bool {
189 sess.crate_types.borrow().iter().any(|ty| {
190 *ty != config::CrateTypeExecutable
194 pub fn is_pie_binary(sess: &Session) -> bool {
195 !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
198 pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
199 let llcx = llvm::LLVMContextCreate();
200 let mod_name = CString::new(mod_name).unwrap();
201 let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
203 // Ensure the data-layout values hardcoded remain the defaults.
204 if sess.target.target.options.is_builtin {
205 let tm = ::back::write::create_target_machine(sess);
206 llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
207 llvm::LLVMRustDisposeTargetMachine(tm);
209 let data_layout = llvm::LLVMGetDataLayout(llmod);
210 let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
211 .ok().expect("got a non-UTF8 data-layout from LLVM");
213 // Unfortunately LLVM target specs change over time, and right now we
214 // don't have proper support to work with any more than one
215 // `data_layout` than the one that is in the rust-lang/rust repo. If
216 // this compiler is configured against a custom LLVM, we may have a
217 // differing data layout, even though we should update our own to use
220 // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
221 // disable this check entirely as we may be configured with something
222 // that has a different target layout.
224 // Unsure if this will actually cause breakage when rustc is configured
228 let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
229 let custom_llvm_used = cfg_llvm_root.trim() != "";
231 if !custom_llvm_used && sess.target.target.data_layout != data_layout {
232 bug!("data-layout for builtin `{}` target, `{}`, \
233 differs from LLVM default, `{}`",
234 sess.target.target.llvm_target,
235 sess.target.target.data_layout,
240 let data_layout = CString::new(&sess.target.target.data_layout[..]).unwrap();
241 llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
243 let llvm_target = sess.target.target.llvm_target.as_bytes();
244 let llvm_target = CString::new(llvm_target).unwrap();
245 llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
247 if is_pie_binary(sess) {
248 llvm::LLVMRustSetModulePIELevel(llmod);
254 impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
255 pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> SharedCrateContext<'b, 'tcx> {
256 // An interesting part of Windows which MSVC forces our hand on (and
257 // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
258 // attributes in LLVM IR as well as native dependencies (in C these
259 // correspond to `__declspec(dllimport)`).
261 // Whenever a dynamic library is built by MSVC it must have its public
262 // interface specified by functions tagged with `dllexport` or otherwise
263 // they're not available to be linked against. This poses a few problems
264 // for the compiler, some of which are somewhat fundamental, but we use
265 // the `use_dll_storage_attrs` variable below to attach the `dllexport`
266 // attribute to all LLVM functions that are exported e.g. they're
267 // already tagged with external linkage). This is suboptimal for a few
270 // * If an object file will never be included in a dynamic library,
271 // there's no need to attach the dllexport attribute. Most object
272 // files in Rust are not destined to become part of a dll as binaries
273 // are statically linked by default.
274 // * If the compiler is emitting both an rlib and a dylib, the same
275 // source object file is currently used but with MSVC this may be less
276 // feasible. The compiler may be able to get around this, but it may
277 // involve some invasive changes to deal with this.
279 // The flipside of this situation is that whenever you link to a dll and
280 // you import a function from it, the import should be tagged with
281 // `dllimport`. At this time, however, the compiler does not emit
282 // `dllimport` for any declarations other than constants (where it is
283 // required), which is again suboptimal for even more reasons!
285 // * Calling a function imported from another dll without using
286 // `dllimport` causes the linker/compiler to have extra overhead (one
287 // `jmp` instruction on x86) when calling the function.
288 // * The same object file may be used in different circumstances, so a
289 // function may be imported from a dll if the object is linked into a
290 // dll, but it may be just linked against if linked into an rlib.
291 // * The compiler has no knowledge about whether native functions should
292 // be tagged dllimport or not.
294 // For now the compiler takes the perf hit (I do not have any numbers to
295 // this effect) by marking very little as `dllimport` and praying the
296 // linker will take care of everything. Fixing this problem will likely
297 // require adding a few attributes to Rust itself (feature gated at the
298 // start) and then strongly recommending static linkage on MSVC!
299 let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
301 let check_overflow = tcx.sess.overflow_checks();
303 let tls_model = get_tls_model(&tcx.sess);
308 use_dll_storage_attrs,
313 pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
314 common::type_needs_drop(self.tcx, ty)
317 pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
318 common::type_is_sized(self.tcx, ty)
321 pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
322 common::type_is_freeze(self.tcx, ty)
325 pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
326 rustc_trans_utils::common::type_has_metadata(self.tcx, ty)
329 pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
333 pub fn sess<'a>(&'a self) -> &'a Session {
337 pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
341 pub fn use_dll_storage_attrs(&self) -> bool {
342 self.use_dll_storage_attrs
346 impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
347 pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
348 codegen_unit: Arc<CodegenUnit<'tcx>>,
350 -> LocalCrateContext<'a, 'tcx> {
352 let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
355 let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
356 let dctx = debuginfo::CrateDebugContext::new(llmod);
357 debuginfo::metadata::compile_unit_metadata(shared,
366 let local_ccx = LocalCrateContext {
369 stats: RefCell::new(Stats::default()),
371 instances: RefCell::new(FxHashMap()),
372 vtables: RefCell::new(FxHashMap()),
373 const_cstr_cache: RefCell::new(FxHashMap()),
374 const_unsized: RefCell::new(FxHashMap()),
375 const_globals: RefCell::new(FxHashMap()),
376 statics: RefCell::new(FxHashMap()),
377 statics_to_rauw: RefCell::new(Vec::new()),
378 used_statics: RefCell::new(Vec::new()),
379 lltypes: RefCell::new(FxHashMap()),
380 isize_ty: Type::from_ref(ptr::null_mut()),
381 opaque_vec_type: Type::from_ref(ptr::null_mut()),
382 str_slice_type: Type::from_ref(ptr::null_mut()),
384 eh_personality: Cell::new(None),
385 eh_unwind_resume: Cell::new(None),
386 rust_try_fn: Cell::new(None),
387 intrinsics: RefCell::new(FxHashMap()),
388 local_gen_sym_counter: Cell::new(0),
389 placeholder: PhantomData,
392 let (isize_ty, opaque_vec_type, str_slice_ty, mut local_ccx) = {
393 // Do a little dance to create a dummy CrateContext, so we can
394 // create some things in the LLVM module of this codegen unit
395 let mut local_ccxs = vec![local_ccx];
396 let (isize_ty, opaque_vec_type, str_slice_ty) = {
397 let dummy_ccx = LocalCrateContext::dummy_ccx(shared,
398 local_ccxs.as_mut_slice());
399 let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice");
400 str_slice_ty.set_struct_body(&[Type::i8p(&dummy_ccx),
401 Type::isize(&dummy_ccx)],
403 (Type::isize(&dummy_ccx), Type::opaque_vec(&dummy_ccx), str_slice_ty)
405 (isize_ty, opaque_vec_type, str_slice_ty, local_ccxs.pop().unwrap())
408 local_ccx.isize_ty = isize_ty;
409 local_ccx.opaque_vec_type = opaque_vec_type;
410 local_ccx.str_slice_type = str_slice_ty;
416 /// Create a dummy `CrateContext` from `self` and the provided
417 /// `SharedCrateContext`. This is somewhat dangerous because `self` may
418 /// not be fully initialized.
420 /// This is used in the `LocalCrateContext` constructor to allow calling
421 /// functions that expect a complete `CrateContext`, even before the local
422 /// portion is fully initialized and attached to the `SharedCrateContext`.
423 fn dummy_ccx(shared: &'a SharedCrateContext<'a, 'tcx>,
424 local_ccxs: &'a [LocalCrateContext<'a, 'tcx>])
425 -> CrateContext<'a, 'tcx> {
426 assert!(local_ccxs.len() == 1);
429 local_ccx: &local_ccxs[0]
433 pub fn into_stats(self) -> Stats {
434 self.stats.into_inner()
438 impl<'b, 'tcx> CrateContext<'b, 'tcx> {
439 pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
443 fn local(&self) -> &'b LocalCrateContext<'b, 'tcx> {
447 pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
451 pub fn sess<'a>(&'a self) -> &'a Session {
452 &self.shared.tcx.sess
455 pub fn get_intrinsic(&self, key: &str) -> ValueRef {
456 if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
459 match declare_intrinsic(self, key) {
461 None => bug!("unknown intrinsic '{}'", key)
465 pub fn llmod(&self) -> ModuleRef {
469 pub fn llcx(&self) -> ContextRef {
473 pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
474 &self.local().codegen_unit
477 pub fn td(&self) -> llvm::TargetDataRef {
478 unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
481 pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
482 &self.local().instances
485 pub fn vtables<'a>(&'a self)
486 -> &'a RefCell<FxHashMap<(Ty<'tcx>,
487 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
488 &self.local().vtables
491 pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<InternedString, ValueRef>> {
492 &self.local().const_cstr_cache
495 pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
496 &self.local().const_unsized
499 pub fn const_globals<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
500 &self.local().const_globals
503 pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> {
504 &self.local().statics
507 pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
508 &self.local().statics_to_rauw
511 pub fn used_statics<'a>(&'a self) -> &'a RefCell<Vec<ValueRef>> {
512 &self.local().used_statics
515 pub fn lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> {
516 &self.local().lltypes
519 pub fn stats<'a>(&'a self) -> &'a RefCell<Stats> {
523 pub fn isize_ty(&self) -> Type {
524 self.local().isize_ty
527 pub fn str_slice_type(&self) -> Type {
528 self.local().str_slice_type
531 pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
535 pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
536 &self.local().rust_try_fn
539 fn intrinsics<'a>(&'a self) -> &'a RefCell<FxHashMap<&'static str, ValueRef>> {
540 &self.local().intrinsics
543 pub fn check_overflow(&self) -> bool {
544 self.shared.check_overflow
547 pub fn use_dll_storage_attrs(&self) -> bool {
548 self.shared.use_dll_storage_attrs()
551 pub fn tls_model(&self) -> llvm::ThreadLocalMode {
552 self.shared.tls_model
555 /// Generate a new symbol name with the given prefix. This symbol name must
556 /// only be used for definitions with `internal` or `private` linkage.
557 pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
558 let idx = self.local().local_gen_sym_counter.get();
559 self.local().local_gen_sym_counter.set(idx + 1);
560 // Include a '.' character, so there can be no accidental conflicts with
561 // user defined names
562 let mut name = String::with_capacity(prefix.len() + 6);
563 name.push_str(prefix);
565 base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
569 pub fn eh_personality(&self) -> ValueRef {
570 // The exception handling personality function.
572 // If our compilation unit has the `eh_personality` lang item somewhere
573 // within it, then we just need to translate that. Otherwise, we're
574 // building an rlib which will depend on some upstream implementation of
575 // this function, so we just codegen a generic reference to it. We don't
576 // specify any of the types for the function, we just make it a symbol
577 // that LLVM can later use.
579 // Note that MSVC is a little special here in that we don't use the
580 // `eh_personality` lang item at all. Currently LLVM has support for
581 // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
582 // *name of the personality function* to decide what kind of unwind side
583 // tables/landing pads to emit. It looks like Dwarf is used by default,
584 // injecting a dependency on the `_Unwind_Resume` symbol for resuming
585 // an "exception", but for MSVC we want to force SEH. This means that we
586 // can't actually have the personality function be our standard
587 // `rust_eh_personality` function, but rather we wired it up to the
588 // CRT's custom personality function, which forces LLVM to consider
589 // landing pads as "landing pads for SEH".
590 if let Some(llpersonality) = self.local().eh_personality.get() {
593 let tcx = self.tcx();
594 let llfn = match tcx.lang_items().eh_personality() {
595 Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
596 callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
599 let name = if base::wants_msvc_seh(self.sess()) {
602 "rust_eh_personality"
604 let fty = Type::variadic_func(&[], &Type::i32(self));
605 declare::declare_cfn(self, name, fty)
608 self.local().eh_personality.set(Some(llfn));
612 // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
613 // otherwise declares it as an external function.
614 pub fn eh_unwind_resume(&self) -> ValueRef {
616 let unwresume = &self.local().eh_unwind_resume;
617 if let Some(llfn) = unwresume.get() {
621 let tcx = self.tcx();
622 assert!(self.sess().target.target.options.custom_unwind_resume);
623 if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
624 let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
625 unwresume.set(Some(llfn));
629 let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
630 iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
633 hir::Unsafety::Unsafe,
637 let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty);
638 attributes::unwind(llfn, true);
639 unwresume.set(Some(llfn));
644 impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
645 fn data_layout(&self) -> &ty::layout::TargetDataLayout {
646 &self.tcx.data_layout
650 impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
651 fn data_layout(&self) -> &ty::layout::TargetDataLayout {
652 &self.shared.tcx.data_layout
656 impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
657 type TyLayout = TyLayout<'tcx>;
659 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
663 fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
664 let param_env = ty::ParamEnv::empty(traits::Reveal::All);
665 LayoutCx::new(self.tcx, param_env)
667 .unwrap_or_else(|e| match e {
668 LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
669 _ => bug!("failed to get layout for `{}`: {}", ty, e)
673 fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
674 self.tcx().fully_normalize_associated_types_in(&ty)
678 impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
679 type TyLayout = TyLayout<'tcx>;
681 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
685 fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
686 self.shared.layout_of(ty)
689 fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
690 self.shared.normalize_projections(ty)
694 /// Declare any llvm intrinsics that you might need
695 fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
697 ($name:expr, fn() -> $ret:expr) => (
699 let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret));
700 llvm::SetUnnamedAddr(f, false);
701 ccx.intrinsics().borrow_mut().insert($name, f.clone());
705 ($name:expr, fn(...) -> $ret:expr) => (
707 let f = declare::declare_cfn(ccx, $name, Type::variadic_func(&[], &$ret));
708 llvm::SetUnnamedAddr(f, false);
709 ccx.intrinsics().borrow_mut().insert($name, f.clone());
713 ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
715 let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret));
716 llvm::SetUnnamedAddr(f, false);
717 ccx.intrinsics().borrow_mut().insert($name, f.clone());
722 macro_rules! mk_struct {
723 ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
726 let i8p = Type::i8p(ccx);
727 let void = Type::void(ccx);
728 let i1 = Type::i1(ccx);
729 let t_i8 = Type::i8(ccx);
730 let t_i16 = Type::i16(ccx);
731 let t_i32 = Type::i32(ccx);
732 let t_i64 = Type::i64(ccx);
733 let t_i128 = Type::i128(ccx);
734 let t_f32 = Type::f32(ccx);
735 let t_f64 = Type::f64(ccx);
737 ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
738 ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
739 ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
740 ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
741 ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
742 ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
743 ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
744 ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
745 ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);
747 ifn!("llvm.trap", fn() -> void);
748 ifn!("llvm.debugtrap", fn() -> void);
749 ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
751 ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
752 ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
753 ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
754 ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
756 ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
757 ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
758 ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
759 ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
760 ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
761 ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
762 ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
763 ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
764 ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
765 ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
766 ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
767 ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
768 ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
769 ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
770 ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
771 ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
773 ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
774 ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
776 ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
777 ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
779 ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
780 ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
781 ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
782 ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
783 ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
784 ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
786 ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
787 ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
788 ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
789 ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
791 ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
792 ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
793 ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
794 ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
796 ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
797 ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
798 ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
799 ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
800 ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128);
802 ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8);
803 ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
804 ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
805 ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
806 ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128);
808 ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8);
809 ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
810 ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
811 ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
812 ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128);
814 ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
815 ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
816 ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
817 ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
819 ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
820 ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
821 ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
822 ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
823 ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
825 ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
826 ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
827 ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
828 ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
829 ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
831 ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
832 ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
833 ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
834 ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
835 ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
837 ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
838 ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
839 ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
840 ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
841 ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
843 ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
844 ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
845 ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
846 ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
847 ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
849 ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
850 ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
851 ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
852 ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
853 ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
855 ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void);
856 ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);
858 ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
859 ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
860 ifn!("llvm.localescape", fn(...) -> void);
861 ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p);
862 ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
864 ifn!("llvm.assume", fn(i1) -> void);
865 ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
867 if ccx.sess().opts.debuginfo != NoDebugInfo {
868 ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
869 ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);