1000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata/*
2000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * This file is part of ltrace.
37e3f650f22b7161f897532aad808d3b8f61fd6f4Petr Machata * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
4000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * Copyright (C) 2007,2008 Juan Cespedes
5000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata *
6000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * This program is free software; you can redistribute it and/or
7000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * modify it under the terms of the GNU General Public License as
8000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * published by the Free Software Foundation; either version 2 of the
9000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * License, or (at your option) any later version.
10000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata *
11000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * This program is distributed in the hope that it will be useful, but
12000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
13000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * General Public License for more details.
15000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata *
16000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * You should have received a copy of the GNU General Public License
17000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * along with this program; if not, write to the Free Software
18000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * 02110-1301 USA
20000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata */
21000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
22000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include <assert.h>
23000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include <stdlib.h>
24c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata#include <limits.h>
25000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
26000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include "type.h"
27000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#include "sysdep.h"
2894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata#include "expr.h"
2931af32cfcd61671cbb5e567870103766b3231521Petr Machata#include "lens.h"
30000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
31000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastruct arg_type_info *
32000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_get_simple(enum arg_type type)
33000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
34000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#define HANDLE(T) {					\
35000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		static struct arg_type_info t = { T };	\
36000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case T:						\
37000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return &t;				\
38000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
39000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
40000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (type) {
41000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_VOID)
42000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_INT)
43000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_UINT)
44000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_LONG)
45000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_ULONG)
46000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_CHAR)
47000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_SHORT)
48000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_USHORT)
49000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_FLOAT)
50000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	HANDLE(ARGTYPE_DOUBLE)
51000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
52000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#undef HANDLE
53000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
54000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
55000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
56000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_POINTER:
57000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		assert(!"Not a simple type!");
58000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	};
59000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	abort();
60000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
61000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
62c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machatastruct arg_type_info *
63c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machatatype_get_voidptr(void)
64c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata{
65c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	struct arg_type_info *void_info = type_get_simple(ARGTYPE_VOID);
66c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	static struct arg_type_info *ret;
67c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	if (ret == NULL) {
68c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata		static struct arg_type_info ptr_info;
69c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata		type_init_pointer(&ptr_info, void_info, 0);
70c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata		ret = &ptr_info;
71c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	}
72c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	return ret;
73c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata}
74c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata
7531af32cfcd61671cbb5e567870103766b3231521Petr Machatastatic void
7631af32cfcd61671cbb5e567870103766b3231521Petr Machatatype_init_common(struct arg_type_info *info, enum arg_type type)
7731af32cfcd61671cbb5e567870103766b3231521Petr Machata{
7831af32cfcd61671cbb5e567870103766b3231521Petr Machata	info->type = type;
7931af32cfcd61671cbb5e567870103766b3231521Petr Machata	info->lens = NULL;
8031af32cfcd61671cbb5e567870103766b3231521Petr Machata	info->own_lens = 0;
8131af32cfcd61671cbb5e567870103766b3231521Petr Machata}
8231af32cfcd61671cbb5e567870103766b3231521Petr Machata
83000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastruct struct_field {
84000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct arg_type_info *info;
85000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	int own_info;
86000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata};
87000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
88000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatavoid
89000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_init_struct(struct arg_type_info *info)
90000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
9131af32cfcd61671cbb5e567870103766b3231521Petr Machata	type_init_common(info, ARGTYPE_STRUCT);
92000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	VECT_INIT(&info->u.entries, struct struct_field);
93000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
94000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
95000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machataint
96000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_struct_add(struct arg_type_info *info,
97000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		struct arg_type_info *field_info, int own)
98000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
99000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(info->type == ARGTYPE_STRUCT);
100000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct struct_field field = { field_info, own };
101000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return VECT_PUSHBACK(&info->u.entries, &field);
102000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
103000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
104000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastruct arg_type_info *
105000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_struct_get(struct arg_type_info *info, size_t idx)
106000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
107000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(info->type == ARGTYPE_STRUCT);
1087e3f650f22b7161f897532aad808d3b8f61fd6f4Petr Machata	return VECT_ELEMENT(&info->u.entries, struct struct_field, idx)->info;
109000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
110000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
111000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
112000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_struct_size(struct arg_type_info *info)
113000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
114000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(info->type == ARGTYPE_STRUCT);
115000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return vect_size(&info->u.entries);
116000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
117000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
118000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastatic void
119000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastruct_field_dtor(struct struct_field *field, void *data)
120000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
121000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (field->own_info) {
122000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_destroy(field->info);
123000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		free(field->info);
124000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
125000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
126000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
127000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastatic void
128000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_struct_destroy(struct arg_type_info *info)
129000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
130000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	VECT_DESTROY(&info->u.entries, struct struct_field,
131000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		     struct_field_dtor, NULL);
132000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
133000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
134000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastatic int
135929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatalayout_struct(struct process *proc, struct arg_type_info *info,
136000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	      size_t *sizep, size_t *alignmentp, size_t *offsetofp)
137000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
138000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t sz = 0;
139000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t max_alignment = 0;
140000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t i;
141000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t offsetof_field = (size_t)-1;
142000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (offsetofp != NULL)
143000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		offsetof_field = *offsetofp;
144000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
145000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(info->type == ARGTYPE_STRUCT);
146000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	for (i = 0; i < vect_size(&info->u.entries); ++i) {
147000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		struct struct_field *field
148000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			= VECT_ELEMENT(&info->u.entries,
149000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata				       struct struct_field, i);
150000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
151000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t alignment = type_alignof(proc, field->info);
152000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (alignment == (size_t)-1)
153000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return -1;
154000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
155000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		/* Add padding to SZ to align the next element.  */
156000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		sz = align(sz, alignment);
157000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (i == offsetof_field) {
158000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			*offsetofp = sz;
159000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			if (sizep == NULL && alignmentp == NULL)
160000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata				return 0;
161000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		}
162000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
163000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t size = type_sizeof(proc, field->info);
164000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (size == (size_t)-1)
165000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return -1;
166000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		sz += size;
167000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
168000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (alignment > max_alignment)
169000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			max_alignment = alignment;
170000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
171000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
172000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (max_alignment > 0)
173000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		sz = align(sz, max_alignment);
174000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
175000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (sizep != NULL)
176000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		*sizep = sz;
177000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
178000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (alignmentp != NULL)
179000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		*alignmentp = max_alignment;
180000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
181000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return 0;
182000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
183000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
184000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatavoid
185000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_init_array(struct arg_type_info *info,
186000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		struct arg_type_info *element_info, int own_info,
187940ec0650bfe0f1deda96d3561be3d0006df92fcPetr Machata		struct expr_node *length_expr, int own_length)
188000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
18931af32cfcd61671cbb5e567870103766b3231521Petr Machata	type_init_common(info, ARGTYPE_ARRAY);
190000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	info->u.array_info.elt_type = element_info;
191000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	info->u.array_info.own_info = own_info;
192940ec0650bfe0f1deda96d3561be3d0006df92fcPetr Machata	info->u.array_info.length = length_expr;
19394078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata	info->u.array_info.own_length = own_length;
194000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
195000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
196000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastatic void
197000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_array_destroy(struct arg_type_info *info)
198000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
199000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (info->u.array_info.own_info) {
200000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_destroy(info->u.array_info.elt_type);
201000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		free(info->u.array_info.elt_type);
202000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
203000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (info->u.array_info.own_length) {
204000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		expr_destroy(info->u.array_info.length);
205000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		free(info->u.array_info.length);
206000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
20794078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata}
20894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata
209000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatavoid
210000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_init_pointer(struct arg_type_info *info,
211000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		  struct arg_type_info *pointee_info, int own_info)
212000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
21331af32cfcd61671cbb5e567870103766b3231521Petr Machata	type_init_common(info, ARGTYPE_POINTER);
214000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	info->u.ptr_info.info = pointee_info;
215000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	info->u.ptr_info.own_info = own_info;
216000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
217000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
218000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastatic void
219000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_pointer_destroy(struct arg_type_info *info)
220000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
221000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (info->u.ptr_info.own_info) {
222000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_destroy(info->u.ptr_info.info);
223000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		free(info->u.ptr_info.info);
224000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
225000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
226000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
227000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatavoid
228000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_destroy(struct arg_type_info *info)
229000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
230000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (info == NULL)
231000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return;
232000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
233000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (info->type) {
234000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
235000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_struct_destroy(info);
236000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		break;
237000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
238000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
239000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_array_destroy(info);
240000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		break;
241000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
242000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_POINTER:
243000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		type_pointer_destroy(info);
244000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		break;
245000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
246000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_VOID:
247000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_INT:
248000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_UINT:
249000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_LONG:
250000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ULONG:
251000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_CHAR:
252000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_SHORT:
253000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_USHORT:
254000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_FLOAT:
255000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_DOUBLE:
256000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		break;
257000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
25831af32cfcd61671cbb5e567870103766b3231521Petr Machata
25931af32cfcd61671cbb5e567870103766b3231521Petr Machata	if (info->own_lens) {
26031af32cfcd61671cbb5e567870103766b3231521Petr Machata		lens_destroy(info->lens);
26131af32cfcd61671cbb5e567870103766b3231521Petr Machata		free(info->lens);
26231af32cfcd61671cbb5e567870103766b3231521Petr Machata	}
263000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
264000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
265cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machatastatic int
266cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machatatype_alloc_and_clone(struct arg_type_info **retpp,
267cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		     struct arg_type_info *info, int own)
268cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata{
269cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	*retpp = info;
270cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	if (own) {
271cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		*retpp = malloc(sizeof **retpp);
272cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (*retpp == NULL || type_clone(*retpp, info) < 0) {
273cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			free(*retpp);
274cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			return -1;
275cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		}
276cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	}
277cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	return 0;
278cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata}
279cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
280cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machatastatic enum callback_status
281cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machataclone_struct_add_field(const struct struct_field *field, void *data)
282cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata{
283cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	struct arg_type_info *retp = data;
284cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	struct arg_type_info *info;
285cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	if (type_alloc_and_clone(&info, field->info, field->own_info) < 0) {
286cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	fail:
287cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (info != field->info)
288cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			free(info);
289cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		return CBS_STOP;
290cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	}
291cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
292cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	if (type_struct_add(retp, info, field->own_info) < 0) {
293cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (field->own_info)
294cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			type_destroy(info);
295cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		goto fail;
296cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	}
297cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
298cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	return CBS_CONT;
299cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata}
300cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
301cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machataint
302cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machatatype_clone(struct arg_type_info *retp, const struct arg_type_info *info)
303cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata{
304cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	switch (info->type) {
305cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_STRUCT:
306cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		type_init_struct(retp);
307cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (VECT_EACH_CST(&info->u.entries, struct struct_field, NULL,
308cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata				  clone_struct_add_field, retp) != NULL) {
309cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			type_destroy(retp);
310cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			return -1;
311cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		}
312cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		break;
313cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
314cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_ARRAY:;
315cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		struct arg_type_info *elt_type;
316cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (type_alloc_and_clone(&elt_type, info->u.array_info.elt_type,
317cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata					 info->u.array_info.own_info) < 0)
318cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			return -1;
319cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
320cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		assert(!info->u.array_info.own_length); // XXXXXXX
321cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		type_init_array(retp, elt_type, info->u.array_info.own_info,
322cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata				info->u.array_info.length,
323cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata				info->u.array_info.own_length);
324cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		break;
325cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
326cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_POINTER:;
327cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		struct arg_type_info *ninfo;
328cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		if (type_alloc_and_clone(&ninfo, info->u.ptr_info.info,
329cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata					 info->u.ptr_info.own_info) < 0)
330cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata			return -1;
331cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		type_init_pointer(retp, ninfo, info->u.ptr_info.own_info);
332cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		break;
333cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
334cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_VOID:
335cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_INT:
336cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_UINT:
337cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_LONG:
338cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_ULONG:
339cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_CHAR:
340cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_SHORT:
341cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_USHORT:
342cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_FLOAT:
343cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	case ARGTYPE_DOUBLE:
344cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		*retp = *info;
345cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata		break;
346cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	}
347cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
348cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	assert(!info->own_lens);
349cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	retp->lens = info->lens;
350cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	retp->own_lens = info->own_lens;
351cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata	return 0;
352cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata}
353cd6ff36657ef51369f72fe109d581bc2530be5f2Petr Machata
354000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#ifdef ARCH_HAVE_SIZEOF
355929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasize_t arch_type_sizeof(struct process *proc, struct arg_type_info *arg);
356000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#else
357000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
358929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_type_sizeof(struct process *proc, struct arg_type_info *arg)
359000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
360000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	/* Use default value.  */
361000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return (size_t)-2;
362000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
363000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#endif
364000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
365000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#ifdef ARCH_HAVE_ALIGNOF
366929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasize_t arch_type_alignof(struct process *proc, struct arg_type_info *arg);
367000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#else
368000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
369929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_type_alignof(struct process *proc, struct arg_type_info *arg)
370000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
371000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	/* Use default value.  */
372000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return (size_t)-2;
373000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
374000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#endif
375000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
376000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata/* We need to support alignments that are not power of two.  E.g. long
377000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata * double on x86 has alignment of 12.  */
378000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
379000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machataalign(size_t sz, size_t alignment)
380000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
381000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(alignment != 0);
382000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
383000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if ((sz % alignment) != 0)
384000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		sz = ((sz / alignment) + 1) * alignment;
385000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
386000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	return sz;
387000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
388000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
389000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
390929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatatype_sizeof(struct process *proc, struct arg_type_info *type)
391000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
392000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t arch_size = arch_type_sizeof(proc, type);
393000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (arch_size != (size_t)-2)
394000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return arch_size;
395000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
396000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (type->type) {
397000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t size;
398000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_CHAR:
399000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(char);
400000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
401000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_SHORT:
402000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_USHORT:
403000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(short);
404000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
405000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_INT:
406000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_UINT:
407000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(int);
408000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
409000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_LONG:
410000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ULONG:
411000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(long);
412000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
413000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_FLOAT:
414000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(float);
415000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
416000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_DOUBLE:
417000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(double);
418000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
419000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
420000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (layout_struct(proc, type, &size, NULL, NULL) < 0)
421000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return (size_t)-1;
422000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return size;
423000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
424000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_POINTER:
425000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return sizeof(void *);
426000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
427000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
42894078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata		if (expr_is_compile_constant(type->u.array_info.length)) {
429000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			long l;
43094078ecce3a103c28457e6f90f1e5b0dacc61146Petr Machata			if (expr_eval_constant(type->u.array_info.length,
431000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata					       &l) < 0)
432000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata				return -1;
433000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
434000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			struct arg_type_info *elt_ti
435000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata				= type->u.array_info.elt_type;
436000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
437000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			size_t elt_size = type_sizeof(proc, elt_ti);
438000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			if (elt_size == (size_t)-1)
439000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata				return (size_t)-1;
440000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
441000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return ((size_t)l) * elt_size;
442000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
443000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		} else {
444000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			/* Flexible arrays don't count into the
445000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			 * sizeof.  */
446000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return 0;
447000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		}
448000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
449000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_VOID:
450000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return 0;
451000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
452000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
453000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	abort();
454000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
455000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
456000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#undef alignof
457000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata#define alignof(field,st) ((size_t) ((char*) &st.field - (char*) &st))
458000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
459000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
460929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatatype_alignof(struct process *proc, struct arg_type_info *type)
461000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
462000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	size_t arch_alignment = arch_type_alignof(proc, type);
463000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	if (arch_alignment != (size_t)-2)
464000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return arch_alignment;
465000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
466000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; char C; } cC;
467000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; short s; } cs;
468000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; int i; } ci;
469000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; long l; } cl;
470000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; void* p; } cp;
471000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; float f; } cf;
472000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	struct { char c; double d; } cd;
473000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
474000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t char_alignment = alignof(C, cC);
475000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t short_alignment = alignof(s, cs);
476000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t int_alignment = alignof(i, ci);
477000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t long_alignment = alignof(l, cl);
478000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t ptr_alignment = alignof(p, cp);
479000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t float_alignment = alignof(f, cf);
480000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	static size_t double_alignment = alignof(d, cd);
481000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
482000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (type->type) {
483000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t alignment;
484000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_LONG:
485000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ULONG:
486000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return long_alignment;
487000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_CHAR:
488000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return char_alignment;
489000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_SHORT:
490000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_USHORT:
491000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return short_alignment;
492000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_FLOAT:
493000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return float_alignment;
494000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_DOUBLE:
495000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return double_alignment;
496000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_POINTER:
497000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return ptr_alignment;
498000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
499000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
500000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return type_alignof(proc, type->u.array_info.elt_type);
501000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
502000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
503000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (layout_struct(proc, type, NULL, &alignment, NULL) < 0)
504000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return (size_t)-1;
505000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return alignment;
506000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
507000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	default:
508000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return int_alignment;
509000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
510000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
511000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
512000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatasize_t
513929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatatype_offsetof(struct process *proc, struct arg_type_info *type, size_t emt)
514000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
515000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(type->type == ARGTYPE_STRUCT
516e3f4a984db115979e09414b7281da98399dd8949Petr Machata	       || type->type == ARGTYPE_ARRAY);
517000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
518000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (type->type) {
519000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t alignment;
520000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size_t size;
521000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
522000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		alignment = type_alignof(proc, type->u.array_info.elt_type);
523000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (alignment == (size_t)-1)
524000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return (size_t)-1;
525000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
526000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		size = type_sizeof(proc, type->u.array_info.elt_type);
527000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (size == (size_t)-1)
528000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return (size_t)-1;
529000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
530000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return emt * align(size, alignment);
531000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
532000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
533000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		if (layout_struct(proc, type, NULL, NULL, &emt) < 0)
534000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata			return (size_t)-1;
535000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return emt;
536000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
537000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	default:
538e3f4a984db115979e09414b7281da98399dd8949Petr Machata		abort();
539000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
540000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
541000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
542000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatastruct arg_type_info *
543000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatatype_element(struct arg_type_info *info, size_t emt)
544000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{
545000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	assert(info->type == ARGTYPE_STRUCT
546e3f4a984db115979e09414b7281da98399dd8949Petr Machata	       || info->type == ARGTYPE_ARRAY);
547000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
548000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	switch (info->type) {
549000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_ARRAY:
550000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return info->u.array_info.elt_type;
551000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
552000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	case ARGTYPE_STRUCT:
553000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		assert(emt < type_struct_size(info));
554000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata		return type_struct_get(info, emt);
555000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata
556000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	default:
557e3f4a984db115979e09414b7281da98399dd8949Petr Machata		abort();
558000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata	}
559000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata}
560c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
56164d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machatasize_t
56264d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machatatype_aggregate_size(struct arg_type_info *info)
56364d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata{
56464d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	assert(info->type == ARGTYPE_STRUCT
56564d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	       || info->type == ARGTYPE_ARRAY);
56664d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata
56764d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	switch (info->type) {
56864d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata		long ret;
56964d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	case ARGTYPE_ARRAY:
57064d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata		if (expr_eval_constant(info->u.array_info.length, &ret) < 0)
57164d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata			return (size_t)-1;
57264d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata		return (size_t)ret;
57364d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata
57464d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	case ARGTYPE_STRUCT:
57564d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata		return type_struct_size(info);
57664d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata
57764d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	default:
57864d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata		abort();
57964d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata	}
58064d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata}
58164d6e060aa1d4607e766e40825bd9c9d13e8e1a4Petr Machata
582c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machataint
583c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machatatype_is_integral(enum arg_type type)
584c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata{
585c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	switch (type) {
586c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_INT:
587c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_UINT:
588c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_LONG:
589c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_ULONG:
590c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_CHAR:
591c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_SHORT:
592c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_USHORT:
593c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		return 1;
594c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
595c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_VOID:
596c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_FLOAT:
597c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_DOUBLE:
598c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_ARRAY:
599c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_STRUCT:
600c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_POINTER:
601c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		return 0;
602c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	}
603c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	abort();
604c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata}
605c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
606c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machataint
607c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machatatype_is_signed(enum arg_type type)
608c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata{
609c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	assert(type_is_integral(type));
610c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
611c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	switch (type) {
612c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_CHAR:
613c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		return CHAR_MIN != 0;
614c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
615c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_SHORT:
616c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_INT:
617c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_LONG:
618c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		return 1;
619c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
620c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_UINT:
621c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_ULONG:
622c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_USHORT:
623c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		return 0;
624c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata
625c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_VOID:
626c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_FLOAT:
627c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_DOUBLE:
628c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_ARRAY:
629c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_STRUCT:
630c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	case ARGTYPE_POINTER:
631c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata		abort();
632c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	}
633c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata	abort();
634c07a26a8d0f86bc4137eb7b7fea8bbf9021275f1Petr Machata}
635fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata
636fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machatastruct arg_type_info *
637fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machatatype_get_fp_equivalent(struct arg_type_info *info)
638fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata{
639fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	/* Extract innermost structure.  Give up early if any
640fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	 * component has more than one element.  */
641fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	while (info->type == ARGTYPE_STRUCT) {
642fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		if (type_struct_size(info) != 1)
643fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata			return NULL;
644fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		info = type_element(info, 0);
645fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	}
646fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata
647fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	switch (info->type) {
648fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_CHAR:
649fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_SHORT:
650fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_INT:
651fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_LONG:
652fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_UINT:
653fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_ULONG:
654fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_USHORT:
655fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_VOID:
656fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_ARRAY:
657fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_POINTER:
658fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		return NULL;
659fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata
660fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_FLOAT:
661fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_DOUBLE:
662fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		return info;
663fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata
664fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	case ARGTYPE_STRUCT:
665fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata		abort();
666fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	}
667fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata	abort();
668fcf256ceeab4b0b74cf1e18122e894aafce94fdcPetr Machata}
669982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata
670982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machatastruct arg_type_info *
671982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machatatype_get_hfa_type(struct arg_type_info *info, size_t *countp)
672982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata{
673982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	assert(info != NULL);
674982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	if (info->type != ARGTYPE_STRUCT
675982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	    && info->type != ARGTYPE_ARRAY)
676982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		return NULL;
677982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata
678982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	size_t n = type_aggregate_size(info);
679982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	if (n == (size_t)-1)
680982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		return NULL;
681982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata
682982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	struct arg_type_info *ret = NULL;
683982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	*countp = 0;
684982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata
685982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	while (n-- > 0) {
686982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		struct arg_type_info *emt = type_element(info, n);
687982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata
688982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		size_t emt_count = 1;
689982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		if (emt->type == ARGTYPE_STRUCT || emt->type == ARGTYPE_ARRAY)
690982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			emt = type_get_hfa_type(emt, &emt_count);
691982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		if (emt == NULL)
692982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			return NULL;
693982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		if (ret == NULL) {
694982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			if (emt->type != ARGTYPE_FLOAT
695982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			    && emt->type != ARGTYPE_DOUBLE)
696982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata				return NULL;
697982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			ret = emt;
698982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		}
699982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		if (emt->type != ret->type)
700982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata			return NULL;
701982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata		*countp += emt_count;
702982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	}
703982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata	return ret;
704982cbca34b2b49a158086ff5f43eb9bba89edeadPetr Machata}
705