]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/context.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / librustc_trans / context.rs
CommitLineData
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
ea8adc8c 11use common;
1a4d82fc 12use llvm;
32a655c1 13use llvm::{ContextRef, ModuleRef, ValueRef};
cc61c64b 14use rustc::dep_graph::{DepGraph, DepGraphSafe};
32a655c1 15use rustc::hir;
54a0048b 16use rustc::hir::def_id::DefId;
ea8adc8c 17use rustc::ich::StableHashingContext;
54a0048b 18use rustc::traits;
54a0048b 19use debuginfo;
cc61c64b 20use callee;
32a655c1 21use base;
54a0048b 22use declare;
54a0048b
SL
23use monomorphize::Instance;
24
a7813a04 25use partitioning::CodegenUnit;
476ff2be
SL
26use type_::Type;
27use rustc_data_structures::base_n;
ea8adc8c
XL
28use rustc::middle::trans::Stats;
29use rustc_data_structures::stable_hasher::StableHashingContextProvider;
30use rustc::session::config::{self, NoDebugInfo};
7cac9316 31use rustc::session::Session;
7cac9316 32use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
ea8adc8c
XL
33use rustc::ty::{self, Ty, TyCtxt};
34use rustc::util::nodemap::FxHashMap;
1a4d82fc 35
54a0048b 36use std::ffi::{CStr, CString};
1a4d82fc
JJ
37use std::cell::{Cell, RefCell};
38use std::ptr;
32a655c1 39use std::iter;
54a0048b 40use std::str;
3b2f2976 41use std::sync::Arc;
7cac9316 42use std::marker::PhantomData;
476ff2be 43use syntax::symbol::InternedString;
cc61c64b 44use abi::Abi;
1a4d82fc 45
1a4d82fc
JJ
46/// The shared portion of a `CrateContext`. There is one `SharedCrateContext`
47/// per crate. The data here is shared between all compilation units of the
48/// crate, so it must not contain references to any LLVM data structures
49/// (aside from metadata-related ones).
62682a34 50pub struct SharedCrateContext<'a, 'tcx: 'a> {
a7813a04 51 tcx: TyCtxt<'a, 'tcx, 'tcx>,
c34b1796 52 check_overflow: bool,
62682a34 53 use_dll_storage_attrs: bool,
1a4d82fc
JJ
54}
55
56/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
57/// per compilation unit. Each one has its own LLVM `ContextRef` so that
58/// several compilation units may be optimized in parallel. All other LLVM
59/// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
cc61c64b 60pub struct LocalCrateContext<'a, 'tcx: 'a> {
1a4d82fc
JJ
61 llmod: ModuleRef,
62 llcx: ContextRef,
ea8adc8c
XL
63 stats: RefCell<Stats>,
64 codegen_unit: Arc<CodegenUnit<'tcx>>,
3b2f2976 65
54a0048b 66 /// Cache instances of monomorphic and polymorphic items
476ff2be 67 instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
1a4d82fc 68 /// Cache generated vtables
ea8adc8c 69 vtables: RefCell<FxHashMap<(Ty<'tcx>,
476ff2be 70 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
1a4d82fc 71 /// Cache of constant strings,
476ff2be 72 const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
1a4d82fc
JJ
73
74 /// Reverse-direction for const ptrs cast from globals.
85aaf69f 75 /// Key is a ValueRef holding a *T,
1a4d82fc
JJ
76 /// Val is a ValueRef holding a *[T].
77 ///
78 /// Needed because LLVM loses pointer->pointee association
79 /// when we ptrcast, and we have to ptrcast during translation
85aaf69f
SL
80 /// of a [T] const because we form a slice, a (*T,usize) pair, not
81 /// a pointer to an LLVM array type. Similar for trait objects.
476ff2be 82 const_unsized: RefCell<FxHashMap<ValueRef, ValueRef>>,
85aaf69f
SL
83
84 /// Cache of emitted const globals (value -> global)
476ff2be 85 const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
1a4d82fc 86
a7813a04 87 /// Mapping from static definitions to their DefId's.
476ff2be 88 statics: RefCell<FxHashMap<ValueRef, DefId>>,
a7813a04 89
c1a9b12d
SL
90 /// List of globals for static variables which need to be passed to the
91 /// LLVM function ReplaceAllUsesWith (RAUW) when translation is complete.
92 /// (We have to make sure we don't invalidate any ValueRefs referring
93 /// to constants.)
94 statics_to_rauw: RefCell<Vec<(ValueRef, ValueRef)>>,
95
cc61c64b
XL
96 /// Statics that will be placed in the llvm.used variable
97 /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
98 used_statics: RefCell<Vec<ValueRef>>,
99
476ff2be 100 lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
ea8adc8c 101 isize_ty: Type,
1a4d82fc 102 opaque_vec_type: Type,
476ff2be 103 str_slice_type: Type,
1a4d82fc 104
1a4d82fc
JJ
105 dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,
106
54a0048b
SL
107 eh_personality: Cell<Option<ValueRef>>,
108 eh_unwind_resume: Cell<Option<ValueRef>>,
109 rust_try_fn: Cell<Option<ValueRef>>,
1a4d82fc 110
476ff2be 111 intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
1a4d82fc 112
c30ab7b3
SL
113 /// A counter that is used for generating local symbol names
114 local_gen_sym_counter: Cell<usize>,
9e0c209e 115
7cac9316
XL
116 /// A placeholder so we can add lifetimes
117 placeholder: PhantomData<&'a ()>,
1a4d82fc
JJ
118}
119
a7813a04
XL
120/// A CrateContext value binds together one LocalCrateContext with the
121/// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
122/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
1a4d82fc 123pub struct CrateContext<'a, 'tcx: 'a> {
62682a34 124 shared: &'a SharedCrateContext<'a, 'tcx>,
cc61c64b 125 local_ccx: &'a LocalCrateContext<'a, 'tcx>,
1a4d82fc
JJ
126}
127
cc61c64b
XL
128impl<'a, 'tcx> CrateContext<'a, 'tcx> {
129 pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
130 local_ccx: &'a LocalCrateContext<'a, 'tcx>)
131 -> Self {
132 CrateContext { shared, local_ccx }
133 }
1a4d82fc
JJ
134}
135
cc61c64b 136impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
1a4d82fc
JJ
137}
138
ea8adc8c
XL
139impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> {
140}
141
142impl<'a, 'tcx> StableHashingContextProvider for SharedCrateContext<'a, 'tcx> {
143 type ContextType = StableHashingContext<'tcx>;
144
145 fn create_stable_hashing_context(&self) -> Self::ContextType {
146 self.tcx.create_stable_hashing_context()
147 }
148}
149
5bcae85e
SL
150pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
151 let reloc_model_arg = match sess.opts.cg.relocation_model {
152 Some(ref s) => &s[..],
153 None => &sess.target.target.options.relocation_model[..],
154 };
155
156 match ::back::write::RELOC_MODEL_ARGS.iter().find(
157 |&&arg| arg.0 == reloc_model_arg) {
158 Some(x) => x.1,
159 _ => {
160 sess.err(&format!("{:?} is not a valid relocation mode",
161 sess.opts
162 .cg
163 .code_model));
164 sess.abort_if_errors();
165 bug!();
166 }
167 }
168}
169
170fn is_any_library(sess: &Session) -> bool {
171 sess.crate_types.borrow().iter().any(|ty| {
172 *ty != config::CrateTypeExecutable
173 })
174}
175
176pub fn is_pie_binary(sess: &Session) -> bool {
177 !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
178}
179
cc61c64b 180pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
1a4d82fc 181 let llcx = llvm::LLVMContextCreate();
85aaf69f 182 let mod_name = CString::new(mod_name).unwrap();
1a4d82fc
JJ
183 let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
184
54a0048b
SL
185 // Ensure the data-layout values hardcoded remain the defaults.
186 if sess.target.target.options.is_builtin {
c1a9b12d
SL
187 let tm = ::back::write::create_target_machine(sess);
188 llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
189 llvm::LLVMRustDisposeTargetMachine(tm);
54a0048b
SL
190
191 let data_layout = llvm::LLVMGetDataLayout(llmod);
192 let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
193 .ok().expect("got a non-UTF8 data-layout from LLVM");
194
5bcae85e
SL
195 // Unfortunately LLVM target specs change over time, and right now we
196 // don't have proper support to work with any more than one
197 // `data_layout` than the one that is in the rust-lang/rust repo. If
198 // this compiler is configured against a custom LLVM, we may have a
199 // differing data layout, even though we should update our own to use
200 // that one.
201 //
202 // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
203 // disable this check entirely as we may be configured with something
204 // that has a different target layout.
205 //
206 // Unsure if this will actually cause breakage when rustc is configured
207 // as such.
208 //
209 // FIXME(#34960)
210 let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
211 let custom_llvm_used = cfg_llvm_root.trim() != "";
212
213 if !custom_llvm_used && sess.target.target.data_layout != data_layout {
54a0048b
SL
214 bug!("data-layout for builtin `{}` target, `{}`, \
215 differs from LLVM default, `{}`",
216 sess.target.target.llvm_target,
217 sess.target.target.data_layout,
218 data_layout);
219 }
c1a9b12d 220 }
1a4d82fc 221
54a0048b
SL
222 let data_layout = CString::new(&sess.target.target.data_layout[..]).unwrap();
223 llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
224
85aaf69f
SL
225 let llvm_target = sess.target.target.llvm_target.as_bytes();
226 let llvm_target = CString::new(llvm_target).unwrap();
1a4d82fc 227 llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
5bcae85e
SL
228
229 if is_pie_binary(sess) {
230 llvm::LLVMRustSetModulePIELevel(llmod);
231 }
232
1a4d82fc
JJ
233 (llcx, llmod)
234}
235
62682a34 236impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
ea8adc8c 237 pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>) -> SharedCrateContext<'b, 'tcx> {
62682a34
SL
238 // An interesting part of Windows which MSVC forces our hand on (and
239 // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
240 // attributes in LLVM IR as well as native dependencies (in C these
241 // correspond to `__declspec(dllimport)`).
242 //
243 // Whenever a dynamic library is built by MSVC it must have its public
244 // interface specified by functions tagged with `dllexport` or otherwise
245 // they're not available to be linked against. This poses a few problems
246 // for the compiler, some of which are somewhat fundamental, but we use
247 // the `use_dll_storage_attrs` variable below to attach the `dllexport`
476ff2be 248 // attribute to all LLVM functions that are exported e.g. they're
62682a34
SL
249 // already tagged with external linkage). This is suboptimal for a few
250 // reasons:
251 //
252 // * If an object file will never be included in a dynamic library,
253 // there's no need to attach the dllexport attribute. Most object
254 // files in Rust are not destined to become part of a dll as binaries
255 // are statically linked by default.
256 // * If the compiler is emitting both an rlib and a dylib, the same
257 // source object file is currently used but with MSVC this may be less
258 // feasible. The compiler may be able to get around this, but it may
259 // involve some invasive changes to deal with this.
260 //
261 // The flipside of this situation is that whenever you link to a dll and
262 // you import a function from it, the import should be tagged with
263 // `dllimport`. At this time, however, the compiler does not emit
264 // `dllimport` for any declarations other than constants (where it is
265 // required), which is again suboptimal for even more reasons!
266 //
267 // * Calling a function imported from another dll without using
268 // `dllimport` causes the linker/compiler to have extra overhead (one
269 // `jmp` instruction on x86) when calling the function.
270 // * The same object file may be used in different circumstances, so a
271 // function may be imported from a dll if the object is linked into a
272 // dll, but it may be just linked against if linked into an rlib.
273 // * The compiler has no knowledge about whether native functions should
274 // be tagged dllimport or not.
275 //
276 // For now the compiler takes the perf hit (I do not have any numbers to
277 // this effect) by marking very little as `dllimport` and praying the
278 // linker will take care of everything. Fixing this problem will likely
279 // require adding a few attributes to Rust itself (feature gated at the
280 // start) and then strongly recommending static linkage on MSVC!
281 let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
282
ea8adc8c
XL
283 let check_overflow = tcx.sess.overflow_checks();
284
a7813a04 285 SharedCrateContext {
3b2f2976
XL
286 tcx,
287 check_overflow,
288 use_dll_storage_attrs,
1a4d82fc
JJ
289 }
290 }
291
32a655c1 292 pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
ea8adc8c 293 common::type_needs_drop(self.tcx, ty)
32a655c1
SL
294 }
295
296 pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
ea8adc8c 297 common::type_is_sized(self.tcx, ty)
32a655c1
SL
298 }
299
cc61c64b 300 pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ea8adc8c 301 common::type_is_freeze(self.tcx, ty)
1a4d82fc
JJ
302 }
303
ea8adc8c 304 pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
1a4d82fc
JJ
305 self.tcx
306 }
307
308 pub fn sess<'a>(&'a self) -> &'a Session {
309 &self.tcx.sess
310 }
311
476ff2be
SL
312 pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
313 &self.tcx.dep_graph
314 }
315
62682a34
SL
316 pub fn use_dll_storage_attrs(&self) -> bool {
317 self.use_dll_storage_attrs
318 }
1a4d82fc
JJ
319}
320
cc61c64b
XL
321impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
322 pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
ea8adc8c
XL
323 codegen_unit: Arc<CodegenUnit<'tcx>>,
324 llmod_id: &str)
cc61c64b 325 -> LocalCrateContext<'a, 'tcx> {
1a4d82fc 326 unsafe {
a7813a04
XL
327 let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
328 &llmod_id[..]);
1a4d82fc 329
1a4d82fc 330 let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
5bcae85e 331 let dctx = debuginfo::CrateDebugContext::new(llmod);
7cac9316
XL
332 debuginfo::metadata::compile_unit_metadata(shared,
333 codegen_unit.name(),
334 &dctx,
335 shared.tcx.sess);
5bcae85e 336 Some(dctx)
1a4d82fc
JJ
337 } else {
338 None
339 };
340
a7813a04 341 let local_ccx = LocalCrateContext {
3b2f2976
XL
342 llmod,
343 llcx,
ea8adc8c 344 stats: RefCell::new(Stats::default()),
3b2f2976 345 codegen_unit,
476ff2be
SL
346 instances: RefCell::new(FxHashMap()),
347 vtables: RefCell::new(FxHashMap()),
348 const_cstr_cache: RefCell::new(FxHashMap()),
349 const_unsized: RefCell::new(FxHashMap()),
350 const_globals: RefCell::new(FxHashMap()),
476ff2be 351 statics: RefCell::new(FxHashMap()),
c1a9b12d 352 statics_to_rauw: RefCell::new(Vec::new()),
cc61c64b 353 used_statics: RefCell::new(Vec::new()),
476ff2be 354 lltypes: RefCell::new(FxHashMap()),
ea8adc8c 355 isize_ty: Type::from_ref(ptr::null_mut()),
1a4d82fc 356 opaque_vec_type: Type::from_ref(ptr::null_mut()),
476ff2be 357 str_slice_type: Type::from_ref(ptr::null_mut()),
3b2f2976 358 dbg_cx,
54a0048b
SL
359 eh_personality: Cell::new(None),
360 eh_unwind_resume: Cell::new(None),
361 rust_try_fn: Cell::new(None),
476ff2be 362 intrinsics: RefCell::new(FxHashMap()),
c30ab7b3 363 local_gen_sym_counter: Cell::new(0),
7cac9316 364 placeholder: PhantomData,
1a4d82fc
JJ
365 };
366
ea8adc8c 367 let (isize_ty, opaque_vec_type, str_slice_ty, mut local_ccx) = {
a7813a04
XL
368 // Do a little dance to create a dummy CrateContext, so we can
369 // create some things in the LLVM module of this codegen unit
370 let mut local_ccxs = vec![local_ccx];
ea8adc8c 371 let (isize_ty, opaque_vec_type, str_slice_ty) = {
a7813a04
XL
372 let dummy_ccx = LocalCrateContext::dummy_ccx(shared,
373 local_ccxs.as_mut_slice());
374 let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice");
375 str_slice_ty.set_struct_body(&[Type::i8p(&dummy_ccx),
ea8adc8c 376 Type::isize(&dummy_ccx)],
a7813a04 377 false);
ea8adc8c 378 (Type::isize(&dummy_ccx), Type::opaque_vec(&dummy_ccx), str_slice_ty)
a7813a04 379 };
ea8adc8c 380 (isize_ty, opaque_vec_type, str_slice_ty, local_ccxs.pop().unwrap())
a7813a04 381 };
1a4d82fc 382
ea8adc8c 383 local_ccx.isize_ty = isize_ty;
a7813a04 384 local_ccx.opaque_vec_type = opaque_vec_type;
476ff2be 385 local_ccx.str_slice_type = str_slice_ty;
1a4d82fc 386
1a4d82fc
JJ
387 local_ccx
388 }
389 }
390
391 /// Create a dummy `CrateContext` from `self` and the provided
392 /// `SharedCrateContext`. This is somewhat dangerous because `self` may
a7813a04 393 /// not be fully initialized.
1a4d82fc
JJ
394 ///
395 /// This is used in the `LocalCrateContext` constructor to allow calling
396 /// functions that expect a complete `CrateContext`, even before the local
397 /// portion is fully initialized and attached to the `SharedCrateContext`.
cc61c64b
XL
398 fn dummy_ccx(shared: &'a SharedCrateContext<'a, 'tcx>,
399 local_ccxs: &'a [LocalCrateContext<'a, 'tcx>])
400 -> CrateContext<'a, 'tcx> {
a7813a04 401 assert!(local_ccxs.len() == 1);
1a4d82fc 402 CrateContext {
3b2f2976 403 shared,
cc61c64b 404 local_ccx: &local_ccxs[0]
1a4d82fc
JJ
405 }
406 }
cc61c64b
XL
407
408 pub fn into_stats(self) -> Stats {
ea8adc8c 409 self.stats.into_inner()
cc61c64b 410 }
1a4d82fc
JJ
411}
412
413impl<'b, 'tcx> CrateContext<'b, 'tcx> {
62682a34 414 pub fn shared(&self) -> &'b SharedCrateContext<'b, 'tcx> {
1a4d82fc
JJ
415 self.shared
416 }
417
cc61c64b
XL
418 fn local(&self) -> &'b LocalCrateContext<'b, 'tcx> {
419 self.local_ccx
1a4d82fc
JJ
420 }
421
ea8adc8c 422 pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
62682a34 423 self.shared.tcx
1a4d82fc
JJ
424 }
425
426 pub fn sess<'a>(&'a self) -> &'a Session {
427 &self.shared.tcx.sess
428 }
429
e9174d1e 430 pub fn get_intrinsic(&self, key: &str) -> ValueRef {
1a4d82fc
JJ
431 if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
432 return v;
433 }
434 match declare_intrinsic(self, key) {
435 Some(v) => return v,
54a0048b 436 None => bug!("unknown intrinsic '{}'", key)
1a4d82fc
JJ
437 }
438 }
439
1a4d82fc 440 pub fn llmod(&self) -> ModuleRef {
a7813a04 441 self.local().llmod
1a4d82fc
JJ
442 }
443
444 pub fn llcx(&self) -> ContextRef {
a7813a04
XL
445 self.local().llcx
446 }
447
448 pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
449 &self.local().codegen_unit
1a4d82fc
JJ
450 }
451
c1a9b12d
SL
452 pub fn td(&self) -> llvm::TargetDataRef {
453 unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
1a4d82fc
JJ
454 }
455
476ff2be 456 pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef>> {
a7813a04 457 &self.local().instances
1a4d82fc
JJ
458 }
459
476ff2be 460 pub fn vtables<'a>(&'a self)
ea8adc8c 461 -> &'a RefCell<FxHashMap<(Ty<'tcx>,
476ff2be 462 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
a7813a04 463 &self.local().vtables
1a4d82fc
JJ
464 }
465
476ff2be 466 pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FxHashMap<InternedString, ValueRef>> {
a7813a04 467 &self.local().const_cstr_cache
1a4d82fc
JJ
468 }
469
476ff2be 470 pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
a7813a04 471 &self.local().const_unsized
85aaf69f
SL
472 }
473
476ff2be 474 pub fn const_globals<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, ValueRef>> {
a7813a04 475 &self.local().const_globals
1a4d82fc
JJ
476 }
477
476ff2be 478 pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> {
a7813a04 479 &self.local().statics
1a4d82fc
JJ
480 }
481
c1a9b12d 482 pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
a7813a04 483 &self.local().statics_to_rauw
c1a9b12d
SL
484 }
485
cc61c64b
XL
486 pub fn used_statics<'a>(&'a self) -> &'a RefCell<Vec<ValueRef>> {
487 &self.local().used_statics
488 }
489
476ff2be 490 pub fn lltypes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, Type>> {
a7813a04 491 &self.local().lltypes
1a4d82fc
JJ
492 }
493
ea8adc8c 494 pub fn stats<'a>(&'a self) -> &'a RefCell<Stats> {
cc61c64b 495 &self.local().stats
1a4d82fc
JJ
496 }
497
ea8adc8c
XL
498 pub fn isize_ty(&self) -> Type {
499 self.local().isize_ty
1a4d82fc
JJ
500 }
501
476ff2be
SL
502 pub fn str_slice_type(&self) -> Type {
503 self.local().str_slice_type
504 }
505
1a4d82fc 506 pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
a7813a04 507 &self.local().dbg_cx
1a4d82fc
JJ
508 }
509
54a0048b 510 pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
a7813a04 511 &self.local().rust_try_fn
c1a9b12d
SL
512 }
513
476ff2be 514 fn intrinsics<'a>(&'a self) -> &'a RefCell<FxHashMap<&'static str, ValueRef>> {
a7813a04 515 &self.local().intrinsics
1a4d82fc
JJ
516 }
517
9e0c209e
SL
518 pub fn check_overflow(&self) -> bool {
519 self.shared.check_overflow
1a4d82fc 520 }
62682a34
SL
521
522 pub fn use_dll_storage_attrs(&self) -> bool {
523 self.shared.use_dll_storage_attrs()
524 }
92a42be0 525
c30ab7b3
SL
526 /// Generate a new symbol name with the given prefix. This symbol name must
527 /// only be used for definitions with `internal` or `private` linkage.
528 pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
529 let idx = self.local().local_gen_sym_counter.get();
530 self.local().local_gen_sym_counter.set(idx + 1);
531 // Include a '.' character, so there can be no accidental conflicts with
532 // user defined names
476ff2be
SL
533 let mut name = String::with_capacity(prefix.len() + 6);
534 name.push_str(prefix);
535 name.push_str(".");
536 base_n::push_str(idx as u64, base_n::ALPHANUMERIC_ONLY, &mut name);
537 name
c30ab7b3 538 }
32a655c1
SL
539
540 pub fn eh_personality(&self) -> ValueRef {
541 // The exception handling personality function.
542 //
543 // If our compilation unit has the `eh_personality` lang item somewhere
544 // within it, then we just need to translate that. Otherwise, we're
545 // building an rlib which will depend on some upstream implementation of
546 // this function, so we just codegen a generic reference to it. We don't
547 // specify any of the types for the function, we just make it a symbol
548 // that LLVM can later use.
549 //
550 // Note that MSVC is a little special here in that we don't use the
551 // `eh_personality` lang item at all. Currently LLVM has support for
552 // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
553 // *name of the personality function* to decide what kind of unwind side
554 // tables/landing pads to emit. It looks like Dwarf is used by default,
555 // injecting a dependency on the `_Unwind_Resume` symbol for resuming
556 // an "exception", but for MSVC we want to force SEH. This means that we
557 // can't actually have the personality function be our standard
558 // `rust_eh_personality` function, but rather we wired it up to the
559 // CRT's custom personality function, which forces LLVM to consider
560 // landing pads as "landing pads for SEH".
561 if let Some(llpersonality) = self.local().eh_personality.get() {
562 return llpersonality
563 }
564 let tcx = self.tcx();
ea8adc8c 565 let llfn = match tcx.lang_items().eh_personality() {
32a655c1 566 Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
cc61c64b 567 callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
32a655c1
SL
568 }
569 _ => {
570 let name = if base::wants_msvc_seh(self.sess()) {
571 "__CxxFrameHandler3"
572 } else {
573 "rust_eh_personality"
574 };
575 let fty = Type::variadic_func(&[], &Type::i32(self));
576 declare::declare_cfn(self, name, fty)
577 }
578 };
579 self.local().eh_personality.set(Some(llfn));
580 llfn
581 }
582
583 // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
584 // otherwise declares it as an external function.
585 pub fn eh_unwind_resume(&self) -> ValueRef {
586 use attributes;
587 let unwresume = &self.local().eh_unwind_resume;
588 if let Some(llfn) = unwresume.get() {
589 return llfn;
590 }
591
592 let tcx = self.tcx();
593 assert!(self.sess().target.target.options.custom_unwind_resume);
ea8adc8c 594 if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
cc61c64b 595 let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
32a655c1
SL
596 unwresume.set(Some(llfn));
597 return llfn;
598 }
599
8bb4bdeb
XL
600 let ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
601 iter::once(tcx.mk_mut_ptr(tcx.types.u8)),
602 tcx.types.never,
603 false,
604 hir::Unsafety::Unsafe,
605 Abi::C
606 )));
32a655c1
SL
607
608 let llfn = declare::declare_fn(self, "rust_eh_unwind_resume", ty);
609 attributes::unwind(llfn, true);
610 unwresume.set(Some(llfn));
611 llfn
612 }
92a42be0
SL
613}
614
cc61c64b
XL
615impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
616 fn data_layout(&self) -> &ty::layout::TargetDataLayout {
617 &self.tcx.data_layout
618 }
619}
620
cc61c64b
XL
621impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
622 fn data_layout(&self) -> &ty::layout::TargetDataLayout {
623 &self.shared.tcx.data_layout
624 }
625}
626
cc61c64b
XL
627impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
628 type TyLayout = TyLayout<'tcx>;
629
7cac9316
XL
630 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
631 self.tcx
632 }
cc61c64b 633
7cac9316
XL
634 fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
635 let param_env = ty::ParamEnv::empty(traits::Reveal::All);
636 LayoutCx::new(self.tcx, param_env)
637 .layout_of(ty)
638 .unwrap_or_else(|e| match e {
639 LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
640 _ => bug!("failed to get layout for `{}`: {}", ty, e)
cc61c64b 641 })
cc61c64b
XL
642 }
643
644 fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
645 self.tcx().normalize_associated_type(&ty)
646 }
647}
648
649impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
650 type TyLayout = TyLayout<'tcx>;
651
7cac9316
XL
652 fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
653 self.shared.tcx
654 }
655
cc61c64b
XL
656 fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
657 self.shared.layout_of(ty)
658 }
659
660 fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
661 self.shared.normalize_projections(ty)
662 }
663}
664
d9579d0f 665/// Declare any llvm intrinsics that you might need
e9174d1e 666fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
1a4d82fc
JJ
667 macro_rules! ifn {
668 ($name:expr, fn() -> $ret:expr) => (
e9174d1e 669 if key == $name {
54a0048b 670 let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret));
e9174d1e 671 llvm::SetUnnamedAddr(f, false);
1a4d82fc
JJ
672 ccx.intrinsics().borrow_mut().insert($name, f.clone());
673 return Some(f);
674 }
675 );
7453a54e
SL
676 ($name:expr, fn(...) -> $ret:expr) => (
677 if key == $name {
54a0048b 678 let f = declare::declare_cfn(ccx, $name, Type::variadic_func(&[], &$ret));
7453a54e
SL
679 llvm::SetUnnamedAddr(f, false);
680 ccx.intrinsics().borrow_mut().insert($name, f.clone());
681 return Some(f);
682 }
683 );
1a4d82fc 684 ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
e9174d1e 685 if key == $name {
54a0048b 686 let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret));
e9174d1e 687 llvm::SetUnnamedAddr(f, false);
1a4d82fc
JJ
688 ccx.intrinsics().borrow_mut().insert($name, f.clone());
689 return Some(f);
690 }
7453a54e 691 );
1a4d82fc
JJ
692 }
693 macro_rules! mk_struct {
694 ($($field_ty:expr),*) => (Type::struct_(ccx, &[$($field_ty),*], false))
695 }
696
697 let i8p = Type::i8p(ccx);
698 let void = Type::void(ccx);
699 let i1 = Type::i1(ccx);
700 let t_i8 = Type::i8(ccx);
701 let t_i16 = Type::i16(ccx);
702 let t_i32 = Type::i32(ccx);
703 let t_i64 = Type::i64(ccx);
32a655c1 704 let t_i128 = Type::i128(ccx);
1a4d82fc
JJ
705 let t_f32 = Type::f32(ccx);
706 let t_f64 = Type::f64(ccx);
707
e9174d1e 708 ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
1a4d82fc
JJ
709 ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
710 ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
e9174d1e 711 ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
1a4d82fc
JJ
712 ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
713 ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
e9174d1e 714 ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
1a4d82fc
JJ
715 ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
716 ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);
717
718 ifn!("llvm.trap", fn() -> void);
719 ifn!("llvm.debugtrap", fn() -> void);
7453a54e 720 ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
1a4d82fc
JJ
721
722 ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
723 ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
724 ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
725 ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
726
727 ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
728 ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
729 ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
730 ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
731 ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
732 ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
733 ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
734 ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
735 ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
736 ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
737 ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
738 ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
739 ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
740 ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
741 ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
742 ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
743
744 ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
745 ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
746
747 ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
748 ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
749
750 ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
751 ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
752 ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
753 ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
754 ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
755 ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
756
62682a34
SL
757 ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
758 ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
759 ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
760 ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
761
1a4d82fc
JJ
762 ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
763 ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
764 ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
765 ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
766
767 ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
768 ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
769 ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
770 ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
32a655c1 771 ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128);
1a4d82fc
JJ
772
773 ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8);
774 ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
775 ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
776 ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
32a655c1 777 ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128);
1a4d82fc
JJ
778
779 ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8);
780 ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
781 ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
782 ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
32a655c1 783 ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128);
1a4d82fc
JJ
784
785 ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
786 ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
787 ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
32a655c1 788 ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
1a4d82fc
JJ
789
790 ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
791 ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
792 ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
793 ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 794 ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
795
796 ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
797 ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
798 ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
799 ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 800 ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
801
802 ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
803 ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
804 ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
805 ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 806 ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
807
808 ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
809 ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
810 ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
811 ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 812 ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
813
814 ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
815 ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
816 ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
817 ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 818 ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
819
820 ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
821 ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
822 ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
823 ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
32a655c1 824 ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
1a4d82fc
JJ
825
826 ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void);
827 ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);
828
829 ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
c1a9b12d 830 ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
7453a54e
SL
831 ifn!("llvm.localescape", fn(...) -> void);
832 ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p);
833 ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
1a4d82fc 834
3157f602 835 ifn!("llvm.assume", fn(i1) -> void);
7cac9316 836 ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
1a4d82fc
JJ
837
838 if ccx.sess().opts.debuginfo != NoDebugInfo {
839 ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
840 ifn!("llvm.dbg.value", fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);
841 }
842 return None;
843}