xref: /freebsd-src/cddl/contrib/opensolaris/tools/ctf/cvt/tdata.c (revision 1673e4046da975ab0e2bf67d45499930ebab0dbe)
1*1673e404SJohn Birrell /*
2*1673e404SJohn Birrell  * CDDL HEADER START
3*1673e404SJohn Birrell  *
4*1673e404SJohn Birrell  * The contents of this file are subject to the terms of the
5*1673e404SJohn Birrell  * Common Development and Distribution License (the "License").
6*1673e404SJohn Birrell  * You may not use this file except in compliance with the License.
7*1673e404SJohn Birrell  *
8*1673e404SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1673e404SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
10*1673e404SJohn Birrell  * See the License for the specific language governing permissions
11*1673e404SJohn Birrell  * and limitations under the License.
12*1673e404SJohn Birrell  *
13*1673e404SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
14*1673e404SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1673e404SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
16*1673e404SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
17*1673e404SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1673e404SJohn Birrell  *
19*1673e404SJohn Birrell  * CDDL HEADER END
20*1673e404SJohn Birrell  */
21*1673e404SJohn Birrell /*
22*1673e404SJohn Birrell  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*1673e404SJohn Birrell  * Use is subject to license terms.
24*1673e404SJohn Birrell  */
25*1673e404SJohn Birrell 
26*1673e404SJohn Birrell #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*1673e404SJohn Birrell 
28*1673e404SJohn Birrell /*
29*1673e404SJohn Birrell  * Routines for manipulating tdesc and tdata structures
30*1673e404SJohn Birrell  */
31*1673e404SJohn Birrell 
32*1673e404SJohn Birrell #include <stdio.h>
33*1673e404SJohn Birrell #include <stdlib.h>
34*1673e404SJohn Birrell #include <strings.h>
35*1673e404SJohn Birrell #include <pthread.h>
36*1673e404SJohn Birrell 
37*1673e404SJohn Birrell #include "ctftools.h"
38*1673e404SJohn Birrell #include "memory.h"
39*1673e404SJohn Birrell #include "traverse.h"
40*1673e404SJohn Birrell 
41*1673e404SJohn Birrell /*
42*1673e404SJohn Birrell  * The layout hash is used during the equivalency checking.  We have a node in
43*1673e404SJohn Birrell  * the child graph that may be equivalent to a node in the parent graph.  To
44*1673e404SJohn Birrell  * find the corresponding node (if any) in the parent, we need a quick way to
45*1673e404SJohn Birrell  * get to all nodes in the parent that look like the node in the child.  Since a
46*1673e404SJohn Birrell  * large number of nodes don't have names, we need to incorporate the layout of
47*1673e404SJohn Birrell  * the node into the hash.  If we don't, we'll end up with the vast majority of
48*1673e404SJohn Birrell  * nodes in bucket zero, with one or two nodes in each of the remaining buckets.
49*1673e404SJohn Birrell  *
50*1673e404SJohn Birrell  * There are a couple of constraints, both of which concern forward
51*1673e404SJohn Birrell  * declarations.  Recall that a forward declaration tdesc is equivalent to a
52*1673e404SJohn Birrell  * tdesc that actually defines the structure or union.  As such, we cannot
53*1673e404SJohn Birrell  * incorporate anything into the hash for a named struct or union node that
54*1673e404SJohn Birrell  * couldn't be found by looking at the forward, and vice versa.
55*1673e404SJohn Birrell  */
56*1673e404SJohn Birrell int
57*1673e404SJohn Birrell tdesc_layouthash(int nbuckets, void *node)
58*1673e404SJohn Birrell {
59*1673e404SJohn Birrell 	tdesc_t *tdp = node;
60*1673e404SJohn Birrell 	char *name = NULL;
61*1673e404SJohn Birrell 	ulong_t h = 0;
62*1673e404SJohn Birrell 
63*1673e404SJohn Birrell 	if (tdp->t_name)
64*1673e404SJohn Birrell 		name = tdp->t_name;
65*1673e404SJohn Birrell 	else {
66*1673e404SJohn Birrell 		switch (tdp->t_type) {
67*1673e404SJohn Birrell 		case POINTER:
68*1673e404SJohn Birrell 		case TYPEDEF:
69*1673e404SJohn Birrell 		case VOLATILE:
70*1673e404SJohn Birrell 		case CONST:
71*1673e404SJohn Birrell 		case RESTRICT:
72*1673e404SJohn Birrell 			name = tdp->t_tdesc->t_name;
73*1673e404SJohn Birrell 			break;
74*1673e404SJohn Birrell 		case FUNCTION:
75*1673e404SJohn Birrell 			h = tdp->t_fndef->fn_nargs +
76*1673e404SJohn Birrell 			    tdp->t_fndef->fn_vargs;
77*1673e404SJohn Birrell 			name = tdp->t_fndef->fn_ret->t_name;
78*1673e404SJohn Birrell 			break;
79*1673e404SJohn Birrell 		case ARRAY:
80*1673e404SJohn Birrell 			h = tdp->t_ardef->ad_nelems;
81*1673e404SJohn Birrell 			name = tdp->t_ardef->ad_contents->t_name;
82*1673e404SJohn Birrell 			break;
83*1673e404SJohn Birrell 		case STRUCT:
84*1673e404SJohn Birrell 		case UNION:
85*1673e404SJohn Birrell 			/*
86*1673e404SJohn Birrell 			 * Unnamed structures, which cannot have forward
87*1673e404SJohn Birrell 			 * declarations pointing to them.  We can therefore
88*1673e404SJohn Birrell 			 * incorporate the name of the first member into
89*1673e404SJohn Birrell 			 * the hash value.
90*1673e404SJohn Birrell 			 */
91*1673e404SJohn Birrell 			name = tdp->t_members->ml_name;
92*1673e404SJohn Birrell 			break;
93*1673e404SJohn Birrell 		case ENUM:
94*1673e404SJohn Birrell 			/* Use the first element in the hash value */
95*1673e404SJohn Birrell 			name = tdp->t_emem->el_name;
96*1673e404SJohn Birrell 			break;
97*1673e404SJohn Birrell 		default:
98*1673e404SJohn Birrell 			/*
99*1673e404SJohn Birrell 			 * Intrinsics, forwards, and typedefs all have
100*1673e404SJohn Birrell 			 * names.
101*1673e404SJohn Birrell 			 */
102*1673e404SJohn Birrell 			warning("Unexpected unnamed %d tdesc (ID %d)\n",
103*1673e404SJohn Birrell 			    tdp->t_type, tdp->t_id);
104*1673e404SJohn Birrell 		}
105*1673e404SJohn Birrell 	}
106*1673e404SJohn Birrell 
107*1673e404SJohn Birrell 	if (name)
108*1673e404SJohn Birrell 		return (hash_name(nbuckets, name));
109*1673e404SJohn Birrell 
110*1673e404SJohn Birrell 	return (h % nbuckets);
111*1673e404SJohn Birrell }
112*1673e404SJohn Birrell 
113*1673e404SJohn Birrell int
114*1673e404SJohn Birrell tdesc_layoutcmp(void *arg1, void *arg2)
115*1673e404SJohn Birrell {
116*1673e404SJohn Birrell 	tdesc_t *tdp1 = arg1, *tdp2 = arg2;
117*1673e404SJohn Birrell 
118*1673e404SJohn Birrell 	if (tdp1->t_name == NULL) {
119*1673e404SJohn Birrell 		if (tdp2->t_name == NULL)
120*1673e404SJohn Birrell 			return (0);
121*1673e404SJohn Birrell 		else
122*1673e404SJohn Birrell 			return (-1);
123*1673e404SJohn Birrell 	} else if (tdp2->t_name == NULL)
124*1673e404SJohn Birrell 		return (1);
125*1673e404SJohn Birrell 	else
126*1673e404SJohn Birrell 		return (strcmp(tdp1->t_name, tdp2->t_name));
127*1673e404SJohn Birrell }
128*1673e404SJohn Birrell 
129*1673e404SJohn Birrell int
130*1673e404SJohn Birrell tdesc_idhash(int nbuckets, void *data)
131*1673e404SJohn Birrell {
132*1673e404SJohn Birrell 	tdesc_t *tdp = data;
133*1673e404SJohn Birrell 
134*1673e404SJohn Birrell 	return (tdp->t_id % nbuckets);
135*1673e404SJohn Birrell }
136*1673e404SJohn Birrell 
137*1673e404SJohn Birrell int
138*1673e404SJohn Birrell tdesc_idcmp(void *arg1, void *arg2)
139*1673e404SJohn Birrell {
140*1673e404SJohn Birrell 	tdesc_t *tdp1 = arg1, *tdp2 = arg2;
141*1673e404SJohn Birrell 
142*1673e404SJohn Birrell 	if (tdp1->t_id == tdp2->t_id)
143*1673e404SJohn Birrell 		return (0);
144*1673e404SJohn Birrell 	else
145*1673e404SJohn Birrell 		return (tdp1->t_id > tdp2->t_id ? 1 : -1);
146*1673e404SJohn Birrell }
147*1673e404SJohn Birrell 
148*1673e404SJohn Birrell int
149*1673e404SJohn Birrell tdesc_namehash(int nbuckets, void *data)
150*1673e404SJohn Birrell {
151*1673e404SJohn Birrell 	tdesc_t *tdp = data;
152*1673e404SJohn Birrell 	ulong_t h, g;
153*1673e404SJohn Birrell 	char *c;
154*1673e404SJohn Birrell 
155*1673e404SJohn Birrell 	if (tdp->t_name == NULL)
156*1673e404SJohn Birrell 		return (0);
157*1673e404SJohn Birrell 
158*1673e404SJohn Birrell 	for (h = 0, c = tdp->t_name; *c; c++) {
159*1673e404SJohn Birrell 		h = (h << 4) + *c;
160*1673e404SJohn Birrell 		if ((g = (h & 0xf0000000)) != 0) {
161*1673e404SJohn Birrell 			h ^= (g >> 24);
162*1673e404SJohn Birrell 			h ^= g;
163*1673e404SJohn Birrell 		}
164*1673e404SJohn Birrell 	}
165*1673e404SJohn Birrell 
166*1673e404SJohn Birrell 	return (h % nbuckets);
167*1673e404SJohn Birrell }
168*1673e404SJohn Birrell 
169*1673e404SJohn Birrell int
170*1673e404SJohn Birrell tdesc_namecmp(void *arg1, void *arg2)
171*1673e404SJohn Birrell {
172*1673e404SJohn Birrell 	tdesc_t *tdp1 = arg1, *tdp2 = arg2;
173*1673e404SJohn Birrell 
174*1673e404SJohn Birrell 	return (!streq(tdp1->t_name, tdp2->t_name));
175*1673e404SJohn Birrell }
176*1673e404SJohn Birrell 
177*1673e404SJohn Birrell #if defined(sun)
178*1673e404SJohn Birrell /*ARGSUSED1*/
179*1673e404SJohn Birrell static int
180*1673e404SJohn Birrell tdesc_print(void *data, void *private __unused)
181*1673e404SJohn Birrell {
182*1673e404SJohn Birrell 	tdesc_t *tdp = data;
183*1673e404SJohn Birrell 
184*1673e404SJohn Birrell 	printf("%7d %s\n", tdp->t_id, tdesc_name(tdp));
185*1673e404SJohn Birrell 
186*1673e404SJohn Birrell 	return (1);
187*1673e404SJohn Birrell }
188*1673e404SJohn Birrell #endif
189*1673e404SJohn Birrell 
190*1673e404SJohn Birrell static void
191*1673e404SJohn Birrell free_intr(tdesc_t *tdp)
192*1673e404SJohn Birrell {
193*1673e404SJohn Birrell 	free(tdp->t_intr);
194*1673e404SJohn Birrell }
195*1673e404SJohn Birrell 
196*1673e404SJohn Birrell static void
197*1673e404SJohn Birrell free_ardef(tdesc_t *tdp)
198*1673e404SJohn Birrell {
199*1673e404SJohn Birrell 	free(tdp->t_ardef);
200*1673e404SJohn Birrell }
201*1673e404SJohn Birrell 
202*1673e404SJohn Birrell static void
203*1673e404SJohn Birrell free_mlist(tdesc_t *tdp)
204*1673e404SJohn Birrell {
205*1673e404SJohn Birrell 	mlist_t *ml = tdp->t_members;
206*1673e404SJohn Birrell 	mlist_t *oml;
207*1673e404SJohn Birrell 
208*1673e404SJohn Birrell 	while (ml) {
209*1673e404SJohn Birrell 		oml = ml;
210*1673e404SJohn Birrell 		ml = ml->ml_next;
211*1673e404SJohn Birrell 
212*1673e404SJohn Birrell 		if (oml->ml_name)
213*1673e404SJohn Birrell 			free(oml->ml_name);
214*1673e404SJohn Birrell 		free(oml);
215*1673e404SJohn Birrell 	}
216*1673e404SJohn Birrell }
217*1673e404SJohn Birrell 
218*1673e404SJohn Birrell static void
219*1673e404SJohn Birrell free_elist(tdesc_t *tdp)
220*1673e404SJohn Birrell {
221*1673e404SJohn Birrell 	elist_t *el = tdp->t_emem;
222*1673e404SJohn Birrell 	elist_t *oel;
223*1673e404SJohn Birrell 
224*1673e404SJohn Birrell 	while (el) {
225*1673e404SJohn Birrell 		oel = el;
226*1673e404SJohn Birrell 		el = el->el_next;
227*1673e404SJohn Birrell 
228*1673e404SJohn Birrell 		if (oel->el_name)
229*1673e404SJohn Birrell 			free(oel->el_name);
230*1673e404SJohn Birrell 		free(oel);
231*1673e404SJohn Birrell 	}
232*1673e404SJohn Birrell }
233*1673e404SJohn Birrell 
234*1673e404SJohn Birrell static void (*free_cbs[])(tdesc_t *) = {
235*1673e404SJohn Birrell 	NULL,
236*1673e404SJohn Birrell 	free_intr,
237*1673e404SJohn Birrell 	NULL,
238*1673e404SJohn Birrell 	free_ardef,
239*1673e404SJohn Birrell 	NULL,
240*1673e404SJohn Birrell 	free_mlist,
241*1673e404SJohn Birrell 	free_mlist,
242*1673e404SJohn Birrell 	free_elist,
243*1673e404SJohn Birrell 	NULL,
244*1673e404SJohn Birrell 	NULL,
245*1673e404SJohn Birrell 	NULL,
246*1673e404SJohn Birrell 	NULL,
247*1673e404SJohn Birrell 	NULL,
248*1673e404SJohn Birrell 	NULL
249*1673e404SJohn Birrell };
250*1673e404SJohn Birrell 
251*1673e404SJohn Birrell /*ARGSUSED1*/
252*1673e404SJohn Birrell static void
253*1673e404SJohn Birrell tdesc_free_cb(void *arg, void *private __unused)
254*1673e404SJohn Birrell {
255*1673e404SJohn Birrell 	tdesc_t *tdp = arg;
256*1673e404SJohn Birrell 	if (tdp->t_name)
257*1673e404SJohn Birrell 		free(tdp->t_name);
258*1673e404SJohn Birrell 	if (free_cbs[tdp->t_type])
259*1673e404SJohn Birrell 		free_cbs[tdp->t_type](tdp);
260*1673e404SJohn Birrell 	free(tdp);
261*1673e404SJohn Birrell 
262*1673e404SJohn Birrell 	return;
263*1673e404SJohn Birrell }
264*1673e404SJohn Birrell 
265*1673e404SJohn Birrell void
266*1673e404SJohn Birrell tdesc_free(tdesc_t *tdp)
267*1673e404SJohn Birrell {
268*1673e404SJohn Birrell 	tdesc_free_cb(tdp, NULL);
269*1673e404SJohn Birrell }
270*1673e404SJohn Birrell 
271*1673e404SJohn Birrell static int
272*1673e404SJohn Birrell tdata_label_cmp(void *arg1, void *arg2)
273*1673e404SJohn Birrell {
274*1673e404SJohn Birrell 	labelent_t *le1 = arg1;
275*1673e404SJohn Birrell 	labelent_t *le2 = arg2;
276*1673e404SJohn Birrell 	return (le1->le_idx - le2->le_idx);
277*1673e404SJohn Birrell }
278*1673e404SJohn Birrell 
279*1673e404SJohn Birrell void
280*1673e404SJohn Birrell tdata_label_add(tdata_t *td, const char *label, int idx)
281*1673e404SJohn Birrell {
282*1673e404SJohn Birrell 	labelent_t *le = xmalloc(sizeof (*le));
283*1673e404SJohn Birrell 
284*1673e404SJohn Birrell 	le->le_name = xstrdup(label);
285*1673e404SJohn Birrell 	le->le_idx = (idx == -1 ? td->td_nextid - 1 : idx);
286*1673e404SJohn Birrell 
287*1673e404SJohn Birrell 	slist_add(&td->td_labels, le, tdata_label_cmp);
288*1673e404SJohn Birrell }
289*1673e404SJohn Birrell 
290*1673e404SJohn Birrell static int
291*1673e404SJohn Birrell tdata_label_top_cb(void *data, void *arg)
292*1673e404SJohn Birrell {
293*1673e404SJohn Birrell 	labelent_t *le = data;
294*1673e404SJohn Birrell 	labelent_t **topp = arg;
295*1673e404SJohn Birrell 
296*1673e404SJohn Birrell 	*topp = le;
297*1673e404SJohn Birrell 
298*1673e404SJohn Birrell 	return (1);
299*1673e404SJohn Birrell }
300*1673e404SJohn Birrell 
301*1673e404SJohn Birrell labelent_t *
302*1673e404SJohn Birrell tdata_label_top(tdata_t *td)
303*1673e404SJohn Birrell {
304*1673e404SJohn Birrell 	labelent_t *top = NULL;
305*1673e404SJohn Birrell 
306*1673e404SJohn Birrell 	(void) list_iter(td->td_labels, tdata_label_top_cb, &top);
307*1673e404SJohn Birrell 
308*1673e404SJohn Birrell 	return (top);
309*1673e404SJohn Birrell }
310*1673e404SJohn Birrell 
311*1673e404SJohn Birrell static int
312*1673e404SJohn Birrell tdata_label_find_cb(void *arg1, void *arg2)
313*1673e404SJohn Birrell {
314*1673e404SJohn Birrell 	labelent_t *le = arg1;
315*1673e404SJohn Birrell 	labelent_t *tmpl = arg2;
316*1673e404SJohn Birrell 	return (streq(le->le_name, tmpl->le_name));
317*1673e404SJohn Birrell }
318*1673e404SJohn Birrell 
319*1673e404SJohn Birrell int
320*1673e404SJohn Birrell tdata_label_find(tdata_t *td, char *label)
321*1673e404SJohn Birrell {
322*1673e404SJohn Birrell 	labelent_t let;
323*1673e404SJohn Birrell 	labelent_t *ret;
324*1673e404SJohn Birrell 
325*1673e404SJohn Birrell 	if (streq(label, "BASE")) {
326*1673e404SJohn Birrell 		ret = (labelent_t *)list_first(td->td_labels);
327*1673e404SJohn Birrell 		return (ret ? ret->le_idx : -1);
328*1673e404SJohn Birrell 	}
329*1673e404SJohn Birrell 
330*1673e404SJohn Birrell 	let.le_name = label;
331*1673e404SJohn Birrell 
332*1673e404SJohn Birrell 	if (!(ret = (labelent_t *)list_find(td->td_labels, &let,
333*1673e404SJohn Birrell 	    tdata_label_find_cb)))
334*1673e404SJohn Birrell 		return (-1);
335*1673e404SJohn Birrell 
336*1673e404SJohn Birrell 	return (ret->le_idx);
337*1673e404SJohn Birrell }
338*1673e404SJohn Birrell 
339*1673e404SJohn Birrell static int
340*1673e404SJohn Birrell tdata_label_newmax_cb(void *data, void *arg)
341*1673e404SJohn Birrell {
342*1673e404SJohn Birrell 	labelent_t *le = data;
343*1673e404SJohn Birrell 	int *newmaxp = arg;
344*1673e404SJohn Birrell 
345*1673e404SJohn Birrell 	if (le->le_idx > *newmaxp) {
346*1673e404SJohn Birrell 		le->le_idx = *newmaxp;
347*1673e404SJohn Birrell 		return (1);
348*1673e404SJohn Birrell 	}
349*1673e404SJohn Birrell 
350*1673e404SJohn Birrell 	return (0);
351*1673e404SJohn Birrell }
352*1673e404SJohn Birrell 
353*1673e404SJohn Birrell void
354*1673e404SJohn Birrell tdata_label_newmax(tdata_t *td, int newmax)
355*1673e404SJohn Birrell {
356*1673e404SJohn Birrell 	(void) list_iter(td->td_labels, tdata_label_newmax_cb, &newmax);
357*1673e404SJohn Birrell }
358*1673e404SJohn Birrell 
359*1673e404SJohn Birrell /*ARGSUSED1*/
360*1673e404SJohn Birrell static void
361*1673e404SJohn Birrell tdata_label_free_cb(void *arg, void *private __unused)
362*1673e404SJohn Birrell {
363*1673e404SJohn Birrell 	labelent_t *le = arg;
364*1673e404SJohn Birrell 	if (le->le_name)
365*1673e404SJohn Birrell 		free(le->le_name);
366*1673e404SJohn Birrell 	free(le);
367*1673e404SJohn Birrell }
368*1673e404SJohn Birrell 
369*1673e404SJohn Birrell void
370*1673e404SJohn Birrell tdata_label_free(tdata_t *td)
371*1673e404SJohn Birrell {
372*1673e404SJohn Birrell 	list_free(td->td_labels, tdata_label_free_cb, NULL);
373*1673e404SJohn Birrell 	td->td_labels = NULL;
374*1673e404SJohn Birrell }
375*1673e404SJohn Birrell 
376*1673e404SJohn Birrell tdata_t *
377*1673e404SJohn Birrell tdata_new(void)
378*1673e404SJohn Birrell {
379*1673e404SJohn Birrell 	tdata_t *new = xcalloc(sizeof (tdata_t));
380*1673e404SJohn Birrell 
381*1673e404SJohn Birrell 	new->td_layouthash = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash,
382*1673e404SJohn Birrell 	    tdesc_layoutcmp);
383*1673e404SJohn Birrell 	new->td_idhash = hash_new(TDATA_ID_HASH_SIZE, tdesc_idhash,
384*1673e404SJohn Birrell 	    tdesc_idcmp);
385*1673e404SJohn Birrell 	/*
386*1673e404SJohn Birrell 	 * This is also traversed as a list, but amortized O(1)
387*1673e404SJohn Birrell 	 * lookup massively impacts part of the merge phase, so
388*1673e404SJohn Birrell 	 * we store the iidescs as a hash.
389*1673e404SJohn Birrell 	 */
390*1673e404SJohn Birrell 	new->td_iihash = hash_new(IIDESC_HASH_SIZE, iidesc_hash, NULL);
391*1673e404SJohn Birrell 	new->td_nextid = 1;
392*1673e404SJohn Birrell 	new->td_curvgen = 1;
393*1673e404SJohn Birrell 
394*1673e404SJohn Birrell 	pthread_mutex_init(&new->td_mergelock, NULL);
395*1673e404SJohn Birrell 
396*1673e404SJohn Birrell 	return (new);
397*1673e404SJohn Birrell }
398*1673e404SJohn Birrell 
399*1673e404SJohn Birrell void
400*1673e404SJohn Birrell tdata_free(tdata_t *td)
401*1673e404SJohn Birrell {
402*1673e404SJohn Birrell 	hash_free(td->td_iihash, iidesc_free, NULL);
403*1673e404SJohn Birrell 	hash_free(td->td_layouthash, tdesc_free_cb, NULL);
404*1673e404SJohn Birrell 	hash_free(td->td_idhash, NULL, NULL);
405*1673e404SJohn Birrell 	list_free(td->td_fwdlist, NULL, NULL);
406*1673e404SJohn Birrell 
407*1673e404SJohn Birrell 	tdata_label_free(td);
408*1673e404SJohn Birrell 
409*1673e404SJohn Birrell 	free(td->td_parlabel);
410*1673e404SJohn Birrell 	free(td->td_parname);
411*1673e404SJohn Birrell 
412*1673e404SJohn Birrell 	pthread_mutex_destroy(&td->td_mergelock);
413*1673e404SJohn Birrell 
414*1673e404SJohn Birrell 	free(td);
415*1673e404SJohn Birrell }
416*1673e404SJohn Birrell 
417*1673e404SJohn Birrell /*ARGSUSED1*/
418*1673e404SJohn Birrell static int
419*1673e404SJohn Birrell build_hashes(tdesc_t *ctdp, tdesc_t **ctdpp __unused, void *private)
420*1673e404SJohn Birrell {
421*1673e404SJohn Birrell 	tdata_t *td = private;
422*1673e404SJohn Birrell 
423*1673e404SJohn Birrell 	hash_add(td->td_idhash, ctdp);
424*1673e404SJohn Birrell 	hash_add(td->td_layouthash, ctdp);
425*1673e404SJohn Birrell 
426*1673e404SJohn Birrell 	return (1);
427*1673e404SJohn Birrell }
428*1673e404SJohn Birrell 
429*1673e404SJohn Birrell static tdtrav_cb_f build_hashes_cbs[] = {
430*1673e404SJohn Birrell 	NULL,
431*1673e404SJohn Birrell 	build_hashes,	/* intrinsic */
432*1673e404SJohn Birrell 	build_hashes,	/* pointer */
433*1673e404SJohn Birrell 	build_hashes,	/* array */
434*1673e404SJohn Birrell 	build_hashes,	/* function */
435*1673e404SJohn Birrell 	build_hashes,	/* struct */
436*1673e404SJohn Birrell 	build_hashes,	/* union */
437*1673e404SJohn Birrell 	build_hashes,	/* enum */
438*1673e404SJohn Birrell 	build_hashes,	/* forward */
439*1673e404SJohn Birrell 	build_hashes,	/* typedef */
440*1673e404SJohn Birrell 	tdtrav_assert,	/* typedef_unres */
441*1673e404SJohn Birrell 	build_hashes,	/* volatile */
442*1673e404SJohn Birrell 	build_hashes,	/* const */
443*1673e404SJohn Birrell 	build_hashes	/* restrict */
444*1673e404SJohn Birrell };
445*1673e404SJohn Birrell 
446*1673e404SJohn Birrell static void
447*1673e404SJohn Birrell tdata_build_hashes_common(tdata_t *td, hash_t *hash)
448*1673e404SJohn Birrell {
449*1673e404SJohn Birrell 	(void) iitraverse_hash(hash, &td->td_curvgen, NULL, NULL,
450*1673e404SJohn Birrell 	    build_hashes_cbs, td);
451*1673e404SJohn Birrell }
452*1673e404SJohn Birrell 
453*1673e404SJohn Birrell void
454*1673e404SJohn Birrell tdata_build_hashes(tdata_t *td)
455*1673e404SJohn Birrell {
456*1673e404SJohn Birrell 	tdata_build_hashes_common(td, td->td_iihash);
457*1673e404SJohn Birrell }
458*1673e404SJohn Birrell 
459*1673e404SJohn Birrell /* Merge td2 into td1.  td2 is destroyed by the merge */
460*1673e404SJohn Birrell void
461*1673e404SJohn Birrell tdata_merge(tdata_t *td1, tdata_t *td2)
462*1673e404SJohn Birrell {
463*1673e404SJohn Birrell 	td1->td_curemark = MAX(td1->td_curemark, td2->td_curemark);
464*1673e404SJohn Birrell 	td1->td_curvgen = MAX(td1->td_curvgen, td2->td_curvgen);
465*1673e404SJohn Birrell 	td1->td_nextid = MAX(td1->td_nextid, td2->td_nextid);
466*1673e404SJohn Birrell 
467*1673e404SJohn Birrell 	hash_merge(td1->td_iihash, td2->td_iihash);
468*1673e404SJohn Birrell 
469*1673e404SJohn Birrell 	/* Add td2's type tree to the hashes */
470*1673e404SJohn Birrell 	tdata_build_hashes_common(td1, td2->td_iihash);
471*1673e404SJohn Birrell 
472*1673e404SJohn Birrell 	list_concat(&td1->td_fwdlist, td2->td_fwdlist);
473*1673e404SJohn Birrell 	td2->td_fwdlist = NULL;
474*1673e404SJohn Birrell 
475*1673e404SJohn Birrell 	slist_merge(&td1->td_labels, td2->td_labels,
476*1673e404SJohn Birrell 	    tdata_label_cmp);
477*1673e404SJohn Birrell 	td2->td_labels = NULL;
478*1673e404SJohn Birrell 
479*1673e404SJohn Birrell 	/* free the td2 hashes (data is now part of td1) */
480*1673e404SJohn Birrell 
481*1673e404SJohn Birrell 	hash_free(td2->td_layouthash, NULL, NULL);
482*1673e404SJohn Birrell 	td2->td_layouthash = NULL;
483*1673e404SJohn Birrell 
484*1673e404SJohn Birrell 	hash_free(td2->td_iihash, NULL, NULL);
485*1673e404SJohn Birrell 	td2->td_iihash = NULL;
486*1673e404SJohn Birrell 
487*1673e404SJohn Birrell 	tdata_free(td2);
488*1673e404SJohn Birrell }
489