Skip to main content

rustc_codegen_llvm/back/
llvm_backend.rs

1//! Module containing [`LlvmCodegenBackend`], which implements [`CodegenBackend`]
2//! and related traits for the LLVM codegen backend.
3
4use std::any::Any;
5use std::ffi::CStr;
6use std::marker::PhantomData;
7use std::mem::ManuallyDrop;
8use std::path::PathBuf;
9use std::ptr;
10use std::sync::OnceLock;
11
12use rustc_ast::expand::allocator::AllocatorMethod;
13use rustc_codegen_ssa::back::lto::ThinModule;
14use rustc_codegen_ssa::back::write::{
15    CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig,
16    TargetMachineFactoryFn, ThinLtoInput,
17};
18use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods};
19use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig};
20use rustc_data_structures::profiling::SelfProfilerRef;
21use rustc_errors::{DiagCtxt, DiagCtxtHandle};
22use rustc_metadata::EncodedMetadata;
23use rustc_middle::dep_graph::{WorkProduct, WorkProductMap};
24use rustc_middle::ty::TyCtxt;
25use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest};
26use rustc_session::{
27    BorrowedIncrCompSession, CodegenBackendInit, EarlySession, IncrCompSession, Session,
28};
29use rustc_span::{Symbol, sym};
30use rustc_target::spec::{RelocModel, TlsModel};
31
32use crate::back::owned_target_machine::OwnedTargetMachine;
33use crate::back::write::{create_informational_target_machine, create_target_machine};
34use crate::context::{self, SimpleCx};
35use crate::llvm::{self, ToLlvmBool};
36use crate::llvm_util::{self, target_config};
37use crate::{allocator, back, base};
38
39#[derive(#[automatically_derived]
impl ::core::clone::Clone for LlvmCodegenBackend {
    #[inline]
    fn clone(&self) -> Self {
        LlvmCodegenBackend(::core::clone::Clone::clone(&self.0))
    }
}Clone)]
40pub struct LlvmCodegenBackend(());
41
42struct TimeTraceProfiler {}
43
44impl TimeTraceProfiler {
45    fn new() -> Self {
46        unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() }
47        TimeTraceProfiler {}
48    }
49}
50
51impl Drop for TimeTraceProfiler {
52    fn drop(&mut self) {
53        unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() }
54    }
55}
56
57impl ExtraBackendMethods for LlvmCodegenBackend {
58    type Module = ModuleLlvm;
59
60    fn codegen_allocator<'tcx>(
61        &self,
62        tcx: TyCtxt<'tcx>,
63        module_name: &str,
64        methods: &[AllocatorMethod],
65    ) -> ModuleLlvm {
66        let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
67        module_llvm.with_module_refs(|ModuleRefs { llcx, llmod, .. }| {
68            let cx = SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size());
69            unsafe { allocator::codegen(tcx, cx, module_name, methods) };
70        });
71        module_llvm
72    }
73    fn compile_codegen_unit(
74        &self,
75        tcx: TyCtxt<'_>,
76        cgu_name: Symbol,
77        bitcode_needed: bool,
78    ) -> (ModuleCodegen<ModuleLlvm>, u64) {
79        base::compile_codegen_unit(tcx, cgu_name, bitcode_needed)
80    }
81}
82
83impl WriteBackendMethods for LlvmCodegenBackend {
84    type Module = ModuleLlvm;
85    type ModuleBuffer = back::lto::ModuleBuffer;
86    type TargetMachine = OwnedTargetMachine;
87    type ThinData = back::lto::ThinData;
88
89    fn thread_profiler() -> Box<dyn Any> {
90        Box::new(TimeTraceProfiler::new())
91    }
92    fn target_machine_factory(
93        &self,
94        sess: &Session,
95        optlvl: OptLevel,
96    ) -> TargetMachineFactoryFn<Self> {
97        back::write::target_machine_factory(sess, optlvl)
98    }
99    fn optimize_and_codegen_fat_lto(
100        sess: &Session,
101        cgcx: &CodegenContext,
102        shared_emitter: &SharedEmitter,
103        tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
104        exported_symbols_for_lto: &[String],
105        each_linked_rlib_for_lto: &[PathBuf],
106        modules: Vec<FatLtoInput<Self>>,
107    ) -> CompiledModule {
108        let mut module = back::lto::run_fat(
109            cgcx,
110            &sess.prof,
111            shared_emitter,
112            tm_factory,
113            exported_symbols_for_lto,
114            each_linked_rlib_for_lto,
115            modules,
116        );
117
118        let dcx = DiagCtxt::new(Box::new(shared_emitter.clone()));
119        let dcx = dcx.handle();
120        back::lto::run_pass_manager(cgcx, &sess.prof, dcx, &mut module, false);
121
122        back::write::codegen(cgcx, &sess.prof, shared_emitter, module, &cgcx.module_config)
123    }
124    fn run_thin_lto(
125        cgcx: &CodegenContext,
126        prof: &SelfProfilerRef,
127        incr_comp_session: Option<&BorrowedIncrCompSession>,
128        dcx: DiagCtxtHandle<'_>,
129        exported_symbols_for_lto: &[String],
130        each_linked_rlib_for_lto: &[PathBuf],
131        modules: Vec<ThinLtoInput<Self>>,
132    ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
133        back::lto::run_thin(
134            cgcx,
135            prof,
136            incr_comp_session,
137            dcx,
138            exported_symbols_for_lto,
139            each_linked_rlib_for_lto,
140            modules,
141        )
142    }
143    fn optimize(
144        cgcx: &CodegenContext,
145        prof: &SelfProfilerRef,
146        shared_emitter: &SharedEmitter,
147        module: &mut ModuleCodegen<Self::Module>,
148        config: &ModuleConfig,
149    ) {
150        back::write::optimize(cgcx, prof, shared_emitter, module, config);
151    }
152    fn optimize_and_codegen_thin(
153        cgcx: &CodegenContext,
154        prof: &SelfProfilerRef,
155        shared_emitter: &SharedEmitter,
156        tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
157        thin: ThinModule<Self>,
158    ) -> CompiledModule {
159        back::lto::optimize_and_codegen_thin_module(cgcx, prof, shared_emitter, tm_factory, thin)
160    }
161    fn codegen(
162        cgcx: &CodegenContext,
163        prof: &SelfProfilerRef,
164        shared_emitter: &SharedEmitter,
165        module: ModuleCodegen<Self::Module>,
166        config: &ModuleConfig,
167    ) -> CompiledModule {
168        back::write::codegen(cgcx, prof, shared_emitter, module, config)
169    }
170    fn serialize_module(module: Self::Module, is_thin: bool) -> Self::ModuleBuffer {
171        module.with_module_refs(|ModuleRefs { llmod, .. }| {
172            back::lto::ModuleBuffer::new(llmod, is_thin)
173        })
174    }
175}
176
177impl LlvmCodegenBackend {
178    pub fn new() -> Box<dyn CodegenBackend> {
179        Box::new(LlvmCodegenBackend(()))
180    }
181}
182
183impl CodegenBackend for LlvmCodegenBackend {
184    fn name(&self) -> &'static str {
185        "llvm"
186    }
187
188    fn init(&mut self, sess: &EarlySession) -> CodegenBackendInit {
189        llvm_util::init(sess); // Make sure llvm is inited
190
191        let global_backend_features =
192            llvm_util::global_llvm_features(sess, /* for_cfg */ false);
193
194        // autodiff is based on Enzyme, a library which we might not have available, when it was
195        // neither build, nor downloaded via rustup. If autodiff is used, but not available we emit
196        // an early error here and abort compilation.
197        {
198            use rustc_session::config::AutoDiff;
199
200            use crate::back::lto::enable_autodiff_settings;
201            if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) {
202                match llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) {
203                    Ok(_) => {}
204                    Err(llvm::EnzymeLibraryError::NotFound { err }) => {
205                        sess.dcx().emit_fatal(crate::diagnostics::AutoDiffComponentMissing { err });
206                    }
207                    Err(llvm::EnzymeLibraryError::LoadFailed { err }) => {
208                        sess.dcx()
209                            .emit_fatal(crate::diagnostics::AutoDiffComponentUnavailable { err });
210                    }
211                }
212                enable_autodiff_settings(&sess.opts.unstable_opts.autodiff);
213            }
214        }
215
216        // Intrinsics whose fallback body will not be used by the LLVM backend.
217        let replaced_intrinsics = {
218            #[rustfmt::skip]
219            let will_not_use_fallback = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [sym::unchecked_funnel_shl, sym::unchecked_funnel_shr,
                sym::carrying_mul_add, sym::carryless_mul, sym::integer_max,
                sym::integer_min, sym::sin, sym::cos, sym::powf, sym::powi,
                sym::sqrt, sym::exp, sym::exp2, sym::log, sym::log10,
                sym::log2, sym::floor, sym::ceil, sym::trunc, sym::round,
                sym::round_ties_even, sym::fma, sym::copysignf16,
                sym::copysignf32, sym::copysignf64, sym::copysignf128]))vec![
220                // These are mapped to LLVM intrinsics instead.
221                sym::unchecked_funnel_shl,
222                sym::unchecked_funnel_shr,
223                sym::carrying_mul_add,
224                sym::carryless_mul,
225                sym::integer_max,
226                sym::integer_min,
227
228                // Fallback via libm/compiler-builtins, but the LLVM intrinsic is used instead.
229                sym::sin,
230                sym::cos,
231                sym::powf,
232                sym::powi,
233                sym::sqrt,
234                sym::exp,
235                sym::exp2,
236                sym::log,
237                sym::log10,
238                sym::log2,
239                sym::floor, sym::ceil, sym::trunc,
240                sym::round, sym::round_ties_even,
241                sym::fma,
242
243                sym::copysignf16, sym::copysignf32, sym::copysignf64, sym::copysignf128,
244            ];
245
246            will_not_use_fallback
247        };
248
249        // `type_id_eq` is a safe choice since *all* backends use the fallback body for that. When
250        // adding more intrinsics, keep in mind that the distributed standard library is compiled
251        // with the LLVM backend but might later be included in a project built with cranelift or
252        // GCC. Adding an intrinsic here can therefore mean the fallback body is used with
253        // cranelift/GCC even if they have dedicated implementations.
254        let fallback_intrinsics = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [sym::type_id_eq]))vec![sym::type_id_eq];
255
256        CodegenBackendInit {
257            global_backend_features,
258            replaced_intrinsics,
259            fallback_intrinsics,
260            thin_lto_supported: true,
261        }
262    }
263
264    fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
265        use std::fmt::Write;
266        match req.kind {
267            PrintKind::RelocationModels => {
268                out.write_fmt(format_args!("Available relocation models:\n"))writeln!(out, "Available relocation models:").unwrap();
269                for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) {
270                    out.write_fmt(format_args!("    {0}\n", name))writeln!(out, "    {name}").unwrap();
271                }
272                out.write_fmt(format_args!("\n"))writeln!(out).unwrap();
273            }
274            PrintKind::CodeModels => {
275                out.write_fmt(format_args!("Available code models:\n"))writeln!(out, "Available code models:").unwrap();
276                for name in &["tiny", "small", "kernel", "medium", "large"] {
277                    out.write_fmt(format_args!("    {0}\n", name))writeln!(out, "    {name}").unwrap();
278                }
279                out.write_fmt(format_args!("\n"))writeln!(out).unwrap();
280            }
281            PrintKind::TlsModels => {
282                out.write_fmt(format_args!("Available TLS models:\n"))writeln!(out, "Available TLS models:").unwrap();
283                for name in TlsModel::ALL.iter().map(TlsModel::desc) {
284                    out.write_fmt(format_args!("    {0}\n", name))writeln!(out, "    {name}").unwrap();
285                }
286                out.write_fmt(format_args!("\n"))writeln!(out).unwrap();
287            }
288            PrintKind::StackProtectorStrategies => {
289                out.write_fmt(format_args!("Available stack protector strategies:\n    all\n        Generate stack canaries in all functions.\n\n    strong\n        Generate stack canaries in a function if it either:\n        - has a local variable of `[T; N]` type, regardless of `T` and `N`\n        - takes the address of a local variable.\n\n          (Note that a local variable being borrowed is not equivalent to its\n          address being taken: e.g. some borrows may be removed by optimization,\n          while by-value argument passing may be implemented with reference to a\n          local stack variable in the ABI.)\n\n    basic\n        Generate stack canaries in functions with local variables of `[T; N]`\n        type, where `T` is byte-sized and `N` >= 8.\n\n    none\n        Do not generate stack canaries.\n\n"))writeln!(
290                    out,
291                    r#"Available stack protector strategies:
292    all
293        Generate stack canaries in all functions.
294
295    strong
296        Generate stack canaries in a function if it either:
297        - has a local variable of `[T; N]` type, regardless of `T` and `N`
298        - takes the address of a local variable.
299
300          (Note that a local variable being borrowed is not equivalent to its
301          address being taken: e.g. some borrows may be removed by optimization,
302          while by-value argument passing may be implemented with reference to a
303          local stack variable in the ABI.)
304
305    basic
306        Generate stack canaries in functions with local variables of `[T; N]`
307        type, where `T` is byte-sized and `N` >= 8.
308
309    none
310        Do not generate stack canaries.
311"#
312                )
313                .unwrap();
314            }
315            _other => llvm_util::print(req, out, sess),
316        }
317    }
318
319    fn print_passes(&self) {
320        llvm_util::print_passes();
321    }
322
323    fn print_version(&self) {
324        llvm_util::print_version();
325    }
326
327    fn has_zstd(&self) -> bool {
328        llvm::LLVMRustLLVMHasZstdCompression()
329    }
330
331    fn has_mnemonic(&self, sess: &Session, mnemonic: &str) -> bool {
332        llvm_util::target_has_mnemonic(sess, mnemonic)
333    }
334
335    fn target_config(&self, sess: &EarlySession) -> TargetConfig {
336        target_config(sess)
337    }
338
339    fn target_cpu(&self, sess: &Session) -> String {
340        crate::llvm_util::target_cpu(sess).to_string()
341    }
342
343    fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any> {
344        use rustc_session::config::Offload;
345
346        if tcx.sess.opts.unstable_opts.offload.iter().any(|o| #[allow(non_exhaustive_omitted_patterns)] match o {
    Offload::Device(_) => true,
    _ => false,
}matches!(o, Offload::Device(_)))
347            || tcx.sess.opts.unstable_opts.offload.iter().any(|o| #[allow(non_exhaustive_omitted_patterns)] match o {
    Offload::Host(_) => true,
    _ => false,
}matches!(o, Offload::Host(_)))
348        {
349            match llvm::RustOffloadWrapper::get_or_init(&tcx.sess.opts.sysroot) {
350                Ok(_) => {}
351                Err(llvm::RustOffloadLibraryError::NotFound { err }) => {
352                    tcx.sess
353                        .dcx()
354                        .emit_fatal(crate::diagnostics::RustOffloadComponentMissing { err });
355                }
356                Err(llvm::RustOffloadLibraryError::LoadFailed { err }) => {
357                    tcx.sess
358                        .dcx()
359                        .emit_fatal(crate::diagnostics::RustOffloadComponentUnavailable { err });
360                }
361            }
362        }
363
364        Box::new(rustc_codegen_ssa::base::codegen_crate(LlvmCodegenBackend(()), tcx))
365    }
366
367    fn join_codegen(
368        &self,
369        ongoing_codegen: Box<dyn Any>,
370        sess: &Session,
371        incr_comp_session: Option<&IncrCompSession>,
372        outputs: &OutputFilenames,
373        crate_info: &CrateInfo,
374    ) -> (CompiledModules, WorkProductMap) {
375        let (compiled_modules, work_products) = ongoing_codegen
376            .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
377            .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
378            .join(sess, incr_comp_session, crate_info);
379
380        if sess.opts.unstable_opts.llvm_time_trace {
381            sess.time("llvm_dump_timing_file", || {
382                let file_name = outputs.with_extension("llvm_timings.json");
383                llvm_util::time_trace_profiler_finish(&file_name);
384            });
385        }
386
387        if sess.codegen_units().as_usize() == 1 && sess.opts.unstable_opts.time_llvm_passes {
388            let timings =
389                llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap();
390            { ::std::io::_print(format_args!("{0}", timings)); };print!("{timings}");
391        }
392
393        if sess.print_llvm_stats() {
394            let stats =
395                llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap();
396            { ::std::io::_print(format_args!("{0}", stats)); };print!("{stats}");
397        }
398
399        if let Some(out_path) = sess.print_llvm_stats_json() {
400            let llvm_stats_json =
401                llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatisticsJSON(s) }).unwrap();
402
403            if !llvm_stats_json.is_empty() {
404                if let Err(e) = std::fs::write(&out_path, llvm_stats_json) {
405                    sess.dcx().err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("failed to write stats to {0}: {1}",
                out_path, e))
    })format!("failed to write stats to {out_path}: {e}"));
406                }
407            } else {
408                sess.dcx().warn(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("requested to print LLVM statistics to JSON file {0}, but the codegen backend did not provide any statistics",
                out_path))
    })format!(
409                    "requested to print LLVM statistics to JSON file {out_path}, but the codegen backend \
410                    did not provide any statistics",
411                ));
412            }
413        }
414
415        (compiled_modules, work_products)
416    }
417
418    fn link(
419        &self,
420        sess: &Session,
421        compiled_modules: CompiledModules,
422        crate_info: CrateInfo,
423        metadata: EncodedMetadata,
424        outputs: &OutputFilenames,
425    ) {
426        use rustc_codegen_ssa::back::link::link_binary;
427
428        use crate::back::archive::LlvmArchiveBuilderBuilder;
429
430        // Run the linker on any artifacts that resulted from the LLVM run.
431        // This should produce either a finished executable or library.
432        link_binary(
433            sess,
434            &LlvmArchiveBuilderBuilder,
435            compiled_modules,
436            crate_info,
437            metadata,
438            outputs,
439            self.name(),
440        );
441    }
442}
443
444pub struct ModuleLlvm {
445    llcx_raw: ptr::NonNull<llvm::Context>,
446    llmod_raw: *const llvm::Module,
447
448    // This field is `ManuallyDrop` because it is important that the `TargetMachine`
449    // is disposed prior to the `Context` being disposed otherwise UAFs can occur.
450    tm: ManuallyDrop<OwnedTargetMachine>,
451
452    /// Saved ThinLTO buffer for embedding in the object file.
453    ///
454    /// This is currently a `OnceLock` to avoid aliasing problems when writing to it
455    /// from code that also wants to pass around a shared ref to `ModuleCodegen`.
456    pub(crate) thin_lto_buffer: OnceLock<Vec<u8>>,
457}
458
459unsafe impl Send for ModuleLlvm {}
460unsafe impl Sync for ModuleLlvm {}
461
462/// Shared helper to call [`llvm::LLVMContextCreate`] and then configure
463/// [`llvm::LLVMContextSetDiscardValueNames`].
464fn create_context_and_set_fewer_names(fewer_names: bool) -> ptr::NonNull<llvm::Context> {
465    unsafe {
466        let llcx_raw = llvm::LLVMContextCreate();
467        llvm::LLVMContextSetDiscardValueNames(llcx_raw.as_ref(), fewer_names.to_llvm_bool());
468        llcx_raw
469    }
470}
471
472impl ModuleLlvm {
473    pub(crate) fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
474        unsafe {
475            let llcx_raw = create_context_and_set_fewer_names(tcx.sess.fewer_names());
476            let llmod_raw = context::create_module(tcx, llcx_raw.as_ref(), mod_name);
477            ModuleLlvm {
478                llmod_raw,
479                llcx_raw,
480                tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)),
481                thin_lto_buffer: OnceLock::new(),
482            }
483        }
484    }
485
486    pub(crate) fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
487        unsafe {
488            let llcx_raw = create_context_and_set_fewer_names(tcx.sess.fewer_names());
489            let llmod_raw = context::create_module(tcx, llcx_raw.as_ref(), mod_name);
490            ModuleLlvm {
491                llmod_raw,
492                llcx_raw,
493                tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
494                thin_lto_buffer: OnceLock::new(),
495            }
496        }
497    }
498
499    pub(crate) fn parse(
500        cgcx: &CodegenContext,
501        tm_factory: TargetMachineFactoryFn<LlvmCodegenBackend>,
502        name: &CStr,
503        buffer: &[u8],
504        dcx: DiagCtxtHandle<'_>,
505    ) -> Self {
506        unsafe {
507            let llcx_raw = create_context_and_set_fewer_names(cgcx.fewer_names);
508            let llmod_raw = back::lto::parse_module(llcx_raw.as_ref(), name, buffer, dcx);
509            let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap()));
510
511            ModuleLlvm {
512                llmod_raw,
513                llcx_raw,
514                tm: ManuallyDrop::new(tm),
515                thin_lto_buffer: OnceLock::new(),
516            }
517        }
518    }
519
520    /// Passes a [`ModuleRefs`] struct to a callback function, giving it scoped
521    /// access to the resources owned by this module.
522    ///
523    /// Passing the references to a callback ensures that they have coherent
524    /// `'ll` lifetimes, and that they can't escape the callback.
525    pub(crate) fn with_module_refs<R>(
526        &self,
527        inner_fn: impl for<'ll> FnOnce(ModuleRefs<'ll>) -> R,
528    ) -> R {
529        inner_fn(ModuleRefs {
530            llcx: unsafe { self.llcx_raw.as_ref() },
531            llmod: unsafe { &*self.llmod_raw },
532            tm: self.tm.raw(),
533            _ph: PhantomData,
534        })
535    }
536}
537
538impl Drop for ModuleLlvm {
539    fn drop(&mut self) {
540        unsafe {
541            ManuallyDrop::drop(&mut self.tm);
542            llvm::LLVMContextDispose(self.llcx_raw);
543        }
544    }
545}
546
547/// Bundle of references provided by [`ModuleLlvm::with_module_refs`].
548#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'ll> ::core::clone::TrivialClone for ModuleRefs<'ll> { }
#[automatically_derived]
impl<'ll> ::core::clone::Clone for ModuleRefs<'ll> {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<&'ll llvm::Context>;
        let _: ::core::clone::AssertParamIsClone<&'ll llvm::Module>;
        let _: ::core::clone::AssertParamIsClone<&'ll llvm::TargetMachine>;
        let _:
                ::core::clone::AssertParamIsClone<PhantomData<fn(&'ll ())
                    -> &'ll ()>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'ll> ::core::marker::Copy for ModuleRefs<'ll> { }Copy)]
549pub(crate) struct ModuleRefs<'ll> {
550    pub(crate) llcx: &'ll llvm::Context,
551    pub(crate) llmod: &'ll llvm::Module,
552    pub(crate) tm: &'ll llvm::TargetMachine,
553    /// Make sure `'ll` is invariant, even if no fields happen to require that.
554    ///
555    /// FIXME(Zalathar): Consider using `PhantomInvariantLifetime` when the API
556    /// for that is settled.
557    _ph: PhantomData<fn(&'ll ()) -> &'ll ()>,
558}