Skip to content

Fix pretty printers to work with the broader enum optimizations #20557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions src/etc/gdb_rust_pretty_printing.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def rust_pretty_printer_lookup_function(val):
enum_member_count = len(enum_members)

if enum_member_count == 0:
return RustStructPrinter(val, false)
return RustStructPrinter(val, False)

if enum_member_count == 1:
first_variant_name = enum_members[0].name
Expand All @@ -60,21 +60,27 @@ def rust_pretty_printer_lookup_function(val):
return rust_pretty_printer_lookup_function(val[enum_members[0]])
else:
assert first_variant_name.startswith("RUST$ENCODED$ENUM$")
# This is a space-optimized enum
# This is a space-optimized enum.
# This means this enum has only two states, and Rust uses one of the
# fields somewhere in the struct to determine which of the two states
# it's in. The location of the field is encoded in the name as something
# like RUST$ENCODED$ENUM$(num$)*name_of_zero_state
last_separator_index = first_variant_name.rfind("$")
second_last_separator_index = first_variant_name.rfind("$", 0, last_separator_index)
disr_field_index = first_variant_name[second_last_separator_index + 1 :
last_separator_index]
disr_field_index = int(disr_field_index)
start_index = len("RUST$ENCODED$ENUM$")
disr_field_indices = first_variant_name[start_index :
last_separator_index].split("$")
disr_field_indices = [int(index) for index in disr_field_indices]

sole_variant_val = val[enum_members[0]]
disr_field = get_field_at_index(sole_variant_val, disr_field_index)
discriminant = sole_variant_val[disr_field]
discriminant = sole_variant_val
for disr_field_index in disr_field_indices:
disr_field = get_field_at_index(discriminant, disr_field_index)
discriminant = discriminant[disr_field]

# If the discriminant field is a fat pointer we have to consider the
# first word as the true discriminant
if discriminant.type.code == gdb.TYPE_CODE_STRUCT:
discriminant = discriminant[get_field_at_index(discriminant, 0)]
discriminant = discriminant[get_field_at_index(discriminant, 0)]

if discriminant == 0:
null_variant_name = first_variant_name[last_separator_index + 1:]
Expand Down Expand Up @@ -234,4 +240,5 @@ def get_field_at_index(val, index):
for field in val.type.fields():
if i == index:
return field
i += 1
return None
26 changes: 13 additions & 13 deletions src/etc/lldb_rust_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
has_field_names = type_has_field_names(t)

if has_field_names:
template = "%(type_name)s {\n%(body)s\n}"
separator = ", \n"
template = "%(type_name)s {\n%(body)s\n}"
separator = ", \n"
else:
template = "%(type_name)s(%(body)s)"
separator = ", "
template = "%(type_name)s(%(body)s)"
separator = ", "

if type_name.startswith("("):
# this is a tuple, so don't print the type name
Expand Down Expand Up @@ -125,25 +125,25 @@ def print_enum_val(val, internal_dict):
if last_separator_index == -1:
return "<invalid enum encoding: %s>" % first_variant_name

second_last_separator_index = first_variant_name.rfind("$", 0, last_separator_index)
if second_last_separator_index == -1:
return "<invalid enum encoding: %s>" % first_variant_name
start_index = len("RUST$ENCODED$ENUM$")

# Extract index of the discriminator field
# Extract indices of the discriminator field
try:
disr_field_index = first_variant_name[second_last_separator_index + 1 :
last_separator_index]
disr_field_index = int(disr_field_index)
disr_field_indices = first_variant_name[start_index :
last_separator_index].split("$")
disr_field_indices = [int(index) for index in disr_field_indices]
except:
return "<invalid enum encoding: %s>" % first_variant_name

# Read the discriminant
disr_val = val.GetChildAtIndex(0).GetChildAtIndex(disr_field_index)
disr_val = val.GetChildAtIndex(0)
for index in disr_field_indices:
disr_val = disr_val.GetChildAtIndex(index)

# If the discriminant field is a fat pointer we have to consider the
# first word as the true discriminant
if disr_val.GetType().GetTypeClass() == lldb.eTypeClassStruct:
disr_val = disr_val.GetChildAtIndex(0)
disr_val = disr_val.GetChildAtIndex(0)

if disr_val.GetValueAsUnsigned() == 0:
# Null case: Print the name of the null-variant
Expand Down
9 changes: 9 additions & 0 deletions src/test/debuginfo/gdb-pretty-struct-and-enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@
// gdb-command: print nested_variant2
// gdb-check:$16 = NestedVariant2 = {abc = NestedStruct = {regular_struct = RegularStruct = {the_first_field = 117, the_second_field = 118.5, the_third_field = false, the_fourth_field = "NestedStructString10"}, tuple_struct = TupleStruct = {119.5, 120}, empty_struct = EmptyStruct, c_style_enum = CStyleEnumVar3, mixed_enum = MixedEnumStructVar = {field1 = 121.5, field2 = -122}}}

// gdb-command: print none_check1
// gdb-check:$17 = None

// gdb-command: print none_check2
// gdb-check:$18 = None

use self::CStyleEnum::{CStyleEnumVar1, CStyleEnumVar2, CStyleEnumVar3};
use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar};
use self::NestedEnum::{NestedVariant1, NestedVariant2};
Expand Down Expand Up @@ -170,6 +176,9 @@ fn main() {
}
};

let none_check1: Option<(uint, Vec<uint>)> = None;
let none_check2: Option<String> = None;

zzz(); // #break
}

Expand Down