@@ -3,10 +3,10 @@ use std::fmt::{self, Write};
33use std:: hash:: { Hash , Hasher } ;
44use std:: path:: PathBuf ;
55use std:: sync:: Arc ;
6- use std:: { iter, ptr} ;
6+ use std:: { assert_matches , iter, ptr} ;
77
88use libc:: { c_longlong, c_uint} ;
9- use rustc_abi:: { Align , Size } ;
9+ use rustc_abi:: { Align , Layout , NumScalableVectors , Size } ;
1010use rustc_codegen_ssa:: debuginfo:: type_names:: { VTableNameKind , cpp_like_debuginfo} ;
1111use rustc_codegen_ssa:: traits:: * ;
1212use rustc_hir:: def:: { CtorKind , DefKind } ;
@@ -16,12 +16,12 @@ use rustc_middle::ty::layout::{
1616 HasTypingEnv , LayoutOf , TyAndLayout , WIDE_PTR_ADDR , WIDE_PTR_EXTRA ,
1717} ;
1818use rustc_middle:: ty:: {
19- self , AdtKind , CoroutineArgsExt , ExistentialTraitRef , Instance , Ty , TyCtxt , Visibility ,
19+ self , AdtDef , AdtKind , CoroutineArgsExt , ExistentialTraitRef , Instance , Ty , TyCtxt , Visibility ,
2020} ;
2121use rustc_session:: config:: { self , DebugInfo , Lto } ;
2222use rustc_span:: { DUMMY_SP , FileName , RemapPathScopeComponents , SourceFile , Span , Symbol , hygiene} ;
2323use rustc_symbol_mangling:: typeid_for_trait_ref;
24- use rustc_target:: spec:: DebuginfoKind ;
24+ use rustc_target:: spec:: { Arch , DebuginfoKind } ;
2525use smallvec:: smallvec;
2626use tracing:: { debug, instrument} ;
2727
@@ -33,7 +33,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na
3333use super :: utils:: { DIB , debug_context, get_namespace_for_item, is_node_local_to_unit} ;
3434use crate :: common:: { AsCCharPtr , CodegenCx } ;
3535use crate :: debuginfo:: metadata:: type_map:: build_type_with_children;
36- use crate :: debuginfo:: utils:: { WidePtrKind , wide_pointer_kind} ;
36+ use crate :: debuginfo:: utils:: { WidePtrKind , create_DIArray , wide_pointer_kind} ;
3737use crate :: debuginfo:: { DIBuilderExt , dwarf_const} ;
3838use crate :: llvm:: debuginfo:: {
3939 DIBasicType , DIBuilder , DICompositeType , DIDescriptor , DIFile , DIFlags , DILexicalBlock ,
@@ -1039,6 +1039,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10391039 span : Span ,
10401040) -> DINodeCreationResult < ' ll > {
10411041 let struct_type = unique_type_id. expect_ty ( ) ;
1042+
10421043 let ty:: Adt ( adt_def, _) = struct_type. kind ( ) else {
10431044 bug ! ( "build_struct_type_di_node() called with non-struct-type: {:?}" , struct_type) ;
10441045 } ;
@@ -1051,14 +1052,29 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10511052 } else {
10521053 None
10531054 } ;
1055+ let name = compute_debuginfo_type_name ( cx. tcx , struct_type, false ) ;
1056+
1057+ if struct_type. is_scalable_vector ( ) {
1058+ let parts = struct_type. scalable_vector_parts ( cx. tcx ) . unwrap ( ) ;
1059+ return build_scalable_vector_di_node (
1060+ cx,
1061+ unique_type_id,
1062+ name,
1063+ * adt_def,
1064+ parts,
1065+ struct_type_and_layout. layout ,
1066+ def_location,
1067+ containing_scope,
1068+ ) ;
1069+ }
10541070
10551071 type_map:: build_type_with_children (
10561072 cx,
10571073 type_map:: stub (
10581074 cx,
10591075 Stub :: Struct ,
10601076 unique_type_id,
1061- & compute_debuginfo_type_name ( cx . tcx , struct_type , false ) ,
1077+ & name ,
10621078 def_location,
10631079 size_and_align_of ( struct_type_and_layout) ,
10641080 Some ( containing_scope) ,
@@ -1101,6 +1117,100 @@ fn build_struct_type_di_node<'ll, 'tcx>(
11011117 )
11021118}
11031119
1120+ /// Generate debuginfo for a `#[rustc_scalable_vector]` type.
1121+ ///
1122+ /// Debuginfo for a scalable vector uses a derived type based on a composite type. The composite
1123+ /// type has the `DIFlagVector` flag set and is based on the element type of the scalable vector.
1124+ /// The composite type has a subrange from 0 to an expression that calculates the number of
1125+ /// elements in the vector.
1126+ ///
1127+ /// ```text,ignore
1128+ /// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...)
1129+ /// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4)
1130+ /// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
1131+ /// !4 = !{!5}
1132+ /// !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))
1133+ /// ```
1134+ ///
1135+ /// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this
1136+ /// is generated for C and C++.
1137+ fn build_scalable_vector_di_node < ' ll , ' tcx > (
1138+ cx : & CodegenCx < ' ll , ' tcx > ,
1139+ unique_type_id : UniqueTypeId < ' tcx > ,
1140+ name : String ,
1141+ adt_def : AdtDef < ' tcx > ,
1142+ ( element_count, element_ty, number_of_vectors) : ( u16 , Ty < ' tcx > , NumScalableVectors ) ,
1143+ layout : Layout < ' tcx > ,
1144+ def_location : Option < DefinitionLocation < ' ll > > ,
1145+ containing_scope : & ' ll DIScope ,
1146+ ) -> DINodeCreationResult < ' ll > {
1147+ use dwarf_const:: { DW_OP_bregx , DW_OP_constu , DW_OP_minus , DW_OP_mul } ;
1148+ assert ! ( adt_def. repr( ) . scalable( ) ) ;
1149+ // This logic is specific to AArch64 for the moment, but can be extended for other architectures
1150+ // later.
1151+ assert_matches ! ( cx. tcx. sess. target. arch, Arch :: AArch64 ) ;
1152+
1153+ let ( file_metadata, line_number) = if let Some ( def_location) = def_location {
1154+ ( def_location. 0 , def_location. 1 )
1155+ } else {
1156+ ( unknown_file_metadata ( cx) , UNKNOWN_LINE_NUMBER )
1157+ } ;
1158+
1159+ let ( bitstride, element_di_node) = if element_ty. is_bool ( ) {
1160+ ( Some ( llvm:: LLVMValueAsMetadata ( cx. const_i64 ( 1 ) ) ) , type_di_node ( cx, cx. tcx . types . u8 ) )
1161+ } else {
1162+ ( None , type_di_node ( cx, element_ty) )
1163+ } ;
1164+
1165+ let number_of_elements: u64 = ( element_count as u64 ) * ( number_of_vectors. 0 as u64 ) ;
1166+ let number_of_elements_per_vg = number_of_elements / 2 ;
1167+ let mut expr = smallvec:: SmallVec :: < [ u64 ; 9 ] > :: new ( ) ;
1168+ // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
1169+ expr. push ( DW_OP_constu ) ; // Push a constant onto the stack
1170+ expr. push ( number_of_elements_per_vg) ;
1171+ expr. push ( DW_OP_bregx ) ; // Push the value of a register + offset on to the stack
1172+ expr. push ( /* AArch64::VG */ 46u64 ) ;
1173+ expr. push ( 0u64 ) ;
1174+ expr. push ( DW_OP_mul ) ; // Multiply top two values on stack
1175+ expr. push ( DW_OP_constu ) ; // Push a constant onto the stack
1176+ expr. push ( 1u64 ) ;
1177+ expr. push ( DW_OP_minus ) ; // Subtract top two values on stack
1178+
1179+ let di_builder = DIB ( cx) ;
1180+ let metadata = unsafe {
1181+ let upper = llvm:: LLVMDIBuilderCreateExpression ( di_builder, expr. as_ptr ( ) , expr. len ( ) ) ;
1182+ let subrange = llvm:: LLVMRustDIGetOrCreateSubrange (
1183+ di_builder,
1184+ /* CountNode */ None ,
1185+ llvm:: LLVMValueAsMetadata ( cx. const_i64 ( 0 ) ) ,
1186+ upper,
1187+ /* Stride */ None ,
1188+ ) ;
1189+ let subscripts = create_DIArray ( di_builder, & [ Some ( subrange) ] ) ;
1190+ let vector_ty = llvm:: LLVMRustDICreateVectorType (
1191+ di_builder,
1192+ /* Size */ 0 ,
1193+ layout. align . bits ( ) as u32 ,
1194+ element_di_node,
1195+ subscripts,
1196+ bitstride,
1197+ ) ;
1198+ llvm:: LLVMDIBuilderCreateTypedef (
1199+ di_builder,
1200+ vector_ty,
1201+ name. as_ptr ( ) ,
1202+ name. len ( ) ,
1203+ file_metadata,
1204+ line_number,
1205+ Some ( containing_scope) ,
1206+ layout. align . bits ( ) as u32 ,
1207+ )
1208+ } ;
1209+
1210+ debug_context ( cx) . type_map . insert ( unique_type_id, metadata) ;
1211+ DINodeCreationResult { di_node : metadata, already_stored_in_typemap : true }
1212+ }
1213+
11041214//=-----------------------------------------------------------------------------
11051215// Tuples
11061216//=-----------------------------------------------------------------------------
0 commit comments