use std::ops::Range;

use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
use rustc_codegen_ssa::common;
use rustc_codegen_ssa::traits::*;
use rustc_hir::LangItem;
use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::interpret::{
    Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar,
    read_target_uint,
};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};
use rustc_span::Symbol;
use rustc_target::spec::Arch;
use tracing::{debug, instrument, trace};

use crate::common::CodegenCx;
use crate::errors::SymbolAlreadyDefined;
use crate::llvm::{self, Type, Value};
use crate::type_of::LayoutLlvmExt;
use crate::{base, debuginfo};

pub(crate) fn const_alloc_to_llvm<'ll>(
    cx: &CodegenCx<'ll, '_>,
    alloc: &Allocation,
    is_static: bool,
) -> &'ll Value {
    // We expect that callers of const_alloc_to_llvm will instead directly codegen a pointer or
    // integer for any &ZST where the ZST is a constant (i.e. not a static). We should never be
    // producing empty LLVM allocations as they're just adding noise to binaries and forcing less
    // optimal codegen.
    //
    // Statics have a guaranteed meaningful address so it's less clear that we want to do
    // something like this; it's also harder.
    if !is_static {
        assert!(alloc.len() != 0);
    }
    let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
    let dl = cx.data_layout();
    let pointer_size = dl.pointer_size();
    let pointer_size_bytes = pointer_size.bytes() as usize;

    // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`, so `range`
    // must be within the bounds of `alloc` and not contain or overlap a pointer provenance.
    fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
        llvals: &mut Vec<&'ll Value>,
        cx: &'a CodegenCx<'ll, 'b>,
        alloc: &'a Allocation,
        range: Range<usize>,
    ) {
        let chunks = alloc.init_mask().range_as_init_chunks(range.clone().into());

        let chunk_to_llval = move |chunk| match chunk {
            InitChunk::Init(range) => {
                let range = (range.start.bytes() as usize)..(range.end.bytes() as usize);
                let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
                cx.const_bytes(bytes)
            }
            InitChunk::Uninit(range) => {
                let len = range.end.bytes() - range.start.bytes();
                cx.const_undef(cx.type_array(cx.type_i8(), len))
            }
        };

        // Generating partially-uninit consts is limited to small numbers of chunks,
        // to avoid the cost of generating large complex const expressions.
        // For example, `[(u32, u8); 1024 * 1024]` contains uninit padding in each element, and
        // would result in `{ [5 x i8] zeroinitializer, [3 x i8] undef, ...repeat 1M times... }`.
        let max = cx.sess().opts.unstable_opts.uninit_const_chunk_threshold;
        let allow_uninit_chunks = chunks.clone().take(max.saturating_add(1)).count() <= max;

        if allow_uninit_chunks {
            llvals.extend(chunks.map(chunk_to_llval));
        } else {
            // If this allocation contains any uninit bytes, codegen as if it was initialized
            // (using some arbitrary value for uninit bytes).
            let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
            llvals.push(cx.const_bytes(bytes));
        }
    }

    let mut next_offset = 0;
    for &(offset, prov) in alloc.provenance().ptrs().iter() {
        let offset = offset.bytes();
        assert_eq!(offset as usize as u64, offset);
        let offset = offset as usize;
        if offset > next_offset {
            // This `inspect` is okay since we have checked that there is no provenance, it
            // is within the bounds of the allocation, and it doesn't affect interpreter execution
            // (we inspect the result after interpreter execution).
            append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, next_offset..offset);
        }
        let ptr_offset = read_target_uint(
            dl.endian,
            // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
            // affect interpreter execution (we inspect the result after interpreter execution),
            // and we properly interpret the provenance as a relocation pointer offset.
            alloc.inspect_with_uninit_and_ptr_outside_interpreter(
                offset..(offset + pointer_size_bytes),
            ),
        )
        .expect("const_alloc_to_llvm: could not read relocation pointer")
            as u64;

        let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx);

        llvals.push(cx.scalar_to_backend(
            InterpScalar::from_pointer(Pointer::new(prov, Size::from_bytes(ptr_offset)), &cx.tcx),
            Scalar::Initialized {
                value: Primitive::Pointer(address_space),
                valid_range: WrappingRange::full(pointer_size),
            },
            cx.type_ptr_ext(address_space),
        ));
        next_offset = offset + pointer_size_bytes;
    }
    if alloc.len() >= next_offset {
        let range = next_offset..alloc.len();
        // This `inspect` is okay since we have check that it is after all provenance, it is
        // within the bounds of the allocation, and it doesn't affect interpreter execution (we
        // inspect the result after interpreter execution).
        append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range);
    }

    // Avoid wrapping in a struct if there is only a single value. This ensures
    // that LLVM is able to perform the string merging optimization if the constant
    // is a valid C string. LLVM only considers bare arrays for this optimization,
    // not arrays wrapped in a struct. LLVM handles this at:
    // https://github.com/rust-lang/llvm-project/blob/acaea3d2bb8f351b740db7ebce7d7a40b9e21488/llvm/lib/Target/TargetLoweringObjectFile.cpp#L249-L280
    if let &[data] = &*llvals { data } else { cx.const_struct(&llvals, true) }
}

fn codegen_static_initializer<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    def_id: DefId,
) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
    let alloc = cx.tcx.eval_static_initializer(def_id)?;
    Ok((const_alloc_to_llvm(cx, alloc.inner(), /*static*/ true), alloc))
}

fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) {
    // The target may require greater alignment for globals than the type does.
    // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
    // which can force it to be smaller. Rust doesn't support this yet.
    if let Some(min_global) = cx.sess().target.min_global_align {
        align = Ord::max(align, min_global);
    }
    llvm::set_alignment(gv, align);
}

fn check_and_apply_linkage<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    attrs: &CodegenFnAttrs,
    llty: &'ll Type,
    sym: &str,
    def_id: DefId,
) -> &'ll Value {
    if let Some(linkage) = attrs.import_linkage {
        debug!("get_static: sym={} linkage={:?}", sym, linkage);

        // Declare a symbol `foo`. If `foo` is an extern_weak symbol, we declare
        // an extern_weak function, otherwise a global with the desired linkage.
        let g1 = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) {
            // An `extern_weak` function is represented as an `Option<unsafe extern ...>`,
            // we extract the function signature and declare it as an extern_weak function
            // instead of an extern_weak i8.
            let instance = Instance::mono(cx.tcx, def_id);
            if let ty::Adt(struct_def, args) = instance.ty(cx.tcx, cx.typing_env()).kind()
                && cx.tcx.is_lang_item(struct_def.did(), LangItem::Option)
                && let ty::FnPtr(sig, header) = args.type_at(0).kind()
            {
                let fn_sig = sig.with(*header);

                let fn_abi = cx.fn_abi_of_fn_ptr(fn_sig, ty::List::empty());
                cx.declare_fn(sym, &fn_abi, None)
            } else {
                cx.declare_global(sym, cx.type_i8())
            }
        } else {
            cx.declare_global(sym, cx.type_i8())
        };
        llvm::set_linkage(g1, base::linkage_to_llvm(linkage));

        // Declare an internal global `extern_with_linkage_foo` which
        // is initialized with the address of `foo`. If `foo` is
        // discarded during linking (for example, if `foo` has weak
        // linkage and there are no definitions), then
        // `extern_with_linkage_foo` will instead be initialized to
        // zero.
        let real_name =
            format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE));
        let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
            cx.sess().dcx().emit_fatal(SymbolAlreadyDefined {
                span: cx.tcx.def_span(def_id),
                symbol_name: sym,
            })
        });
        llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
        llvm::set_initializer(g2, g1);
        g2
    } else if cx.tcx.sess.target.arch == Arch::X86
        && common::is_mingw_gnu_toolchain(&cx.tcx.sess.target)
        && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
    {
        cx.declare_global(&common::i686_decorated_name(dllimport, true, true, false), llty)
    } else {
        // Generate an external declaration.
        // FIXME(nagisa): investigate whether it can be changed into define_global
        cx.declare_global(sym, llty)
    }
}

impl<'ll> CodegenCx<'ll, '_> {
    pub(crate) fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
        unsafe { llvm::LLVMConstBitCast(val, ty) }
    }

    pub(crate) fn const_pointercast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value {
        unsafe { llvm::LLVMConstPointerCast(val, ty) }
    }

    /// Create a global variable.
    ///
    /// The returned global variable is a pointer in the default address space for globals.
    /// Fails if a symbol with the given name already exists.
    pub(crate) fn static_addr_of_mut(
        &self,
        cv: &'ll Value,
        align: Align,
        kind: Option<&str>,
    ) -> &'ll Value {
        let gv = match kind {
            Some(kind) if !self.tcx.sess.fewer_names() => {
                let name = self.generate_local_symbol_name(kind);
                let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| {
                    bug!("symbol `{}` is already defined", name);
                });
                gv
            }
            _ => self.define_global("", self.val_ty(cv)).unwrap_or_else(|| {
                bug!("anonymous global symbol is already defined");
            }),
        };
        llvm::set_linkage(gv, llvm::Linkage::PrivateLinkage);
        llvm::set_initializer(gv, cv);
        set_global_alignment(self, gv, align);
        llvm::set_unnamed_address(gv, llvm::UnnamedAddr::Global);
        gv
    }

    /// Create a global constant.
    ///
    /// The returned global variable is a pointer in the default address space for globals.
    pub(crate) fn static_addr_of_impl(
        &self,
        cv: &'ll Value,
        align: Align,
        kind: Option<&str>,
    ) -> &'ll Value {
        if let Some(&gv) = self.const_globals.borrow().get(&cv) {
            unsafe {
                // Upgrade the alignment in cases where the same constant is used with different
                // alignment requirements
                let llalign = align.bytes() as u32;
                if llalign > llvm::LLVMGetAlignment(gv) {
                    llvm::LLVMSetAlignment(gv, llalign);
                }
            }
            return gv;
        }
        let gv = self.static_addr_of_mut(cv, align, kind);
        llvm::set_global_constant(gv, true);

        self.const_globals.borrow_mut().insert(cv, gv);
        gv
    }

    #[instrument(level = "debug", skip(self))]
    pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value {
        let instance = Instance::mono(self.tcx, def_id);
        trace!(?instance);

        let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
        // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure
        // out the llvm type from the actual evaluated initializer.
        let llty = if nested {
            self.type_i8()
        } else {
            let ty = instance.ty(self.tcx, self.typing_env());
            trace!(?ty);
            self.layout_of(ty).llvm_type(self)
        };
        self.get_static_inner(def_id, llty)
    }

    #[instrument(level = "debug", skip(self, llty))]
    fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
        let instance = Instance::mono(self.tcx, def_id);
        if let Some(&g) = self.instances.borrow().get(&instance) {
            trace!("used cached value");
            return g;
        }

        let defined_in_current_codegen_unit =
            self.codegen_unit.items().contains_key(&MonoItem::Static(def_id));
        assert!(
            !defined_in_current_codegen_unit,
            "consts::get_static() should always hit the cache for \
                 statics defined in the same CGU, but did not for `{def_id:?}`"
        );

        let sym = self.tcx.symbol_name(instance).name;
        let fn_attrs = self.tcx.codegen_fn_attrs(def_id);

        debug!(?sym, ?fn_attrs);

        let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
            if let Some(g) = self.get_declared_value(sym) {
                if self.val_ty(g) != self.type_ptr() {
                    span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
                }
            }

            let g = self.declare_global(sym, llty);

            if !self.tcx.is_reachable_non_generic(def_id) {
                llvm::set_visibility(g, llvm::Visibility::Hidden);
            }

            g
        } else if let Some(classname) = fn_attrs.objc_class {
            self.get_objc_classref(classname)
        } else if let Some(methname) = fn_attrs.objc_selector {
            self.get_objc_selref(methname)
        } else {
            check_and_apply_linkage(self, fn_attrs, llty, sym, def_id)
        };

        // Thread-local statics in some other crate need to *always* be linked
        // against in a thread-local fashion, so we need to be sure to apply the
        // thread-local attribute locally if it was present remotely. If we
        // don't do this then linker errors can be generated where the linker
        // complains that one object files has a thread local version of the
        // symbol and another one doesn't.
        if fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
            llvm::set_thread_local_mode(g, self.tls_model);
        }

        let dso_local = self.assume_dso_local(g, true);

        if !def_id.is_local() {
            let needs_dll_storage_attr = self.use_dll_storage_attrs
                && !self.tcx.is_foreign_item(def_id)
                // Local definitions can never be imported, so we must not apply
                // the DLLImport annotation.
                && !dso_local
                // Linker plugin ThinLTO doesn't create the self-dllimport Rust uses for rlibs
                // as the code generation happens out of process. Instead we assume static linkage
                // and disallow dynamic linking when linker plugin based LTO is enabled.
                // Regular in-process ThinLTO doesn't need this workaround.
                && !self.tcx.sess.opts.cg.linker_plugin_lto.enabled();

            // If this assertion triggers, there's something wrong with commandline
            // argument validation.
            assert!(
                !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
                    && self.tcx.sess.target.is_like_windows
                    && self.tcx.sess.opts.cg.prefer_dynamic)
            );

            if needs_dll_storage_attr {
                // This item is external but not foreign, i.e., it originates from an external Rust
                // crate. Since we don't know whether this crate will be linked dynamically or
                // statically in the final application, we always mark such symbols as 'dllimport'.
                // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs
                // to make things work.
                //
                // However, in some scenarios we defer emission of statics to downstream
                // crates, so there are cases where a static with an upstream DefId
                // is actually present in the current crate. We can find out via the
                // is_codegened_item query.
                if !self.tcx.is_codegened_item(def_id) {
                    llvm::set_dllimport_storage_class(g);
                }
            }
        }

        if self.use_dll_storage_attrs
            && let Some(library) = self.tcx.native_library(def_id)
            && library.kind.is_dllimport()
        {
            // For foreign (native) libs we know the exact storage type to use.
            llvm::set_dllimport_storage_class(g);
        }

        self.instances.borrow_mut().insert(instance, g);
        g
    }

    fn codegen_static_item(&mut self, def_id: DefId) {
        assert!(
            llvm::LLVMGetInitializer(
                self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap()
            )
            .is_none()
        );
        let attrs = self.tcx.codegen_fn_attrs(def_id);

        let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
            // Error has already been reported
            return;
        };
        let alloc = alloc.inner();

        let val_llty = self.val_ty(v);

        let g = self.get_static_inner(def_id, val_llty);
        let llty = self.get_type_of_global(g);

        let g = if val_llty == llty {
            g
        } else {
            // codegen_static_initializer creates the global value just from the
            // `Allocation` data by generating one big struct value that is just
            // all the bytes and pointers after each other. This will almost never
            // match the type that the static was declared with. Unfortunately
            // we can't just LLVMConstBitCast our way out of it because that has very
            // specific rules on what can be cast. So instead of adding a new way to
            // generate static initializers that match the static's type, we picked
            // the easier option and retroactively change the type of the static item itself.
            let name = String::from_utf8(llvm::get_value_name(g))
                .expect("we declare our statics with a utf8-valid name");
            llvm::set_value_name(g, b"");

            let linkage = llvm::get_linkage(g);
            let visibility = llvm::get_visibility(g);

            let new_g = self.declare_global(&name, val_llty);

            llvm::set_linkage(new_g, linkage);
            llvm::set_visibility(new_g, visibility);

            // The old global has had its name removed but is returned by
            // get_static since it is in the instance cache. Provide an
            // alternative lookup that points to the new global so that
            // global_asm! can compute the correct mangled symbol name
            // for the global.
            self.renamed_statics.borrow_mut().insert(def_id, new_g);

            // To avoid breaking any invariants, we leave around the old
            // global for the moment; we'll replace all references to it
            // with the new global later. (See base::codegen_backend.)
            self.statics_to_rauw.borrow_mut().push((g, new_g));
            new_g
        };

        // NOTE: Alignment from attributes has already been applied to the allocation.
        set_global_alignment(self, g, alloc.align);
        llvm::set_initializer(g, v);

        self.assume_dso_local(g, true);

        // Forward the allocation's mutability (picked by the const interner) to LLVM.
        if alloc.mutability.is_not() {
            llvm::set_global_constant(g, true);
        }

        debuginfo::build_global_var_di_node(self, def_id, g);

        if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
            llvm::set_thread_local_mode(g, self.tls_model);
        }

        // Wasm statics with custom link sections get special treatment as they
        // go into custom sections of the wasm executable. The exception to this
        // is the `.init_array` section which are treated specially by the wasm linker.
        if self.tcx.sess.target.is_like_wasm
            && attrs
                .link_section
                .map(|link_section| !link_section.as_str().starts_with(".init_array"))
                .unwrap_or(true)
        {
            if let Some(section) = attrs.link_section {
                let section = self.create_metadata(section.as_str().as_bytes());
                assert!(alloc.provenance().ptrs().is_empty());

                // The `inspect` method is okay here because we checked for provenance, and
                // because we are doing this access to inspect the final interpreter state (not
                // as part of the interpreter execution).
                let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
                let alloc = self.create_metadata(bytes);
                let data = [section, alloc];
                self.module_add_named_metadata_node(self.llmod(), c"wasm.custom_sections", &data);
            }
        } else {
            base::set_link_section(g, attrs);
        }

        base::set_variable_sanitizer_attrs(g, attrs);

        if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) {
            // `USED` and `USED_LINKER` can't be used together.
            assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));

            // The semantics of #[used] in Rust only require the symbol to make it into the
            // object file. It is explicitly allowed for the linker to strip the symbol if it
            // is dead, which means we are allowed to use `llvm.compiler.used` instead of
            // `llvm.used` here.
            //
            // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
            // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs
            // in the handling of `.init_array` (the static constructor list) in versions of
            // the gold linker (prior to the one released with binutils 2.36).
            //
            // That said, we only ever emit these when `#[used(compiler)]` is explicitly
            // requested. This is to avoid similar breakage on other targets, in particular
            // MachO targets have *their* static constructor lists broken if `llvm.compiler.used`
            // is emitted rather than `llvm.used`. However, that check happens when assigning
            // the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to
            // take care of it here.
            self.add_compiler_used_global(g);
        }
        if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
            // `USED` and `USED_LINKER` can't be used together.
            assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER));

            self.add_used_global(g);
        }
    }

    /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr.
    pub(crate) fn add_used_global(&mut self, global: &'ll Value) {
        self.used_statics.push(global);
    }

    /// Add a global value to a list to be stored in the `llvm.compiler.used` variable,
    /// an array of ptr.
    pub(crate) fn add_compiler_used_global(&self, global: &'ll Value) {
        self.compiler_used_statics.borrow_mut().push(global);
    }

    // We do our best here to match what Clang does when compiling Objective-C natively.
    // See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
    fn define_objc_classname(&self, classname: &str) -> &'ll Value {
        assert_eq!(self.objc_abi_version(), 1);

        let llval = self.null_terminate_const_bytes(classname.as_bytes());
        let llty = self.val_ty(llval);
        let sym = self.generate_local_symbol_name("OBJC_CLASS_NAME_");
        let g = self.define_global(&sym, llty).unwrap_or_else(|| {
            bug!("symbol `{}` is already defined", sym);
        });
        set_global_alignment(self, g, self.tcx.data_layout.i8_align);
        llvm::set_initializer(g, llval);
        llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
        llvm::set_section(g, c"__TEXT,__cstring,cstring_literals");
        llvm::LLVMSetGlobalConstant(g, llvm::TRUE);
        llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
        self.add_compiler_used_global(g);

        g
    }

    // We do our best here to match what Clang does when compiling Objective-C natively.
    // See Clang's `ObjCNonFragileABITypesHelper`:
    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L6052
    fn get_objc_class_t(&self) -> &'ll Type {
        if let Some(class_t) = self.objc_class_t.get() {
            return class_t;
        }

        assert_eq!(self.objc_abi_version(), 2);

        // struct _class_t {
        //     struct _class_t* isa;
        //     struct _class_t* const superclass;
        //     void* cache;
        //     IMP* vtable;
        //     struct class_ro_t* ro;
        // }

        let class_t = self.type_named_struct("struct._class_t");
        let els = [self.type_ptr(); 5];
        let packed = false;
        self.set_struct_body(class_t, &els, packed);

        self.objc_class_t.set(Some(class_t));
        class_t
    }

    // We do our best here to match what Clang does when compiling Objective-C natively. We
    // deduplicate references within a CGU, but we need a reference definition in each referencing
    // CGU. All attempts at using external references to a single reference definition result in
    // linker errors.
    fn get_objc_classref(&self, classname: Symbol) -> &'ll Value {
        let mut classrefs = self.objc_classrefs.borrow_mut();
        if let Some(classref) = classrefs.get(&classname).copied() {
            return classref;
        }

        let g = match self.objc_abi_version() {
            1 => {
                // See Clang's `CGObjCMac::EmitClassRefFromId`:
                // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5205
                let llval = self.define_objc_classname(classname.as_str());
                let llty = self.type_ptr();
                let sym = self.generate_local_symbol_name("OBJC_CLASS_REFERENCES_");
                let g = self.define_global(&sym, llty).unwrap_or_else(|| {
                    bug!("symbol `{}` is already defined", sym);
                });
                set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
                llvm::set_initializer(g, llval);
                llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
                llvm::set_section(g, c"__OBJC,__cls_refs,literal_pointers,no_dead_strip");
                self.add_compiler_used_global(g);
                g
            }
            2 => {
                // See Clang's `CGObjCNonFragileABIMac::EmitClassRefFromId`:
                // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7423
                let llval = {
                    let extern_sym = format!("OBJC_CLASS_$_{}", classname.as_str());
                    let extern_llty = self.get_objc_class_t();
                    self.declare_global(&extern_sym, extern_llty)
                };
                let llty = self.type_ptr();
                let sym = self.generate_local_symbol_name("OBJC_CLASSLIST_REFERENCES_$_");
                let g = self.define_global(&sym, llty).unwrap_or_else(|| {
                    bug!("symbol `{}` is already defined", sym);
                });
                set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
                llvm::set_initializer(g, llval);
                llvm::set_linkage(g, llvm::Linkage::InternalLinkage);
                llvm::set_section(g, c"__DATA,__objc_classrefs,regular,no_dead_strip");
                self.add_compiler_used_global(g);
                g
            }
            _ => unreachable!(),
        };

        classrefs.insert(classname, g);
        g
    }

    // We do our best here to match what Clang does when compiling Objective-C natively. We
    // deduplicate references within a CGU, but we need a reference definition in each referencing
    // CGU. All attempts at using external references to a single reference definition result in
    // linker errors.
    //
    // Newer versions of Apple Clang generate calls to `@"objc_msgSend$methname"` selector stub
    // functions. We don't currently do that. The code we generate is closer to what Apple Clang
    // generates with the `-fno-objc-msgsend-selector-stubs` option.
    fn get_objc_selref(&self, methname: Symbol) -> &'ll Value {
        let mut selrefs = self.objc_selrefs.borrow_mut();
        if let Some(selref) = selrefs.get(&methname).copied() {
            return selref;
        }

        let abi_version = self.objc_abi_version();

        // See Clang's `CGObjCCommonMac::CreateCStringLiteral`:
        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L4134
        let methname_llval = self.null_terminate_const_bytes(methname.as_str().as_bytes());
        let methname_llty = self.val_ty(methname_llval);
        let methname_sym = self.generate_local_symbol_name("OBJC_METH_VAR_NAME_");
        let methname_g = self.define_global(&methname_sym, methname_llty).unwrap_or_else(|| {
            bug!("symbol `{}` is already defined", methname_sym);
        });
        set_global_alignment(self, methname_g, self.tcx.data_layout.i8_align);
        llvm::set_initializer(methname_g, methname_llval);
        llvm::set_linkage(methname_g, llvm::Linkage::PrivateLinkage);
        llvm::set_section(
            methname_g,
            match abi_version {
                1 => c"__TEXT,__cstring,cstring_literals",
                2 => c"__TEXT,__objc_methname,cstring_literals",
                _ => unreachable!(),
            },
        );
        llvm::LLVMSetGlobalConstant(methname_g, llvm::TRUE);
        llvm::LLVMSetUnnamedAddress(methname_g, llvm::UnnamedAddr::Global);
        self.add_compiler_used_global(methname_g);

        // See Clang's `CGObjCMac::EmitSelectorAddr`:
        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5243
        // And Clang's `CGObjCNonFragileABIMac::EmitSelectorAddr`:
        // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L7586
        let selref_llval = methname_g;
        let selref_llty = self.type_ptr();
        let selref_sym = self.generate_local_symbol_name("OBJC_SELECTOR_REFERENCES_");
        let selref_g = self.define_global(&selref_sym, selref_llty).unwrap_or_else(|| {
            bug!("symbol `{}` is already defined", selref_sym);
        });
        set_global_alignment(self, selref_g, self.tcx.data_layout.pointer_align().abi);
        llvm::set_initializer(selref_g, selref_llval);
        llvm::set_externally_initialized(selref_g, true);
        llvm::set_linkage(
            selref_g,
            match abi_version {
                1 => llvm::Linkage::PrivateLinkage,
                2 => llvm::Linkage::InternalLinkage,
                _ => unreachable!(),
            },
        );
        llvm::set_section(
            selref_g,
            match abi_version {
                1 => c"__OBJC,__message_refs,literal_pointers,no_dead_strip",
                2 => c"__DATA,__objc_selrefs,literal_pointers,no_dead_strip",
                _ => unreachable!(),
            },
        );
        self.add_compiler_used_global(selref_g);

        selrefs.insert(methname, selref_g);
        selref_g
    }

    // We do our best here to match what Clang does when compiling Objective-C natively.
    // See Clang's `ObjCTypesHelper`:
    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5936
    // And Clang's `CGObjCMac::EmitModuleInfo`:
    // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.8/clang/lib/CodeGen/CGObjCMac.cpp#L5151
    pub(crate) fn define_objc_module_info(&mut self) {
        assert_eq!(self.objc_abi_version(), 1);

        // struct _objc_module {
        //     long version;                // Hardcoded to 7 in Clang.
        //     long size;                   // sizeof(struct _objc_module)
        //     char* name;                  // Hardcoded to classname "" in Clang.
        //     struct _objc_symtab* symtab; // Null without class or category definitions.
        //  }

        let llty = self.type_named_struct("struct._objc_module");
        let i32_llty = self.type_i32();
        let ptr_llty = self.type_ptr();
        let packed = false;
        self.set_struct_body(llty, &[i32_llty, i32_llty, ptr_llty, ptr_llty], packed);

        let version = self.const_uint(i32_llty, 7);
        let size = self.const_uint(i32_llty, 16);
        let name = self.define_objc_classname("");
        let symtab = self.const_null(ptr_llty);
        let llval = crate::common::named_struct(llty, &[version, size, name, symtab]);

        let sym = "OBJC_MODULES";
        let g = self.define_global(&sym, llty).unwrap_or_else(|| {
            bug!("symbol `{}` is already defined", sym);
        });
        set_global_alignment(self, g, self.tcx.data_layout.pointer_align().abi);
        llvm::set_initializer(g, llval);
        llvm::set_linkage(g, llvm::Linkage::PrivateLinkage);
        llvm::set_section(g, c"__OBJC,__module_info,regular,no_dead_strip");

        self.add_compiler_used_global(g);
    }
}

impl<'ll> StaticCodegenMethods for CodegenCx<'ll, '_> {
    /// Get a pointer to a global variable.
    ///
    /// The pointer will always be in the default address space. If global variables default to a
    /// different address space, an addrspacecast is inserted.
    fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value {
        let gv = self.static_addr_of_impl(cv, align, kind);
        // static_addr_of_impl returns the bare global variable, which might not be in the default
        // address space. Cast to the default address space if necessary.
        self.const_pointercast(gv, self.type_ptr())
    }

    fn codegen_static(&mut self, def_id: DefId) {
        self.codegen_static_item(def_id)
    }
}
