1+ use std:: assert_matches:: assert_matches;
12use std:: borrow:: Cow ;
23use std:: fmt:: { self , Write } ;
34use std:: hash:: { Hash , Hasher } ;
@@ -6,7 +7,7 @@ use std::sync::Arc;
67use std:: { iter, ptr} ;
78
89use libc:: { c_longlong, c_uint} ;
9- use rustc_abi:: { Align , Size } ;
10+ use rustc_abi:: { Align , Layout , NumScalableVectors , Size } ;
1011use rustc_codegen_ssa:: debuginfo:: type_names:: { VTableNameKind , cpp_like_debuginfo} ;
1112use rustc_codegen_ssa:: traits:: * ;
1213use 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} ;
1819use rustc_middle:: ty:: {
19- self , AdtKind , CoroutineArgsExt , ExistentialTraitRef , Instance , Ty , TyCtxt , Visibility ,
20+ self , AdtDef , AdtKind , CoroutineArgsExt , ExistentialTraitRef , Instance , Ty , TyCtxt , Visibility ,
2021} ;
2122use rustc_session:: config:: { self , DebugInfo , Lto } ;
2223use rustc_span:: { DUMMY_SP , FileName , RemapPathScopeComponents , SourceFile , Span , Symbol , hygiene} ;
2324use rustc_symbol_mangling:: typeid_for_trait_ref;
24- use rustc_target:: spec:: DebuginfoKind ;
25+ use rustc_target:: spec:: { Arch , DebuginfoKind } ;
2526use smallvec:: smallvec;
2627use tracing:: { debug, instrument} ;
2728
@@ -33,7 +34,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
3334use super :: utils:: { DIB , debug_context, get_namespace_for_item, is_node_local_to_unit} ;
3435use crate :: common:: { AsCCharPtr , CodegenCx } ;
3536use 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} ;
3738use crate :: debuginfo:: { DIBuilderExt , dwarf_const} ;
3839use 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//=-----------------------------------------------------------------------------
0 commit comments