]>
git.proxmox.com Git - rustc.git/blob - src/etc/lldb_rust_formatters.py
42c83b6a42ed6f6df6ad7ec765fa5eb5e809b897
1 # Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 # file at the top-level directory of this distribution and at
3 # http://rust-lang.org/COPYRIGHT.
5 # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 # option. This file may not be copied, modified, or distributed
9 # except according to those terms.
14 def print_val(val
, internal_dict
):
15 '''Prints the given value with Rust syntax'''
16 type_class
= val
.GetType().GetTypeClass()
18 if type_class
== lldb
.eTypeClassStruct
:
19 return print_struct_val(val
, internal_dict
)
21 if type_class
== lldb
.eTypeClassUnion
:
22 return print_enum_val(val
, internal_dict
)
24 if type_class
== lldb
.eTypeClassPointer
:
25 return print_pointer_val(val
, internal_dict
)
27 if type_class
== lldb
.eTypeClassArray
:
28 return print_fixed_size_vec_val(val
, internal_dict
)
33 #=--------------------------------------------------------------------------------------------------
34 # Type-Specialized Printing Functions
35 #=--------------------------------------------------------------------------------------------------
37 def print_struct_val(val
, internal_dict
):
38 '''Prints a struct, tuple, or tuple struct value with Rust syntax'''
39 assert val
.GetType().GetTypeClass() == lldb
.eTypeClassStruct
42 return print_vec_slice_val(val
, internal_dict
)
44 return print_struct_val_starting_from(0, val
, internal_dict
)
47 def print_vec_slice_val(val
, internal_dict
):
48 length
= val
.GetChildAtIndex(1).GetValueAsUnsigned()
50 data_ptr_val
= val
.GetChildAtIndex(0)
51 data_ptr_type
= data_ptr_val
.GetType()
52 assert data_ptr_type
.IsPointerType()
54 element_type
= data_ptr_type
.GetPointeeType()
55 element_type_size
= element_type
.GetByteSize()
57 start_address
= data_ptr_val
.GetValueAsUnsigned()
59 def render_element(i
):
60 address
= start_address
+ i
* element_type_size
61 element_val
= val
.CreateValueFromAddress(val
.GetName() +
62 ("[%s]" % i
), address
, element_type
)
63 return print_val(element_val
, internal_dict
)
65 return "&[%s]" % (', '.join([render_element(i
) for i
in range(length
)]))
68 def print_struct_val_starting_from(field_start_index
, val
, internal_dict
):
70 Prints a struct, tuple, or tuple struct value with Rust syntax.
71 Ignores any fields before field_start_index.
73 assert val
.GetType().GetTypeClass() == lldb
.eTypeClassStruct
76 type_name
= extract_type_name(t
.GetName())
77 num_children
= val
.num_children
79 if (num_children
- field_start_index
) == 0:
80 # The only field of this struct is the enum discriminant
83 has_field_names
= type_has_field_names(t
)
86 template
= "%(type_name)s {\n%(body)s\n}"
89 template
= "%(type_name)s(%(body)s)"
92 if type_name
.startswith("("):
93 # this is a tuple, so don't print the type name
96 def render_child(child_index
):
99 field_name
= t
.GetFieldAtIndex(child_index
).GetName()
100 this
+= field_name
+ ": "
102 field_val
= val
.GetChildAtIndex(child_index
)
103 return this
+ print_val(field_val
, internal_dict
)
105 body
= separator
.join([render_child(idx
) for idx
in range(field_start_index
, num_children
)])
107 return template
% {"type_name": type_name
,
111 def print_enum_val(val
, internal_dict
):
112 '''Prints an enum value with Rust syntax'''
114 assert val
.GetType().GetTypeClass() == lldb
.eTypeClassUnion
116 if val
.num_children
== 1:
117 # This is either an enum with just one variant, or it is an Option-like
118 # enum where the discriminant is encoded in a non-nullable pointer
119 # field. We find out which one it is by looking at the member name of
120 # the sole union variant. If it starts with "RUST$ENCODED$ENUM$" then
121 # we have an Option-like enum.
122 first_variant_name
= val
.GetChildAtIndex(0).GetName()
123 if first_variant_name
and first_variant_name
.startswith("RUST$ENCODED$ENUM$"):
125 # This is an Option-like enum. The position of the discriminator field is
126 # encoded in the name which has the format:
127 # RUST$ENCODED$ENUM$<index of discriminator field>$<name of null variant>
128 last_separator_index
= first_variant_name
.rfind("$")
129 if last_separator_index
== -1:
130 return "<invalid enum encoding: %s>" % first_variant_name
132 start_index
= len("RUST$ENCODED$ENUM$")
134 # Extract indices of the discriminator field
136 disr_field_indices
= first_variant_name
[start_index
:last_separator_index
].split("$")
137 disr_field_indices
= [int(index
) for index
in disr_field_indices
]
139 return "<invalid enum encoding: %s>" % first_variant_name
141 # Read the discriminant
142 disr_val
= val
.GetChildAtIndex(0)
143 for index
in disr_field_indices
:
144 disr_val
= disr_val
.GetChildAtIndex(index
)
146 # If the discriminant field is a fat pointer we have to consider the
147 # first word as the true discriminant
148 if disr_val
.GetType().GetTypeClass() == lldb
.eTypeClassStruct
:
149 disr_val
= disr_val
.GetChildAtIndex(0)
151 if disr_val
.GetValueAsUnsigned() == 0:
152 # Null case: Print the name of the null-variant
153 null_variant_name
= first_variant_name
[last_separator_index
+ 1:]
154 return null_variant_name
156 # Non-null case: Interpret the data as a value of the non-null variant type
157 return print_struct_val_starting_from(0, val
.GetChildAtIndex(0), internal_dict
)
159 # This is just a regular uni-variant enum without discriminator field
160 return print_struct_val_starting_from(0, val
.GetChildAtIndex(0), internal_dict
)
162 # If we are here, this is a regular enum with more than one variant
163 disr_val
= val
.GetChildAtIndex(0).GetChildMemberWithName("RUST$ENUM$DISR")
164 disr_type
= disr_val
.GetType()
166 if disr_type
.GetTypeClass() != lldb
.eTypeClassEnumeration
:
167 return "<Invalid enum value encountered: Discriminator is not an enum>"
169 variant_index
= disr_val
.GetValueAsUnsigned()
170 return print_struct_val_starting_from(1, val
.GetChildAtIndex(variant_index
), internal_dict
)
173 def print_pointer_val(val
, internal_dict
):
174 '''Prints a pointer value with Rust syntax'''
175 assert val
.GetType().IsPointerType()
177 type_name
= extract_type_name(val
.GetType().GetName())
178 if type_name
and type_name
[0:1] in ["&", "~", "*"]:
179 sigil
= type_name
[0:1]
181 return sigil
+ hex(val
.GetValueAsUnsigned()) #print_val(val.Dereference(), internal_dict)
184 def print_fixed_size_vec_val(val
, internal_dict
):
185 assert val
.GetType().GetTypeClass() == lldb
.eTypeClassArray
189 for i
in range(val
.num_children
):
190 output
+= print_val(val
.GetChildAtIndex(i
), internal_dict
)
191 if i
!= val
.num_children
- 1:
198 #=--------------------------------------------------------------------------------------------------
200 #=--------------------------------------------------------------------------------------------------
202 unqualified_type_markers
= frozenset(["(", "[", "&", "*"])
205 def extract_type_name(qualified_type_name
):
206 '''Extracts the type name from a fully qualified path'''
207 if qualified_type_name
[0] in unqualified_type_markers
:
208 return qualified_type_name
210 end_of_search
= qualified_type_name
.find("<")
211 if end_of_search
< 0:
212 end_of_search
= len(qualified_type_name
)
214 index
= qualified_type_name
.rfind("::", 0, end_of_search
)
216 return qualified_type_name
218 return qualified_type_name
[index
+ 2:]
221 def type_has_field_names(ty
):
222 '''Returns true of this is a type with field names (struct, struct-like enum variant)'''
223 # This may also be an enum variant where the first field doesn't have a name but the rest has
224 if ty
.GetNumberOfFields() > 1:
225 return ty
.GetFieldAtIndex(1).GetName() is not None
227 return ty
.GetFieldAtIndex(0).GetName() is not None
230 def is_vec_slice(val
):
232 if ty
.GetTypeClass() != lldb
.eTypeClassStruct
:
235 if ty
.GetNumberOfFields() != 2:
238 if ty
.GetFieldAtIndex(0).GetName() != "data_ptr":
241 if ty
.GetFieldAtIndex(1).GetName() != "length":
244 type_name
= extract_type_name(ty
.GetName()).replace("&'static", "&").replace(" ", "")
245 return type_name
.startswith("&[") and type_name
.endswith("]")