1# Copyright 2018-2021 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16# Test DW_TAG_variant_part and DW_TAG_variant.
17
18load_lib dwarf.exp
19
20# This test can only be run on targets which support DWARF-2 and use
21# gas.
22if {![dwarf2_support]} {
23    return 0
24}
25
26standard_testfile .c .S
27
28# Make some DWARF for the test.
29set asm_file [standard_output_file $srcfile2]
30Dwarf::assemble $asm_file {
31    upvar cu_lang cu_lang
32
33    declare_labels uinteger_label float_label int8_label
34    declare_labels discr_1_label discr_2_label discr_3_label
35    declare_labels one_label two_label
36
37    # Creating a CU with 4-byte addresses lets this test link on
38    # both 32- and 64-bit machines.
39    cu { addr_size 4 } {
40	compile_unit {
41	    {name file1.txt}
42	    {language @DW_LANG_Rust}
43	} {
44            uinteger_label: DW_TAG_base_type {
45                {DW_AT_byte_size 4 DW_FORM_sdata}
46                {DW_AT_encoding  @DW_ATE_unsigned}
47                {DW_AT_name      {unsigned integer}}
48            }
49
50            int8_label: DW_TAG_base_type {
51                {DW_AT_byte_size 1 DW_FORM_sdata}
52                {DW_AT_encoding  @DW_ATE_signed}
53                {DW_AT_name      i8}
54            }
55
56	    float_label: base_type {
57		{name float}
58		{encoding @DW_ATE_float}
59		{byte_size 4 DW_FORM_sdata}
60	    }
61
62	    one_label: structure_type {
63		{name One}
64		{byte_size 4 DW_FORM_sdata}
65	    } {
66		member {
67		    {name __0}
68		    {type :$uinteger_label}
69		    {data_member_location 0 data1}
70		}
71	    }
72
73	    two_label: structure_type {
74		{name Two}
75		{byte_size 4 DW_FORM_sdata}
76	    } {
77		member {
78		    {name __0}
79		    {type :$float_label}
80		    {data_member_location 0 data1}
81		}
82	    }
83
84	    structure_type {
85		{name Simple}
86		{byte_size 8 DW_FORM_sdata}
87	    } {
88		variant_part {
89		    {discr :$discr_1_label DW_FORM_ref4}
90		} {
91		    discr_1_label: member {
92			{type :$uinteger_label}
93			{data_member_location 0 data1}
94			{artificial 1 DW_FORM_flag_present}
95		    }
96
97		    variant {
98			{discr_value 23 udata}
99		    } {
100			member {
101			    {type :$one_label}
102			    {data_member_location 4 data1}
103			}
104		    }
105
106		    variant {
107			{discr_value 1 udata}
108		    } {
109			member {
110			    {type :$two_label}
111			    {data_member_location 4 data1}
112			}
113		    }
114		}
115	    }
116
117	    structure_type {
118		{name Defaulted}
119		{byte_size 8 DW_FORM_sdata}
120	    } {
121		variant_part {
122		    {discr :$discr_2_label DW_FORM_ref4}
123		} {
124		    discr_2_label: member {
125			{type :$uinteger_label}
126			{data_member_location 0 data1}
127			{artificial 1 DW_FORM_flag_present}
128		    }
129
130		    variant {
131		    } {
132			member {
133			    {type :$one_label}
134			    {data_member_location 4 data1}
135			}
136		    }
137
138		    variant {
139			{discr_value 1 udata}
140		    } {
141			member {
142			    {type :$two_label}
143			    {data_member_location 4 data1}
144			}
145		    }
146		}
147	    }
148
149	    structure_type {
150		{name Univariant}
151		{byte_size 8 DW_FORM_sdata}
152	    } {
153		variant_part {
154		} {
155		    variant {
156		    } {
157			member {
158			    {type :$one_label}
159			    {data_member_location 4 data1}
160			}
161		    }
162		}
163	    }
164
165	    # Rust won't emit a negative discriminant like this, but
166	    # we want to test the code path anyway.
167	    structure_type {
168		{name Negative}
169		{byte_size 8 DW_FORM_sdata}
170	    } {
171		variant_part {
172		    {discr :$discr_3_label DW_FORM_ref4}
173		} {
174		    discr_3_label: member {
175			{type :$int8_label}
176			{data_member_location 0 data1}
177			{artificial 1 DW_FORM_flag_present}
178		    }
179
180		    variant {
181			{discr_value -1 sdata}
182		    } {
183			member {
184			    {type :$one_label}
185			    {data_member_location 4 data1}
186			}
187		    }
188
189		    # Make this the default value so we'll see an
190		    # incorrect result if we mishandle signed
191		    # discriminants.
192		    variant {
193		    } {
194			member {
195			    {type :$two_label}
196			    {data_member_location 4 data1}
197			}
198		    }
199		}
200	    }
201	}
202    }
203}
204
205if { [prepare_for_testing "failed to prepare" ${testfile} \
206	  [list $srcfile $asm_file] debug] } {
207    return -1
208}
209
210if ![runto func] {
211    return -1
212}
213
214# Get the values into history so we can use it from Rust.
215gdb_test "print (void *) buffer" "\\\$1 = .void .. $hex .buffer."
216gdb_test "print (void *) buffer2" "\\\$2 = .void .. $hex .buffer2."
217
218gdb_test "set language rust"
219gdb_test "print *(\$1 as *mut Simple)" " = One\\(23\\)" \
220    "print as Simple"
221gdb_test "print *(\$1 as *mut Defaulted)" " = One\\(23\\)" \
222    "print as Defaulted"
223gdb_test "print *(\$1 as *mut Univariant)" " = One\\(23\\)" \
224    "print as Univariant"
225
226gdb_test "print *(\$2 as *mut Negative)" " = One\\(23\\)" \
227    "print as Negative"
228