1*7304104dSAndroid Build Coastguard Worker /* Function return value location for Linux/AArch64 ABI.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2013 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
34*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
35*7304104dSAndroid Build Coastguard Worker
36*7304104dSAndroid Build Coastguard Worker #include <assert.h>
37*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker #define BACKEND aarch64_
40*7304104dSAndroid Build Coastguard Worker #include "libebl_CPU.h"
41*7304104dSAndroid Build Coastguard Worker
42*7304104dSAndroid Build Coastguard Worker static int
skip_until(Dwarf_Die * child,int tag)43*7304104dSAndroid Build Coastguard Worker skip_until (Dwarf_Die *child, int tag)
44*7304104dSAndroid Build Coastguard Worker {
45*7304104dSAndroid Build Coastguard Worker int i;
46*7304104dSAndroid Build Coastguard Worker while (DWARF_TAG_OR_RETURN (child) != tag)
47*7304104dSAndroid Build Coastguard Worker if ((i = dwarf_siblingof (child, child)) != 0)
48*7304104dSAndroid Build Coastguard Worker /* If there are no members, then this is not a HFA. Errors
49*7304104dSAndroid Build Coastguard Worker are propagated. */
50*7304104dSAndroid Build Coastguard Worker return i;
51*7304104dSAndroid Build Coastguard Worker return 0;
52*7304104dSAndroid Build Coastguard Worker }
53*7304104dSAndroid Build Coastguard Worker
54*7304104dSAndroid Build Coastguard Worker static int
dwarf_bytesize_aux(Dwarf_Die * die,Dwarf_Word * sizep)55*7304104dSAndroid Build Coastguard Worker dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
56*7304104dSAndroid Build Coastguard Worker {
57*7304104dSAndroid Build Coastguard Worker int bits;
58*7304104dSAndroid Build Coastguard Worker if (((bits = 8 * dwarf_bytesize (die)) < 0
59*7304104dSAndroid Build Coastguard Worker && (bits = dwarf_bitsize (die)) < 0)
60*7304104dSAndroid Build Coastguard Worker || bits % 8 != 0)
61*7304104dSAndroid Build Coastguard Worker return -1;
62*7304104dSAndroid Build Coastguard Worker
63*7304104dSAndroid Build Coastguard Worker *sizep = bits / 8;
64*7304104dSAndroid Build Coastguard Worker return 0;
65*7304104dSAndroid Build Coastguard Worker }
66*7304104dSAndroid Build Coastguard Worker
67*7304104dSAndroid Build Coastguard Worker /* HFA (Homogeneous Floating-point Aggregate) is an aggregate type
68*7304104dSAndroid Build Coastguard Worker whose members are all of the same floating-point type, which is
69*7304104dSAndroid Build Coastguard Worker then base type of this HFA. Instead of being floating-point types
70*7304104dSAndroid Build Coastguard Worker directly, members can instead themselves be HFA. Such HFA fields
71*7304104dSAndroid Build Coastguard Worker are handled as if their type were HFA base type.
72*7304104dSAndroid Build Coastguard Worker
73*7304104dSAndroid Build Coastguard Worker This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if
74*7304104dSAndroid Build Coastguard Worker there were errors. In the former case, *SIZEP contains byte size
75*7304104dSAndroid Build Coastguard Worker of the base type (e.g. 8 for IEEE double). *COUNT is set to the
76*7304104dSAndroid Build Coastguard Worker number of leaf members of the HFA. */
77*7304104dSAndroid Build Coastguard Worker static int hfa_type (Dwarf_Die *ftypedie, int tag,
78*7304104dSAndroid Build Coastguard Worker Dwarf_Word *sizep, Dwarf_Word *countp);
79*7304104dSAndroid Build Coastguard Worker
80*7304104dSAndroid Build Coastguard Worker /* Return 0 if MEMBDIE refers to a member with a floating-point or HFA
81*7304104dSAndroid Build Coastguard Worker type, or 1 if it's not. Return -1 for errors. The meaning of the
82*7304104dSAndroid Build Coastguard Worker remaining arguments is as documented at hfa_type. */
83*7304104dSAndroid Build Coastguard Worker static int
member_is_fp(Dwarf_Die * membdie,Dwarf_Word * sizep,Dwarf_Word * countp)84*7304104dSAndroid Build Coastguard Worker member_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp)
85*7304104dSAndroid Build Coastguard Worker {
86*7304104dSAndroid Build Coastguard Worker Dwarf_Die typedie;
87*7304104dSAndroid Build Coastguard Worker int tag = dwarf_peeled_die_type (membdie, &typedie);
88*7304104dSAndroid Build Coastguard Worker switch (tag)
89*7304104dSAndroid Build Coastguard Worker {
90*7304104dSAndroid Build Coastguard Worker case DW_TAG_base_type:;
91*7304104dSAndroid Build Coastguard Worker Dwarf_Word encoding;
92*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem;
93*7304104dSAndroid Build Coastguard Worker if (dwarf_attr_integrate (&typedie, DW_AT_encoding, &attr_mem) == NULL
94*7304104dSAndroid Build Coastguard Worker || dwarf_formudata (&attr_mem, &encoding) != 0)
95*7304104dSAndroid Build Coastguard Worker return -1;
96*7304104dSAndroid Build Coastguard Worker
97*7304104dSAndroid Build Coastguard Worker switch (encoding)
98*7304104dSAndroid Build Coastguard Worker {
99*7304104dSAndroid Build Coastguard Worker case DW_ATE_complex_float:
100*7304104dSAndroid Build Coastguard Worker *countp = 2;
101*7304104dSAndroid Build Coastguard Worker break;
102*7304104dSAndroid Build Coastguard Worker
103*7304104dSAndroid Build Coastguard Worker case DW_ATE_float:
104*7304104dSAndroid Build Coastguard Worker *countp = 1;
105*7304104dSAndroid Build Coastguard Worker break;
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker default:
108*7304104dSAndroid Build Coastguard Worker return 1;
109*7304104dSAndroid Build Coastguard Worker }
110*7304104dSAndroid Build Coastguard Worker
111*7304104dSAndroid Build Coastguard Worker if (dwarf_bytesize_aux (&typedie, sizep) < 0)
112*7304104dSAndroid Build Coastguard Worker return -1;
113*7304104dSAndroid Build Coastguard Worker
114*7304104dSAndroid Build Coastguard Worker *sizep /= *countp;
115*7304104dSAndroid Build Coastguard Worker return 0;
116*7304104dSAndroid Build Coastguard Worker
117*7304104dSAndroid Build Coastguard Worker case DW_TAG_structure_type:
118*7304104dSAndroid Build Coastguard Worker case DW_TAG_union_type:
119*7304104dSAndroid Build Coastguard Worker case DW_TAG_array_type:
120*7304104dSAndroid Build Coastguard Worker return hfa_type (&typedie, tag, sizep, countp);
121*7304104dSAndroid Build Coastguard Worker }
122*7304104dSAndroid Build Coastguard Worker
123*7304104dSAndroid Build Coastguard Worker return 1;
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker
126*7304104dSAndroid Build Coastguard Worker static int
hfa_type(Dwarf_Die * ftypedie,int tag,Dwarf_Word * sizep,Dwarf_Word * countp)127*7304104dSAndroid Build Coastguard Worker hfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp)
128*7304104dSAndroid Build Coastguard Worker {
129*7304104dSAndroid Build Coastguard Worker assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type
130*7304104dSAndroid Build Coastguard Worker || tag == DW_TAG_union_type || tag == DW_TAG_array_type);
131*7304104dSAndroid Build Coastguard Worker
132*7304104dSAndroid Build Coastguard Worker int i;
133*7304104dSAndroid Build Coastguard Worker if (tag == DW_TAG_array_type)
134*7304104dSAndroid Build Coastguard Worker {
135*7304104dSAndroid Build Coastguard Worker Dwarf_Word tot_size;
136*7304104dSAndroid Build Coastguard Worker if (dwarf_aggregate_size (ftypedie, &tot_size) < 0)
137*7304104dSAndroid Build Coastguard Worker return -1;
138*7304104dSAndroid Build Coastguard Worker
139*7304104dSAndroid Build Coastguard Worker /* For vector types, we don't care about the underlying
140*7304104dSAndroid Build Coastguard Worker type, but only about the vector type itself. */
141*7304104dSAndroid Build Coastguard Worker bool vec;
142*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem;
143*7304104dSAndroid Build Coastguard Worker if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector,
144*7304104dSAndroid Build Coastguard Worker &attr_mem), &vec) == 0
145*7304104dSAndroid Build Coastguard Worker && vec)
146*7304104dSAndroid Build Coastguard Worker {
147*7304104dSAndroid Build Coastguard Worker *sizep = tot_size;
148*7304104dSAndroid Build Coastguard Worker *countp = 1;
149*7304104dSAndroid Build Coastguard Worker
150*7304104dSAndroid Build Coastguard Worker return 0;
151*7304104dSAndroid Build Coastguard Worker }
152*7304104dSAndroid Build Coastguard Worker
153*7304104dSAndroid Build Coastguard Worker if ((i = member_is_fp (ftypedie, sizep, countp)) == 0)
154*7304104dSAndroid Build Coastguard Worker {
155*7304104dSAndroid Build Coastguard Worker *countp = tot_size / *sizep;
156*7304104dSAndroid Build Coastguard Worker return 0;
157*7304104dSAndroid Build Coastguard Worker }
158*7304104dSAndroid Build Coastguard Worker
159*7304104dSAndroid Build Coastguard Worker return i;
160*7304104dSAndroid Build Coastguard Worker }
161*7304104dSAndroid Build Coastguard Worker
162*7304104dSAndroid Build Coastguard Worker /* Find first DW_TAG_member and determine its type. */
163*7304104dSAndroid Build Coastguard Worker Dwarf_Die member;
164*7304104dSAndroid Build Coastguard Worker if ((i = dwarf_child (ftypedie, &member) != 0))
165*7304104dSAndroid Build Coastguard Worker return i;
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker if ((i = skip_until (&member, DW_TAG_member)) != 0)
168*7304104dSAndroid Build Coastguard Worker return i;
169*7304104dSAndroid Build Coastguard Worker
170*7304104dSAndroid Build Coastguard Worker *countp = 0;
171*7304104dSAndroid Build Coastguard Worker if ((i = member_is_fp (&member, sizep, countp)) != 0)
172*7304104dSAndroid Build Coastguard Worker return i;
173*7304104dSAndroid Build Coastguard Worker
174*7304104dSAndroid Build Coastguard Worker while ((i = dwarf_siblingof (&member, &member)) == 0
175*7304104dSAndroid Build Coastguard Worker && (i = skip_until (&member, DW_TAG_member)) == 0)
176*7304104dSAndroid Build Coastguard Worker {
177*7304104dSAndroid Build Coastguard Worker Dwarf_Word size, count;
178*7304104dSAndroid Build Coastguard Worker if ((i = member_is_fp (&member, &size, &count)) != 0)
179*7304104dSAndroid Build Coastguard Worker return i;
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker if (*sizep != size)
182*7304104dSAndroid Build Coastguard Worker return 1;
183*7304104dSAndroid Build Coastguard Worker
184*7304104dSAndroid Build Coastguard Worker *countp += count;
185*7304104dSAndroid Build Coastguard Worker }
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker /* At this point we already have at least one FP member, which means
188*7304104dSAndroid Build Coastguard Worker FTYPEDIE is an HFA. So either return 0, or propagate error. */
189*7304104dSAndroid Build Coastguard Worker return i < 0 ? i : 0;
190*7304104dSAndroid Build Coastguard Worker }
191*7304104dSAndroid Build Coastguard Worker
192*7304104dSAndroid Build Coastguard Worker static int
pass_in_gpr(const Dwarf_Op ** locp,Dwarf_Word size)193*7304104dSAndroid Build Coastguard Worker pass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size)
194*7304104dSAndroid Build Coastguard Worker {
195*7304104dSAndroid Build Coastguard Worker static const Dwarf_Op loc[] =
196*7304104dSAndroid Build Coastguard Worker {
197*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
198*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 }
199*7304104dSAndroid Build Coastguard Worker };
200*7304104dSAndroid Build Coastguard Worker
201*7304104dSAndroid Build Coastguard Worker *locp = loc;
202*7304104dSAndroid Build Coastguard Worker return size <= 8 ? 1 : 4;
203*7304104dSAndroid Build Coastguard Worker }
204*7304104dSAndroid Build Coastguard Worker
205*7304104dSAndroid Build Coastguard Worker static int
pass_by_ref(const Dwarf_Op ** locp)206*7304104dSAndroid Build Coastguard Worker pass_by_ref (const Dwarf_Op **locp)
207*7304104dSAndroid Build Coastguard Worker {
208*7304104dSAndroid Build Coastguard Worker static const Dwarf_Op loc[] = { { .atom = DW_OP_breg0 } };
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker *locp = loc;
211*7304104dSAndroid Build Coastguard Worker return 1;
212*7304104dSAndroid Build Coastguard Worker }
213*7304104dSAndroid Build Coastguard Worker
214*7304104dSAndroid Build Coastguard Worker static int
pass_hfa(const Dwarf_Op ** locp,Dwarf_Word size,Dwarf_Word count)215*7304104dSAndroid Build Coastguard Worker pass_hfa (const Dwarf_Op **locp, Dwarf_Word size, Dwarf_Word count)
216*7304104dSAndroid Build Coastguard Worker {
217*7304104dSAndroid Build Coastguard Worker assert (count >= 1 && count <= 4);
218*7304104dSAndroid Build Coastguard Worker assert (size == 2 || size == 4 || size == 8 || size == 16);
219*7304104dSAndroid Build Coastguard Worker
220*7304104dSAndroid Build Coastguard Worker #define DEFINE_FPREG(NAME, SIZE) \
221*7304104dSAndroid Build Coastguard Worker static const Dwarf_Op NAME[] = { \
222*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_regx, .number = 64 }, \
223*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_piece, .number = SIZE }, \
224*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_regx, .number = 65 }, \
225*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_piece, .number = SIZE }, \
226*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_regx, .number = 66 }, \
227*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_piece, .number = SIZE }, \
228*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_regx, .number = 67 }, \
229*7304104dSAndroid Build Coastguard Worker { .atom = DW_OP_piece, .number = SIZE } \
230*7304104dSAndroid Build Coastguard Worker }
231*7304104dSAndroid Build Coastguard Worker
232*7304104dSAndroid Build Coastguard Worker switch (size)
233*7304104dSAndroid Build Coastguard Worker {
234*7304104dSAndroid Build Coastguard Worker case 2:;
235*7304104dSAndroid Build Coastguard Worker DEFINE_FPREG (loc_hfa_2, 2);
236*7304104dSAndroid Build Coastguard Worker *locp = loc_hfa_2;
237*7304104dSAndroid Build Coastguard Worker break;
238*7304104dSAndroid Build Coastguard Worker
239*7304104dSAndroid Build Coastguard Worker case 4:;
240*7304104dSAndroid Build Coastguard Worker DEFINE_FPREG (loc_hfa_4, 4);
241*7304104dSAndroid Build Coastguard Worker *locp = loc_hfa_4;
242*7304104dSAndroid Build Coastguard Worker break;
243*7304104dSAndroid Build Coastguard Worker
244*7304104dSAndroid Build Coastguard Worker case 8:;
245*7304104dSAndroid Build Coastguard Worker DEFINE_FPREG (loc_hfa_8, 8);
246*7304104dSAndroid Build Coastguard Worker *locp = loc_hfa_8;
247*7304104dSAndroid Build Coastguard Worker break;
248*7304104dSAndroid Build Coastguard Worker
249*7304104dSAndroid Build Coastguard Worker case 16:;
250*7304104dSAndroid Build Coastguard Worker DEFINE_FPREG (loc_hfa_16, 16);
251*7304104dSAndroid Build Coastguard Worker *locp = loc_hfa_16;
252*7304104dSAndroid Build Coastguard Worker break;
253*7304104dSAndroid Build Coastguard Worker }
254*7304104dSAndroid Build Coastguard Worker #undef DEFINE_FPREG
255*7304104dSAndroid Build Coastguard Worker
256*7304104dSAndroid Build Coastguard Worker return count == 1 ? 1 : 2 * count;
257*7304104dSAndroid Build Coastguard Worker }
258*7304104dSAndroid Build Coastguard Worker
259*7304104dSAndroid Build Coastguard Worker static int
pass_in_simd(const Dwarf_Op ** locp)260*7304104dSAndroid Build Coastguard Worker pass_in_simd (const Dwarf_Op **locp)
261*7304104dSAndroid Build Coastguard Worker {
262*7304104dSAndroid Build Coastguard Worker /* This is like passing single-element HFA. Size doesn't matter, so
263*7304104dSAndroid Build Coastguard Worker pretend it's for example double. */
264*7304104dSAndroid Build Coastguard Worker return pass_hfa (locp, 8, 1);
265*7304104dSAndroid Build Coastguard Worker }
266*7304104dSAndroid Build Coastguard Worker
267*7304104dSAndroid Build Coastguard Worker int
aarch64_return_value_location(Dwarf_Die * functypedie,const Dwarf_Op ** locp)268*7304104dSAndroid Build Coastguard Worker aarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
269*7304104dSAndroid Build Coastguard Worker {
270*7304104dSAndroid Build Coastguard Worker /* Start with the function's type, and get the DW_AT_type attribute,
271*7304104dSAndroid Build Coastguard Worker which is the type of the return value. */
272*7304104dSAndroid Build Coastguard Worker Dwarf_Die typedie;
273*7304104dSAndroid Build Coastguard Worker int tag = dwarf_peeled_die_type (functypedie, &typedie);
274*7304104dSAndroid Build Coastguard Worker if (tag <= 0)
275*7304104dSAndroid Build Coastguard Worker return tag;
276*7304104dSAndroid Build Coastguard Worker
277*7304104dSAndroid Build Coastguard Worker Dwarf_Word size = (Dwarf_Word)-1;
278*7304104dSAndroid Build Coastguard Worker
279*7304104dSAndroid Build Coastguard Worker /* If the argument type is a Composite Type that is larger than 16
280*7304104dSAndroid Build Coastguard Worker bytes, then the argument is copied to memory allocated by the
281*7304104dSAndroid Build Coastguard Worker caller and the argument is replaced by a pointer to the copy. */
282*7304104dSAndroid Build Coastguard Worker if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
283*7304104dSAndroid Build Coastguard Worker || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
284*7304104dSAndroid Build Coastguard Worker {
285*7304104dSAndroid Build Coastguard Worker Dwarf_Word base_size, count;
286*7304104dSAndroid Build Coastguard Worker switch (hfa_type (&typedie, tag, &base_size, &count))
287*7304104dSAndroid Build Coastguard Worker {
288*7304104dSAndroid Build Coastguard Worker default:
289*7304104dSAndroid Build Coastguard Worker return -1;
290*7304104dSAndroid Build Coastguard Worker
291*7304104dSAndroid Build Coastguard Worker case 0:
292*7304104dSAndroid Build Coastguard Worker assert (count > 0);
293*7304104dSAndroid Build Coastguard Worker if (count <= 4)
294*7304104dSAndroid Build Coastguard Worker return pass_hfa (locp, base_size, count);
295*7304104dSAndroid Build Coastguard Worker FALLTHROUGH;
296*7304104dSAndroid Build Coastguard Worker
297*7304104dSAndroid Build Coastguard Worker case 1:
298*7304104dSAndroid Build Coastguard Worker /* Not a HFA. */
299*7304104dSAndroid Build Coastguard Worker if (dwarf_aggregate_size (&typedie, &size) < 0)
300*7304104dSAndroid Build Coastguard Worker return -1;
301*7304104dSAndroid Build Coastguard Worker if (size > 16)
302*7304104dSAndroid Build Coastguard Worker return pass_by_ref (locp);
303*7304104dSAndroid Build Coastguard Worker }
304*7304104dSAndroid Build Coastguard Worker }
305*7304104dSAndroid Build Coastguard Worker
306*7304104dSAndroid Build Coastguard Worker if (tag == DW_TAG_base_type || dwarf_is_pointer (tag))
307*7304104dSAndroid Build Coastguard Worker {
308*7304104dSAndroid Build Coastguard Worker if (dwarf_bytesize_aux (&typedie, &size) < 0)
309*7304104dSAndroid Build Coastguard Worker {
310*7304104dSAndroid Build Coastguard Worker if (dwarf_is_pointer (tag))
311*7304104dSAndroid Build Coastguard Worker size = 8;
312*7304104dSAndroid Build Coastguard Worker else
313*7304104dSAndroid Build Coastguard Worker return -1;
314*7304104dSAndroid Build Coastguard Worker }
315*7304104dSAndroid Build Coastguard Worker
316*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem;
317*7304104dSAndroid Build Coastguard Worker if (tag == DW_TAG_base_type)
318*7304104dSAndroid Build Coastguard Worker {
319*7304104dSAndroid Build Coastguard Worker Dwarf_Word encoding;
320*7304104dSAndroid Build Coastguard Worker if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
321*7304104dSAndroid Build Coastguard Worker &attr_mem),
322*7304104dSAndroid Build Coastguard Worker &encoding) != 0)
323*7304104dSAndroid Build Coastguard Worker return -1;
324*7304104dSAndroid Build Coastguard Worker
325*7304104dSAndroid Build Coastguard Worker switch (encoding)
326*7304104dSAndroid Build Coastguard Worker {
327*7304104dSAndroid Build Coastguard Worker /* If the argument is a Half-, Single-, Double- or Quad-
328*7304104dSAndroid Build Coastguard Worker precision Floating-point [...] the argument is allocated
329*7304104dSAndroid Build Coastguard Worker to the least significant bits of register v[NSRN]. */
330*7304104dSAndroid Build Coastguard Worker case DW_ATE_float:
331*7304104dSAndroid Build Coastguard Worker switch (size)
332*7304104dSAndroid Build Coastguard Worker {
333*7304104dSAndroid Build Coastguard Worker case 2: /* half */
334*7304104dSAndroid Build Coastguard Worker case 4: /* single */
335*7304104dSAndroid Build Coastguard Worker case 8: /* double */
336*7304104dSAndroid Build Coastguard Worker case 16: /* quad */
337*7304104dSAndroid Build Coastguard Worker return pass_in_simd (locp);
338*7304104dSAndroid Build Coastguard Worker
339*7304104dSAndroid Build Coastguard Worker default:
340*7304104dSAndroid Build Coastguard Worker return -2;
341*7304104dSAndroid Build Coastguard Worker }
342*7304104dSAndroid Build Coastguard Worker
343*7304104dSAndroid Build Coastguard Worker case DW_ATE_complex_float:
344*7304104dSAndroid Build Coastguard Worker switch (size)
345*7304104dSAndroid Build Coastguard Worker {
346*7304104dSAndroid Build Coastguard Worker case 8: /* float _Complex */
347*7304104dSAndroid Build Coastguard Worker case 16: /* double _Complex */
348*7304104dSAndroid Build Coastguard Worker case 32: /* long double _Complex */
349*7304104dSAndroid Build Coastguard Worker return pass_hfa (locp, size / 2, 2);
350*7304104dSAndroid Build Coastguard Worker
351*7304104dSAndroid Build Coastguard Worker default:
352*7304104dSAndroid Build Coastguard Worker return -2;
353*7304104dSAndroid Build Coastguard Worker }
354*7304104dSAndroid Build Coastguard Worker
355*7304104dSAndroid Build Coastguard Worker /* If the argument is an Integral or Pointer Type, the
356*7304104dSAndroid Build Coastguard Worker size of the argument is less than or equal to 8 bytes
357*7304104dSAndroid Build Coastguard Worker [...] the argument is copied to the least significant
358*7304104dSAndroid Build Coastguard Worker bits in x[NGRN]. */
359*7304104dSAndroid Build Coastguard Worker case DW_ATE_boolean:
360*7304104dSAndroid Build Coastguard Worker case DW_ATE_signed:
361*7304104dSAndroid Build Coastguard Worker case DW_ATE_unsigned:
362*7304104dSAndroid Build Coastguard Worker case DW_ATE_unsigned_char:
363*7304104dSAndroid Build Coastguard Worker case DW_ATE_signed_char:
364*7304104dSAndroid Build Coastguard Worker return pass_in_gpr (locp, size);
365*7304104dSAndroid Build Coastguard Worker }
366*7304104dSAndroid Build Coastguard Worker
367*7304104dSAndroid Build Coastguard Worker return -2;
368*7304104dSAndroid Build Coastguard Worker }
369*7304104dSAndroid Build Coastguard Worker else
370*7304104dSAndroid Build Coastguard Worker return pass_in_gpr (locp, size);
371*7304104dSAndroid Build Coastguard Worker }
372*7304104dSAndroid Build Coastguard Worker
373*7304104dSAndroid Build Coastguard Worker *locp = NULL;
374*7304104dSAndroid Build Coastguard Worker return 0;
375*7304104dSAndroid Build Coastguard Worker }
376