@@ -2501,8 +2501,163 @@ struct PropertyAttributes {
2501
2501
// / \see clang::ObjCPropertyAttribute
2502
2502
uint32_t prop_attributes = 0 ;
2503
2503
};
2504
+
2505
+ struct DiscriminantValue {
2506
+ explicit DiscriminantValue (const DWARFDIE &die, ModuleSP module_sp);
2507
+
2508
+ uint32_t byte_offset;
2509
+ uint32_t byte_size;
2510
+ DWARFFormValue type_ref;
2511
+ };
2512
+
2513
+ struct VariantMember {
2514
+ explicit VariantMember (DWARFDIE &die, ModuleSP module_sp);
2515
+ bool IsDefault () const ;
2516
+
2517
+ std::optional<u_int32_t > discr_value;
2518
+ DWARFFormValue type_ref;
2519
+ ConstString variant_name;
2520
+ uint32_t byte_offset;
2521
+ ConstString GetName () const ;
2522
+ };
2523
+
2524
+ struct VariantPart {
2525
+ explicit VariantPart (const DWARFDIE &die, const DWARFDIE &parent_die,
2526
+ ModuleSP module_sp);
2527
+
2528
+ std::vector<VariantMember> &members ();
2529
+
2530
+ DiscriminantValue &discriminant ();
2531
+
2532
+ private:
2533
+ std::vector<VariantMember> _members;
2534
+ DiscriminantValue _discriminant;
2535
+ };
2536
+
2504
2537
} // namespace
2505
2538
2539
+ ConstString VariantMember::GetName () const { return this ->variant_name ; }
2540
+
2541
+ bool VariantMember::IsDefault () const { return !discr_value; }
2542
+
2543
+ VariantMember::VariantMember (DWARFDIE &die, lldb::ModuleSP module_sp) {
2544
+ assert (die.Tag () == llvm::dwarf::DW_TAG_variant);
2545
+ this ->discr_value =
2546
+ die.GetAttributeValueAsOptionalUnsigned (DW_AT_discr_value);
2547
+
2548
+ for (auto child_die : die.children ()) {
2549
+ switch (child_die.Tag ()) {
2550
+ case llvm::dwarf::DW_TAG_member: {
2551
+ DWARFAttributes attributes = child_die.GetAttributes ();
2552
+ for (std::size_t i = 0 ; i < attributes.Size (); ++i) {
2553
+ DWARFFormValue form_value;
2554
+ const dw_attr_t attr = attributes.AttributeAtIndex (i);
2555
+ if (attributes.ExtractFormValueAtIndex (i, form_value)) {
2556
+ switch (attr) {
2557
+ case DW_AT_name:
2558
+ variant_name = ConstString (form_value.AsCString ());
2559
+ break ;
2560
+ case DW_AT_type:
2561
+ type_ref = form_value;
2562
+ break ;
2563
+
2564
+ case DW_AT_data_member_location:
2565
+ if (form_value.BlockData ()) {
2566
+ Value initialValue (0 );
2567
+ Value memberOffset (0 );
2568
+ const DWARFDataExtractor &debug_info_data = die.GetData ();
2569
+ uint32_t block_length = form_value.Unsigned ();
2570
+ uint32_t block_offset =
2571
+ form_value.BlockData () - debug_info_data.GetDataStart ();
2572
+ if (DWARFExpression::Evaluate (
2573
+ nullptr , // ExecutionContext *
2574
+ nullptr , // RegisterContext *
2575
+ module_sp,
2576
+ DataExtractor (debug_info_data, block_offset,
2577
+ block_length),
2578
+ die.GetCU (), eRegisterKindDWARF, &initialValue, nullptr ,
2579
+ memberOffset, nullptr )) {
2580
+ byte_offset = memberOffset.ResolveValue (nullptr ).UInt ();
2581
+ }
2582
+ } else {
2583
+ // With DWARF 3 and later, if the value is an integer constant,
2584
+ // this form value is the offset in bytes from the beginning of
2585
+ // the containing entity.
2586
+ byte_offset = form_value.Unsigned ();
2587
+ }
2588
+ break ;
2589
+
2590
+ default :
2591
+ break ;
2592
+ }
2593
+ }
2594
+ }
2595
+ break ;
2596
+ }
2597
+ default :
2598
+ break ;
2599
+ }
2600
+ break ;
2601
+ }
2602
+ }
2603
+
2604
+ DiscriminantValue::DiscriminantValue (const DWARFDIE &die, ModuleSP module_sp) {
2605
+ auto referenced_die = die.GetReferencedDIE (DW_AT_discr);
2606
+ DWARFAttributes attributes = referenced_die.GetAttributes ();
2607
+ for (std::size_t i = 0 ; i < attributes.Size (); ++i) {
2608
+ const dw_attr_t attr = attributes.AttributeAtIndex (i);
2609
+ DWARFFormValue form_value;
2610
+ if (attributes.ExtractFormValueAtIndex (i, form_value)) {
2611
+ switch (attr) {
2612
+ case DW_AT_type:
2613
+ type_ref = form_value;
2614
+ break ;
2615
+ case DW_AT_data_member_location:
2616
+ if (form_value.BlockData ()) {
2617
+ Value initialValue (0 );
2618
+ Value memberOffset (0 );
2619
+ const DWARFDataExtractor &debug_info_data = die.GetData ();
2620
+ uint32_t block_length = form_value.Unsigned ();
2621
+ uint32_t block_offset =
2622
+ form_value.BlockData () - debug_info_data.GetDataStart ();
2623
+ if (DWARFExpression::Evaluate (
2624
+ nullptr , // ExecutionContext *
2625
+ nullptr , // RegisterContext *
2626
+ module_sp,
2627
+ DataExtractor (debug_info_data, block_offset, block_length),
2628
+ die.GetCU (), eRegisterKindDWARF, &initialValue, nullptr ,
2629
+ memberOffset, nullptr )) {
2630
+ byte_offset = memberOffset.ResolveValue (nullptr ).UInt ();
2631
+ }
2632
+ } else {
2633
+ // With DWARF 3 and later, if the value is an integer constant,
2634
+ // this form value is the offset in bytes from the beginning of
2635
+ // the containing entity.
2636
+ byte_offset = form_value.Unsigned ();
2637
+ }
2638
+ break ;
2639
+ default :
2640
+ break ;
2641
+ }
2642
+ }
2643
+ }
2644
+ }
2645
+
2646
+ VariantPart::VariantPart (const DWARFDIE &die, const DWARFDIE &parent_die,
2647
+ lldb::ModuleSP module_sp)
2648
+ : _members(), _discriminant(die, module_sp) {
2649
+
2650
+ for (auto child : die.children ()) {
2651
+ if (child.Tag () == llvm::dwarf::DW_TAG_variant) {
2652
+ _members.push_back (VariantMember (child, module_sp));
2653
+ }
2654
+ }
2655
+ }
2656
+
2657
+ std::vector<VariantMember> &VariantPart::members () { return this ->_members ; }
2658
+
2659
+ DiscriminantValue &VariantPart::discriminant () { return this ->_discriminant ; }
2660
+
2506
2661
MemberAttributes::MemberAttributes (const DWARFDIE &die,
2507
2662
const DWARFDIE &parent_die,
2508
2663
ModuleSP module_sp) {
@@ -3037,6 +3192,13 @@ bool DWARFASTParserClang::ParseChildMembers(
3037
3192
ParseObjCProperty (die, parent_die, class_clang_type, delayed_properties);
3038
3193
break ;
3039
3194
3195
+ case DW_TAG_variant_part:
3196
+ if (die.GetCU ()->GetDWARFLanguageType () == eLanguageTypeRust) {
3197
+ ParseRustVariantPart (die, parent_die, class_clang_type,
3198
+ default_accessibility, layout_info);
3199
+ }
3200
+ break ;
3201
+
3040
3202
case DW_TAG_member:
3041
3203
ParseSingleMember (die, parent_die, class_clang_type,
3042
3204
default_accessibility, layout_info, last_field_info);
@@ -3721,3 +3883,76 @@ bool DWARFASTParserClang::ShouldCreateUnnamedBitfield(
3721
3883
3722
3884
return true ;
3723
3885
}
3886
+
3887
+ void DWARFASTParserClang::ParseRustVariantPart (
3888
+ DWARFDIE &die, const DWARFDIE &parent_die, CompilerType &class_clang_type,
3889
+ const lldb::AccessType default_accesibility,
3890
+ ClangASTImporter::LayoutInfo &layout_info) {
3891
+ assert (die.Tag () == llvm::dwarf::DW_TAG_variant_part);
3892
+ assert (SymbolFileDWARF::GetLanguage (*die.GetCU ()) ==
3893
+ LanguageType::eLanguageTypeRust);
3894
+
3895
+ ModuleSP module_sp = parent_die.GetDWARF ()->GetObjectFile ()->GetModule ();
3896
+
3897
+ VariantPart variants (die, parent_die, module_sp);
3898
+
3899
+ auto discriminant_type =
3900
+ die.ResolveTypeUID (variants.discriminant ().type_ref .Reference ());
3901
+
3902
+ auto decl_context = m_ast.GetDeclContextForType (class_clang_type);
3903
+
3904
+ auto inner_holder = m_ast.CreateRecordType (
3905
+ decl_context, OptionalClangModuleID (), lldb::eAccessPublic,
3906
+ std::string (
3907
+ llvm::formatv (" {0}$Inner" , class_clang_type.GetTypeName (false ))),
3908
+ clang::TTK_Union, lldb::eLanguageTypeRust);
3909
+ m_ast.StartTagDeclarationDefinition (inner_holder);
3910
+ m_ast.SetIsPacked (inner_holder);
3911
+
3912
+ for (auto member : variants.members ()) {
3913
+
3914
+ auto has_discriminant = !member.IsDefault ();
3915
+
3916
+ auto member_type = die.ResolveTypeUID (member.type_ref .Reference ());
3917
+
3918
+ auto field_type = m_ast.CreateRecordType (
3919
+ m_ast.GetDeclContextForType (inner_holder), OptionalClangModuleID (),
3920
+ lldb::eAccessPublic,
3921
+ std::string (llvm::formatv (" {0}$Variant" , member.GetName ())),
3922
+ clang::TTK_Struct, lldb::eLanguageTypeRust);
3923
+
3924
+ m_ast.StartTagDeclarationDefinition (field_type);
3925
+ auto offset = member.byte_offset ;
3926
+
3927
+ if (has_discriminant) {
3928
+ m_ast.AddFieldToRecordType (
3929
+ field_type, " $discr$" , discriminant_type->GetFullCompilerType (),
3930
+ lldb::eAccessPublic, variants.discriminant ().byte_offset );
3931
+ offset += discriminant_type->GetByteSize (nullptr ).value_or (0 );
3932
+ }
3933
+
3934
+ m_ast.AddFieldToRecordType (field_type, " value" ,
3935
+ member_type->GetFullCompilerType (),
3936
+ lldb::eAccessPublic, offset * 8 );
3937
+
3938
+ m_ast.CompleteTagDeclarationDefinition (field_type);
3939
+
3940
+ auto name = has_discriminant
3941
+ ? llvm::formatv (" $variant${0}" , member.discr_value .value ())
3942
+ : std::string (" $variant$" );
3943
+
3944
+ auto variant_decl =
3945
+ m_ast.AddFieldToRecordType (inner_holder, llvm::StringRef (name),
3946
+ field_type, default_accesibility, 0 );
3947
+
3948
+ layout_info.field_offsets .insert ({variant_decl, 0 });
3949
+ }
3950
+
3951
+ auto inner_field = m_ast.AddFieldToRecordType (class_clang_type,
3952
+ llvm::StringRef (" $variants$" ),
3953
+ inner_holder, eAccessPublic, 0 );
3954
+
3955
+ m_ast.CompleteTagDeclarationDefinition (inner_holder);
3956
+
3957
+ layout_info.field_offsets .insert ({inner_field, 0 });
3958
+ }
0 commit comments