diff options
author | Tom Tromey <tom@tromey.com> | 2018-01-10 13:53:18 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-02-26 09:21:08 -0700 |
commit | 2ddeaf8a7d64094f4caf6cdc412d8162f49f73a1 (patch) | |
tree | 74a0c3ecfeaebf20f7d1fb730dbafeb2648ab7ad /gdb/testsuite | |
parent | c9317f214b274b805190b8e878c79f4181d93bb4 (diff) | |
download | gdb-2ddeaf8a7d64094f4caf6cdc412d8162f49f73a1.zip gdb-2ddeaf8a7d64094f4caf6cdc412d8162f49f73a1.tar.gz gdb-2ddeaf8a7d64094f4caf6cdc412d8162f49f73a1.tar.bz2 |
Handle DW_TAG_variant_part and DW_TAG_variant
This changes dwarf2read to understand DW_TAG_variant_part and
DW_TAG_variant.
Note that DW_AT_discr_list is not handled. I did not need this for
Rust. I imagine this should not be too hard to add later, should
someone need it. Meanwhile I have gdb emit a complaint if it is seen.
There is a lurking issue concerning the placement of the discriminant
in the DWARF. For Rust, I ended up following the letter of the
standard and having the discriminant be a child of the
DW_TAG_variant_part. However, GCC's Ada support does not do this.
Pierre-Marie filed this with the DWARF committee:
http://dwarfstd.org/ShowIssue.php?issue=180123.1
However as that is read-only, if you have comments you might consider
adding them to the GCC bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83935
Finally, there is a DWARF extension lurking in here. In Rust, a
univariant enum will not have a discriminant. However, in order to
unify the representation of all data-carrying enums, I've made LLVM
(and my forthcoming rustc patch) emit a univariant enum using a
DW_TAG_variant with a single variant part and without DW_AT_discr.
The lack of this DW_AT_discr is the extension. I will submit an issue
on dwarfstd.org about this.
2018-02-26 Tom Tromey <tom@tromey.com>
* dwarf2read.c (struct variant_field): New.
(struct nextfield) <variant>: New field.
(dwarf2_add_field): Handle DW_TAG_variant_part.
(dwarf2_attach_fields_to_type): Attach a discriminant_info to a
discriminated union.
(read_structure_type): Handle DW_TAG_variant_part.
(handle_struct_member_die): New function, extracted from
process_structure_scope. Handle DW_TAG_variant.
(process_structure_scope): Handle discriminated unions. Call
handle_struct_member_die.
2018-02-26 Tom Tromey <tom@tromey.com>
* gdb.dwarf2/variant.c: New file.
* gdb.dwarf2/variant.exp: New file.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/variant.c | 47 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/variant.exp | 224 |
3 files changed, 276 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8d7792f..755fe94 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2018-02-26 Tom Tromey <tom@tromey.com> + * gdb.dwarf2/variant.c: New file. + * gdb.dwarf2/variant.exp: New file. + +2018-02-26 Tom Tromey <tom@tromey.com> + * gdb.rust/simple.exp: Accept more possible results in enum test. 2018-02-25 Simon Marchi <simon.marchi@polymtl.ca> diff --git a/gdb/testsuite/gdb.dwarf2/variant.c b/gdb/testsuite/gdb.dwarf2/variant.c new file mode 100644 index 0000000..e145e78 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/variant.c @@ -0,0 +1,47 @@ +/* Copyright 2018 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +unsigned char buffer[8]; +unsigned char buffer2[8]; + +static void +func (void) +{ +} + +int +main (void) +{ + /* Write the expected values into the buffer. */ + unsigned int x = 23; + if (*(char *) &x) + { + /* Little endian. */ + buffer[0] = 23; + buffer[4] = 23; + buffer2[0] = 255; + buffer2[4] = 23; + } + else + { + buffer[3] = 23; + buffer[7] = 23; + buffer2[0] = 255; + buffer2[7] = 23; + } + + func (); + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/variant.exp b/gdb/testsuite/gdb.dwarf2/variant.exp new file mode 100644 index 0000000..b61659f --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/variant.exp @@ -0,0 +1,224 @@ +# Copyright 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Test DW_TAG_variant_part and DW_TAG_variant. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use +# gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile .c variant.S + +# Make some DWARF for the test. +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + upvar cu_lang cu_lang + + declare_labels uinteger_label float_label int8_label + declare_labels discr_1_label discr_2_label discr_3_label + declare_labels one_label two_label + + # Creating a CU with 4-byte addresses lets this test link on + # both 32- and 64-bit machines. + cu { addr_size 4 } { + compile_unit { + {name file1.txt} + {language @DW_LANG_Rust} + } { + uinteger_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_unsigned} + {DW_AT_name {unsigned integer}} + } + + int8_label: DW_TAG_base_type { + {DW_AT_byte_size 1 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name i8} + } + + float_label: base_type { + {name float} + {encoding @DW_ATE_float} + {byte_size 4 DW_FORM_sdata} + } + + one_label: structure_type { + {name One} + {byte_size 4 DW_FORM_sdata} + } { + member { + {name __0} + {type :$uinteger_label} + {data_member_location 0 data1} + } + } + + two_label: structure_type { + {name Two} + {byte_size 4 DW_FORM_sdata} + } { + member { + {name __0} + {type :$float_label} + {data_member_location 0 data1} + } + } + + structure_type { + {name Simple} + {byte_size 8 DW_FORM_sdata} + } { + variant_part { + {discr :$discr_1_label DW_FORM_ref4} + } { + discr_1_label: member { + {type :$uinteger_label} + {data_member_location 0 data1} + } + + variant { + {discr_value 23 udata} + } { + member { + {type :$one_label} + {data_member_location 4 data1} + } + } + + variant { + {discr_value 1 udata} + } { + member { + {type :$two_label} + {data_member_location 4 data1} + } + } + } + } + + structure_type { + {name Defaulted} + {byte_size 8 DW_FORM_sdata} + } { + variant_part { + {discr :$discr_2_label DW_FORM_ref4} + } { + discr_2_label: member { + {type :$uinteger_label} + {data_member_location 0 data1} + } + + variant { + } { + member { + {type :$one_label} + {data_member_location 4 data1} + } + } + + variant { + {discr_value 1 udata} + } { + member { + {type :$two_label} + {data_member_location 4 data1} + } + } + } + } + + structure_type { + {name Univariant} + {byte_size 8 DW_FORM_sdata} + } { + variant_part { + } { + variant { + } { + member { + {type :$one_label} + {data_member_location 4 data1} + } + } + } + } + + # Rust won't emit a negative discriminant like this, but + # we want to test the code path anyway. + structure_type { + {name Negative} + {byte_size 8 DW_FORM_sdata} + } { + variant_part { + {discr :$discr_3_label DW_FORM_ref4} + } { + discr_3_label: member { + {type :$int8_label} + {data_member_location 0 data1} + } + + variant { + {discr_value -1 sdata} + } { + member { + {type :$one_label} + {data_member_location 4 data1} + } + } + + # Make this the default value so we'll see an + # incorrect result if we mishandle signed + # discriminants. + variant { + } { + member { + {type :$two_label} + {data_member_location 4 data1} + } + } + } + } + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] debug] } { + return -1 +} + +if ![runto func] { + return -1 +} + +# Get the values into history so we can use it from Rust. +gdb_test "print (void *) buffer" "\\\$1 = .void .. $hex .buffer." +gdb_test "print (void *) buffer2" "\\\$2 = .void .. $hex .buffer2." + +gdb_test "set language rust" +gdb_test "print *(\$1 as *mut Simple)" " = One\\(23\\)" \ + "print as Simple" +gdb_test "print *(\$1 as *mut Defaulted)" " = One\\(23\\)" \ + "print as Defaulted" +gdb_test "print *(\$1 as *mut Univariant)" " = One\\(23\\)" \ + "print as Univariant" + +gdb_test "print *(\$2 as *mut Negative)" " = One\\(23\\)" \ + "print as Negative" |