1use std::borrow::{Borrow, Cow};
2use std::cell::{Cell, RefCell};
3use std::ffi::{CStr, 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::base::{wants_msvc_seh, wants_wasm_eh};
10use rustc_codegen_ssa::diagnostics as ssa_errors;
11use rustc_codegen_ssa::traits::*;
12use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN};
13use rustc_data_structures::fx::FxHashMap;
14use rustc_data_structures::small_c_str::SmallCStr;
15use rustc_hir::def_id::DefId;
16use rustc_middle::mono::CodegenUnit;
17use rustc_middle::ty::layout::{
18 FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
19 codegen_handle_fn_abi_err,
20};
21use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
22use rustc_sanitizers::ignorelist::{SanitizerIgnoreList, typename_for_ignore_list};
23use rustc_session::config::{
24 BranchProtection, CFGuard, CFProtection, DebugInfo, FunctionReturn, PAuthKey, PacRet,
25};
26use rustc_session::{PointerAuthSchema, Session};
27use rustc_span::{DUMMY_SP, Span, Symbol, bug, sym};
28use rustc_structures::CrateType;
29use rustc_target::spec::{
30 Arch, CfgAbi, Env, FramePointer, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport,
31 Target, TlsModel,
32};
33use smallvec::SmallVec;
34
35use crate::abi::to_llvm_calling_convention;
36use crate::back::llvm_backend::ModuleRefs;
37use crate::back::write::to_llvm_code_model;
38use crate::builder::gpu_offload::{OffloadGlobals, OffloadKernelGlobals};
39use crate::callee::get_fn;
40use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
41use crate::llvm::{self, Metadata, MetadataKindId, Module, Type, Value};
42use crate::{attributes, common, coverageinfo, debuginfo, llvm_util};
43
44pub(crate) struct SCx<'ll> {
49 pub llmod: llvm::Module<'ll>,
50 pub llcx: llvm::Context<'ll>,
51 pub isize_ty: Type<'ll>,
52}
53
54impl<'ll> Borrow<SCx<'ll>> for FullCx<'ll, '_> {
55 fn borrow(&self) -> &SCx<'ll> {
56 &self.scx
57 }
58}
59
60impl<'ll, 'tcx> Deref for FullCx<'ll, 'tcx> {
61 type Target = SimpleCx<'ll>;
62
63 #[inline]
64 fn deref(&self) -> &Self::Target {
65 &self.scx
66 }
67}
68
69pub(crate) struct GenericCx<'ll, T: Borrow<SCx<'ll>>>(T, PhantomData<SCx<'ll>>);
70
71impl<'ll, T: Borrow<SCx<'ll>>> Deref for GenericCx<'ll, T> {
72 type Target = T;
73
74 #[inline]
75 fn deref(&self) -> &Self::Target {
76 &self.0
77 }
78}
79
80impl<'ll, T: Borrow<SCx<'ll>>> DerefMut for GenericCx<'ll, T> {
81 #[inline]
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87pub(crate) type SimpleCx<'ll> = GenericCx<'ll, SCx<'ll>>;
88
89pub(crate) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;
93
94pub(crate) struct FullCx<'ll, 'tcx> {
95 pub tcx: TyCtxt<'tcx>,
96 pub bitcode_needed: bool,
97 pub scx: SimpleCx<'ll>,
98 pub use_dll_storage_attrs: bool,
99 pub tls_model: llvm::ThreadLocalMode,
100
101 pub codegen_unit: &'tcx CodegenUnit<'tcx>,
102
103 pub instances: RefCell<FxHashMap<Instance<'tcx>, Value<'ll>>>,
105 pub intrinsic_instances: RefCell<FxHashMap<Instance<'tcx>, Value<'ll>>>,
107 pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), Value<'ll>>>,
109 pub const_str_cache: RefCell<FxHashMap<String, Value<'ll>>>,
111
112 pub const_globals: RefCell<FxHashMap<Value<'ll>, Value<'ll>>>,
114
115 pub statics_to_rauw: RefCell<Vec<(Value<'ll>, Value<'ll>)>>,
120
121 pub used_statics: Vec<Value<'ll>>,
124
125 pub compiler_used_statics: RefCell<Vec<Value<'ll>>>,
128
129 pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), Type<'ll>>>,
131
132 pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, Type<'ll>>>,
134
135 pub coverage_cx: Option<coverageinfo::CguCoverageContext<'ll, 'tcx>>,
137 pub dbg_cx: Option<debuginfo::CodegenUnitDebugContext<'ll, 'tcx>>,
138 pub sanitizer_ignorelist: Option<SanitizerIgnoreList>,
139
140 eh_personality: Cell<Option<Value<'ll>>>,
141 pub rust_try_fn: Cell<Option<(Type<'ll>, Value<'ll>)>>,
142
143 intrinsics:
144 RefCell<FxHashMap<(Cow<'static, str>, SmallVec<[Type<'ll>; 2]>), (Type<'ll>, Value<'ll>)>>,
145
146 local_gen_sym_counter: Cell<usize>,
148
149 global_gen_sym_counter: Cell<usize>,
151
152 pub renamed_statics: RefCell<FxHashMap<DefId, Value<'ll>>>,
157
158 pub objc_class_t: Cell<Option<Type<'ll>>>,
160
161 pub objc_classrefs: RefCell<FxHashMap<Symbol, Value<'ll>>>,
163
164 pub objc_selrefs: RefCell<FxHashMap<Symbol, Value<'ll>>>,
166
167 pub offload_globals: RefCell<Option<OffloadGlobals<'ll>>>,
169
170 pub offload_kernel_cache: RefCell<FxHashMap<String, OffloadKernelGlobals<'ll>>>,
172}
173
174fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
175 match tls_model {
176 TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
177 TlsModel::LocalDynamic => llvm::ThreadLocalMode::LocalDynamic,
178 TlsModel::InitialExec => llvm::ThreadLocalMode::InitialExec,
179 TlsModel::LocalExec => llvm::ThreadLocalMode::LocalExec,
180 TlsModel::Emulated => llvm::ThreadLocalMode::GeneralDynamic,
181 }
182}
183
184pub(crate) unsafe fn create_module<'ll>(
185 tcx: TyCtxt<'_>,
186 llcx: llvm::Context<'ll>,
187 mod_name: &str,
188) -> llvm::Module<'ll> {
189 let mod_name_cstr = SmallCStr::new(mod_name);
190 let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name_cstr.as_ptr(), llcx) };
191 init_module(tcx, llcx, llmod);
192 llmod
193}
194
195fn init_module<'ll, 'tcx>(tcx: TyCtxt<'tcx>, llcx: llvm::Context<'ll>, llmod: llvm::Module<'ll>) {
196 let sess = tcx.sess;
197 let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size());
198
199 let mut target_data_layout = sess.target.data_layout.to_string();
200 let llvm_version = llvm_util::get_version();
201
202 if llvm_version < (23, 0, 0) {
203 if sess.target.arch == Arch::S390x {
204 target_data_layout = target_data_layout.replace("-S64", "");
206 }
207 }
208 if llvm_version < (24, 0, 0) {
209 if sess.target.arch == Arch::AmdGpu {
210 target_data_layout = target_data_layout
212 .replace("-p10:32:32-p11:32:32-p12:32:32-p13:32:32-p14:32:32-p15:32:32", "");
213 }
214 }
215 {
217 let tm = crate::back::write::create_informational_target_machine(sess);
218 unsafe {
219 llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm.raw());
220 }
221
222 let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) };
223 let llvm_data_layout =
224 str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes())
225 .expect("got a non-UTF8 data-layout from LLVM");
226
227 if target_data_layout != llvm_data_layout {
228 tcx.dcx().emit_err(crate::diagnostics::MismatchedDataLayout {
229 rustc_target: sess.opts.target_triple.to_string().as_str(),
230 rustc_layout: target_data_layout.as_str(),
231 llvm_target: sess.target.llvm_target.borrow(),
232 llvm_layout: llvm_data_layout,
233 });
234 }
235 }
236
237 let data_layout = SmallCStr::new(&target_data_layout);
238 unsafe {
239 llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
240 }
241
242 let llvm_target = SmallCStr::new(&llvm_util::llvm_target(sess));
243 unsafe {
244 llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
245 }
246
247 let reloc_model = sess.relocation_model();
248 if #[allow(non_exhaustive_omitted_patterns)] match reloc_model {
RelocModel::Pic | RelocModel::Pie => true,
_ => false,
}matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
249 unsafe {
250 llvm::LLVMRustSetModulePICLevel(llmod);
251 }
252 if reloc_model == RelocModel::Pie
255 || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
256 {
257 unsafe {
258 llvm::LLVMRustSetModulePIELevel(llmod);
259 }
260 }
261 }
262
263 unsafe {
269 llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
270 }
271
272 if let Some(large_data_threshold) = sess.opts.unstable_opts.large_data_threshold {
273 unsafe {
274 llvm::LLVMRustSetModuleLargeDataThreshold(llmod, large_data_threshold);
275 }
276 }
277
278 if !sess.needs_plt() {
281 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "RtLibUseGOT", 1);
282 }
283
284 if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
286 llvm::add_module_flag_u32(
287 llmod,
288 llvm::ModuleFlagMergeBehavior::Override,
289 "CFI Canonical Jump Tables",
290 1,
291 );
292 }
293
294 if sess.is_sanitizer_cfi_normalize_integers_enabled() {
297 llvm::add_module_flag_u32(
298 llmod,
299 llvm::ModuleFlagMergeBehavior::Override,
300 "cfi-normalize-integers",
301 1,
302 );
303 }
304
305 if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
308 llvm::add_module_flag_u32(
309 llmod,
310 llvm::ModuleFlagMergeBehavior::Override,
311 "EnableSplitLTOUnit",
312 1,
313 );
314 }
315
316 if sess.must_emit_unwind_tables() {
317 const {
320 if !((llvm::UWTableKind::None as u32) < (llvm::UWTableKind::Sync as u32)) {
::core::panicking::panic("assertion failed: (llvm::UWTableKind::None as u32) < (llvm::UWTableKind::Sync as u32)")
};assert!((llvm::UWTableKind::None as u32) < (llvm::UWTableKind::Sync as u32));
321 if !((llvm::UWTableKind::Sync as u32) < (llvm::UWTableKind::Async as u32)) {
::core::panicking::panic("assertion failed: (llvm::UWTableKind::Sync as u32) < (llvm::UWTableKind::Async as u32)")
};assert!((llvm::UWTableKind::Sync as u32) < (llvm::UWTableKind::Async as u32));
322 }
323
324 llvm::add_module_flag_u32(
325 llmod,
326 llvm::ModuleFlagMergeBehavior::Max,
327 "uwtable",
328 match sess.opts.unstable_opts.use_sync_unwind {
329 Some(true) => llvm::UWTableKind::Sync as u32,
330 Some(false) | None => llvm::UWTableKind::Async as u32,
331 },
332 );
333 }
334
335 if sess.is_sanitizer_kcfi_enabled() {
337 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi", 1);
338
339 let patchable_prefix_nops = sess.opts.unstable_opts.patchable_function_entry.prefix();
342 if patchable_prefix_nops > 0 {
343 llvm::add_module_flag_u32(
344 llmod,
345 llvm::ModuleFlagMergeBehavior::Override,
346 "kcfi-offset",
347 patchable_prefix_nops.into(),
348 );
349 }
350
351 if sess.is_sanitizer_kcfi_arity_enabled() {
354 llvm::add_module_flag_u32(
355 llmod,
356 llvm::ModuleFlagMergeBehavior::Override,
357 "kcfi-arity",
358 1,
359 );
360 }
361 }
362
363 if sess.target.is_like_msvc
365 || (sess.target.options.os == Os::Windows
366 && sess.target.options.env == Env::Gnu
367 && sess.target.options.cfg_abi == CfgAbi::Llvm)
368 {
369 match sess.opts.cg.control_flow_guard {
370 CFGuard::Disabled => {}
371 CFGuard::NoChecks => {
372 llvm::add_module_flag_u32(
374 llmod,
375 llvm::ModuleFlagMergeBehavior::Warning,
376 "cfguard",
377 1,
378 );
379 }
380 CFGuard::Checks => {
381 llvm::add_module_flag_u32(
383 llmod,
384 llvm::ModuleFlagMergeBehavior::Warning,
385 "cfguard",
386 2,
387 );
388 }
389 }
390 }
391
392 if let Some(regparm_count) = sess.opts.unstable_opts.regparm {
393 llvm::add_module_flag_u32(
394 llmod,
395 llvm::ModuleFlagMergeBehavior::Error,
396 "NumRegisterParameters",
397 regparm_count,
398 );
399 }
400
401 if let Some(BranchProtection { bti, pac_ret, gcs }) = sess.branch_protection() {
402 if sess.target.arch == Arch::AArch64 {
403 llvm::add_module_flag_u32(
404 llmod,
405 llvm::ModuleFlagMergeBehavior::Min,
406 "branch-target-enforcement",
407 bti.into(),
408 );
409 llvm::add_module_flag_u32(
410 llmod,
411 llvm::ModuleFlagMergeBehavior::Min,
412 "sign-return-address",
413 pac_ret.is_some().into(),
414 );
415 let pac_opts = pac_ret.unwrap_or_else(|| {
416 let key = if sess.target.os == Os::Windows { PAuthKey::B } else { PAuthKey::A };
418 PacRet { leaf: false, pc: false, key }
419 });
420 llvm::add_module_flag_u32(
421 llmod,
422 llvm::ModuleFlagMergeBehavior::Min,
423 "branch-protection-pauth-lr",
424 pac_opts.pc.into(),
425 );
426 llvm::add_module_flag_u32(
427 llmod,
428 llvm::ModuleFlagMergeBehavior::Min,
429 "sign-return-address-all",
430 pac_opts.leaf.into(),
431 );
432 llvm::add_module_flag_u32(
433 llmod,
434 llvm::ModuleFlagMergeBehavior::Min,
435 "sign-return-address-with-bkey",
436 u32::from(pac_opts.key == PAuthKey::B),
437 );
438 llvm::add_module_flag_u32(
439 llmod,
440 llvm::ModuleFlagMergeBehavior::Min,
441 "guarded-control-stack",
442 gcs.into(),
443 );
444 } else {
445 ::rustc_span::macros::bug_impl(None,
format_args!("branch-protection used on non-AArch64 target; this should be checked in rustc_session."),
Location::caller());bug!(
446 "branch-protection used on non-AArch64 target; \
447 this should be checked in rustc_session."
448 );
449 }
450 }
451
452 if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
454 llvm::add_module_flag_u32(
455 llmod,
456 llvm::ModuleFlagMergeBehavior::Override,
457 "cf-protection-branch",
458 1,
459 );
460 }
461 if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
462 llvm::add_module_flag_u32(
463 llmod,
464 llvm::ModuleFlagMergeBehavior::Override,
465 "cf-protection-return",
466 1,
467 );
468 }
469
470 if sess.opts.unstable_opts.virtual_function_elimination {
471 llvm::add_module_flag_u32(
472 llmod,
473 llvm::ModuleFlagMergeBehavior::Error,
474 "Virtual Function Elim",
475 1,
476 );
477 }
478
479 if sess.opts.unstable_opts.ehcont_guard {
481 llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Warning, "ehcontguard", 1);
482 }
483
484 match sess.opts.unstable_opts.function_return {
485 FunctionReturn::Keep => {}
486 FunctionReturn::ThunkExtern => {
487 llvm::add_module_flag_u32(
488 llmod,
489 llvm::ModuleFlagMergeBehavior::Override,
490 "function_return_thunk_extern",
491 1,
492 );
493 }
494 }
495
496 let fp = attributes::frame_pointer(sess);
497 if fp != FramePointer::MayOmit {
498 llvm::add_module_flag_u32(
499 llmod,
500 llvm::ModuleFlagMergeBehavior::Max,
501 "frame-pointer",
502 match fp {
503 FramePointer::Always => llvm::FramePointerKind::All as u32,
504 FramePointer::NonLeaf => llvm::FramePointerKind::NonLeaf as u32,
505 FramePointer::MayOmit => llvm::FramePointerKind::None as u32,
506 },
507 );
508 }
509
510 if sess.opts.unstable_opts.indirect_branch_cs_prefix {
511 llvm::add_module_flag_u32(
512 llmod,
513 llvm::ModuleFlagMergeBehavior::Override,
514 "indirect_branch_cs_prefix",
515 1,
516 );
517 }
518
519 if let Some(threshold) = sess.opts.unstable_opts.small_data_threshold
522 && let SmallDataThresholdSupport::LlvmModuleFlag(flag) =
523 sess.target.small_data_threshold_support()
524 {
525 llvm::add_module_flag_u32(
526 llmod,
527 llvm::ModuleFlagMergeBehavior::Error,
528 &flag,
529 threshold as u32,
530 );
531 }
532
533 #[allow(clippy::option_env_unwrap)]
538 let rustc_producer =
539 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("rustc version {0}",
::core::option::Option::Some("1.102.0-nightly (5f4effd57 2026-11-13)").expect("CFG_VERSION")))
})format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
540
541 let name_metadata = cx.create_metadata(rustc_producer.as_bytes());
542 cx.module_add_named_metadata_node(llmod, c"llvm.ident", &[name_metadata]);
543
544 let llvm_abiname = &sess.target.options.llvm_abiname;
546 if #[allow(non_exhaustive_omitted_patterns)] match sess.target.arch {
Arch::LoongArch32 | Arch::LoongArch64 | Arch::RiscV32 | Arch::RiscV64 =>
true,
_ => false,
}matches!(
547 sess.target.arch,
548 Arch::LoongArch32 | Arch::LoongArch64 | Arch::RiscV32 | Arch::RiscV64
549 ) {
550 llvm::add_module_flag_str(
551 llmod,
552 llvm::ModuleFlagMergeBehavior::Error,
553 "target-abi",
554 llvm_abiname.desc(),
555 );
556 }
557
558 if llvm_version >= (24, 0, 0)
559 && let Some(floatabi) = sess.target.llvm_floatabi
560 {
561 llvm::add_module_flag_str(
562 llmod,
563 llvm::ModuleFlagMergeBehavior::Error,
564 "float-abi",
565 floatabi.desc(),
566 );
567 }
568
569 if llvm_version >= (24, 0, 0) {
570 if sess.target.singlethread(&sess.internal_target_features) {
571 llvm::add_module_flag_str(
572 llmod,
573 llvm::ModuleFlagMergeBehavior::Error,
574 "thread-model",
575 "single",
576 );
577 }
578 if wants_wasm_eh(&sess.target) {
579 llvm::add_module_flag_str(
580 llmod,
581 llvm::ModuleFlagMergeBehavior::Error,
582 "exception-model",
583 "wasm",
584 );
585 }
586 }
587
588 for (key, value, merge_behavior) in &sess.opts.unstable_opts.llvm_module_flag {
590 let merge_behavior = match merge_behavior.as_str() {
591 "error" => llvm::ModuleFlagMergeBehavior::Error,
592 "warning" => llvm::ModuleFlagMergeBehavior::Warning,
593 "require" => llvm::ModuleFlagMergeBehavior::Require,
594 "override" => llvm::ModuleFlagMergeBehavior::Override,
595 "append" => llvm::ModuleFlagMergeBehavior::Append,
596 "appendunique" => llvm::ModuleFlagMergeBehavior::AppendUnique,
597 "max" => llvm::ModuleFlagMergeBehavior::Max,
598 "min" => llvm::ModuleFlagMergeBehavior::Min,
599 _ => ::core::panicking::unreachable_default_msg()unreachable!(),
601 };
602 llvm::add_module_flag_u32(llmod, merge_behavior, key, *value);
603 }
604}
605
606impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
607 pub(crate) fn new(
608 tcx: TyCtxt<'tcx>,
609 codegen_unit: &'tcx CodegenUnit<'tcx>,
610 module_refs: ModuleRefs<'ll>,
611 bitcode_needed: bool,
612 ) -> Self {
613 let use_dll_storage_attrs = tcx.sess.target.is_like_windows;
666
667 let tls_model = to_llvm_tls_model(tcx.sess.tls_model());
668
669 let ModuleRefs { llcx, llmod, .. } = module_refs;
670
671 let coverage_cx =
672 tcx.sess.instrument_coverage().then(coverageinfo::CguCoverageContext::new);
673
674 let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
675 let dctx = debuginfo::CodegenUnitDebugContext::new(llmod, tcx.sess);
676 debuginfo::metadata::build_compile_unit_di_node(
677 tcx,
678 codegen_unit.name().as_str(),
679 &dctx,
680 );
681 Some(dctx)
682 } else {
683 None
684 };
685
686 let sanitizer_ignorelist = if !tcx.sess.opts.unstable_opts.sanitizer_ignorelist.is_empty() {
691 for path in &tcx.sess.opts.unstable_opts.sanitizer_ignorelist {
692 let _ = tcx.sess.source_map().load_file(std::path::Path::new(path));
693 }
694 match SanitizerIgnoreList::new(&tcx.sess.opts.unstable_opts.sanitizer_ignorelist) {
695 Ok(list) => Some(list),
696 Err(err) => {
697 tcx.dcx().fatal(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("failed to parse sanitizer ignorelist: {0}",
err))
})format!("failed to parse sanitizer ignorelist: {}", err));
698 }
699 }
700 } else {
701 None
702 };
703
704 GenericCx(
705 FullCx {
706 tcx,
707 bitcode_needed,
708 scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
709 use_dll_storage_attrs,
710 tls_model,
711 codegen_unit,
712 instances: Default::default(),
713 intrinsic_instances: Default::default(),
714 vtables: Default::default(),
715 const_str_cache: Default::default(),
716 const_globals: Default::default(),
717 statics_to_rauw: RefCell::new(Vec::new()),
718 used_statics: Vec::new(),
719 compiler_used_statics: Default::default(),
720 type_lowering: Default::default(),
721 scalar_lltypes: Default::default(),
722 coverage_cx,
723 dbg_cx,
724 sanitizer_ignorelist,
725 eh_personality: Cell::new(None),
726 rust_try_fn: Cell::new(None),
727 intrinsics: Default::default(),
728 local_gen_sym_counter: Cell::new(0),
729 global_gen_sym_counter: Cell::new(0),
730 renamed_statics: Default::default(),
731 objc_class_t: Cell::new(None),
732 objc_classrefs: Default::default(),
733 objc_selrefs: Default::default(),
734 offload_globals: Default::default(),
735 offload_kernel_cache: Default::default(),
736 },
737 PhantomData,
738 )
739 }
740
741 pub(crate) fn statics_to_rauw(&self) -> &RefCell<Vec<(Value<'ll>, Value<'ll>)>> {
742 &self.statics_to_rauw
743 }
744
745 #[inline]
747 #[track_caller]
748 pub(crate) fn coverage_cx(&self) -> &coverageinfo::CguCoverageContext<'ll, 'tcx> {
749 self.coverage_cx.as_ref().expect("only called when coverage instrumentation is enabled")
750 }
751
752 pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[Value<'ll>]) {
753 let array = self.const_array(self.type_ptr(), values);
754
755 let g = llvm::add_global(self.llmod, self.val_ty(array), name);
756 llvm::set_initializer(g, array);
757 llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
758 llvm::set_section(g, c"llvm.metadata");
759 }
760
761 pub(crate) fn objc_abi_version(&self) -> u32 {
765 if !self.tcx.sess.target.is_like_darwin {
::core::panicking::panic("assertion failed: self.tcx.sess.target.is_like_darwin")
};assert!(self.tcx.sess.target.is_like_darwin);
766 if self.tcx.sess.target.arch == Arch::X86 && self.tcx.sess.target.os == Os::MacOs {
767 1
769 } else {
770 2
773 }
774 }
775
776 pub(crate) fn add_ptrauth_elf_got_flag(&self) {
777 llvm::add_module_flag_u32(
778 self.llmod,
779 llvm::ModuleFlagMergeBehavior::Error,
780 "ptrauth-elf-got",
781 1,
782 );
783 }
784
785 pub(crate) fn add_ptrauth_sign_personality_flag(&self) {
786 llvm::add_module_flag_u32(
787 self.llmod,
788 llvm::ModuleFlagMergeBehavior::Error,
789 "ptrauth-sign-personality",
790 1,
791 );
792 }
793
794 pub(crate) fn add_ptrauth_pauthabi_version_and_platform_flags(
795 &self,
796 aarch64_elf_pauthabi_version: u32,
797 ) {
798 const AARCH64_PAUTH_PLATFORM_LLVM_LINUX: u32 = 0x10000002;
803 llvm::add_module_flag_u32(
804 self.llmod,
805 llvm::ModuleFlagMergeBehavior::Error,
806 "aarch64-elf-pauthabi-platform",
807 AARCH64_PAUTH_PLATFORM_LLVM_LINUX,
808 );
809 llvm::add_module_flag_u32(
810 self.llmod,
811 llvm::ModuleFlagMergeBehavior::Error,
812 "aarch64-elf-pauthabi-version",
813 aarch64_elf_pauthabi_version,
814 );
815 }
816
817 pub(crate) fn add_objc_module_flags(&self) {
821 let abi_version = self.objc_abi_version();
822
823 llvm::add_module_flag_u32(
824 self.llmod,
825 llvm::ModuleFlagMergeBehavior::Error,
826 "Objective-C Version",
827 abi_version,
828 );
829
830 llvm::add_module_flag_u32(
831 self.llmod,
832 llvm::ModuleFlagMergeBehavior::Error,
833 "Objective-C Image Info Version",
834 0,
835 );
836
837 llvm::add_module_flag_str(
838 self.llmod,
839 llvm::ModuleFlagMergeBehavior::Error,
840 "Objective-C Image Info Section",
841 match abi_version {
842 1 => "__OBJC,__image_info,regular",
843 2 => "__DATA,__objc_imageinfo,regular,no_dead_strip",
844 _ => ::core::panicking::unreachable_default_msg()unreachable!(),
845 },
846 );
847
848 if self.tcx.sess.target.env == Env::Sim {
849 llvm::add_module_flag_u32(
850 self.llmod,
851 llvm::ModuleFlagMergeBehavior::Error,
852 "Objective-C Is Simulated",
853 1 << 5,
854 );
855 }
856
857 llvm::add_module_flag_u32(
858 self.llmod,
859 llvm::ModuleFlagMergeBehavior::Error,
860 "Objective-C Class Properties",
861 1 << 6,
862 );
863 }
864
865 pub(crate) fn is_sanitizer_type_ignored(
866 &self,
867 sanitizer: &std::ffi::CStr,
868 fn_abi: &rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>,
869 ) -> bool {
870 self.sanitizer_ignorelist.as_ref().is_some_and(|ignorelist| {
871 let type_name = typename_for_ignore_list(self.tcx, fn_abi);
872 ignorelist.contains_prefix(sanitizer, c"type", &type_name)
873 })
874 }
875}
876impl<'ll> SimpleCx<'ll> {
877 pub(crate) fn get_type_of_global(&self, val: Value<'ll>) -> Type<'ll> {
878 unsafe { llvm::LLVMGlobalGetValueType(val) }
879 }
880 pub(crate) fn val_ty(&self, v: Value<'ll>) -> Type<'ll> {
881 common::val_ty(v)
882 }
883}
884impl<'ll> SimpleCx<'ll> {
885 pub(crate) fn new(
886 llmod: llvm::Module<'ll>,
887 llcx: llvm::Context<'ll>,
888 pointer_size: Size,
889 ) -> Self {
890 let isize_ty = llvm::LLVMIntTypeInContext(llcx, pointer_size.bits() as c_uint);
891 Self(SCx { llmod, llcx, isize_ty }, PhantomData)
892 }
893}
894
895impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
896 pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> Value<'ll> {
897 llvm::LLVMMetadataAsValue(self.llcx(), metadata)
898 }
899
900 pub(crate) fn get_const_int(&self, ty: Type<'ll>, val: u64) -> Value<'ll> {
901 unsafe { llvm::LLVMConstInt(ty, val, llvm::FALSE) }
902 }
903
904 pub(crate) fn get_const_i64(&self, n: u64) -> Value<'ll> {
905 self.get_const_int(self.type_i64(), n)
906 }
907
908 pub(crate) fn get_const_i32(&self, n: u64) -> Value<'ll> {
909 self.get_const_int(self.type_i32(), n)
910 }
911
912 pub(crate) fn get_const_i16(&self, n: u64) -> Value<'ll> {
913 self.get_const_int(self.type_i16(), n)
914 }
915
916 pub(crate) fn get_const_i8(&self, n: u64) -> Value<'ll> {
917 self.get_const_int(self.type_i8(), n)
918 }
919
920 pub(crate) fn get_md_kind_id(&self, name: &str) -> llvm::MetadataKindId {
921 unsafe { llvm::LLVMGetMDKindIDInContext(self.llcx(), name.as_ptr(), name.len() as c_uint) }
922 }
923
924 pub(crate) fn create_metadata(&self, name: &[u8]) -> &'ll Metadata {
925 unsafe { llvm::LLVMMDStringInContext2(self.llcx(), name.as_ptr(), name.len()) }
926 }
927
928 pub(crate) fn get_functions(&self) -> Vec<Value<'ll>> {
929 let mut functions = ::alloc::vec::Vec::new()vec![];
930 let mut func = unsafe { llvm::LLVMGetFirstFunction(self.llmod()) };
931 while let Some(f) = func {
932 functions.push(f);
933 func = unsafe { llvm::LLVMGetNextFunction(f) }
934 }
935 functions
936 }
937}
938
939impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
940 fn vtables(
941 &self,
942 ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>), Value<'ll>>> {
943 &self.vtables
944 }
945
946 fn apply_vcall_visibility_metadata(
947 &self,
948 ty: Ty<'tcx>,
949 poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
950 vtable: Value<'ll>,
951 ) {
952 apply_vcall_visibility_metadata(self, ty, poly_trait_ref, vtable);
953 }
954
955 fn get_fn(&self, instance: Instance<'tcx>) -> Value<'ll> {
956 get_fn(self, instance)
957 }
958
959 fn get_fn_addr(
960 &self,
961 instance: Instance<'tcx>,
962 pointer_auth_schema: Option<&PointerAuthSchema>,
963 ) -> Value<'ll> {
964 let llfn = get_fn(self, instance);
977 match pointer_auth_schema {
978 Some(schema) => common::maybe_sign_fn_ptr(self, instance, llfn, schema),
979 None => llfn,
980 }
981 }
982
983 fn eh_personality(&self) -> Value<'ll> {
984 if let Some(llpersonality) = self.eh_personality.get() {
1005 return llpersonality;
1006 }
1007
1008 let name = if wants_msvc_seh(&self.sess().target) {
1009 Some("__CxxFrameHandler3")
1010 } else if wants_wasm_eh(&self.sess().target) {
1011 Some("__gxx_wasm_personality_v0")
1016 } else {
1017 None
1018 };
1019
1020 let tcx = self.tcx;
1021 let llfn = match tcx.lang_items().eh_personality() {
1022 Some(def_id) if name.is_none() => self.get_fn_addr(
1023 ty::Instance::expect_resolve(
1024 tcx,
1025 self.typing_env(),
1026 def_id,
1027 ty::GenericArgs::empty(),
1028 DUMMY_SP,
1029 ),
1030 tcx.sess.pointer_authentication_functions(),
1031 ),
1032 _ => {
1033 let mangled_symbol;
1034 let name = match name {
1035 Some(name) => name,
1036 None => {
1037 mangled_symbol = rustc_symbol_mangling::eh_personality_symbol(tcx);
1038 mangled_symbol.as_str()
1039 }
1040 };
1041 if let Some(llfn) = self.get_declared_value(name) {
1042 llfn
1043 } else {
1044 let fty = self.type_variadic_func(&[], self.type_i32());
1045 let llfn = self.declare_cfn(name, llvm::UnnamedAddr::Global, fty);
1046 let target_cpu = attributes::target_cpu_attr(self, self.sess());
1047 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[target_cpu]);
1048 llfn
1049 }
1050 }
1051 };
1052 self.eh_personality.set(Some(llfn));
1053 llfn
1054 }
1055
1056 fn sess(&self) -> &Session {
1057 self.tcx.sess
1058 }
1059
1060 fn set_frame_pointer_type(&self, llfn: Value<'ll>) {
1061 if let Some(attr) = attributes::frame_pointer_type_attr(self, self.sess()) {
1062 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[attr]);
1063 }
1064 }
1065
1066 fn apply_target_cpu_attr(&self, llfn: Value<'ll>) {
1067 let mut attrs = SmallVec::<[_; 2]>::new();
1068 attrs.push(attributes::target_cpu_attr(self, self.sess()));
1069 attrs.extend(attributes::tune_cpu_attr(self, self.sess()));
1070 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &attrs);
1071 }
1072
1073 fn apply_default_optimisation_attrs(&self, llfn: Value<'ll>) {
1074 let attrs = attributes::default_optimisation_attrs(self, self.sess());
1075 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &attrs);
1076 }
1077
1078 fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
1079 let entry_name = self.sess().target.entry_name.as_ref();
1080 if self.get_declared_value(entry_name).is_none() {
1081 let llfn = self.declare_entry_fn(
1082 entry_name,
1083 to_llvm_calling_convention(self.sess(), self.sess().target.entry_abi),
1084 llvm::UnnamedAddr::Global,
1085 fn_type,
1086 );
1087 attributes::apply_to_llfn(
1088 llfn,
1089 llvm::AttributePlace::Function,
1090 attributes::target_features_attr(self, self.tcx, ::alloc::vec::Vec::new()vec![]).as_slice(),
1091 );
1092 Some(llfn)
1093 } else {
1094 None
1097 }
1098 }
1099
1100 fn intrinsic_call_expects_place_always(&self, name: Symbol) -> bool {
1101 #[allow(non_exhaustive_omitted_patterns)] match name {
sym::black_box => true,
_ => false,
}matches!(name, sym::black_box)
1102 }
1103}
1104
1105impl<'ll> CodegenCx<'ll, '_> {
1106 pub(crate) fn get_intrinsic(
1107 &self,
1108 base_name: Cow<'static, str>,
1109 type_params: &[Type<'ll>],
1110 ) -> (Type<'ll>, Value<'ll>) {
1111 *self
1112 .intrinsics
1113 .borrow_mut()
1114 .entry((base_name, SmallVec::from_slice(type_params)))
1115 .or_insert_with_key(|(base_name, type_params)| {
1116 self.declare_intrinsic(base_name, type_params)
1117 })
1118 }
1119
1120 fn declare_intrinsic(
1121 &self,
1122 base_name: &str,
1123 type_params: &[Type<'ll>],
1124 ) -> (Type<'ll>, Value<'ll>) {
1125 match base_name {
1126 "memcmp" => {
1130 let fn_ty = self.type_func(
1131 &[self.type_ptr(), self.type_ptr(), self.type_isize()],
1132 self.type_int(),
1133 );
1134 let f = self.declare_cfn("memcmp", llvm::UnnamedAddr::No, fn_ty);
1135
1136 (fn_ty, f)
1137 }
1138 "__rust_retag_reg" => {
1142 let fn_ty = self.type_func(type_params, self.type_ptr());
1143 let llfn = self.declare_cfn(base_name, llvm::UnnamedAddr::No, fn_ty);
1144 let nounwind = llvm::AttributeKind::NoUnwind.create_attr(self.llcx);
1145 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[nounwind]);
1146 (fn_ty, llfn)
1147 }
1148 "__rust_retag_mem" => {
1153 let fn_ty = self.type_func(type_params, self.type_void());
1154 let llfn = self.declare_cfn(base_name, llvm::UnnamedAddr::No, fn_ty);
1155 let nounwind = llvm::AttributeKind::NoUnwind.create_attr(self.llcx);
1156 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[nounwind]);
1157 (fn_ty, llfn)
1158 }
1159 _ => {
1160 let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes())
1161 .unwrap_or_else(|| ::rustc_span::macros::bug_impl(None,
format_args!("Unknown intrinsic: `{0}`", base_name), Location::caller())bug!("Unknown intrinsic: `{base_name}`"));
1162 let f = intrinsic.get_declaration(self.llmod, type_params);
1163 (self.get_type_of_global(f), f)
1164 }
1165 }
1166 }
1167}
1168
1169impl CodegenCx<'_, '_> {
1170 pub(crate) fn generate_local_symbol_name(&self, prefix: &str) -> String {
1173 let idx = self.local_gen_sym_counter.get();
1174 self.local_gen_sym_counter.set(idx + 1);
1175 let mut name = String::with_capacity(prefix.len() + 6);
1178 name.push_str(prefix);
1179 name.push('.');
1180 name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
1181 name
1182 }
1183
1184 pub(crate) fn generate_global_symbol_name(&self) -> String {
1186 let idx = self.global_gen_sym_counter.get();
1187 self.global_gen_sym_counter.set(idx + 1);
1188
1189 let sym = self.codegen_unit.symbol_name();
1190 let prefix = sym.as_str();
1191 let mut name = String::with_capacity(prefix.len() + 6);
1192 name.push_str(prefix);
1193 name.push('.');
1194 name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY));
1195 name
1196 }
1197}
1198
1199impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
1200 pub(crate) fn md_node_in_context(&self, md_list: &[&'ll Metadata]) -> &'ll Metadata {
1202 unsafe { llvm::LLVMMDNodeInContext2(self.llcx(), md_list.as_ptr(), md_list.len()) }
1203 }
1204
1205 pub(crate) fn set_metadata(&self, val: Value<'ll>, kind_id: MetadataKindId, md: &'ll Metadata) {
1207 let node = self.get_metadata_value(md);
1208 llvm::LLVMSetMetadata(val, kind_id, node);
1209 }
1210
1211 pub(crate) fn set_metadata_node(
1216 &self,
1217 instruction: Value<'ll>,
1218 kind_id: MetadataKindId,
1219 md_list: &[&'ll Metadata],
1220 ) -> &'ll Metadata {
1221 let md = self.md_node_in_context(md_list);
1222 self.set_metadata(instruction, kind_id, md);
1223 md
1224 }
1225
1226 pub(crate) fn module_add_named_metadata_node(
1231 &self,
1232 module: Module<'ll>,
1233 kind_name: &CStr,
1234 md_list: &[&'ll Metadata],
1235 ) {
1236 let md = self.md_node_in_context(md_list);
1237 let md_as_val = self.get_metadata_value(md);
1238 unsafe { llvm::LLVMAddNamedMetadataOperand(module, kind_name.as_ptr(), md_as_val) };
1239 }
1240
1241 pub(crate) fn global_add_metadata_node(
1245 &self,
1246 global: Value<'ll>,
1247 kind_id: MetadataKindId,
1248 md_list: &[&'ll Metadata],
1249 ) {
1250 let md = self.md_node_in_context(md_list);
1251 unsafe { llvm::LLVMGlobalAddMetadata(global, kind_id, md) };
1252 }
1253
1254 pub(crate) fn global_set_metadata_node(
1258 &self,
1259 global: Value<'ll>,
1260 kind_id: MetadataKindId,
1261 md_list: &[&'ll Metadata],
1262 ) {
1263 let md = self.md_node_in_context(md_list);
1264 unsafe { llvm::LLVMGlobalSetMetadata(global, kind_id, md) };
1265 }
1266}
1267
1268impl HasDataLayout for CodegenCx<'_, '_> {
1269 #[inline]
1270 fn data_layout(&self) -> &TargetDataLayout {
1271 &self.tcx.data_layout
1272 }
1273}
1274
1275impl HasTargetSpec for CodegenCx<'_, '_> {
1276 #[inline]
1277 fn target_spec(&self) -> &Target {
1278 &self.tcx.sess.target
1279 }
1280}
1281
1282impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> {
1283 #[inline]
1284 fn tcx(&self) -> TyCtxt<'tcx> {
1285 self.tcx
1286 }
1287}
1288
1289impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> {
1290 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
1291 ty::TypingEnv::fully_monomorphized()
1292 }
1293}
1294
1295impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
1296 #[inline]
1297 fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
1298 if let LayoutError::SizeOverflow(_)
1299 | LayoutError::ReferencesError(_)
1300 | LayoutError::InvalidSimd { .. } = err
1301 {
1302 self.tcx.dcx().span_fatal(span, err.to_string())
1303 } else {
1304 self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
1305 }
1306 }
1307}
1308
1309impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
1310 #[inline]
1311 fn handle_fn_abi_err(
1312 &self,
1313 err: FnAbiError<'tcx>,
1314 span: Span,
1315 fn_abi_request: FnAbiRequest<'tcx>,
1316 ) -> ! {
1317 codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal()
1318 }
1319}