]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/context.rs
New upstream version 1.53.0+dfsg1
[rustc.git] / compiler / rustc_codegen_llvm / src / context.rs
CommitLineData
9fa01778 1use crate::attributes;
6a06907d 2use crate::back::write::to_llvm_code_model;
ba9703b0 3use crate::callee::get_fn;
f035d41b 4use crate::coverageinfo;
dfeec247 5use crate::debuginfo;
9fa01778 6use crate::llvm;
416331ca 7use crate::llvm_util;
9fa01778 8use crate::type_::Type;
ba9703b0 9use crate::value::Value;
ff7c6d11 10
6a06907d 11use cstr::cstr;
a1dfa0c6 12use rustc_codegen_ssa::base::wants_msvc_seh;
ba9703b0 13use rustc_codegen_ssa::traits::*;
dfeec247 14use rustc_data_structures::base_n;
dfeec247
XL
15use rustc_data_structures::fx::FxHashMap;
16use rustc_data_structures::small_c_str::SmallCStr;
ba9703b0
XL
17use rustc_middle::bug;
18use rustc_middle::mir::mono::CodegenUnit;
19use rustc_middle::ty::layout::{HasParamEnv, LayoutError, TyAndLayout};
20use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
f9f354fc 21use rustc_session::config::{CFGuard, CrateType, DebugInfo};
ba9703b0 22use rustc_session::Session;
dfeec247
XL
23use rustc_span::source_map::{Span, DUMMY_SP};
24use rustc_span::symbol::Symbol;
ba9703b0 25use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx};
f9f354fc 26use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
ba9703b0 27
1a4d82fc 28use std::cell::{Cell, RefCell};
dfeec247 29use std::ffi::CStr;
54a0048b 30use std::str;
1a4d82fc 31
2c00a5a8 32/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
b7449926
XL
33/// `llvm::Context` so that several compilation units may be optimized in parallel.
34/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
dc9dc135
XL
35pub struct CodegenCx<'ll, 'tcx> {
36 pub tcx: TyCtxt<'tcx>,
2c00a5a8
XL
37 pub check_overflow: bool,
38 pub use_dll_storage_attrs: bool,
39 pub tls_model: llvm::ThreadLocalMode,
1a4d82fc 40
a1dfa0c6
XL
41 pub llmod: &'ll llvm::Module,
42 pub llcx: &'ll llvm::Context,
ba9703b0 43 pub codegen_unit: &'tcx CodegenUnit<'tcx>,
3b2f2976 44
54a0048b 45 /// Cache instances of monomorphic and polymorphic items
a1dfa0c6 46 pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
1a4d82fc 47 /// Cache generated vtables
dc9dc135
XL
48 pub vtables:
49 RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
1a4d82fc 50 /// Cache of constant strings,
e1599b0c 51 pub const_cstr_cache: RefCell<FxHashMap<Symbol, &'ll Value>>,
1a4d82fc
JJ
52
53 /// Reverse-direction for const ptrs cast from globals.
f9f354fc
XL
54 ///
55 /// Key is a Value holding a `*T`,
56 /// Val is a Value holding a `*[T]`.
1a4d82fc
JJ
57 ///
58 /// Needed because LLVM loses pointer->pointee association
94b46f34 59 /// when we ptrcast, and we have to ptrcast during codegen
f9f354fc 60 /// of a `[T]` const because we form a slice, a `(*T,usize)` pair, not
85aaf69f 61 /// a pointer to an LLVM array type. Similar for trait objects.
a1dfa0c6 62 pub const_unsized: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
85aaf69f
SL
63
64 /// Cache of emitted const globals (value -> global)
a1dfa0c6 65 pub const_globals: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
a7813a04 66
c1a9b12d 67 /// List of globals for static variables which need to be passed to the
94b46f34 68 /// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete.
b7449926 69 /// (We have to make sure we don't invalidate any Values referring
c1a9b12d 70 /// to constants.)
a1dfa0c6 71 pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
c1a9b12d 72
cc61c64b 73 /// Statics that will be placed in the llvm.used variable
9fa01778 74 /// See <http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
a1dfa0c6 75 pub used_statics: RefCell<Vec<&'ll Value>>,
cc61c64b 76
a1dfa0c6
XL
77 pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
78 pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
2c00a5a8 79 pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
a1dfa0c6 80 pub isize_ty: &'ll Type,
1a4d82fc 81
cdc7bbd5 82 pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
a1dfa0c6 83 pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
1a4d82fc 84
a1dfa0c6 85 eh_personality: Cell<Option<&'ll Value>>,
1b1a35ee 86 eh_catch_typeinfo: Cell<Option<&'ll Value>>,
a1dfa0c6 87 pub rust_try_fn: Cell<Option<&'ll Value>>,
1a4d82fc 88
a1dfa0c6 89 intrinsics: RefCell<FxHashMap<&'static str, &'ll Value>>,
1a4d82fc 90
c30ab7b3
SL
91 /// A counter that is used for generating local symbol names
92 local_gen_sym_counter: Cell<usize>,
ea8adc8c
XL
93}
94
f9f354fc
XL
95fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
96 match tls_model {
97 TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
98 TlsModel::LocalDynamic => llvm::ThreadLocalMode::LocalDynamic,
99 TlsModel::InitialExec => llvm::ThreadLocalMode::InitialExec,
100 TlsModel::LocalExec => llvm::ThreadLocalMode::LocalExec,
abe05a73
XL
101 }
102}
103
6a06907d
XL
104fn strip_powerpc64_vectors(data_layout: String) -> String {
105 data_layout.replace("-v256:256:256-v512:512:512", "")
106}
107
b7449926 108pub unsafe fn create_module(
dc9dc135 109 tcx: TyCtxt<'_>,
b7449926
XL
110 llcx: &'ll llvm::Context,
111 mod_name: &str,
112) -> &'ll llvm::Module {
9fa01778 113 let sess = tcx.sess;
b7449926 114 let mod_name = SmallCStr::new(mod_name);
1a4d82fc
JJ
115 let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
116
29967ef6 117 let mut target_data_layout = sess.target.data_layout.clone();
6a06907d
XL
118 if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
119 target_data_layout = strip_powerpc64_vectors(target_data_layout);
120 }
416331ca 121
54a0048b 122 // Ensure the data-layout values hardcoded remain the defaults.
29967ef6 123 if sess.target.is_builtin {
f9f354fc 124 let tm = crate::back::write::create_informational_target_machine(tcx.sess);
c1a9b12d
SL
125 llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
126 llvm::LLVMRustDisposeTargetMachine(tm);
54a0048b 127
ba9703b0 128 let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
416331ca 129 let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
dfeec247 130 .expect("got a non-UTF8 data-layout from LLVM");
54a0048b 131
5bcae85e
SL
132 // Unfortunately LLVM target specs change over time, and right now we
133 // don't have proper support to work with any more than one
134 // `data_layout` than the one that is in the rust-lang/rust repo. If
135 // this compiler is configured against a custom LLVM, we may have a
136 // differing data layout, even though we should update our own to use
137 // that one.
138 //
139 // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
140 // disable this check entirely as we may be configured with something
141 // that has a different target layout.
142 //
143 // Unsure if this will actually cause breakage when rustc is configured
144 // as such.
145 //
146 // FIXME(#34960)
147 let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
148 let custom_llvm_used = cfg_llvm_root.trim() != "";
149
416331ca 150 if !custom_llvm_used && target_data_layout != llvm_data_layout {
dfeec247
XL
151 bug!(
152 "data-layout for builtin `{}` target, `{}`, \
54a0048b 153 differs from LLVM default, `{}`",
29967ef6 154 sess.target.llvm_target,
dfeec247
XL
155 target_data_layout,
156 llvm_data_layout
157 );
54a0048b 158 }
c1a9b12d 159 }
1a4d82fc 160
416331ca 161 let data_layout = SmallCStr::new(&target_data_layout);
54a0048b
SL
162 llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
163
29967ef6 164 let llvm_target = SmallCStr::new(&sess.target.llvm_target);
1a4d82fc 165 llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
5bcae85e 166
f9f354fc 167 if sess.relocation_model() == RelocModel::Pic {
60c5eb7d 168 llvm::LLVMRustSetModulePICLevel(llmod);
f9f354fc
XL
169 // PIE is potentially more effective than PIC, but can only be used in executables.
170 // If all our outputs are executables, then we can relax PIC to PIE.
171 if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
172 llvm::LLVMRustSetModulePIELevel(llmod);
173 }
5bcae85e
SL
174 }
175
6a06907d
XL
176 // Linking object files with different code models is undefined behavior
177 // because the compiler would have to generate additional code (to span
178 // longer jumps) if a larger code model is used with a smaller one.
179 //
180 // See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.
181 llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
182
0bf4aa26
XL
183 // If skipping the PLT is enabled, we need to add some module metadata
184 // to ensure intrinsic calls don't use it.
185 if !sess.needs_plt() {
e74abb32 186 let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
0bf4aa26
XL
187 llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
188 }
189
f035d41b 190 // Control Flow Guard is currently only supported by the MSVC linker on Windows.
29967ef6 191 if sess.target.is_like_msvc {
3dfed10e 192 match sess.opts.cg.control_flow_guard {
f035d41b
XL
193 CFGuard::Disabled => {}
194 CFGuard::NoChecks => {
195 // Set `cfguard=1` module flag to emit metadata only.
196 llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 1)
197 }
198 CFGuard::Checks => {
199 // Set `cfguard=2` module flag to emit metadata and checks.
200 llvm::LLVMRustAddModuleFlag(llmod, "cfguard\0".as_ptr() as *const _, 2)
201 }
74b04a01 202 }
74b04a01
XL
203 }
204
b7449926 205 llmod
1a4d82fc
JJ
206}
207
a1dfa0c6 208impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
dc9dc135
XL
209 crate fn new(
210 tcx: TyCtxt<'tcx>,
ba9703b0 211 codegen_unit: &'tcx CodegenUnit<'tcx>,
dc9dc135
XL
212 llvm_module: &'ll crate::ModuleLlvm,
213 ) -> Self {
62682a34
SL
214 // An interesting part of Windows which MSVC forces our hand on (and
215 // apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
216 // attributes in LLVM IR as well as native dependencies (in C these
217 // correspond to `__declspec(dllimport)`).
218 //
3dfed10e
XL
219 // LD (BFD) in MinGW mode can often correctly guess `dllexport` but
220 // relying on that can result in issues like #50176.
221 // LLD won't support that and expects symbols with proper attributes.
222 // Because of that we make MinGW target emit dllexport just like MSVC.
223 // When it comes to dllimport we use it for constants but for functions
224 // rely on the linker to do the right thing. Opposed to dllexport this
225 // task is easy for them (both LD and LLD) and allows us to easily use
226 // symbols from static libraries in shared libraries.
227 //
228 // Whenever a dynamic library is built on Windows it must have its public
62682a34
SL
229 // interface specified by functions tagged with `dllexport` or otherwise
230 // they're not available to be linked against. This poses a few problems
231 // for the compiler, some of which are somewhat fundamental, but we use
232 // the `use_dll_storage_attrs` variable below to attach the `dllexport`
0731742a 233 // attribute to all LLVM functions that are exported e.g., they're
62682a34
SL
234 // already tagged with external linkage). This is suboptimal for a few
235 // reasons:
236 //
237 // * If an object file will never be included in a dynamic library,
238 // there's no need to attach the dllexport attribute. Most object
239 // files in Rust are not destined to become part of a dll as binaries
240 // are statically linked by default.
241 // * If the compiler is emitting both an rlib and a dylib, the same
242 // source object file is currently used but with MSVC this may be less
243 // feasible. The compiler may be able to get around this, but it may
244 // involve some invasive changes to deal with this.
245 //
246 // The flipside of this situation is that whenever you link to a dll and
247 // you import a function from it, the import should be tagged with
248 // `dllimport`. At this time, however, the compiler does not emit
249 // `dllimport` for any declarations other than constants (where it is
250 // required), which is again suboptimal for even more reasons!
251 //
252 // * Calling a function imported from another dll without using
253 // `dllimport` causes the linker/compiler to have extra overhead (one
254 // `jmp` instruction on x86) when calling the function.
255 // * The same object file may be used in different circumstances, so a
256 // function may be imported from a dll if the object is linked into a
257 // dll, but it may be just linked against if linked into an rlib.
258 // * The compiler has no knowledge about whether native functions should
259 // be tagged dllimport or not.
260 //
261 // For now the compiler takes the perf hit (I do not have any numbers to
262 // this effect) by marking very little as `dllimport` and praying the
263 // linker will take care of everything. Fixing this problem will likely
264 // require adding a few attributes to Rust itself (feature gated at the
3dfed10e 265 // start) and then strongly recommending static linkage on Windows!
29967ef6 266 let use_dll_storage_attrs = tcx.sess.target.is_like_windows;
62682a34 267
ea8adc8c
XL
268 let check_overflow = tcx.sess.overflow_checks();
269
f9f354fc 270 let tls_model = to_llvm_tls_model(tcx.sess.tls_model());
abe05a73 271
b7449926 272 let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
cc61c64b 273
cdc7bbd5 274 let coverage_cx = if tcx.sess.instrument_coverage() {
f035d41b
XL
275 let covctx = coverageinfo::CrateCoverageContext::new();
276 Some(covctx)
277 } else {
278 None
279 };
280
b7449926
XL
281 let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
282 let dctx = debuginfo::CrateDebugContext::new(llmod);
dfeec247 283 debuginfo::metadata::compile_unit_metadata(tcx, &codegen_unit.name().as_str(), &dctx);
b7449926
XL
284 Some(dctx)
285 } else {
286 None
287 };
288
289 let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits());
290
291 CodegenCx {
292 tcx,
293 check_overflow,
294 use_dll_storage_attrs,
295 tls_model,
296 llmod,
297 llcx,
b7449926 298 codegen_unit,
0bf4aa26
XL
299 instances: Default::default(),
300 vtables: Default::default(),
301 const_cstr_cache: Default::default(),
302 const_unsized: Default::default(),
303 const_globals: Default::default(),
b7449926
XL
304 statics_to_rauw: RefCell::new(Vec::new()),
305 used_statics: RefCell::new(Vec::new()),
0bf4aa26
XL
306 lltypes: Default::default(),
307 scalar_lltypes: Default::default(),
308 pointee_infos: Default::default(),
b7449926 309 isize_ty,
f035d41b 310 coverage_cx,
b7449926
XL
311 dbg_cx,
312 eh_personality: Cell::new(None),
1b1a35ee 313 eh_catch_typeinfo: Cell::new(None),
b7449926 314 rust_try_fn: Cell::new(None),
0bf4aa26 315 intrinsics: Default::default(),
b7449926
XL
316 local_gen_sym_counter: Cell::new(0),
317 }
cc61c64b 318 }
a1dfa0c6
XL
319
320 crate fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
321 &self.statics_to_rauw
322 }
f035d41b
XL
323
324 #[inline]
cdc7bbd5 325 pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> {
29967ef6 326 self.coverage_cx.as_ref()
f035d41b 327 }
1a4d82fc
JJ
328}
329
a1dfa0c6 330impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
dfeec247
XL
331 fn vtables(
332 &self,
333 ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
a1dfa0c6
XL
334 {
335 &self.vtables
1a4d82fc
JJ
336 }
337
e74abb32
XL
338 fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
339 get_fn(self, instance)
a1dfa0c6 340 }
0bf4aa26 341
e74abb32 342 fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value {
a1dfa0c6 343 get_fn(self, instance)
1a4d82fc
JJ
344 }
345
a1dfa0c6 346 fn eh_personality(&self) -> &'ll Value {
32a655c1
SL
347 // The exception handling personality function.
348 //
349 // If our compilation unit has the `eh_personality` lang item somewhere
94b46f34 350 // within it, then we just need to codegen that. Otherwise, we're
32a655c1
SL
351 // building an rlib which will depend on some upstream implementation of
352 // this function, so we just codegen a generic reference to it. We don't
353 // specify any of the types for the function, we just make it a symbol
354 // that LLVM can later use.
355 //
356 // Note that MSVC is a little special here in that we don't use the
357 // `eh_personality` lang item at all. Currently LLVM has support for
358 // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
359 // *name of the personality function* to decide what kind of unwind side
360 // tables/landing pads to emit. It looks like Dwarf is used by default,
361 // injecting a dependency on the `_Unwind_Resume` symbol for resuming
362 // an "exception", but for MSVC we want to force SEH. This means that we
363 // can't actually have the personality function be our standard
364 // `rust_eh_personality` function, but rather we wired it up to the
365 // CRT's custom personality function, which forces LLVM to consider
366 // landing pads as "landing pads for SEH".
2c00a5a8 367 if let Some(llpersonality) = self.eh_personality.get() {
dfeec247 368 return llpersonality;
32a655c1 369 }
2c00a5a8 370 let tcx = self.tcx;
ea8adc8c 371 let llfn = match tcx.lang_items().eh_personality() {
dfeec247
XL
372 Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr(
373 ty::Instance::resolve(
374 tcx,
375 ty::ParamEnv::reveal_all(),
376 def_id,
377 tcx.intern_substs(&[]),
e74abb32 378 )
f9f354fc 379 .unwrap()
dfeec247
XL
380 .unwrap(),
381 ),
32a655c1 382 _ => {
a1dfa0c6 383 let name = if wants_msvc_seh(self.sess()) {
32a655c1
SL
384 "__CxxFrameHandler3"
385 } else {
386 "rust_eh_personality"
387 };
a1dfa0c6 388 let fty = self.type_variadic_func(&[], self.type_i32());
6a06907d 389 self.declare_cfn(name, llvm::UnnamedAddr::Global, fty)
32a655c1
SL
390 }
391 };
b7449926 392 attributes::apply_target_cpu_attr(self, llfn);
2c00a5a8 393 self.eh_personality.set(Some(llfn));
32a655c1
SL
394 llfn
395 }
396
a1dfa0c6
XL
397 fn sess(&self) -> &Session {
398 &self.tcx.sess
399 }
400
401 fn check_overflow(&self) -> bool {
402 self.check_overflow
403 }
404
ba9703b0
XL
405 fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> {
406 self.codegen_unit
a1dfa0c6
XL
407 }
408
409 fn used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
410 &self.used_statics
411 }
412
413 fn set_frame_pointer_elimination(&self, llfn: &'ll Value) {
414 attributes::set_frame_pointer_elimination(self, llfn)
415 }
416
417 fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
29967ef6
XL
418 attributes::apply_target_cpu_attr(self, llfn);
419 attributes::apply_tune_cpu_attr(self, llfn);
a1dfa0c6
XL
420 }
421
a1dfa0c6 422 fn create_used_variable(&self) {
6a06907d
XL
423 let name = cstr!("llvm.used");
424 let section = cstr!("llvm.metadata");
dfeec247
XL
425 let array =
426 self.const_array(&self.type_ptr_to(self.type_i8()), &*self.used_statics.borrow());
a1dfa0c6
XL
427
428 unsafe {
dfeec247 429 let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr());
a1dfa0c6
XL
430 llvm::LLVMSetInitializer(g, array);
431 llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);
432 llvm::LLVMSetSection(g, section.as_ptr());
433 }
2c00a5a8 434 }
1b1a35ee
XL
435
436 fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
437 if self.get_declared_value("main").is_none() {
6a06907d 438 Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type))
1b1a35ee
XL
439 } else {
440 // If the symbol already exists, it is an error: for example, the user wrote
441 // #[no_mangle] extern "C" fn main(..) {..}
442 // instead of #[start]
443 None
444 }
445 }
a1dfa0c6
XL
446}
447
448impl CodegenCx<'b, 'tcx> {
449 crate fn get_intrinsic(&self, key: &str) -> &'b Value {
450 if let Some(v) = self.intrinsics.borrow().get(key).cloned() {
451 return v;
452 }
2c00a5a8 453
a1dfa0c6 454 self.declare_intrinsic(key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key))
2c00a5a8
XL
455 }
456
9fa01778 457 fn insert_intrinsic(
dfeec247
XL
458 &self,
459 name: &'static str,
460 args: Option<&[&'b llvm::Type]>,
461 ret: &'b llvm::Type,
9fa01778
XL
462 ) -> &'b llvm::Value {
463 let fn_ty = if let Some(args) = args {
464 self.type_func(args, ret)
465 } else {
466 self.type_variadic_func(&[], ret)
467 };
6a06907d 468 let f = self.declare_cfn(name, llvm::UnnamedAddr::No, fn_ty);
dc9dc135 469 self.intrinsics.borrow_mut().insert(name, f);
9fa01778
XL
470 f
471 }
472
dfeec247 473 fn declare_intrinsic(&self, key: &str) -> Option<&'b Value> {
a1dfa0c6
XL
474 macro_rules! ifn {
475 ($name:expr, fn() -> $ret:expr) => (
476 if key == $name {
9fa01778 477 return Some(self.insert_intrinsic($name, Some(&[]), $ret));
a1dfa0c6
XL
478 }
479 );
480 ($name:expr, fn(...) -> $ret:expr) => (
481 if key == $name {
9fa01778 482 return Some(self.insert_intrinsic($name, None, $ret));
a1dfa0c6
XL
483 }
484 );
485 ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
486 if key == $name {
9fa01778 487 return Some(self.insert_intrinsic($name, Some(&[$($arg),*]), $ret));
a1dfa0c6
XL
488 }
489 );
490 }
491 macro_rules! mk_struct {
492 ($($field_ty:expr),*) => (self.type_struct( &[$($field_ty),*], false))
2c00a5a8
XL
493 }
494
a1dfa0c6
XL
495 let i8p = self.type_i8p();
496 let void = self.type_void();
497 let i1 = self.type_i1();
498 let t_i8 = self.type_i8();
499 let t_i16 = self.type_i16();
500 let t_i32 = self.type_i32();
501 let t_i64 = self.type_i64();
502 let t_i128 = self.type_i128();
503 let t_f32 = self.type_f32();
504 let t_f64 = self.type_f64();
505
3dfed10e
XL
506 ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32);
507 ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32);
508 ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64);
509 ifn!("llvm.wasm.trunc.unsigned.i64.f64", fn(t_f64) -> t_i64);
510 ifn!("llvm.wasm.trunc.signed.i32.f32", fn(t_f32) -> t_i32);
511 ifn!("llvm.wasm.trunc.signed.i32.f64", fn(t_f64) -> t_i32);
512 ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64);
513 ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64);
f035d41b 514
cdc7bbd5
XL
515 ifn!("llvm.fptosi.sat.i8.f32", fn(t_f32) -> t_i8);
516 ifn!("llvm.fptosi.sat.i16.f32", fn(t_f32) -> t_i16);
517 ifn!("llvm.fptosi.sat.i32.f32", fn(t_f32) -> t_i32);
518 ifn!("llvm.fptosi.sat.i64.f32", fn(t_f32) -> t_i64);
519 ifn!("llvm.fptosi.sat.i128.f32", fn(t_f32) -> t_i128);
520 ifn!("llvm.fptosi.sat.i8.f64", fn(t_f64) -> t_i8);
521 ifn!("llvm.fptosi.sat.i16.f64", fn(t_f64) -> t_i16);
522 ifn!("llvm.fptosi.sat.i32.f64", fn(t_f64) -> t_i32);
523 ifn!("llvm.fptosi.sat.i64.f64", fn(t_f64) -> t_i64);
524 ifn!("llvm.fptosi.sat.i128.f64", fn(t_f64) -> t_i128);
525
526 ifn!("llvm.fptoui.sat.i8.f32", fn(t_f32) -> t_i8);
527 ifn!("llvm.fptoui.sat.i16.f32", fn(t_f32) -> t_i16);
528 ifn!("llvm.fptoui.sat.i32.f32", fn(t_f32) -> t_i32);
529 ifn!("llvm.fptoui.sat.i64.f32", fn(t_f32) -> t_i64);
530 ifn!("llvm.fptoui.sat.i128.f32", fn(t_f32) -> t_i128);
531 ifn!("llvm.fptoui.sat.i8.f64", fn(t_f64) -> t_i8);
532 ifn!("llvm.fptoui.sat.i16.f64", fn(t_f64) -> t_i16);
533 ifn!("llvm.fptoui.sat.i32.f64", fn(t_f64) -> t_i32);
534 ifn!("llvm.fptoui.sat.i64.f64", fn(t_f64) -> t_i64);
535 ifn!("llvm.fptoui.sat.i128.f64", fn(t_f64) -> t_i128);
536
a1dfa0c6
XL
537 ifn!("llvm.trap", fn() -> void);
538 ifn!("llvm.debugtrap", fn() -> void);
539 ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
e74abb32 540 ifn!("llvm.sideeffect", fn() -> void);
a1dfa0c6
XL
541
542 ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
a1dfa0c6 543 ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
a1dfa0c6
XL
544
545 ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
a1dfa0c6 546 ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64);
a1dfa0c6
XL
547
548 ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32);
a1dfa0c6 549 ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
550
551 ifn!("llvm.sin.f32", fn(t_f32) -> t_f32);
a1dfa0c6 552 ifn!("llvm.sin.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
553
554 ifn!("llvm.cos.f32", fn(t_f32) -> t_f32);
a1dfa0c6 555 ifn!("llvm.cos.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
556
557 ifn!("llvm.exp.f32", fn(t_f32) -> t_f32);
a1dfa0c6 558 ifn!("llvm.exp.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
559
560 ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32);
a1dfa0c6 561 ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
562
563 ifn!("llvm.log.f32", fn(t_f32) -> t_f32);
a1dfa0c6 564 ifn!("llvm.log.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
565
566 ifn!("llvm.log10.f32", fn(t_f32) -> t_f32);
a1dfa0c6 567 ifn!("llvm.log10.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
568
569 ifn!("llvm.log2.f32", fn(t_f32) -> t_f32);
a1dfa0c6 570 ifn!("llvm.log2.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
571
572 ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32);
a1dfa0c6 573 ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64);
a1dfa0c6
XL
574
575 ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32);
a1dfa0c6 576 ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64);
a1dfa0c6 577
dc9dc135
XL
578 ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32);
579 ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
580 ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32);
581 ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
582
a1dfa0c6 583 ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
a1dfa0c6 584 ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
585
586 ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32);
a1dfa0c6 587 ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64);
a1dfa0c6
XL
588
589 ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32);
590 ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64);
591
592 ifn!("llvm.copysign.f32", fn(t_f32, t_f32) -> t_f32);
593 ifn!("llvm.copysign.f64", fn(t_f64, t_f64) -> t_f64);
594 ifn!("llvm.round.f32", fn(t_f32) -> t_f32);
595 ifn!("llvm.round.f64", fn(t_f64) -> t_f64);
596
597 ifn!("llvm.rint.f32", fn(t_f32) -> t_f32);
598 ifn!("llvm.rint.f64", fn(t_f64) -> t_f64);
599 ifn!("llvm.nearbyint.f32", fn(t_f32) -> t_f32);
600 ifn!("llvm.nearbyint.f64", fn(t_f64) -> t_f64);
601
602 ifn!("llvm.ctpop.i8", fn(t_i8) -> t_i8);
603 ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
604 ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
605 ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
606 ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128);
607
dfeec247 608 ifn!("llvm.ctlz.i8", fn(t_i8, i1) -> t_i8);
a1dfa0c6
XL
609 ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
610 ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
611 ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
612 ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128);
613
dfeec247 614 ifn!("llvm.cttz.i8", fn(t_i8, i1) -> t_i8);
a1dfa0c6
XL
615 ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
616 ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
617 ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
618 ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128);
619
620 ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
621 ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
622 ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
623 ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
624
625 ifn!("llvm.bitreverse.i8", fn(t_i8) -> t_i8);
626 ifn!("llvm.bitreverse.i16", fn(t_i16) -> t_i16);
627 ifn!("llvm.bitreverse.i32", fn(t_i32) -> t_i32);
628 ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64);
629 ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128);
630
631 ifn!("llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
632 ifn!("llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
633 ifn!("llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
634 ifn!("llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
635 ifn!("llvm.fshl.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
636
637 ifn!("llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
638 ifn!("llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
639 ifn!("llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
640 ifn!("llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
641 ifn!("llvm.fshr.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
642
dfeec247
XL
643 ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
644 ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
645 ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
646 ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
647 ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
648
649 ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
650 ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
651 ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
652 ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
653 ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
654
655 ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
656 ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
657 ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
658 ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
659 ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
660
661 ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
662 ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
663 ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
664 ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
665 ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
666
667 ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
668 ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
669 ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
670 ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
671 ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
672
673 ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct! {t_i8, i1});
674 ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct! {t_i16, i1});
675 ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct! {t_i32, i1});
676 ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct! {t_i64, i1});
677 ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct! {t_i128, i1});
a1dfa0c6 678
9fa01778
XL
679 ifn!("llvm.sadd.sat.i8", fn(t_i8, t_i8) -> t_i8);
680 ifn!("llvm.sadd.sat.i16", fn(t_i16, t_i16) -> t_i16);
681 ifn!("llvm.sadd.sat.i32", fn(t_i32, t_i32) -> t_i32);
682 ifn!("llvm.sadd.sat.i64", fn(t_i64, t_i64) -> t_i64);
683 ifn!("llvm.sadd.sat.i128", fn(t_i128, t_i128) -> t_i128);
684
685 ifn!("llvm.uadd.sat.i8", fn(t_i8, t_i8) -> t_i8);
686 ifn!("llvm.uadd.sat.i16", fn(t_i16, t_i16) -> t_i16);
687 ifn!("llvm.uadd.sat.i32", fn(t_i32, t_i32) -> t_i32);
688 ifn!("llvm.uadd.sat.i64", fn(t_i64, t_i64) -> t_i64);
689 ifn!("llvm.uadd.sat.i128", fn(t_i128, t_i128) -> t_i128);
690
691 ifn!("llvm.ssub.sat.i8", fn(t_i8, t_i8) -> t_i8);
692 ifn!("llvm.ssub.sat.i16", fn(t_i16, t_i16) -> t_i16);
693 ifn!("llvm.ssub.sat.i32", fn(t_i32, t_i32) -> t_i32);
694 ifn!("llvm.ssub.sat.i64", fn(t_i64, t_i64) -> t_i64);
695 ifn!("llvm.ssub.sat.i128", fn(t_i128, t_i128) -> t_i128);
696
697 ifn!("llvm.usub.sat.i8", fn(t_i8, t_i8) -> t_i8);
698 ifn!("llvm.usub.sat.i16", fn(t_i16, t_i16) -> t_i16);
699 ifn!("llvm.usub.sat.i32", fn(t_i32, t_i32) -> t_i32);
700 ifn!("llvm.usub.sat.i64", fn(t_i64, t_i64) -> t_i64);
701 ifn!("llvm.usub.sat.i128", fn(t_i128, t_i128) -> t_i128);
702
74b04a01
XL
703 ifn!("llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void);
704 ifn!("llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
a1dfa0c6
XL
705
706 ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
707 ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);
708 ifn!("llvm.localescape", fn(...) -> void);
709 ifn!("llvm.localrecover", fn(i8p, i8p, t_i32) -> i8p);
710 ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
711
712 ifn!("llvm.assume", fn(i1) -> void);
713 ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
714
715 // variadic intrinsics
716 ifn!("llvm.va_start", fn(i8p) -> void);
717 ifn!("llvm.va_end", fn(i8p) -> void);
718 ifn!("llvm.va_copy", fn(i8p, i8p) -> void);
719
cdc7bbd5 720 if self.sess().instrument_coverage() {
f035d41b
XL
721 ifn!("llvm.instrprof.increment", fn(i8p, t_i64, t_i32, t_i32) -> void);
722 }
723
a1dfa0c6
XL
724 if self.sess().opts.debuginfo != DebugInfo::None {
725 ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
726 ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
2c00a5a8 727 }
ba9703b0 728 None
a1dfa0c6 729 }
1b1a35ee
XL
730
731 crate fn eh_catch_typeinfo(&self) -> &'b Value {
732 if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() {
733 return eh_catch_typeinfo;
734 }
735 let tcx = self.tcx;
29967ef6 736 assert!(self.sess().target.is_like_emscripten);
1b1a35ee
XL
737 let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
738 Some(def_id) => self.get_static(def_id),
739 _ => {
740 let ty = self
741 .type_struct(&[self.type_ptr_to(self.type_isize()), self.type_i8p()], false);
742 self.declare_global("rust_eh_catch_typeinfo", ty)
743 }
744 };
745 let eh_catch_typeinfo = self.const_bitcast(eh_catch_typeinfo, self.type_i8p());
746 self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
747 eh_catch_typeinfo
748 }
a1dfa0c6
XL
749}
750
751impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
9fa01778 752 /// Generates a new symbol name with the given prefix. This symbol name must
a1dfa0c6
XL
753 /// only be used for definitions with `internal` or `private` linkage.
754 pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
755 let idx = self.local_gen_sym_counter.get();
756 self.local_gen_sym_counter.set(idx + 1);
757 // Include a '.' character, so there can be no accidental conflicts with
758 // user defined names
759 let mut name = String::with_capacity(prefix.len() + 6);
760 name.push_str(prefix);
29967ef6 761 name.push('.');
a1dfa0c6
XL
762 base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name);
763 name
ff7c6d11
XL
764 }
765}
766
ba9703b0
XL
767impl HasDataLayout for CodegenCx<'ll, 'tcx> {
768 fn data_layout(&self) -> &TargetDataLayout {
2c00a5a8 769 &self.tcx.data_layout
cc61c64b
XL
770 }
771}
772
a1dfa0c6 773impl HasTargetSpec for CodegenCx<'ll, 'tcx> {
83c7162d 774 fn target_spec(&self) -> &Target {
29967ef6 775 &self.tcx.sess.target
83c7162d
XL
776 }
777}
778
a1dfa0c6 779impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
dc9dc135 780 fn tcx(&self) -> TyCtxt<'tcx> {
2c00a5a8 781 self.tcx
7cac9316 782 }
ff7c6d11
XL
783}
784
a1dfa0c6 785impl LayoutOf for CodegenCx<'ll, 'tcx> {
83c7162d 786 type Ty = Ty<'tcx>;
ba9703b0 787 type TyAndLayout = TyAndLayout<'tcx>;
cc61c64b 788
ba9703b0 789 fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
416331ca
XL
790 self.spanned_layout_of(ty, DUMMY_SP)
791 }
792
ba9703b0 793 fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyAndLayout {
dfeec247
XL
794 self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| {
795 if let LayoutError::SizeOverflow(_) = e {
416331ca 796 self.sess().span_fatal(span, &e.to_string())
0bf4aa26
XL
797 } else {
798 bug!("failed to get layout for `{}`: {}", ty, e)
dfeec247
XL
799 }
800 })
cc61c64b 801 }
cc61c64b 802}
48663c56
XL
803
804impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
805 fn param_env(&self) -> ty::ParamEnv<'tcx> {
806 ty::ParamEnv::reveal_all()
807 }
808}