]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
ea8adc8c | 11 | use common; |
1a4d82fc | 12 | use llvm; |
32a655c1 | 13 | use llvm::{ContextRef, ModuleRef, ValueRef}; |
cc61c64b | 14 | use rustc::dep_graph::{DepGraph, DepGraphSafe}; |
32a655c1 | 15 | use rustc::hir; |
54a0048b | 16 | use rustc::hir::def_id::DefId; |
ea8adc8c | 17 | use rustc::ich::StableHashingContext; |
54a0048b | 18 | use rustc::traits; |
54a0048b | 19 | use debuginfo; |
cc61c64b | 20 | use callee; |
32a655c1 | 21 | use base; |
54a0048b | 22 | use declare; |
54a0048b SL |
23 | use monomorphize::Instance; |
24 | ||
a7813a04 | 25 | use partitioning::CodegenUnit; |
476ff2be SL |
26 | use type_::Type; |
27 | use rustc_data_structures::base_n; | |
ea8adc8c XL |
28 | use rustc::middle::trans::Stats; |
29 | use rustc_data_structures::stable_hasher::StableHashingContextProvider; | |
30 | use rustc::session::config::{self, NoDebugInfo}; | |
7cac9316 | 31 | use rustc::session::Session; |
7cac9316 | 32 | use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout}; |
ea8adc8c XL |
33 | use rustc::ty::{self, Ty, TyCtxt}; |
34 | use rustc::util::nodemap::FxHashMap; | |
1a4d82fc | 35 | |
54a0048b | 36 | use std::ffi::{CStr, CString}; |
1a4d82fc JJ |
37 | use std::cell::{Cell, RefCell}; |
38 | use std::ptr; | |
32a655c1 | 39 | use std::iter; |
54a0048b | 40 | use std::str; |
3b2f2976 | 41 | use std::sync::Arc; |
7cac9316 | 42 | use std::marker::PhantomData; |
476ff2be | 43 | use syntax::symbol::InternedString; |
cc61c64b | 44 | use 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 | 50 | pub 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 | 60 | pub 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 | 123 | pub 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 |
128 | impl<'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 | 136 | impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> { |
1a4d82fc JJ |
137 | } |
138 | ||
ea8adc8c XL |
139 | impl<'a, 'tcx> DepGraphSafe for SharedCrateContext<'a, 'tcx> { |
140 | } | |
141 | ||
142 | impl<'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 |
150 | pub 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 | ||
170 | fn is_any_library(sess: &Session) -> bool { | |
171 | sess.crate_types.borrow().iter().any(|ty| { | |
172 | *ty != config::CrateTypeExecutable | |
173 | }) | |
174 | } | |
175 | ||
176 | pub fn is_pie_binary(sess: &Session) -> bool { | |
177 | !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC | |
178 | } | |
179 | ||
cc61c64b | 180 | pub 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 | 236 | impl<'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 |
321 | impl<'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 | ||
413 | impl<'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 |
615 | impl<'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 |
621 | impl<'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 |
627 | impl<'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 | ||
649 | impl<'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 | 666 | fn 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 | } |