diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index a93b42e1cc449..db3afb00369da 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -86,7 +86,8 @@ def synthetic_lookup(valobj, dict): return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict) if rust_type == RustType.SINGLETON_ENUM: return synthetic_lookup(valobj.GetChildAtIndex(0), dict) - + if rust_type == RustType.ENUM: + return ClangEncodedEnumProvider(valobj, dict) if rust_type == RustType.STD_VEC: return StdVecSyntheticProvider(valobj, dict) if rust_type == RustType.STD_VEC_DEQUE: diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 1c43977a501a0..a87fd6078b866 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -247,6 +247,58 @@ def has_children(self): # type: () -> bool return True +class ClangEncodedEnumProvider: + """Pretty-printer for 'clang-encoded' enums support implemented in LLDB""" + DISCRIMINANT_MEMBER_NAME = "$discr$" + VALUE_MEMBER_NAME = "value" + + def __init__(self, valobj, dict): + self.valobj = valobj + self.update() + + def has_children(self): + return True + + def num_children(self): + if self.is_default: + return 1 + return 2 + + def get_child_index(self, name): + if name == ClangEncodedEnumProvider.VALUE_MEMBER_NAME: + return 0 + if name == ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME: + return 1 + return -1 + + def get_child_at_index(self, index): + if index == 0: + return self.variant.GetChildMemberWithName(ClangEncodedEnumProvider.VALUE_MEMBER_NAME) + if index == 1: + return self.variant.GetChildMemberWithName( + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) + + + def update(self): + all_variants = self.valobj.GetChildAtIndex(0) + index = self._getCurrentVariantIndex(all_variants) + self.variant = all_variants.GetChildAtIndex(index) + self.is_default = self.variant.GetIndexOfChildWithName( + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) == -1 + + def _getCurrentVariantIndex(self, all_variants): + default_index = 0 + for i in range(all_variants.GetNumChildren()): + variant = all_variants.GetChildAtIndex(i) + discr = variant.GetChildMemberWithName( + ClangEncodedEnumProvider.DISCRIMINANT_MEMBER_NAME) + if discr.IsValid(): + discr_unsigned_value = discr.GetValueAsUnsigned() + if variant.GetName() == f"$variant${discr_unsigned_value}": + return i + else: + default_index = i + return default_index class TupleSyntheticProvider: """Pretty-printer for tuples and tuple enum variants""" diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py index c0415a3cdcfe4..190fbc13a173f 100644 --- a/src/etc/rust_types.py +++ b/src/etc/rust_types.py @@ -60,6 +60,7 @@ class RustType(object): ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$" ENUM_DISR_FIELD_NAME = "<>" +ENUM_LLDB_ENCODED_VARIANTS = "$variants$" STD_TYPE_TO_REGEX = { RustType.STD_STRING: STD_STRING_REGEX, @@ -96,7 +97,11 @@ def classify_struct(name, fields): if regex.match(name): return ty - if fields[0].name == ENUM_DISR_FIELD_NAME: + # <> is emitted by GDB while LLDB(18.1+) emits "$variants$" + if ( + fields[0].name == ENUM_DISR_FIELD_NAME + or fields[0].name == ENUM_LLDB_ENCODED_VARIANTS + ): return RustType.ENUM if is_tuple_fields(fields): diff --git a/tests/debuginfo/borrowed-enum.rs b/tests/debuginfo/borrowed-enum.rs index 39883ffd0b6ab..fc2ab62a21c49 100644 --- a/tests/debuginfo/borrowed-enum.rs +++ b/tests/debuginfo/borrowed-enum.rs @@ -1,6 +1,6 @@ // Require a gdb or lldb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 -//@ needs-rust-lldb +//@ min-lldb-version: 1800 //@ compile-flags:-g @@ -23,10 +23,13 @@ // lldb-command:run // lldb-command:v *the_a_ref +// lldbg-check:(borrowed_enum::ABC) *the_a_ref = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } // lldbr-check:(borrowed_enum::ABC::TheA) *the_a_ref = TheA { TheA: 0, TheB: 8970181431921507452 } // lldb-command:v *the_b_ref +// lldbg-check:(borrowed_enum::ABC) *the_b_ref = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldbr-check:(borrowed_enum::ABC::TheB) *the_b_ref = { = 0 = 286331153 = 286331153 } // lldb-command:v *univariant_ref +// lldbg-check:(borrowed_enum::Univariant) *univariant_ref = { value = { 0 = 4820353753753434 } } // lldbr-check:(borrowed_enum::Univariant) *univariant_ref = { TheOnlyCase = { = 4820353753753434 } } #![allow(unused_variables)] diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs index 9e1bd5d62e7a1..eca31a6e5de61 100644 --- a/tests/debuginfo/coroutine-objects.rs +++ b/tests/debuginfo/coroutine-objects.rs @@ -1,8 +1,9 @@ // Require a gdb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 +//@ min-lldb-version: 1800 -// LLDB without native Rust support cannot read DW_TAG_variant_part, -// so it prints nothing for coroutines. But those tests are kept to +// LLDB (18.1+) now supports DW_TAG_variant_part, but there is some bug in either compiler or LLDB +// with memory layout of discriminant for this particular enum // ensure that LLDB won't crash at least (like #57822). //@ compile-flags:-g @@ -26,16 +27,7 @@ // lldb-command:run // lldb-command:v b -// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b = -// lldb-command:continue -// lldb-command:v b -// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b = -// lldb-command:continue -// lldb-command:v b -// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b = -// lldb-command:continue -// lldb-command:v b -// lldbg-check:(coroutine_objects::main::{coroutine_env#0}) b = +// lldb-check:(coroutine_objects::main::{coroutine_env#0}) b = { value = { _ref__a = 0x[...] } $discr$ = ',' } // === CDB TESTS =================================================================================== diff --git a/tests/debuginfo/enum-thinlto.rs b/tests/debuginfo/enum-thinlto.rs index f3f177589318c..42a0d1e28f8e5 100644 --- a/tests/debuginfo/enum-thinlto.rs +++ b/tests/debuginfo/enum-thinlto.rs @@ -1,6 +1,6 @@ // Require a gdb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 - +//@ min-lldb-version: 1800 //@ compile-flags:-g -Z thinlto // === GDB TESTS =================================================================================== @@ -15,7 +15,7 @@ // lldb-command:run // lldb-command:v *abc -// lldbg-check:(enum_thinlto::ABC) *abc = +// lldbg-check:(enum_thinlto::ABC) *abc = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } // lldbr-check:(enum_thinlto::ABC) *abc = (x = 0, y = 8970181431921507452) #![allow(unused_variables)] diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs index 93e1a2558f693..66912fc471a94 100644 --- a/tests/debuginfo/issue-57822.rs +++ b/tests/debuginfo/issue-57822.rs @@ -3,7 +3,7 @@ // Require a gdb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 - +//@ min-lldb-version: 1800 //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -24,7 +24,7 @@ // lldbg-check:(issue_57822::main::{closure_env#1}) g = { f = { x = 1 } } // lldb-command:v b -// lldbg-check:(issue_57822::main::{coroutine_env#3}) b = +// lldbg-check:(issue_57822::main::{coroutine_env#3}) b = { value = { a = { value = { y = 2 } $discr$ = '\x02' } } $discr$ = '\x02' } #![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)] #![omit_gdb_pretty_printer_section] diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs index cfac14a22c418..c267da0e1b759 100644 --- a/tests/debuginfo/msvc-pretty-enums.rs +++ b/tests/debuginfo/msvc-pretty-enums.rs @@ -1,5 +1,84 @@ -//@ only-cdb +//@ min-lldb-version: 1800 +//@ ignore-gdb //@ compile-flags:-g + +// === LLDB TESTS ================================================================================== + +// lldb-command:run +// lldb-command:v a +// lldbg-check:(core::option::Option) a = { value = { 0 = Low } } + +// lldb-command:v b +// lldbg-check:(core::option::Option) b = { value = $discr$ = '\x01' } + +// lldb-command:v c +// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) c = { value = $discr$ = '\x11' } + +// lldb-command:v d +// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) d = { value = { my_data = High } } + +// lldb-command:v e +// lldbg-check:(msvc_pretty_enums::NicheLayoutEnum) e = { value = $discr$ = '\x13' } + +// lldb-command:v h +// lldbg-check:(core::option::Option) h = { value = { 0 = 12 } $discr$ = 1 } + +// lldb-command:v i +// lldbg-check:(core::option::Option) i = { value = $discr$ = 0 } + +// lldb-command:v j +// lldbg-check:(msvc_pretty_enums::CStyleEnum) j = High + +// lldb-command:v k +// lldbg-check:(core::option::Option) k = { value = { 0 = "IAMA optional string!" { vec = size=21 { [0] = 'I' [1] = 'A' [2] = 'M' [3] = 'A' [4] = ' ' [5] = 'o' [6] = 'p' [7] = 't' [8] = 'i' [9] = 'o' [10] = 'n' [11] = 'a' [12] = 'l' [13] = ' ' [14] = 's' [15] = 't' [16] = 'r' [17] = 'i' [18] = 'n' [19] = 'g' [20] = '!' } } } } + +// lldb-command:v l +// lldbg-check:(core::result::Result) l = { value = { 0 = {} } } + +// lldb-command:v niche128_some +// lldbg-check:(core::option::Option>) niche128_some = { value = $discr$ = 123456 } + +// lldb-command:v niche128_none +// lldbg-check:(core::option::Option>) niche128_none = { value = $discr$ = 0 } + +// lldb-command:v wrapping_niche128_untagged +// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_untagged = { value = { 0 = { 0 = 340282366920938463463374607431768211454 } } } + +// lldb-command:v wrapping_niche128_none1 +// lldbg-check:(msvc_pretty_enums::Wrapping128Niche) wrapping_niche128_none1 = { value = { 0 = { 0 = 2 } } } + +// lldb-command:v direct_tag_128_a +// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_a = { value = { 0 = 42 } $discr$ = 0 } + +// lldb-command:v direct_tag_128_b +// lldbg-check:(msvc_pretty_enums::DirectTag128) direct_tag_128_b = { value = { 0 = 137 } $discr$ = 1 } + +// &u32 is incorrectly formatted and LLDB thinks it's a char* so skipping niche_w_fields_1_some + +// lldb-command:v niche_w_fields_1_none +// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields1) niche_w_fields_1_none = { value = { 0 = 99 } $discr$ = 1 } + +// lldb-command:v niche_w_fields_2_some +// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields2) niche_w_fields_2_some = { value = { 0 = 800 { __0 = { 0 = 800 } } 1 = 900 } $discr$ = 0 } + +// lldb-command:v niche_w_fields_3_some +// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_some = { value = { 0 = '\x89' 1 = true } } + +// lldb-command:v niche_w_fields_3_niche3 +// lldbg-check:(msvc_pretty_enums::NicheLayoutWithFields3) niche_w_fields_3_niche3 = { value = { 0 = '"' } $discr$ = '\x04' } + +// lldb-command:v arbitrary_discr1 +// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr1 = { value = { 0 = 1234 } $discr$ = 1000 } + +// lldb-command:v arbitrary_discr2 +// lldbg-check:(msvc_pretty_enums::ArbitraryDiscr) arbitrary_discr2 = { value = { 0 = 5678 } $discr$ = 5000000 } + +// === CDB TESTS ================================================================================== +// cdb-command: g +// +// cdb-command: dx a +// cdb-check:a : Some [Type: enum2$ >] +// cdb-check: [+0x000] __0 : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum] // // cdb-command: g // diff --git a/tests/debuginfo/struct-style-enum.rs b/tests/debuginfo/struct-style-enum.rs index 517b76c14120b..42368017cae69 100644 --- a/tests/debuginfo/struct-style-enum.rs +++ b/tests/debuginfo/struct-style-enum.rs @@ -1,7 +1,6 @@ // Require a gdb or lldb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 -//@ needs-rust-lldb - +//@ min-lldb-version: 1800 //@ compile-flags:-g // === GDB TESTS =================================================================================== @@ -27,15 +26,19 @@ // lldb-command:run // lldb-command:v case1 +// lldbg-check:(struct_style_enum::Regular) case1 = { value = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } $discr$ = 0 } // lldbr-check:(struct_style_enum::Regular::Case1) case1 = { a = 0 b = 31868 c = 31868 d = 31868 e = 31868 } // lldb-command:v case2 +// lldbg-check:(struct_style_enum::Regular) case2 = { value = { a = 0 b = 286331153 c = 286331153 } $discr$ = 1 } // lldbr-check:(struct_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } // lldb-command:v case3 +// lldbg-check:(struct_style_enum::Regular) case3 = { value = { a = 0 b = 6438275382588823897 } $discr$ = 2 } // lldbr-check:(struct_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 } // lldb-command:v univariant +// lldbg-check:(struct_style_enum::Univariant) univariant = { value = { a = -1 } } // lldbr-check:(struct_style_enum::Univariant) univariant = Univariant { TheOnlyCase: TheOnlyCase { a: -1 } } #![allow(unused_variables)] diff --git a/tests/debuginfo/tuple-style-enum.rs b/tests/debuginfo/tuple-style-enum.rs index 883aa658eb2c7..3de4ecb128494 100644 --- a/tests/debuginfo/tuple-style-enum.rs +++ b/tests/debuginfo/tuple-style-enum.rs @@ -1,6 +1,6 @@ // Require a gdb or lldb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 -//@ needs-rust-lldb +//@ min-lldb-version: 1800 //@ compile-flags:-g @@ -27,15 +27,19 @@ // lldb-command:run // lldb-command:v case1 +// lldbg-check:(tuple_style_enum::Regular) case1 = { value = { 0 = 0 1 = 31868 2 = 31868 3 = 31868 4 = 31868 } $discr$ = 0 } // lldbr-check:(tuple_style_enum::Regular::Case1) case1 = { = 0 = 31868 = 31868 = 31868 = 31868 } // lldb-command:v case2 +// lldbg-check:(tuple_style_enum::Regular) case2 = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldbr-check:(tuple_style_enum::Regular::Case2) case2 = Case2 { Case1: 0, Case2: 286331153, Case3: 286331153 } // lldb-command:v case3 +// lldbg-check:(tuple_style_enum::Regular) case3 = { value = { 0 = 0 1 = 6438275382588823897 } $discr$ = 2 } // lldbr-check:(tuple_style_enum::Regular::Case3) case3 = Case3 { Case1: 0, Case2: 6438275382588823897 } // lldb-command:v univariant +// lldbg-check:(tuple_style_enum::Univariant) univariant = { value = { 0 = -1 } } // lldbr-check:(tuple_style_enum::Univariant) univariant = { TheOnlyCase = { = -1 } } #![allow(unused_variables)] diff --git a/tests/debuginfo/unique-enum.rs b/tests/debuginfo/unique-enum.rs index b3879468e0a98..514c7c50812c6 100644 --- a/tests/debuginfo/unique-enum.rs +++ b/tests/debuginfo/unique-enum.rs @@ -1,6 +1,6 @@ // Require a gdb or lldb that can read DW_TAG_variant_part. //@ min-gdb-version: 8.2 -//@ needs-rust-lldb +//@ min-lldb-version: 1800 //@ compile-flags:-g @@ -23,12 +23,15 @@ // lldb-command:run // lldb-command:v *the_a +// lldbg-check:(unique_enum::ABC) *the_a = { value = { x = 0 y = 8970181431921507452 } $discr$ = 0 } // lldbr-check:(unique_enum::ABC::TheA) *the_a = TheA { TheA: 0, TheB: 8970181431921507452 } // lldb-command:v *the_b +// lldbg-check:(unique_enum::ABC) *the_b = { value = { 0 = 0 1 = 286331153 2 = 286331153 } $discr$ = 1 } // lldbr-check:(unique_enum::ABC::TheB) *the_b = { = 0 = 286331153 = 286331153 } // lldb-command:v *univariant +// lldbg-check:(unique_enum::Univariant) *univariant = { value = { 0 = 123234 } } // lldbr-check:(unique_enum::Univariant) *univariant = { TheOnlyCase = { = 123234 } } #![allow(unused_variables)]