about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_llvm/src')
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs22
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs38
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs38
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/utils.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs12
16 files changed, 134 insertions, 97 deletions
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index e9b66b54c58..c3994cef14f 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -37,7 +37,7 @@ impl ArgAttributeExt for ArgAttribute {
     where
         F: FnMut(llvm::Attribute),
     {
-        for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg)
+        for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg, NoUndef)
     }
 }
 
@@ -599,13 +599,11 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         if self.conv == Conv::CCmseNonSecureCall {
             // This will probably get ignored on all targets but those supporting the TrustZone-M
             // extension (thumbv8m targets).
-            unsafe {
-                llvm::AddCallSiteAttrString(
-                    callsite,
-                    llvm::AttributePlace::Function,
-                    cstr::cstr!("cmse_nonsecure_call"),
-                );
-            }
+            llvm::AddCallSiteAttrString(
+                callsite,
+                llvm::AttributePlace::Function,
+                cstr::cstr!("cmse_nonsecure_call"),
+            );
         }
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 30d91b41a8e..7680d4fd233 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -64,7 +64,7 @@ pub(crate) unsafe fn codegen(
             llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
         }
         if tcx.sess.must_emit_unwind_tables() {
-            attributes::emit_uwtable(llfn, true);
+            attributes::emit_uwtable(llfn);
         }
 
         let callee = kind.fn_name(method.name);
@@ -111,7 +111,7 @@ pub(crate) unsafe fn codegen(
         llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
     }
     if tcx.sess.must_emit_unwind_tables() {
-        attributes::emit_uwtable(llfn, true);
+        attributes::emit_uwtable(llfn);
     }
 
     let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default };
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 2472789601e..f6d7221d4e9 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -55,12 +55,28 @@ pub fn sanitize<'ll>(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &
     if enabled.contains(SanitizerSet::HWADDRESS) {
         llvm::Attribute::SanitizeHWAddress.apply_llfn(Function, llfn);
     }
+    if enabled.contains(SanitizerSet::MEMTAG) {
+        // Check to make sure the mte target feature is actually enabled.
+        let sess = cx.tcx.sess;
+        let features = llvm_util::llvm_global_features(sess).join(",");
+        let mte_feature_enabled = features.rfind("+mte");
+        let mte_feature_disabled = features.rfind("-mte");
+
+        if mte_feature_enabled.is_none() || (mte_feature_disabled > mte_feature_enabled) {
+            sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
+        }
+
+        llvm::Attribute::SanitizeMemTag.apply_llfn(Function, llfn);
+    }
 }
 
 /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function.
 #[inline]
-pub fn emit_uwtable(val: &Value, emit: bool) {
-    Attribute::UWTable.toggle_llfn(Function, val, emit);
+pub fn emit_uwtable(val: &Value) {
+    // 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.
+    llvm::EmitUWTableAttr(val, true);
 }
 
 /// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue.
@@ -275,7 +291,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
     // 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() {
-        attributes::emit_uwtable(llfn, true);
+        attributes::emit_uwtable(llfn);
     }
 
     if cx.sess().opts.debugging_opts.profile_sample_use.is_some() {
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 21bd1dae7ac..1a2cec2a0d9 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -310,10 +310,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
             if let Some(archive) = self.src_archive() {
                 for child in archive.iter() {
                     let child = child.map_err(string_to_io_error)?;
-                    let child_name = match child.name() {
-                        Some(s) => s,
-                        None => continue,
-                    };
+                    let Some(child_name) = child.name() else { continue };
                     if removals.iter().any(|r| r == child_name) {
                         continue;
                     }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 384596dfff5..e60ad170434 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -826,20 +826,14 @@ pub(crate) unsafe fn codegen(
                 let input =
                     unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) };
 
-                let input = match str::from_utf8(input) {
-                    Ok(s) => s,
-                    Err(_) => return 0,
-                };
+                let Ok(input) = str::from_utf8(input) else { return 0 };
 
                 let output = unsafe {
                     slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
                 };
                 let mut cursor = io::Cursor::new(output);
 
-                let demangled = match rustc_demangle::try_demangle(input) {
-                    Ok(d) => d,
-                    Err(_) => return 0,
-                };
+                let Ok(demangled) = rustc_demangle::try_demangle(input) else { return 0 };
 
                 if write!(cursor, "{:#}", demangled).is_err() {
                     // Possible only if provided buffer is not big enough
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 7b6ce5ea89b..e15b86aa84f 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -138,10 +138,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
 }
 
 pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) {
-    let sect = match attrs.link_section {
-        Some(name) => name,
-        None => return,
-    };
+    let Some(sect) = attrs.link_section else { return };
     unsafe {
         let buf = SmallCStr::new(sect.as_str());
         llvm::LLVMSetSection(llval, buf.as_ptr());
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 6707de93352..51223697dbd 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -369,10 +369,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
         unsafe {
             let attrs = self.tcx.codegen_fn_attrs(def_id);
 
-            let (v, alloc) = match codegen_static_initializer(self, def_id) {
-                Ok(v) => v,
+            let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else {
                 // Error has already been reported
-                Err(_) => return,
+                return;
             };
 
             let g = self.get_static(def_id);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 8672459b5da..90ddf791450 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -21,7 +21,8 @@ use rustc_middle::ty::layout::{
 };
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
-use rustc_session::config::{BranchProtection, CFGuard, CrateType, DebugInfo, PAuthKey, PacRet};
+use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
+use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
 use rustc_session::Session;
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
@@ -134,7 +135,8 @@ pub unsafe fn create_module<'ll>(
     let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
 
     let mut target_data_layout = sess.target.data_layout.clone();
-    if llvm_util::get_version() < (13, 0, 0) {
+    let llvm_version = llvm_util::get_version();
+    if llvm_version < (13, 0, 0) {
         if sess.target.arch == "powerpc64" {
             target_data_layout = target_data_layout.replace("-S128", "");
         }
@@ -145,6 +147,18 @@ pub unsafe fn create_module<'ll>(
             target_data_layout = "e-m:e-p:64:64-i64:64-n32:64-S128".to_string();
         }
     }
+    if llvm_version < (14, 0, 0) {
+        if sess.target.llvm_target == "i686-pc-windows-msvc"
+            || sess.target.llvm_target == "i586-pc-windows-msvc"
+        {
+            target_data_layout =
+                "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
+                    .to_string();
+        }
+        if sess.target.arch == "wasm32" {
+            target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
+        }
+    }
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.is_builtin {
@@ -278,7 +292,7 @@ pub unsafe fn create_module<'ll>(
             "sign-return-address-all\0".as_ptr().cast(),
             pac_opts.leaf.into(),
         );
-        let is_bkey = if pac_opts.key == PAuthKey::A { false } else { true };
+        let is_bkey: bool = pac_opts.key != PAuthKey::A;
         llvm::LLVMRustAddModuleFlag(
             llmod,
             llvm::LLVMModFlagBehavior::Error,
@@ -287,6 +301,24 @@ pub unsafe fn create_module<'ll>(
         );
     }
 
+    // Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
+    if let CFProtection::Branch | CFProtection::Full = sess.opts.debugging_opts.cf_protection {
+        llvm::LLVMRustAddModuleFlag(
+            llmod,
+            llvm::LLVMModFlagBehavior::Override,
+            "cf-protection-branch\0".as_ptr().cast(),
+            1,
+        )
+    }
+    if let CFProtection::Return | CFProtection::Full = sess.opts.debugging_opts.cf_protection {
+        llvm::LLVMRustAddModuleFlag(
+            llmod,
+            llvm::LLVMModFlagBehavior::Override,
+            "cf-protection-return\0".as_ptr().cast(),
+            1,
+        )
+    }
+
     llmod
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index da997dd9879..ef87b7b1a7e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -185,9 +185,9 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
     ///
     /// This function is used to remove the temporary metadata
     /// mapping after we've computed the actual metadata.
-    fn remove_type(&mut self, type_: Ty<'tcx>) {
-        if self.type_to_metadata.remove(type_).is_none() {
-            bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_);
+    fn remove_type(&mut self, ty: Ty<'tcx>) {
+        if self.type_to_metadata.remove(&ty).is_none() {
+            bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", ty);
         }
     }
 
@@ -397,7 +397,7 @@ fn fixed_size_array_metadata<'ll, 'tcx>(
         bug!("fixed_size_array_metadata() called with non-ty::Array type `{:?}`", array_type)
     };
 
-    let element_type_metadata = type_metadata(cx, element_type);
+    let element_type_metadata = type_metadata(cx, *element_type);
 
     return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
@@ -546,7 +546,7 @@ fn subroutine_type_metadata<'ll, 'tcx>(
     )
     .chain(
         // regular arguments
-        signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type))),
+        signature.inputs().iter().map(|&argument_type| Some(type_metadata(cx, argument_type))),
     )
     .collect();
 
@@ -601,7 +601,7 @@ fn slice_type_metadata<'ll, 'tcx>(
     unique_type_id: UniqueTypeId,
 ) -> MetadataCreationResult<'ll> {
     let element_type = match slice_type.kind() {
-        ty::Slice(element_type) => element_type,
+        ty::Slice(element_type) => *element_type,
         ty::Str => cx.tcx.types.u8,
         _ => {
             bug!(
@@ -752,9 +752,8 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
                 prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx)
             }
         },
-        ty::Tuple(elements) => {
-            let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect();
-            prepare_tuple_metadata(cx, t, &tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx)
+        ty::Tuple(tys) => {
+            prepare_tuple_metadata(cx, t, tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx)
         }
         // Type parameters from polymorphized functions.
         ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false),
@@ -766,18 +765,15 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll
 
         if already_stored_in_typemap {
             // Also make sure that we already have a `TypeMap` entry for the unique type ID.
-            let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
-                Some(metadata) => metadata,
-                None => {
-                    bug!(
-                        "expected type metadata for unique \
-                               type ID '{}' to already be in \
-                               the `debuginfo::TypeMap` but it \
-                               was not. (Ty = {})",
-                        type_map.get_unique_type_id_as_string(unique_type_id),
-                        t
-                    );
-                }
+            let Some(metadata_for_uid) = type_map.find_metadata_for_unique_id(unique_type_id) else {
+                bug!(
+                    "expected type metadata for unique \
+                            type ID '{}' to already be in \
+                            the `debuginfo::TypeMap` but it \
+                            was not. (Ty = {})",
+                    type_map.get_unique_type_id_as_string(unique_type_id),
+                    t
+                );
             };
 
             match type_map.find_metadata_for_type(t) {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 6bc7d8518dc..247cb9ee6e8 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -430,9 +430,9 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     let t = arg.layout.ty;
                     let t = match t.kind() {
                         ty::Array(ct, _)
-                            if (*ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() =>
+                            if (*ct == cx.tcx.types.u8) || cx.layout_of(*ct).is_zst() =>
                         {
-                            cx.tcx.mk_imm_ptr(ct)
+                            cx.tcx.mk_imm_ptr(*ct)
                         }
                         _ => t,
                     };
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 6dd0d58efe3..acd032a7dc6 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -6,7 +6,7 @@ use super::CrateDebugContext;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, DefIdTree, Ty};
-use rustc_target::abi::VariantIdx;
+use rustc_target::abi::Variants;
 
 use crate::common::CodegenCx;
 use crate::llvm;
@@ -72,20 +72,15 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
     match *pointee_ty.kind() {
         ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
         ty::Dynamic(..) => Some(FatPtrKind::Dyn),
-        ty::Adt(adt_def, _) => {
-            assert!(adt_def.is_struct());
-            assert!(adt_def.variants.len() == 1);
-            let variant = &adt_def.variants[VariantIdx::from_usize(0)];
-            assert!(!variant.fields.is_empty());
-            let last_field_index = variant.fields.len() - 1;
-
+        ty::Adt(..) | ty::Tuple(..) if matches!(layout.variants, Variants::Single { .. }) => {
+            let last_field_index = layout.fields.count() - 1;
             debug_assert!(
                 (0..last_field_index)
                     .all(|field_index| { !layout.field(cx, field_index).is_unsized() })
             );
 
             let unsized_field = layout.field(cx, last_field_index);
-            assert!(unsized_field.is_unsized());
+            debug_assert!(unsized_field.is_unsized());
             fat_pointer_kind(cx, unsized_field.ty)
         }
         ty::Foreign(_) => {
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index f51d014bfb3..f471f461e86 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -88,9 +88,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         let tcx = self.tcx;
         let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
 
-        let (def_id, substs) = match *callee_ty.kind() {
-            ty::FnDef(def_id, substs) => (def_id, substs),
-            _ => bug!("expected fn item type, found {}", callee_ty),
+        let ty::FnDef(def_id, substs) = *callee_ty.kind() else {
+            bug!("expected fn item type, found {}", callee_ty);
         };
 
         let sig = callee_ty.fn_sig(tcx);
@@ -1000,9 +999,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 }
             })
             .collect();
-        let indices = match indices {
-            Some(i) => i,
-            None => return Ok(bx.const_null(llret_ty)),
+        let Some(indices) = indices else {
+            return Ok(bx.const_null(llret_ty));
         };
 
         return Ok(bx.shuffle_vector(
@@ -1132,8 +1130,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
 
     fn simd_simple_float_intrinsic<'ll, 'tcx>(
         name: Symbol,
-        in_elem: &::rustc_middle::ty::TyS<'_>,
-        in_ty: &::rustc_middle::ty::TyS<'_>,
+        in_elem: Ty<'_>,
+        in_ty: Ty<'_>,
         in_len: u64,
         bx: &mut Builder<'_, 'll, 'tcx>,
         span: Span,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 367c86a1dc9..657f1fcf31e 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -189,6 +189,8 @@ pub enum Attribute {
     StackProtectReq = 30,
     StackProtectStrong = 31,
     StackProtect = 32,
+    NoUndef = 33,
+    SanitizeMemTag = 34,
 }
 
 /// LLVMIntPredicate
@@ -1181,6 +1183,7 @@ extern "C" {
     pub fn LLVMRustAddByValAttr(Fn: &Value, index: c_uint, ty: &Type);
     pub fn LLVMRustAddStructRetAttr(Fn: &Value, index: c_uint, ty: &Type);
     pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustEmitUWTableAttr(Fn: &Value, async_: bool);
     pub fn LLVMRustAddFunctionAttrStringValue(
         Fn: &Value,
         index: c_uint,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index a1117a11fc7..8586b0466c8 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -31,6 +31,10 @@ impl LLVMRustResult {
     }
 }
 
+pub fn EmitUWTableAttr(llfn: &Value, async_: bool) {
+    unsafe { LLVMRustEmitUWTableAttr(llfn, async_) }
+}
+
 pub fn AddFunctionAttrStringValue(llfn: &Value, idx: AttributePlace, attr: &CStr, value: &CStr) {
     unsafe {
         LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), value.as_ptr())
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 727d079d83d..b1c14c7e44b 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -217,24 +217,32 @@ pub fn check_tied_features(
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
     let target_machine = create_informational_target_machine(sess);
-    supported_target_features(sess)
-        .iter()
-        .filter_map(
-            |&(feature, gate)| {
+    let mut features: Vec<Symbol> =
+        supported_target_features(sess)
+            .iter()
+            .filter_map(|&(feature, gate)| {
                 if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None }
-            },
-        )
-        .filter(|feature| {
-            for llvm_feature in to_llvm_feature(sess, feature) {
-                let cstr = CString::new(llvm_feature).unwrap();
-                if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
-                    return true;
+            })
+            .filter(|feature| {
+                for llvm_feature in to_llvm_feature(sess, feature) {
+                    let cstr = CString::new(llvm_feature).unwrap();
+                    if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
+                        return true;
+                    }
                 }
-            }
-            false
-        })
-        .map(|feature| Symbol::intern(feature))
-        .collect()
+                false
+            })
+            .map(|feature| Symbol::intern(feature))
+            .collect();
+
+    // LLVM 14 changed the ABI for i128 arguments to __float/__fix builtins on Win64
+    // (see https://reviews.llvm.org/D110413). This unstable target feature is intended for use
+    // by compiler-builtins, to export the builtins with the expected, LLVM-version-dependent ABI.
+    // The target feature can be dropped once we no longer support older LLVM versions.
+    if sess.is_nightly_build() && get_version() >= (14, 0, 0) {
+        features.push(Symbol::intern("llvm14-builtins-abi"));
+    }
+    features
 }
 
 pub fn print_version() {
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 81d0603bc52..02a263637a6 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -43,8 +43,7 @@ fn uncached_llvm_type<'a, 'tcx>(
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
         ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => {
-            let mut name =
-                with_no_visible_paths(|| with_no_trimmed_paths(|| layout.ty.to_string()));
+            let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string()));
             if let (&ty::Adt(def, _), &Variants::Single { index }) =
                 (layout.ty.kind(), &layout.variants)
             {
@@ -330,16 +329,17 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
             ty::Ref(..) | ty::RawPtr(_) => {
                 return self.field(cx, index).llvm_type(cx);
             }
-            ty::Adt(def, _) if def.is_box() => {
+            // only wide pointer boxes are handled as pointers
+            // thin pointer boxes with scalar allocators are handled by the general logic below
+            ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => {
                 let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
                 return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
             }
             _ => {}
         }
 
-        let (a, b) = match self.abi {
-            Abi::ScalarPair(a, b) => (a, b),
-            _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
+        let Abi::ScalarPair(a, b) = self.abi else {
+            bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self);
         };
         let scalar = [a, b][index];