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