Skip to content

Commit e76eec9

Browse files
committed
cg_llvm/debuginfo: scalable vectors
Generate debuginfo for scalable vectors, following the structure that Clang generates for scalable vectors.
1 parent 0b1e337 commit e76eec9

12 files changed

Lines changed: 759 additions & 6 deletions

File tree

compiler/rustc_abi/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,16 @@ impl NumScalableVectors {
17631763
_ => None,
17641764
}
17651765
}
1766+
1767+
/// Returns number of scalable vectors as a `u64`.
1768+
pub fn as_u64(self) -> u64 {
1769+
match self {
1770+
NumScalableVectors::One => 1,
1771+
NumScalableVectors::Two => 2,
1772+
NumScalableVectors::Three => 3,
1773+
NumScalableVectors::Four => 4,
1774+
}
1775+
}
17661776
}
17671777

17681778
/// The way we represent values to the backend

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
144144
self.const_int(self.type_i32(), i as i64)
145145
}
146146

147+
fn const_i64(&self, i: i64) -> RValue<'gcc> {
148+
self.const_int(self.type_i64(), i)
149+
}
150+
147151
fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
148152
self.gcc_int(typ, int)
149153
}

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
159159
self.const_int(self.type_i32(), i as i64)
160160
}
161161

162+
fn const_i64(&self, i: i64) -> &'ll Value {
163+
self.const_int(self.type_i64(), i as i64)
164+
}
165+
162166
fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
163167
debug_assert!(
164168
self.type_kind(t) == TypeKind::Integer,

compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ declare_constant!(DW_OP_plus_uconst: u64);
3535
/// Double-checked by a static assertion in `RustWrapper.cpp`.
3636
#[allow(non_upper_case_globals)]
3737
pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
38+
#[allow(non_upper_case_globals)]
39+
pub(crate) const DW_OP_constu: u64 = 0x10;
40+
#[allow(non_upper_case_globals)]
41+
pub(crate) const DW_OP_minus: u64 = 0x1c;
42+
#[allow(non_upper_case_globals)]
43+
pub(crate) const DW_OP_mul: u64 = 0x1e;
44+
#[allow(non_upper_case_globals)]
45+
pub(crate) const DW_OP_bregx: u64 = 0x92;
3846
// It describes the actual value of a source variable which might not exist in registers or in memory.
3947
#[allow(non_upper_case_globals)]
4048
pub(crate) const DW_OP_stack_value: u64 = 0x9f;

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

Lines changed: 116 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::assert_matches::assert_matches;
12
use std::borrow::Cow;
23
use std::fmt::{self, Write};
34
use std::hash::{Hash, Hasher};
@@ -6,7 +7,7 @@ use std::sync::Arc;
67
use std::{iter, ptr};
78

89
use libc::{c_longlong, c_uint};
9-
use rustc_abi::{Align, Size};
10+
use rustc_abi::{Align, Layout, NumScalableVectors, Size};
1011
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
1112
use rustc_codegen_ssa::traits::*;
1213
use rustc_hir::def::{CtorKind, DefKind};
@@ -16,12 +17,12 @@ use rustc_middle::ty::layout::{
1617
HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
1718
};
1819
use rustc_middle::ty::{
19-
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
20+
self, AdtDef, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
2021
};
2122
use rustc_session::config::{self, DebugInfo, Lto};
2223
use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
2324
use rustc_symbol_mangling::typeid_for_trait_ref;
24-
use rustc_target::spec::DebuginfoKind;
25+
use rustc_target::spec::{Arch, DebuginfoKind};
2526
use smallvec::smallvec;
2627
use tracing::{debug, instrument};
2728

@@ -33,7 +34,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
3334
use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
3435
use crate::common::{AsCCharPtr, CodegenCx};
3536
use crate::debuginfo::metadata::type_map::build_type_with_children;
36-
use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
37+
use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind};
3738
use crate::debuginfo::{DIBuilderExt, dwarf_const};
3839
use crate::llvm::debuginfo::{
3940
DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,
@@ -1039,6 +1040,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10391040
span: Span,
10401041
) -> DINodeCreationResult<'ll> {
10411042
let struct_type = unique_type_id.expect_ty();
1043+
10421044
let ty::Adt(adt_def, _) = struct_type.kind() else {
10431045
bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
10441046
};
@@ -1051,14 +1053,29 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10511053
} else {
10521054
None
10531055
};
1056+
let name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
1057+
1058+
if struct_type.is_scalable_vector() {
1059+
let parts = struct_type.scalable_vector_parts(cx.tcx).unwrap();
1060+
return build_scalable_vector_di_node(
1061+
cx,
1062+
unique_type_id,
1063+
name,
1064+
*adt_def,
1065+
parts,
1066+
struct_type_and_layout.layout,
1067+
def_location,
1068+
containing_scope,
1069+
);
1070+
}
10541071

10551072
type_map::build_type_with_children(
10561073
cx,
10571074
type_map::stub(
10581075
cx,
10591076
Stub::Struct,
10601077
unique_type_id,
1061-
&compute_debuginfo_type_name(cx.tcx, struct_type, false),
1078+
&name,
10621079
def_location,
10631080
size_and_align_of(struct_type_and_layout),
10641081
Some(containing_scope),
@@ -1101,6 +1118,100 @@ fn build_struct_type_di_node<'ll, 'tcx>(
11011118
)
11021119
}
11031120

1121+
/// Generate debuginfo for a `#[rustc_scalable_vector]` type.
1122+
///
1123+
/// Debuginfo for a scalable vector takes the form of a derived type with a composite base type
1124+
/// with `DIFlagVector` that itself has a base type of whatever the element of the scalable vector
1125+
/// is. The composite type has a subrange from 0 to an expression that calculates the number of
1126+
/// elements in the vector.
1127+
///
1128+
/// ```text, ignore
1129+
/// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...)
1130+
/// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4)
1131+
/// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
1132+
/// !4 = !{!5}
1133+
/// !5 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
1134+
/// ```
1135+
///
1136+
/// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this
1137+
/// is generated for C and C++.
1138+
fn build_scalable_vector_di_node<'ll, 'tcx>(
1139+
cx: &CodegenCx<'ll, 'tcx>,
1140+
unique_type_id: UniqueTypeId<'tcx>,
1141+
name: String,
1142+
adt_def: AdtDef<'tcx>,
1143+
(element_count, element_ty, number_of_vectors): (u16, Ty<'tcx>, NumScalableVectors),
1144+
layout: Layout<'tcx>,
1145+
def_location: Option<DefinitionLocation<'ll>>,
1146+
containing_scope: &'ll DIScope,
1147+
) -> DINodeCreationResult<'ll> {
1148+
use dwarf_const::{DW_OP_bregx, DW_OP_constu, DW_OP_minus, DW_OP_mul};
1149+
assert!(adt_def.repr().scalable());
1150+
// This logic is specific to AArch64 for the moment, but can be extended for other architectures
1151+
// later.
1152+
assert_matches!(cx.tcx.sess.target.arch, Arch::AArch64);
1153+
1154+
let (file_metadata, line_number) = if let Some(def_location) = def_location {
1155+
(def_location.0, def_location.1)
1156+
} else {
1157+
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
1158+
};
1159+
1160+
let (bitstride, element_di_node) = if element_ty.is_bool() {
1161+
(Some(llvm::LLVMValueAsMetadata(cx.const_i64(1))), type_di_node(cx, cx.tcx.types.u8))
1162+
} else {
1163+
(None, type_di_node(cx, element_ty))
1164+
};
1165+
1166+
let number_of_elements: u64 = (element_count as u64) * number_of_vectors.as_u64();
1167+
let number_of_elements_per_vg = number_of_elements / 2;
1168+
let mut expr = smallvec::SmallVec::<[u64; 9]>::new();
1169+
// `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
1170+
expr.push(DW_OP_constu); // Push a constant onto the stack
1171+
expr.push(number_of_elements_per_vg);
1172+
expr.push(DW_OP_bregx); // Push the value of a register + offset on to the stack
1173+
expr.push(/* AArch64::VG */ 46u64);
1174+
expr.push(0u64);
1175+
expr.push(DW_OP_mul); // Multiply top two values on stack
1176+
expr.push(DW_OP_constu); // Push a constant onto the stack
1177+
expr.push(1u64);
1178+
expr.push(DW_OP_minus); // Subtract top two values on stack
1179+
1180+
let di_builder = DIB(cx);
1181+
let metadata = unsafe {
1182+
let upper = llvm::LLVMDIBuilderCreateExpression(di_builder, expr.as_ptr(), expr.len());
1183+
let subrange = llvm::LLVMRustDIGetOrCreateSubrange(
1184+
di_builder,
1185+
/* CountNode */ None,
1186+
llvm::LLVMValueAsMetadata(cx.const_i64(0)),
1187+
upper,
1188+
/* Stride */ None,
1189+
);
1190+
let subscripts = create_DIArray(di_builder, &[Some(subrange)]);
1191+
let vector_ty = llvm::LLVMRustDICreateVectorType(
1192+
di_builder,
1193+
/* Size */ 0,
1194+
layout.align.bits() as u32,
1195+
element_di_node,
1196+
subscripts,
1197+
bitstride,
1198+
);
1199+
llvm::LLVMDIBuilderCreateTypedef(
1200+
di_builder,
1201+
vector_ty,
1202+
name.as_ptr(),
1203+
name.len(),
1204+
file_metadata,
1205+
line_number,
1206+
Some(containing_scope),
1207+
layout.align.bits() as u32,
1208+
)
1209+
};
1210+
1211+
debug_context(cx).type_map.insert(unique_type_id, metadata);
1212+
DINodeCreationResult { di_node: metadata, already_stored_in_typemap: true }
1213+
}
1214+
11041215
//=-----------------------------------------------------------------------------
11051216
// Tuples
11061217
//=-----------------------------------------------------------------------------

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,23 @@ unsafe extern "C" {
22992299
Params: Option<&'a DIArray>,
23002300
);
23012301

2302+
pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>(
2303+
Builder: &DIBuilder<'a>,
2304+
CountNode: Option<&'a Metadata>,
2305+
LB: &'a Metadata,
2306+
UB: &'a Metadata,
2307+
Stride: Option<&'a Metadata>,
2308+
) -> &'a Metadata;
2309+
2310+
pub(crate) fn LLVMRustDICreateVectorType<'a>(
2311+
Builder: &DIBuilder<'a>,
2312+
Size: u64,
2313+
AlignInBits: u32,
2314+
Type: &'a DIType,
2315+
Subscripts: &'a DIArray,
2316+
BitStride: Option<&'a Metadata>,
2317+
) -> &'a Metadata;
2318+
23022319
pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>(
23032320
Location: &'a DILocation,
23042321
BD: c_uint,

compiler/rustc_codegen_ssa/src/traits/consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub trait ConstCodegenMethods: BackendTypes {
2020
fn const_i8(&self, i: i8) -> Self::Value;
2121
fn const_i16(&self, i: i16) -> Self::Value;
2222
fn const_i32(&self, i: i32) -> Self::Value;
23+
fn const_i64(&self, i: i64) -> Self::Value;
2324
fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
2425
fn const_u8(&self, i: u8) -> Self::Value;
2526
fn const_u32(&self, i: u32) -> Self::Value;

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ using namespace llvm::object;
7070
// This opcode is an LLVM detail that could hypothetically change (?), so
7171
// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.
7272
static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000);
73+
static_assert(dwarf::DW_OP_constu == 0x10);
74+
static_assert(dwarf::DW_OP_minus == 0x1c);
75+
static_assert(dwarf::DW_OP_mul == 0x1e);
76+
static_assert(dwarf::DW_OP_bregx == 0x92);
7377
static_assert(dwarf::DW_OP_stack_value == 0x9f);
7478

7579
static LLVM_THREAD_LOCAL char *LastError;
@@ -734,7 +738,7 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
734738
}
735739

736740
template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
737-
return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
741+
return (DIT *)(Ref ? unwrap<Metadata>(Ref) : nullptr);
738742
}
739743

740744
#define DIDescriptor DIScope
@@ -1210,6 +1214,36 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays(
12101214
DINodeArray(unwrap<MDTuple>(Params)));
12111215
}
12121216

1217+
// LLVM's C FFI bindings don't expose the overload of `GetOrCreateSubrange`
1218+
// which takes a metadata node as the upper bound.
1219+
extern "C" LLVMMetadataRef
1220+
LLVMRustDIGetOrCreateSubrange(LLVMDIBuilderRef Builder,
1221+
LLVMMetadataRef CountNode, LLVMMetadataRef LB,
1222+
LLVMMetadataRef UB, LLVMMetadataRef Stride) {
1223+
return wrap(unwrap(Builder)->getOrCreateSubrange(
1224+
unwrapDI<Metadata>(CountNode), unwrapDI<Metadata>(LB),
1225+
unwrapDI<Metadata>(UB), unwrapDI<Metadata>(Stride)));
1226+
}
1227+
1228+
// LLVM's CI FFI bindings don't expose the `BitStride` parameter of
1229+
// `createVectorType`.
1230+
extern "C" LLVMMetadataRef
1231+
LLVMRustDICreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size,
1232+
uint32_t AlignInBits, LLVMMetadataRef Type,
1233+
LLVMMetadataRef Subscripts,
1234+
LLVMMetadataRef BitStride) {
1235+
#if LLVM_VERSION_GE(22, 0)
1236+
return wrap(unwrap(Builder)->createVectorType(
1237+
Size, AlignInBits, unwrapDI<DIType>(Type),
1238+
DINodeArray(unwrapDI<MDTuple>(Subscripts)),
1239+
unwrapDI<Metadata>(BitStride)));
1240+
#else
1241+
return wrap(unwrap(Builder)->createVectorType(
1242+
Size, AlignInBits, unwrapDI<DIType>(Type),
1243+
DINodeArray(unwrapDI<MDTuple>(Subscripts))));
1244+
#endif
1245+
}
1246+
12131247
extern "C" LLVMMetadataRef
12141248
LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
12151249
unsigned BD) {

0 commit comments

Comments
 (0)