//! Set and unset common attributes on LLVM values.
use rustc_attr_data_structures::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
use smallvec::SmallVec;

use crate::context::CodegenCx;
use crate::errors::SanitizerMemtagRequiresMte;
use crate::llvm::AttributePlace::Function;
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
use crate::value::Value;
use crate::{attributes, llvm_util};

pub(crate) fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) {
    if !attrs.is_empty() {
        llvm::AddFunctionAttributes(llfn, idx, attrs);
    }
}

pub(crate) fn apply_to_callsite(callsite: &Value, idx: AttributePlace, attrs: &[&Attribute]) {
    if !attrs.is_empty() {
        llvm::AddCallSiteAttributes(callsite, idx, attrs);
    }
}

pub(crate) fn has_attr(llfn: &Value, idx: AttributePlace, attr: AttributeKind) -> bool {
    llvm::HasAttributeAtIndex(llfn, idx, attr)
}

pub(crate) fn has_string_attr(llfn: &Value, name: &str) -> bool {
    llvm::HasStringAttribute(llfn, name)
}

pub(crate) fn remove_from_llfn(llfn: &Value, place: AttributePlace, kind: AttributeKind) {
    llvm::RemoveRustEnumAttributeAtIndex(llfn, place, kind);
}

pub(crate) fn remove_string_attr_from_llfn(llfn: &Value, name: &str) {
    llvm::RemoveStringAttrFromFn(llfn, name);
}

/// Get LLVM attribute for the provided inline heuristic.
#[inline]
fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll Attribute> {
    if !cx.tcx.sess.opts.unstable_opts.inline_llvm {
        // disable LLVM inlining
        return Some(AttributeKind::NoInline.create_attr(cx.llcx));
    }
    match inline {
        InlineAttr::Hint => Some(AttributeKind::InlineHint.create_attr(cx.llcx)),
        InlineAttr::Always | InlineAttr::Force { .. } => {
            Some(AttributeKind::AlwaysInline.create_attr(cx.llcx))
        }
        InlineAttr::Never => {
            if cx.sess().target.arch != "amdgpu" {
                Some(AttributeKind::NoInline.create_attr(cx.llcx))
            } else {
                None
            }
        }
        InlineAttr::None => None,
    }
}

#[inline]
fn patchable_function_entry_attrs<'ll>(
    cx: &CodegenCx<'ll, '_>,
    attr: Option<PatchableFunctionEntry>,
) -> SmallVec<[&'ll Attribute; 2]> {
    let mut attrs = SmallVec::new();
    let patchable_spec = attr.unwrap_or_else(|| {
        PatchableFunctionEntry::from_config(cx.tcx.sess.opts.unstable_opts.patchable_function_entry)
    });
    let entry = patchable_spec.entry();
    let prefix = patchable_spec.prefix();
    if entry > 0 {
        attrs.push(llvm::CreateAttrStringValue(
            cx.llcx,
            "patchable-function-entry",
            &format!("{}", entry),
        ));
    }
    if prefix > 0 {
        attrs.push(llvm::CreateAttrStringValue(
            cx.llcx,
            "patchable-function-prefix",
            &format!("{}", prefix),
        ));
    }
    attrs
}

/// Get LLVM sanitize attributes.
#[inline]
pub(crate) fn sanitize_attrs<'ll>(
    cx: &CodegenCx<'ll, '_>,
    no_sanitize: SanitizerSet,
) -> SmallVec<[&'ll Attribute; 4]> {
    let mut attrs = SmallVec::new();
    let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
    if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
        attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::MEMORY) {
        attrs.push(llvm::AttributeKind::SanitizeMemory.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::THREAD) {
        attrs.push(llvm::AttributeKind::SanitizeThread.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::HWADDRESS) {
        attrs.push(llvm::AttributeKind::SanitizeHWAddress.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::SHADOWCALLSTACK) {
        attrs.push(llvm::AttributeKind::ShadowCallStack.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::MEMTAG) {
        // Check to make sure the mte target feature is actually enabled.
        let features = cx.tcx.global_backend_features(());
        let mte_feature =
            features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
        if let None | Some("-mte") = mte_feature {
            cx.tcx.dcx().emit_err(SanitizerMemtagRequiresMte);
        }

        attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
    }
    if enabled.contains(SanitizerSet::SAFESTACK) {
        attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx));
    }
    attrs
}

/// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
#[inline]
pub(crate) fn uwtable_attr(llcx: &llvm::Context, use_sync_unwind: Option<bool>) -> &Attribute {
    // NOTE: We should determine if we even need async unwind tables, as they
    // take have more overhead and if we can use sync unwind tables we
    // probably should.
    let async_unwind = !use_sync_unwind.unwrap_or(false);
    llvm::CreateUWTableAttr(llcx, async_unwind)
}

pub(crate) fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    let mut fp = cx.sess().target.frame_pointer;
    let opts = &cx.sess().opts;
    // "mcount" function relies on stack pointer.
    // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
    if opts.unstable_opts.instrument_mcount {
        fp.ratchet(FramePointer::Always);
    }
    fp.ratchet(opts.cg.force_frame_pointers);
    let attr_value = match fp {
        FramePointer::Always => "all",
        FramePointer::NonLeaf => "non-leaf",
        FramePointer::MayOmit => return None,
    };
    Some(llvm::CreateAttrStringValue(cx.llcx, "frame-pointer", attr_value))
}

fn function_return_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    let function_return_attr = match cx.sess().opts.unstable_opts.function_return {
        FunctionReturn::Keep => return None,
        FunctionReturn::ThunkExtern => AttributeKind::FnRetThunkExtern,
    };

    Some(function_return_attr.create_attr(cx.llcx))
}

/// Tell LLVM what instrument function to insert.
#[inline]
fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attribute; 4]> {
    let mut attrs = SmallVec::new();
    if cx.sess().opts.unstable_opts.instrument_mcount {
        // Similar to `clang -pg` behavior. Handled by the
        // `post-inline-ee-instrument` LLVM pass.

        // The function name varies on platforms.
        // See test/CodeGen/mcount.c in clang.
        let mcount_name = match &cx.sess().target.llvm_mcount_intrinsic {
            Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
            None => cx.sess().target.mcount.as_ref(),
        };

        attrs.push(llvm::CreateAttrStringValue(
            cx.llcx,
            "instrument-function-entry-inlined",
            mcount_name,
        ));
    }
    if let Some(options) = &cx.sess().opts.unstable_opts.instrument_xray {
        // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
        // Function prologue and epilogue are instrumented with NOP sleds,
        // a runtime library later replaces them with detours into tracing code.
        if options.always {
            attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
        }
        if options.never {
            attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-never"));
        }
        if options.ignore_loops {
            attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
        }
        // LLVM will not choose the default for us, but rather requires specific
        // threshold in absence of "xray-always". Use the same default as Clang.
        let threshold = options.instruction_threshold.unwrap_or(200);
        attrs.push(llvm::CreateAttrStringValue(
            cx.llcx,
            "xray-instruction-threshold",
            &threshold.to_string(),
        ));
        if options.skip_entry {
            attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-entry"));
        }
        if options.skip_exit {
            attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-exit"));
        }
    }
    attrs
}

fn nojumptables_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    if !cx.sess().opts.unstable_opts.no_jump_tables {
        return None;
    }

    Some(llvm::CreateAttrStringValue(cx.llcx, "no-jump-tables", "true"))
}

fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    // Currently stack probes seem somewhat incompatible with the address
    // sanitizer and thread sanitizer. With asan we're already protected from
    // stack overflow anyway so we don't really need stack probes regardless.
    if cx
        .sess()
        .opts
        .unstable_opts
        .sanitizer
        .intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD)
    {
        return None;
    }

    // probestack doesn't play nice either with `-C profile-generate`.
    if cx.sess().opts.cg.profile_generate.enabled() {
        return None;
    }

    let attr_value = match cx.sess().target.stack_probes {
        StackProbeType::None => return None,
        // Request LLVM to generate the probes inline. If the given LLVM version does not support
        // this, no probe is generated at all (even if the attribute is specified).
        StackProbeType::Inline => "inline-asm",
        // Flag our internal `__rust_probestack` function as the stack probe symbol.
        // This is defined in the `compiler-builtins` crate for each architecture.
        StackProbeType::Call => &mangle_internal_symbol(cx.tcx, "__rust_probestack"),
        // Pick from the two above based on the LLVM version.
        StackProbeType::InlineOrCall { min_llvm_version_for_inline } => {
            if llvm_util::get_version() < min_llvm_version_for_inline {
                &mangle_internal_symbol(cx.tcx, "__rust_probestack")
            } else {
                "inline-asm"
            }
        }
    };
    Some(llvm::CreateAttrStringValue(cx.llcx, "probe-stack", attr_value))
}

fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    let sspattr = match cx.sess().stack_protector() {
        StackProtector::None => return None,
        StackProtector::All => AttributeKind::StackProtectReq,
        StackProtector::Strong => AttributeKind::StackProtectStrong,
        StackProtector::Basic => AttributeKind::StackProtect,
    };

    Some(sspattr.create_attr(cx.llcx))
}

fn backchain_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    if cx.sess().target.arch != "s390x" {
        return None;
    }

    let requested_features = cx.sess().opts.cg.target_feature.split(',');
    let found_positive = requested_features.clone().any(|r| r == "+backchain");

    if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None }
}

pub(crate) fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute {
    let target_cpu = llvm_util::target_cpu(cx.tcx.sess);
    llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu)
}

pub(crate) fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    llvm_util::tune_cpu(cx.tcx.sess)
        .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu))
}

/// Get the `NonLazyBind` LLVM attribute,
/// if the codegen options allow skipping the PLT.
pub(crate) fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
    // Don't generate calls through PLT if it's not necessary
    if !cx.sess().needs_plt() {
        Some(AttributeKind::NonLazyBind.create_attr(cx.llcx))
    } else {
        None
    }
}

/// Get the default optimizations attrs for a function.
#[inline]
pub(crate) fn default_optimisation_attrs<'ll>(
    cx: &CodegenCx<'ll, '_>,
) -> SmallVec<[&'ll Attribute; 2]> {
    let mut attrs = SmallVec::new();
    match cx.sess().opts.optimize {
        OptLevel::Size => {
            attrs.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx));
        }
        OptLevel::SizeMin => {
            attrs.push(llvm::AttributeKind::MinSize.create_attr(cx.llcx));
            attrs.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx));
        }
        _ => {}
    }
    attrs
}

fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute {
    llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc")
}

/// Helper for `FnAbi::apply_attrs_llfn`:
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
/// attributes.
pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    llfn: &'ll Value,
    instance: ty::Instance<'tcx>,
) {
    let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());

    let mut to_add = SmallVec::<[_; 16]>::new();

    match codegen_fn_attrs.optimize {
        OptimizeAttr::Default => {
            to_add.extend(default_optimisation_attrs(cx));
        }
        OptimizeAttr::DoNotOptimize => {
            to_add.push(llvm::AttributeKind::OptimizeNone.create_attr(cx.llcx));
        }
        OptimizeAttr::Size => {
            to_add.push(llvm::AttributeKind::MinSize.create_attr(cx.llcx));
            to_add.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx));
        }
        OptimizeAttr::Speed => {}
    }

    // `optnone` requires `noinline`
    let inline = match (codegen_fn_attrs.inline, &codegen_fn_attrs.optimize) {
        (_, OptimizeAttr::DoNotOptimize) => InlineAttr::Never,
        (InlineAttr::None, _) if instance.def.requires_inline(cx.tcx) => InlineAttr::Hint,
        (inline, _) => inline,
    };
    to_add.extend(inline_attr(cx, inline));

    // The `uwtable` attribute according to LLVM is:
    //
    //     This attribute indicates that the ABI being targeted requires that an
    //     unwind table entry be produced for this function even if we can show
    //     that no exceptions passes by it. This is normally the case for the
    //     ELF x86-64 abi, but it can be disabled for some compilation units.
    //
    // Typically when we're compiling with `-C panic=abort` (which implies this
    // `no_landing_pads` check) we don't need `uwtable` because we can't
    // generate any exceptions! On Windows, however, exceptions include other
    // events such as illegal instructions, segfaults, etc. This means that on
    // Windows we end up still needing the `uwtable` attribute even if the `-C
    // panic=abort` flag is passed.
    //
    // You can also find more info on why Windows always requires uwtables here:
    //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
    if cx.sess().must_emit_unwind_tables() {
        to_add.push(uwtable_attr(cx.llcx, cx.sess().opts.unstable_opts.use_sync_unwind));
    }

    if cx.sess().opts.unstable_opts.profile_sample_use.is_some() {
        to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile"));
    }

    // FIXME: none of these functions interact with source level attributes.
    to_add.extend(frame_pointer_type_attr(cx));
    to_add.extend(function_return_attr(cx));
    to_add.extend(instrument_function_attr(cx));
    to_add.extend(nojumptables_attr(cx));
    to_add.extend(probestack_attr(cx));
    to_add.extend(stackprotector_attr(cx));

    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_BUILTINS) {
        to_add.push(llvm::CreateAttrString(cx.llcx, "no-builtins"));
    }

    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
        to_add.push(AttributeKind::Cold.create_attr(cx.llcx));
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) {
        to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx));
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_CONST) {
        to_add.push(MemoryEffects::None.create_attr(cx.llcx));
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
        // do nothing; a naked function is converted into an extern function
        // and a global assembly block. LLVM's support for naked functions is
        // not used.
    } else {
        // Do not set sanitizer attributes for naked functions.
        to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));

        // For non-naked functions, set branch protection attributes on aarch64.
        if let Some(BranchProtection { bti, pac_ret }) =
            cx.sess().opts.unstable_opts.branch_protection
        {
            assert!(cx.sess().target.arch == "aarch64");
            if bti {
                to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
            }
            if let Some(PacRet { leaf, pc, key }) = pac_ret {
                if pc {
                    to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
                }
                to_add.push(llvm::CreateAttrStringValue(
                    cx.llcx,
                    "sign-return-address",
                    if leaf { "all" } else { "non-leaf" },
                ));
                to_add.push(llvm::CreateAttrStringValue(
                    cx.llcx,
                    "sign-return-address-key",
                    if key == PAuthKey::A { "a_key" } else { "b_key" },
                ));
            }
        }
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR)
        || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED)
    {
        to_add.push(create_alloc_family_attr(cx.llcx));
        // apply to argument place instead of function
        let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]);
        to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0));
        let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned;
        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
            flags |= AllocKindFlags::Uninitialized;
        } else {
            flags |= AllocKindFlags::Zeroed;
        }
        to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
        // apply to return place instead of function (unlike all other attributes applied in this
        // function)
        let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::REALLOCATOR) {
        to_add.push(create_alloc_family_attr(cx.llcx));
        to_add.push(llvm::CreateAllocKindAttr(
            cx.llcx,
            AllocKindFlags::Realloc | AllocKindFlags::Aligned,
        ));
        // applies to argument place instead of function place
        let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
        // apply to argument place instead of function
        let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]);
        to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3));
        let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
    }
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::DEALLOCATOR) {
        to_add.push(create_alloc_family_attr(cx.llcx));
        to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
        // applies to argument place instead of function place
        let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
        attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
    }
    if let Some(align) = codegen_fn_attrs.alignment {
        llvm::set_alignment(llfn, align);
    }
    if let Some(backchain) = backchain_attr(cx) {
        to_add.push(backchain);
    }
    to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));

    // Always annotate functions with the target-cpu they are compiled for.
    // Without this, ThinLTO won't inline Rust functions into Clang generated
    // functions (because Clang annotates functions this way too).
    to_add.push(target_cpu_attr(cx));
    // tune-cpu is only conveyed through the attribute for our purpose.
    // The target doesn't care; the subtarget reads our attribute.
    to_add.extend(tune_cpu_attr(cx));

    let function_features =
        codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::<Vec<&str>>();

    let function_features = function_features
        .iter()
        // Convert to LLVMFeatures and filter out unavailable ones
        .flat_map(|feat| llvm_util::to_llvm_features(cx.tcx.sess, feat))
        // Convert LLVMFeatures & dependencies to +<feats>s
        .flat_map(|feat| feat.into_iter().map(|f| format!("+{f}")))
        .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
            InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
            InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(),
        }))
        .collect::<Vec<String>>();

    if cx.tcx.sess.target.is_like_wasm {
        // If this function is an import from the environment but the wasm
        // import has a specific module/name, apply them here.
        if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) {
            to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", module));

            let name =
                codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id()));
            let name = name.as_str();
            to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-name", name));
        }
    }

    let global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
    let function_features = function_features.iter().map(|s| s.as_str());
    let target_features: String =
        global_features.chain(function_features).intersperse(",").collect();
    if !target_features.is_empty() {
        to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features));
    }

    attributes::apply_to_llfn(llfn, Function, &to_add);
}

fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<&String> {
    tcx.wasm_import_module_map(id.krate).get(&id)
}
