about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs79
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs29
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs30
3 files changed, 104 insertions, 34 deletions
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index f683832e3df..845b5791161 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -7,10 +7,10 @@
 ///
 /// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
 /// see design document in the tracking issue #89653.
-use core::fmt::Display;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
+use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{
     self, Const, ExistentialPredicate, FloatTy, FnSig, Instance, IntTy, List, Region, RegionKind,
     TermKind, Ty, TyCtxt, UintTy,
@@ -19,6 +19,7 @@ use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
 use rustc_span::def_id::DefId;
 use rustc_span::sym;
 use rustc_target::abi::call::{Conv, FnAbi};
+use rustc_target::abi::Integer;
 use rustc_target::spec::abi::Abi;
 use std::fmt::Write as _;
 
@@ -93,44 +94,54 @@ fn encode_const<'tcx>(
     dict: &mut FxHashMap<DictKey<'tcx>, usize>,
     options: EncodeTyOptions,
 ) -> String {
-    // L<element-type>[n]<element-value>E as literal argument
+    // L<element-type>[n][<element-value>]E as literal argument
     let mut s = String::from('L');
 
-    // Element type
-    s.push_str(&encode_ty(tcx, c.ty(), dict, options));
+    match c.kind() {
+        // Const parameters
+        ty::ConstKind::Param(..) => {
+            // L<element-type>E as literal argument
 
-    // The only allowed types of const parameters are bool, u8, u16, u32, u64, u128, usize i8, i16,
-    // i32, i64, i128, isize, and char. The bool value false is encoded as 0 and true as 1.
-    fn push_signed_value<T: Display + PartialOrd>(s: &mut String, value: T, zero: T) {
-        if value < zero {
-            s.push('n')
-        };
-        let _ = write!(s, "{value}");
-    }
-
-    fn push_unsigned_value<T: Display>(s: &mut String, value: T) {
-        let _ = write!(s, "{value}");
-    }
+            // Element type
+            s.push_str(&encode_ty(tcx, c.ty(), dict, options));
+        }
 
-    if let Some(scalar_int) = c.try_to_scalar_int() {
-        let signed = c.ty().is_signed();
-        match scalar_int.size().bits() {
-            8 if signed => push_signed_value(&mut s, scalar_int.try_to_i8().unwrap(), 0),
-            16 if signed => push_signed_value(&mut s, scalar_int.try_to_i16().unwrap(), 0),
-            32 if signed => push_signed_value(&mut s, scalar_int.try_to_i32().unwrap(), 0),
-            64 if signed => push_signed_value(&mut s, scalar_int.try_to_i64().unwrap(), 0),
-            128 if signed => push_signed_value(&mut s, scalar_int.try_to_i128().unwrap(), 0),
-            8 => push_unsigned_value(&mut s, scalar_int.try_to_u8().unwrap()),
-            16 => push_unsigned_value(&mut s, scalar_int.try_to_u16().unwrap()),
-            32 => push_unsigned_value(&mut s, scalar_int.try_to_u32().unwrap()),
-            64 => push_unsigned_value(&mut s, scalar_int.try_to_u64().unwrap()),
-            128 => push_unsigned_value(&mut s, scalar_int.try_to_u128().unwrap()),
-            _ => {
-                bug!("encode_const: unexpected size `{:?}`", scalar_int.size().bits());
+        // Literal arguments
+        ty::ConstKind::Value(..) => {
+            // L<element-type>[n]<element-value>E as literal argument
+
+            // Element type
+            s.push_str(&encode_ty(tcx, c.ty(), dict, options));
+
+            // The only allowed types of const values are bool, u8, u16, u32,
+            // u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The
+            // bool value false is encoded as 0 and true as 1.
+            match c.ty().kind() {
+                ty::Int(ity) => {
+                    let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty());
+                    let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
+                    if val < 0 {
+                        s.push('n');
+                    }
+                    let _ = write!(s, "{val}");
+                }
+                ty::Uint(_) => {
+                    let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty());
+                    let _ = write!(s, "{val}");
+                }
+                ty::Bool => {
+                    let val = c.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
+                    let _ = write!(s, "{val}");
+                }
+                _ => {
+                    bug!("encode_const: unexpected type `{:?}`", c.ty());
+                }
             }
-        };
-    } else {
-        bug!("encode_const: unexpected type `{:?}`", c.ty());
+        }
+
+        _ => {
+            bug!("encode_const: unexpected kind `{:?}`", c.kind());
+        }
     }
 
     // Close the "L..E" pair
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
index 0f79adab7bd..d24e416b67e 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -53,6 +53,18 @@ impl<'a, T, U> Trait4<'a, U> for T {
     }
 }
 
+pub trait Trait5<T, const N: usize> {
+    fn quux(&self, _: &[T; N]);
+}
+
+#[derive(Copy, Clone)]
+pub struct Type5;
+
+impl<T, U, const N: usize> Trait5<U, N> for T {
+    fn quux(&self, _: &[U; N]) {
+    }
+}
+
 pub fn foo1(a: &dyn Trait1) {
     a.foo();
     // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
@@ -114,7 +126,24 @@ pub fn bar4<'a>() {
     // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
 }
 
+pub fn foo5(a: &dyn Trait5<Type5, 32>) {
+    let b = &[Type5; 32];
+    a.quux(&b);
+    // CHECK-LABEL: define{{.*}}4foo5{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
+}
+
+pub fn bar5() {
+    let a = &[Type5; 32];
+    foo5(&a);
+    let b = &a as &dyn Trait5<Type5, 32>;
+    b.quux(&a);
+    // CHECK-LABEL: define{{.*}}4bar5{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]")
+}
+
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE5]]"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
index 004a67e7df2..78ecc187b8e 100644
--- a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -77,6 +77,19 @@ impl<'a, T, U> Trait4<'a, U> for T {
     }
 }
 
+pub trait Trait5<T, const N: usize> {
+    fn quux(&self, _: &[T; N]);
+}
+
+pub struct Type5;
+
+impl Copy for Type5 {}
+
+impl<T, U, const N: usize> Trait5<U, N> for T {
+    fn quux(&self, _: &[U; N]) {
+    }
+}
+
 pub fn foo1(a: &dyn Trait1) {
     a.foo();
     // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
@@ -138,7 +151,24 @@ pub fn bar4<'a>() {
     // CHECK:       call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
 }
 
+pub fn foo5(a: &dyn Trait5<Type5, 32>) {
+    let b = &[Type5; 32];
+    a.quux(&b);
+    // CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, {{\{\}\*|ptr|\[32 x %Type5\]\*}} align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
+}
+
+pub fn bar5() {
+    let a = &[Type5; 32];
+    foo5(&a);
+    let b = &a as &dyn Trait5<Type5, 32>;
+    b.quux(&a);
+    // CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, {{\{\}\*|ptr|\[32 x %Type5\]\*}} align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
+}
+
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE5]]}