@@ -6,7 +6,7 @@ use std::sync::Arc;
66use std:: { 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,7 +16,7 @@ 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} ;
@@ -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 ,
@@ -1040,6 +1040,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10401040 span : Span ,
10411041) -> DINodeCreationResult < ' ll > {
10421042 let struct_type = unique_type_id. expect_ty ( ) ;
1043+
10431044 let ty:: Adt ( adt_def, _) = struct_type. kind ( ) else {
10441045 bug ! ( "build_struct_type_di_node() called with non-struct-type: {:?}" , struct_type) ;
10451046 } ;
@@ -1052,14 +1053,29 @@ fn build_struct_type_di_node<'ll, 'tcx>(
10521053 } else {
10531054 None
10541055 } ;
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+ }
10551071
10561072 type_map:: build_type_with_children (
10571073 cx,
10581074 type_map:: stub (
10591075 cx,
10601076 Stub :: Struct ,
10611077 unique_type_id,
1062- & compute_debuginfo_type_name ( cx . tcx , struct_type , false ) ,
1078+ & name ,
10631079 def_location,
10641080 size_and_align_of ( struct_type_and_layout) ,
10651081 Some ( containing_scope) ,
@@ -1102,6 +1118,97 @@ fn build_struct_type_di_node<'ll, 'tcx>(
11021118 )
11031119}
11041120
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+
1151+ let ( file_metadata, line_number) = if let Some ( def_location) = def_location {
1152+ ( def_location. 0 , def_location. 1 )
1153+ } else {
1154+ ( unknown_file_metadata ( cx) , UNKNOWN_LINE_NUMBER )
1155+ } ;
1156+
1157+ let ( bitstride, element_di_node) = if element_ty. is_bool ( ) {
1158+ ( Some ( llvm:: LLVMValueAsMetadata ( cx. const_i64 ( 1 ) ) ) , type_di_node ( cx, cx. tcx . types . u8 ) )
1159+ } else {
1160+ ( None , type_di_node ( cx, element_ty) )
1161+ } ;
1162+
1163+ let number_of_elements: u64 = ( element_count as u64 ) * number_of_vectors. as_u64 ( ) ;
1164+ let number_of_elements_per_vg = number_of_elements / 2 ;
1165+ let mut expr = smallvec:: SmallVec :: < [ u64 ; 9 ] > :: new ( ) ;
1166+ // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
1167+ expr. push ( DW_OP_constu ) ; // Push a constant onto the stack
1168+ expr. push ( number_of_elements_per_vg) ;
1169+ expr. push ( DW_OP_bregx ) ; // Push the value of a register + offset on to the stack
1170+ expr. push ( /* AArch64::VG */ 46u64 ) ;
1171+ expr. push ( 0u64 ) ;
1172+ expr. push ( DW_OP_mul ) ; // Multiply top two values on stack
1173+ expr. push ( DW_OP_constu ) ; // Push a constant onto the stack
1174+ expr. push ( 1u64 ) ;
1175+ expr. push ( DW_OP_minus ) ; // Subtract top two values on stack
1176+
1177+ let di_builder = DIB ( cx) ;
1178+ let metadata = unsafe {
1179+ let upper = llvm:: LLVMDIBuilderCreateExpression ( di_builder, expr. as_ptr ( ) , expr. len ( ) ) ;
1180+ let subrange = llvm:: LLVMRustDIGetOrCreateSubrange (
1181+ di_builder,
1182+ /* CountNode */ None ,
1183+ llvm:: LLVMValueAsMetadata ( cx. const_i64 ( 0 ) ) ,
1184+ upper,
1185+ /* Stride */ None ,
1186+ ) ;
1187+ let subscripts = create_DIArray ( di_builder, & [ Some ( subrange) ] ) ;
1188+ let vector_ty = llvm:: LLVMRustDICreateVectorType (
1189+ di_builder,
1190+ /* Size */ 0 ,
1191+ layout. align . bits ( ) as u32 ,
1192+ element_di_node,
1193+ subscripts,
1194+ bitstride,
1195+ ) ;
1196+ llvm:: LLVMDIBuilderCreateTypedef (
1197+ di_builder,
1198+ vector_ty,
1199+ name. as_ptr ( ) ,
1200+ name. len ( ) ,
1201+ file_metadata,
1202+ line_number,
1203+ Some ( containing_scope) ,
1204+ layout. align . bits ( ) as u32 ,
1205+ )
1206+ } ;
1207+
1208+ debug_context ( cx) . type_map . insert ( unique_type_id, metadata) ;
1209+ DINodeCreationResult { di_node : metadata, already_stored_in_typemap : true }
1210+ }
1211+
11051212//=-----------------------------------------------------------------------------
11061213// Tuples
11071214//=-----------------------------------------------------------------------------
0 commit comments