1use std::borrow::{Borrow, Cow};
2use std::cell::{Cell, RefCell};
3use std::ffi::{CStr, c_char, c_uint};
4use std::marker::PhantomData;
5use std::ops::{Deref, DerefMut};
6use std::str;
7
8use rustc_abi::{HasDataLayout, Size, TargetDataLayout, VariantIdx};
9use rustc_codegen_ssa::back::versioned_llvm_target;
10use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
11use rustc_codegen_ssa::errors as ssa_errors;
12use rustc_codegen_ssa::traits::*;
13use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
14use rustc_data_structures::fx::FxHashMap;
15use rustc_data_structures::small_c_str::SmallCStr;
16use rustc_hir::def_id::DefId;
17use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
18use rustc_middle::mir::mono::CodegenUnit;
19use rustc_middle::ty::layout::{
20 FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
21};
22use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
23use rustc_middle::{bug, span_bug};
24use rustc_session::Session;
25use rustc_session::config::{
26 BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, FunctionReturn, PAuthKey, PacRet,
27};
28use rustc_span::source_map::Spanned;
29use rustc_span::{DUMMY_SP, Span, Symbol};
30use rustc_symbol_mangling::mangle_internal_symbol;
31use rustc_target::spec::{
32 Arch, HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel,
33};
34use smallvec::SmallVec;
35
36use crate::abi::to_llvm_calling_convention;
37use crate::back::write::to_llvm_code_model;
38use crate::callee::get_fn;
39use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
40use crate::llvm::{self, Metadata, MetadataKindId, Module, Type, Value};
41use crate::{attributes, common, coverageinfo, debuginfo, llvm_util};
42
43pub(crate) struct SCx<'ll> {
48 pub llmod: &'ll llvm::Module,
49 pub llcx: &'ll llvm::Context,
50 pub isize_ty: &'ll Type,
51}
52
53impl<'ll> Borrow<SCx<'ll>> for FullCx<'ll, '_> {
54 fn borrow(&self) -> &SCx<'ll> {
55 &self.scx
56 }
57}
58
59impl<'ll, 'tcx> Deref for FullCx<'ll, 'tcx> {
60 type Target = SimpleCx<'ll>;
61
62 #[inline]
63 fn deref(&self) -> &Self::Target {
64 &self.scx
65 }
66}
67
68pub(crate) struct GenericCx<'ll, T: Borrow<SCx<'ll>>>(T, PhantomData<SCx<'ll>>);
69
70impl<'ll, T: Borrow<SCx<'ll>>> Deref for GenericCx<'ll, T> {
71 type Target = T;
72
73 #[inline]
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79impl<'ll, T: Borrow<SCx<'ll>>> DerefMut for GenericCx<'ll, T> {
80 #[inline]
81 fn deref_mut(&mut self) -> &mut Self::Target {
82 &mut self.0
83 }
84}
85
86pub(crate) type SimpleCx<'ll> = GenericCx<'ll, SCx<'ll>>;
87
88pub(crate) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;
92
93pub(crate) struct FullCx<'ll, 'tcx> {
94 pub tcx: TyCtxt<'tcx>,
95 pub scx: SimpleCx<'ll>,
96 pub use_dll_storage_attrs: bool,
97 pub tls_model: llvm::ThreadLocalMode,
98
99 pub codegen_unit: &'tcx CodegenUnit<'tcx>,
100
101 pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
103 pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>>,
105 pub const_str_cache: RefCell<FxHashMap<String, &'ll Value>>,
107
108 pub const_globals: RefCell<FxHashMap<&'ll Value, &'ll Value>>,
110
111 pub statics_to_rauw: RefCell<Vec<(&'ll Value, &'ll Value)>>,
116
117 pub used_statics: Vec<&'ll Value>,
120
121 pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
124
125 pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
127
128 pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
130
131 pub coverage_cx: Option<coverageinfo::CguCoverageContext<'ll, 'tcx>>,
133 pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>,
134
135 eh_personality: Cell<Option<&'ll Value>>,
136 eh_catch_typeinfo: Cell<Option<&'ll Value>>,
137 pub rust_try_fn: Cell<Option<(&'ll Type, &'ll Value)>>,
138
139 intrinsics:
140 RefCell<FxHashMap<(Cow<'static, str>, SmallVec<[&'ll Type; 2]>), (&'ll Type, &'ll Value)>>,
141
142 local_gen_sym_counter: Cell<usize>,
144
145 pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
150
151 pub objc_class_t: Cell<Option<&'ll Type>>,
153
154 pub objc_classrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
156
157 pub objc_selrefs: RefCell<FxHashMap<Symbol, &'ll Value>>,
159}
160
161fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
162 match tls_model {
163 TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
164 TlsModel::LocalDynamic => llvm::ThreadLocalMode::LocalDynamic,
165 TlsModel::InitialExec => llvm::ThreadLocalMode::InitialExec,
166 TlsModel::LocalExec => llvm::ThreadLocalMode::LocalExec,
167 TlsModel::Emulated => llvm::ThreadLocalMode::GeneralDynamic,
168 }
169}
170
171pub(crate) unsafe fn create_module<'ll>(
172 tcx: TyCtxt<'_>,
173 llcx: &'ll llvm::Context,
174 mod_name: &str,
175) -> &'ll llvm::Module {
176 let sess = tcx.sess;
177 let mod_name = SmallCStr::new(mod_name);
178 let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
179
180 let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size());
181
182 let mut target_data_layout = sess.target.data_layout.to_string();
183 let llvm_version = llvm_util::get_version();
184
185 if llvm_version < (21, 0, 0) {
186 if sess.target.arch == Arch::Nvptx64 {
187 target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
189 }
190 if sess.target.arch == Arch::AmdGpu {
191 target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
194 }
195 }
196 if llvm_version < (22, 0, 0) {
197 if sess.target.arch == Arch::Avr {
198 target_data_layout = target_data_layout.replace("n8:16", "n8")
200 }
201 if sess.target.arch == Arch::Nvptx64 {
202 target_data_layout = target_data_layout.replace("-i256:256", "");
204 }
205 }
206
207 {
209 let tm = crate::back::write::create_informational_target_machine(sess, false);
210 unsafe {
211 llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm.raw());
212 }
213
214 let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) };
215 let llvm_data_layout =
216 str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes())
217 .expect("got a non-UTF8 data-layout from LLVM");
218
219 if target_data_layout != llvm_data_layout {
220 tcx.dcx().emit_err(crate::errors::MismatchedDataLayout {
221 rustc_target: sess.opts.target_triple.to_string().as_str(),
222 rustc_layout: target_data_layout.as_str(),
223 llvm_target: sess.target.llvm_target.borrow(),
224 llvm_layout: llvm_data_layout,
225 });
226 }
227 }
228
229 let data_layout = SmallCStr::new(&target_data_layout);
230 unsafe {
231 llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
232 }
233
234 let llvm_target = SmallCStr::new(&versioned_llvm_target(sess));
235 unsafe {
236 llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
237 }
238
239 let reloc_model = sess.relocation_model();
240 if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
241 unsafe {
242 llvm::LLVMRustSetModulePICLevel(llmod);
243 }
244 if reloc_model == RelocModel::Pie
247 || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
248 {
249 unsafe {
250 llvm::LLVMRustSetModulePIELevel(llmod);
251 }
252 }
253 }
254
255 unsafe {
261 llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
262 }
263
264 if !sess.needs_plt() {
267 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "RtLibUseGOT", 1);
268 }
269
270 if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
272 llvm::add_module_flag_u32(
273 llmod,
274 llvm::ModuleFlagMergeBehavior::Override,
275 "CFI Canonical Jump Tables",
276 1,
277 );
278 }
279
280 if sess.is_sanitizer_cfi_normalize_integers_enabled() {
283 llvm::add_module_flag_u32(
284 llmod,
285 llvm::ModuleFlagMergeBehavior::Override,
286 "cfi-normalize-integers",
287 1,
288 );
289 }
290
291 if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
294 llvm::add_module_flag_u32(
295 llmod,
296 llvm::ModuleFlagMergeBehavior::Override,
297 "EnableSplitLTOUnit",
298 1,
299 );
300 }
301
302 if sess.is_sanitizer_kcfi_enabled() {
304 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi", 1);
305
306 let pfe =
309 PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry);
310 if pfe.prefix() > 0 {
311 llvm::add_module_flag_u32(
312 llmod,
313 llvm::ModuleFlagMergeBehavior::Override,
314 "kcfi-offset",
315 pfe.prefix().into(),
316 );
317 }
318
319 if sess.is_sanitizer_kcfi_arity_enabled() {
322 if llvm_version < (21, 0, 0) {
324 tcx.dcx().emit_err(crate::errors::SanitizerKcfiArityRequiresLLVM2100);
325 }
326
327 llvm::add_module_flag_u32(
328 llmod,
329 llvm::ModuleFlagMergeBehavior::Override,
330 "kcfi-arity",
331 1,
332 );
333 }
334 }
335
336 if sess.target.is_like_msvc
338 || (sess.target.options.os == "windows"
339 && sess.target.options.env == "gnu"
340 && sess.target.options.abi == "llvm")
341 {
342 match sess.opts.cg.control_flow_guard {
343 CFGuard::Disabled => {}
344 CFGuard::NoChecks => {
345 llvm::add_module_flag_u32(
347 llmod,
348 llvm::ModuleFlagMergeBehavior::Warning,
349 "cfguard",
350 1,
351 );
352 }
353 CFGuard::Checks => {
354 llvm::add_module_flag_u32(
356 llmod,
357 llvm::ModuleFlagMergeBehavior::Warning,
358 "cfguard",
359 2,
360 );
361 }
362 }
363 }
364
365 if let Some(regparm_count) = sess.opts.unstable_opts.regparm {
366 llvm::add_module_flag_u32(
367 llmod,
368 llvm::ModuleFlagMergeBehavior::Error,
369 "NumRegisterParameters",
370 regparm_count,
371 );
372 }
373
374 if let Some(BranchProtection { bti, pac_ret, gcs }) = sess.opts.unstable_opts.branch_protection
375 {
376 if sess.target.arch == Arch::AArch64 {
377 llvm::add_module_flag_u32(
378 llmod,
379 llvm::ModuleFlagMergeBehavior::Min,
380 "branch-target-enforcement",
381 bti.into(),
382 );
383 llvm::add_module_flag_u32(
384 llmod,
385 llvm::ModuleFlagMergeBehavior::Min,
386 "sign-return-address",
387 pac_ret.is_some().into(),
388 );
389 let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, pc: false, key: PAuthKey::A });
390 llvm::add_module_flag_u32(
391 llmod,
392 llvm::ModuleFlagMergeBehavior::Min,
393 "branch-protection-pauth-lr",
394 pac_opts.pc.into(),
395 );
396 llvm::add_module_flag_u32(
397 llmod,
398 llvm::ModuleFlagMergeBehavior::Min,
399 "sign-return-address-all",
400 pac_opts.leaf.into(),
401 );
402 llvm::add_module_flag_u32(
403 llmod,
404 llvm::ModuleFlagMergeBehavior::Min,
405 "sign-return-address-with-bkey",
406 u32::from(pac_opts.key == PAuthKey::B),
407 );
408 llvm::add_module_flag_u32(
409 llmod,
410 llvm::ModuleFlagMergeBehavior::Min,
411 "guarded-control-stack",
412 gcs.into(),
413 );
414 } else {
415 bug!(
416 "branch-protection used on non-AArch64 target; \
417 this should be checked in rustc_session."
418 );
419 }
420 }
421
422 if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
424 llvm::add_module_flag_u32(
425 llmod,
426 llvm::ModuleFlagMergeBehavior::Override,
427 "cf-protection-branch",
428 1,
429 );
430 }
431 if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
432 llvm::add_module_flag_u32(
433 llmod,
434 llvm::ModuleFlagMergeBehavior::Override,
435 "cf-protection-return",
436 1,
437 );
438 }
439
440 if sess.opts.unstable_opts.virtual_function_elimination {
441 llvm::add_module_flag_u32(
442 llmod,
443 llvm::ModuleFlagMergeBehavior::Error,
444 "Virtual Function Elim",
445 1,
446 );
447 }
448
449 if sess.opts.unstable_opts.ehcont_guard {
451 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "ehcontguard", 1);
452 }
453
454 match sess.opts.unstable_opts.function_return {
455 FunctionReturn::Keep => {}
456 FunctionReturn::ThunkExtern => {
457 llvm::add_module_flag_u32(
458 llmod,
459 llvm::ModuleFlagMergeBehavior::Override,
460 "function_return_thunk_extern",
461 1,
462 );
463 }
464 }
465
466 if sess.opts.unstable_opts.indirect_branch_cs_prefix {
467 llvm::add_module_flag_u32(
468 llmod,
469 llvm::ModuleFlagMergeBehavior::Override,
470 "indirect_branch_cs_prefix",
471 1,
472 );
473 }
474
475 match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support())
476 {
477 (Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
480 llvm::add_module_flag_u32(
481 llmod,
482 llvm::ModuleFlagMergeBehavior::Error,
483 &flag,
484 threshold as u32,
485 );
486 }
487 _ => (),
488 };
489
490 #[allow(clippy::option_env_unwrap)]
495 let rustc_producer =
496 format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
497
498 let name_metadata = cx.create_metadata(rustc_producer.as_bytes());
499 cx.module_add_named_metadata_node(llmod, c"llvm.ident", &[name_metadata]);
500
501 let llvm_abiname = &sess.target.options.llvm_abiname;
507 if matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) && !llvm_abiname.is_empty() {
508 llvm::add_module_flag_str(
509 llmod,
510 llvm::ModuleFlagMergeBehavior::Error,
511 "target-abi",
512 llvm_abiname,
513 );
514 }
515
516 for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
518 let merge_behavior = match merge_behavior.as_str() {
519 "error" => llvm::ModuleFlagMergeBehavior::Error,
520 "warning" => llvm::ModuleFlagMergeBehavior::Warning,
521 "require" => llvm::ModuleFlagMergeBehavior::Require,
522 "override" => llvm::ModuleFlagMergeBehavior::Override,
523 "append" => llvm::ModuleFlagMergeBehavior::Append,
524 "appendunique" => llvm::ModuleFlagMergeBehavior::AppendUnique,
525 "max" => llvm::ModuleFlagMergeBehavior::Max,
526 "min" => llvm::ModuleFlagMergeBehavior::Min,
527 _ => unreachable!(),
529 };
530 llvm::add_module_flag_u32(llmod, merge_behavior, key, *value);
531 }
532
533 llmod
534}
535
536impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
537 pub(crate) fn new(
538 tcx: TyCtxt<'tcx>,
539 codegen_unit: &'tcx CodegenUnit<'tcx>,
540 llvm_module: &'ll crate::ModuleLlvm,
541 ) -> Self {
542 let use_dll_storage_attrs = tcx.sess.target.is_like_windows;
595
596 let tls_model = to_llvm_tls_model(tcx.sess.tls_model());
597
598 let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
599
600 let coverage_cx =
601 tcx.sess.instrument_coverage().then(coverageinfo::CguCoverageContext::new);
602
603 let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
604 let dctx = debuginfo::CodegenUnitDebugContext::new(llmod);
605 debuginfo::metadata::build_compile_unit_di_node(
606 tcx,
607 codegen_unit.name().as_str(),
608 &dctx,
609 );
610 Some(dctx)
611 } else {
612 None
613 };
614
615 GenericCx(
616 FullCx {
617 tcx,
618 scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
619 use_dll_storage_attrs,
620 tls_model,
621 codegen_unit,
622 instances: Default::default(),
623 vtables: Default::default(),
624 const_str_cache: Default::default(),
625 const_globals: Default::default(),
626 statics_to_rauw: RefCell::new(Vec::new()),
627 used_statics: Vec::new(),
628 compiler_used_statics: Default::default(),
629 type_lowering: Default::default(),
630 scalar_lltypes: Default::default(),
631 coverage_cx,
632 dbg_cx,
633 eh_personality: Cell::new(None),
634 eh_catch_typeinfo: Cell::new(None),
635 rust_try_fn: Cell::new(None),
636 intrinsics: Default::default(),
637 local_gen_sym_counter: Cell::new(0),
638 renamed_statics: Default::default(),
639 objc_class_t: Cell::new(None),
640 objc_classrefs: Default::default(),
641 objc_selrefs: Default::default(),
642 },
643 PhantomData,
644 )
645 }
646
647 pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(&'ll Value, &'ll Value)>> {
648 &self.statics_to_rauw
649 }
650
651 #[inline]
653 #[track_caller]
654 pub(crate) fn coverage_cx(&self) -> &coverageinfo::CguCoverageContext<'ll, 'tcx> {
655 self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled")
656 }
657
658 pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
659 let array = self.const_array(self.type_ptr(), values);
660
661 let g = llvm::add_global(self.llmod, self.val_ty(array), name);
662 llvm::set_initializer(g, array);
663 llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
664 llvm::set_section(g, c"llvm.metadata");
665 }
666
667 pub(crate) fn objc_abi_version(&self) -> u32 {
671 assert!(self.tcx.sess.target.is_like_darwin);
672 if self.tcx.sess.target.arch == Arch::X86 && self.tcx.sess.target.os == "macos" {
673 1
675 } else {
676 2
679 }
680 }
681
682 pub(crate) fn add_objc_module_flags(&self) {
686 let abi_version = self.objc_abi_version();
687
688 llvm::add_module_flag_u32(
689 self.llmod,
690 llvm::ModuleFlagMergeBehavior::Error,
691 "Objective-C Version",
692 abi_version,
693 );
694
695 llvm::add_module_flag_u32(
696 self.llmod,
697 llvm::ModuleFlagMergeBehavior::Error,
698 "Objective-C Image Info Version",
699 0,
700 );
701
702 llvm::add_module_flag_str(
703 self.llmod,
704 llvm::ModuleFlagMergeBehavior::Error,
705 "Objective-C Image Info Section",
706 match abi_version {
707 1 => "__OBJC,__image_info,regular",
708 2 => "__DATA,__objc_imageinfo,regular,no_dead_strip",
709 _ => unreachable!(),
710 },
711 );
712
713 if self.tcx.sess.target.env == "sim" {
714 llvm::add_module_flag_u32(
715 self.llmod,
716 llvm::ModuleFlagMergeBehavior::Error,
717 "Objective-C Is Simulated",
718 1 << 5,
719 );
720 }
721
722 llvm::add_module_flag_u32(
723 self.llmod,
724 llvm::ModuleFlagMergeBehavior::Error,
725 "Objective-C Class Properties",
726 1 << 6,
727 );
728 }
729}
730impl<'ll> SimpleCx<'ll> {
731 pub(crate) fn get_type_of_global(&self, val: &'ll Value) -> &'ll Type {
732 unsafe { llvm::LLVMGlobalGetValueType(val) }
733 }
734 pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type {
735 common::val_ty(v)
736 }
737}
738impl<'ll> SimpleCx<'ll> {
739 pub(crate) fn new(
740 llmod: &'ll llvm::Module,
741 llcx: &'ll llvm::Context,
742 pointer_size: Size,
743 ) -> Self {
744 let isize_ty = llvm::LLVMIntTypeInContext(llcx, pointer_size.bits() as c_uint);
745 Self(SCx { llmod, llcx, isize_ty }, PhantomData)
746 }
747}
748
749impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
750 pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value {
751 llvm::LLVMMetadataAsValue(self.llcx(), metadata)
752 }
753
754 pub(crate) fn get_const_int(&self, ty: &'ll Type, val: u64) -> &'ll Value {
755 unsafe { llvm::LLVMConstInt(ty, val, llvm::FALSE) }
756 }
757
758 pub(crate) fn get_const_i64(&self, n: u64) -> &'ll Value {
759 self.get_const_int(self.type_i64(), n)
760 }
761
762 pub(crate) fn get_const_i32(&self, n: u64) -> &'ll Value {
763 self.get_const_int(self.type_i32(), n)
764 }
765
766 pub(crate) fn get_const_i16(&self, n: u64) -> &'ll Value {
767 self.get_const_int(self.type_i16(), n)
768 }
769
770 pub(crate) fn get_const_i8(&self, n: u64) -> &'ll Value {
771 self.get_const_int(self.type_i8(), n)
772 }
773
774 pub(crate) fn get_function(&self, name: &str) -> Option<&'ll Value> {
775 let name = SmallCStr::new(name);
776 unsafe { llvm::LLVMGetNamedFunction((**self).borrow().llmod, name.as_ptr()) }
777 }
778
779 pub(crate) fn get_md_kind_id(&self, name: &str) -> llvm::MetadataKindId {
780 unsafe {
781 llvm::LLVMGetMDKindIDInContext(
782 self.llcx(),
783 name.as_ptr() as *const c_char,
784 name.len() as c_uint,
785 )
786 }
787 }
788
789 pub(crate) fn create_metadata(&self, name: &[u8]) -> &'ll Metadata {
790 unsafe {
791 llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr() as *const c_char, name.len())
792 }
793 }
794}
795
796impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
797 fn vtables(
798 &self,
799 ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), &'ll Value>> {
800 &self.vtables
801 }
802
803 fn apply_vcall_visibility_metadata(
804 &self,
805 ty: Ty<'tcx>,
806 poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
807 vtable: &'ll Value,
808 ) {
809 apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);
810 }
811
812 fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
813 get_fn(self, instance)
814 }
815
816 fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value {
817 get_fn(self, instance)
818 }
819
820 fn eh_personality(&self) -> &'ll Value {
821 if let Some(llpersonality) = self.eh_personality.get() {
842 return llpersonality;
843 }
844
845 let name = if wants_msvc_seh(self.sess()) {
846 Some("__CxxFrameHandler3")
847 } else if wants_wasm_eh(self.sess()) {
848 Some("__gxx_wasm_personality_v0")
853 } else {
854 None
855 };
856
857 let tcx = self.tcx;
858 let llfn = match tcx.lang_items().eh_personality() {
859 Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve(
860 tcx,
861 self.typing_env(),
862 def_id,
863 ty::List::empty(),
864 DUMMY_SP,
865 )),
866 _ => {
867 let name = name.unwrap_or("rust_eh_personality");
868 if let Some(llfn) = self.get_declared_value(name) {
869 llfn
870 } else {
871 let fty = self.type_variadic_func(&[], self.type_i32());
872 let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty);
873 let target_cpu = attributes::target_cpu_attr(self, self.sess());
874 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[target_cpu]);
875 llfn
876 }
877 }
878 };
879 self.eh_personality.set(Some(llfn));
880 llfn
881 }
882
883 fn sess(&self) -> &Session {
884 self.tcx.sess
885 }
886
887 fn set_frame_pointer_type(&self, llfn: &'ll Value) {
888 if let Some(attr) = attributes::frame_pointer_type_attr(self, self.sess()) {
889 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[attr]);
890 }
891 }
892
893 fn apply_target_cpu_attr(&self, llfn: &'ll Value) {
894 let mut attrs = SmallVec::<[_; 2]>::new();
895 attrs.push(attributes::target_cpu_attr(self, self.sess()));
896 attrs.extend(attributes::tune_cpu_attr(self, self.sess()));
897 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &attrs);
898 }
899
900 fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
901 let entry_name = self.sess().target.entry_name.as_ref();
902 if self.get_declared_value(entry_name).is_none() {
903 let llfn = self.declare_entry_fn(
904 entry_name,
905 to_llvm_calling_convention(self.sess(), self.sess().target.entry_abi),
906 llvm::UnnamedAddr::Global,
907 fn_type,
908 );
909 attributes::apply_to_llfn(
910 llfn,
911 llvm::AttributePlace::Function,
912 attributes::target_features_attr(self, self.tcx, vec![]).as_slice(),
913 );
914 Some(llfn)
915 } else {
916 None
919 }
920 }
921}
922
923impl<'ll> CodegenCx<'ll, '_> {
924 pub(crate) fn get_intrinsic(
925 &self,
926 base_name: Cow<'static, str>,
927 type_params: &[&'ll Type],
928 ) -> (&'ll Type, &'ll Value) {
929 *self
930 .intrinsics
931 .borrow_mut()
932 .entry((base_name, SmallVec::from_slice(type_params)))
933 .or_insert_with_key(|(base_name, type_params)| {
934 self.declare_intrinsic(base_name, type_params)
935 })
936 }
937
938 fn declare_intrinsic(
939 &self,
940 base_name: &str,
941 type_params: &[&'ll Type],
942 ) -> (&'ll Type, &'ll Value) {
943 if base_name == "memcmp" {
947 let fn_ty = self
948 .type_func(&[self.type_ptr(), self.type_ptr(), self.type_isize()], self.type_int());
949 let f = self.declare_cfn("memcmp", llvm::UnnamedAddr::No, fn_ty);
950
951 return (fn_ty, f);
952 }
953
954 let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes())
955 .unwrap_or_else(|| bug!("Unknown intrinsic: `{base_name}`"));
956 let f = intrinsic.get_declaration(self.llmod, &type_params);
957
958 (self.get_type_of_global(f), f)
959 }
960
961 pub(crate) fn eh_catch_typeinfo(&self) -> &'ll Value {
962 if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() {
963 return eh_catch_typeinfo;
964 }
965 let tcx = self.tcx;
966 assert!(self.sess().target.os == "emscripten");
967 let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() {
968 Some(def_id) => self.get_static(def_id),
969 _ => {
970 let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false);
971 self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty)
972 }
973 };
974 self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo));
975 eh_catch_typeinfo
976 }
977}
978
979impl CodegenCx<'_, '_> {
980 pub(crate) fn generate_local_symbol_name(&self, prefix: &str) -> String {
983 let idx = self.local_gen_sym_counter.get();
984 self.local_gen_sym_counter.set(idx + 1);
985 let mut name = String::with_capacity(prefix.len() + 6);
988 name.push_str(prefix);
989 name.push('.');
990 name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
991 name
992 }
993}
994
995impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
996 pub(crate) fn md_node_in_context(&self, md_list: &[&'ll Metadata]) -> &'ll Metadata {
998 unsafe { llvm::LLVMMDNodeInContext2(self.llcx(), md_list.as_ptr(), md_list.len()) }
999 }
1000
1001 pub(crate) fn set_metadata<'a>(
1003 &self,
1004 val: &'a Value,
1005 kind_id: MetadataKindId,
1006 md: &'ll Metadata,
1007 ) {
1008 let node = self.get_metadata_value(md);
1009 llvm::LLVMSetMetadata(val, kind_id, node);
1010 }
1011
1012 pub(crate) fn set_metadata_node(
1017 &self,
1018 instruction: &'ll Value,
1019 kind_id: MetadataKindId,
1020 md_list: &[&'ll Metadata],
1021 ) {
1022 let md = self.md_node_in_context(md_list);
1023 self.set_metadata(instruction, kind_id, md);
1024 }
1025
1026 pub(crate) fn module_add_named_metadata_node(
1031 &self,
1032 module: &'ll Module,
1033 kind_name: &CStr,
1034 md_list: &[&'ll Metadata],
1035 ) {
1036 let md = self.md_node_in_context(md_list);
1037 let md_as_val = self.get_metadata_value(md);
1038 unsafe { llvm::LLVMAddNamedMetadataOperand(module, kind_name.as_ptr(), md_as_val) };
1039 }
1040
1041 pub(crate) fn global_add_metadata_node(
1045 &self,
1046 global: &'ll Value,
1047 kind_id: MetadataKindId,
1048 md_list: &[&'ll Metadata],
1049 ) {
1050 let md = self.md_node_in_context(md_list);
1051 unsafe { llvm::LLVMRustGlobalAddMetadata(global, kind_id, md) };
1052 }
1053
1054 pub(crate) fn global_set_metadata_node(
1058 &self,
1059 global: &'ll Value,
1060 kind_id: MetadataKindId,
1061 md_list: &[&'ll Metadata],
1062 ) {
1063 let md = self.md_node_in_context(md_list);
1064 unsafe { llvm::LLVMGlobalSetMetadata(global, kind_id, md) };
1065 }
1066}
1067
1068impl HasDataLayout for CodegenCx<'_, '_> {
1069 #[inline]
1070 fn data_layout(&self) -> &TargetDataLayout {
1071 &self.tcx.data_layout
1072 }
1073}
1074
1075impl HasTargetSpec for CodegenCx<'_, '_> {
1076 #[inline]
1077 fn target_spec(&self) -> &Target {
1078 &self.tcx.sess.target
1079 }
1080}
1081
1082impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> {
1083 #[inline]
1084 fn tcx(&self) -> TyCtxt<'tcx> {
1085 self.tcx
1086 }
1087}
1088
1089impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> {
1090 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
1091 ty::TypingEnv::fully_monomorphized()
1092 }
1093}
1094
1095impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
1096 #[inline]
1097 fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
1098 if let LayoutError::SizeOverflow(_)
1099 | LayoutError::ReferencesError(_)
1100 | LayoutError::InvalidSimd { .. } = err
1101 {
1102 self.tcx.dcx().emit_fatal(Spanned { span, node: err.into_diagnostic() })
1103 } else {
1104 self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
1105 }
1106 }
1107}
1108
1109impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
1110 #[inline]
1111 fn handle_fn_abi_err(
1112 &self,
1113 err: FnAbiError<'tcx>,
1114 span: Span,
1115 fn_abi_request: FnAbiRequest<'tcx>,
1116 ) -> ! {
1117 match err {
1118 FnAbiError::Layout(
1119 LayoutError::SizeOverflow(_)
1120 | LayoutError::Cycle(_)
1121 | LayoutError::InvalidSimd { .. },
1122 ) => {
1123 self.tcx.dcx().emit_fatal(Spanned { span, node: err });
1124 }
1125 _ => match fn_abi_request {
1126 FnAbiRequest::OfFnPtr { sig, extra_args } => {
1127 span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",);
1128 }
1129 FnAbiRequest::OfInstance { instance, extra_args } => {
1130 span_bug!(
1131 span,
1132 "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",
1133 );
1134 }
1135 },
1136 }
1137 }
1138}