xref: /titanic_53/usr/src/tools/ctf/cvt/merge.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * This file contains routines that merge one tdata_t tree, called the child,
31*7c478bd9Sstevel@tonic-gate  * into another, called the parent.  Note that these names are used mainly for
32*7c478bd9Sstevel@tonic-gate  * convenience and to represent the direction of the merge.  They are not meant
33*7c478bd9Sstevel@tonic-gate  * to imply any relationship between the tdata_t graphs prior to the merge.
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * tdata_t structures contain two main elements - a hash of iidesc_t nodes, and
36*7c478bd9Sstevel@tonic-gate  * a directed graph of tdesc_t nodes, pointed to by the iidesc_t nodes.  Simply
37*7c478bd9Sstevel@tonic-gate  * put, we merge the tdesc_t graphs, followed by the iidesc_t nodes, and then we
38*7c478bd9Sstevel@tonic-gate  * clean up loose ends.
39*7c478bd9Sstevel@tonic-gate  *
40*7c478bd9Sstevel@tonic-gate  * The algorithm is as follows:
41*7c478bd9Sstevel@tonic-gate  *
42*7c478bd9Sstevel@tonic-gate  * 1. Mapping iidesc_t nodes
43*7c478bd9Sstevel@tonic-gate  *
44*7c478bd9Sstevel@tonic-gate  * For each child iidesc_t node, we first try to map its tdesc_t subgraph
45*7c478bd9Sstevel@tonic-gate  * against the tdesc_t graph in the parent.  For each node in the child subgraph
46*7c478bd9Sstevel@tonic-gate  * that exists in the parent, a mapping between the two (between their type IDs)
47*7c478bd9Sstevel@tonic-gate  * is established.  For the child nodes that cannot be mapped onto existing
48*7c478bd9Sstevel@tonic-gate  * parent nodes, a mapping is established between the child node ID and a
49*7c478bd9Sstevel@tonic-gate  * newly-allocated ID that the node will use when it is re-created in the
50*7c478bd9Sstevel@tonic-gate  * parent.  These unmappable nodes are added to the md_tdtba (tdesc_t To Be
51*7c478bd9Sstevel@tonic-gate  * Added) hash, which tracks nodes that need to be created in the parent.
52*7c478bd9Sstevel@tonic-gate  *
53*7c478bd9Sstevel@tonic-gate  * If all of the nodes in the subgraph for an iidesc_t in the child can be
54*7c478bd9Sstevel@tonic-gate  * mapped to existing nodes in the parent, then we can try to map the child
55*7c478bd9Sstevel@tonic-gate  * iidesc_t onto an iidesc_t in the parent.  If we cannot find an equivalent
56*7c478bd9Sstevel@tonic-gate  * iidesc_t, or if we were not able to completely map the tdesc_t subgraph(s),
57*7c478bd9Sstevel@tonic-gate  * then we add this iidesc_t to the md_iitba (iidesc_t To Be Added) list.  This
58*7c478bd9Sstevel@tonic-gate  * list tracks iidesc_t nodes that are to be created in the parent.
59*7c478bd9Sstevel@tonic-gate  *
60*7c478bd9Sstevel@tonic-gate  * While visiting the tdesc_t nodes, we may discover a forward declaration (a
61*7c478bd9Sstevel@tonic-gate  * FORWARD tdesc_t) in the parent that is resolved in the child.  That is, there
62*7c478bd9Sstevel@tonic-gate  * may be a structure or union definition in the child with the same name as the
63*7c478bd9Sstevel@tonic-gate  * forward declaration in the parent.  If we find such a node, we record an
64*7c478bd9Sstevel@tonic-gate  * association in the md_fdida (Forward => Definition ID Association) list
65*7c478bd9Sstevel@tonic-gate  * between the parent ID of the forward declaration and the ID that the
66*7c478bd9Sstevel@tonic-gate  * definition will use when re-created in the parent.
67*7c478bd9Sstevel@tonic-gate  *
68*7c478bd9Sstevel@tonic-gate  * 2. Creating new tdesc_t nodes (the md_tdtba hash)
69*7c478bd9Sstevel@tonic-gate  *
70*7c478bd9Sstevel@tonic-gate  * We have now attempted to map all tdesc_t nodes from the child into the
71*7c478bd9Sstevel@tonic-gate  * parent, and have, in md_tdtba, a hash of all tdesc_t nodes that need to be
72*7c478bd9Sstevel@tonic-gate  * created (or, as we so wittily call it, conjured) in the parent.  We iterate
73*7c478bd9Sstevel@tonic-gate  * through this hash, creating the indicated tdesc_t nodes.  For a given tdesc_t
74*7c478bd9Sstevel@tonic-gate  * node, conjuring requires two steps - the copying of the common tdesc_t data
75*7c478bd9Sstevel@tonic-gate  * (name, type, etc) from the child node, and the creation of links from the
76*7c478bd9Sstevel@tonic-gate  * newly-created node to the parent equivalents of other tdesc_t nodes pointed
77*7c478bd9Sstevel@tonic-gate  * to by node being conjured.  Note that in some cases, the targets of these
78*7c478bd9Sstevel@tonic-gate  * links will be on the md_tdtba hash themselves, and may not have been created
79*7c478bd9Sstevel@tonic-gate  * yet.  As such, we can't establish the links from these new nodes into the
80*7c478bd9Sstevel@tonic-gate  * parent graph.  We therefore conjure them with links to nodes in the *child*
81*7c478bd9Sstevel@tonic-gate  * graph, and add pointers to the links to be created to the md_tdtbr (tdesc_t
82*7c478bd9Sstevel@tonic-gate  * To Be Remapped) hash.  For example, a POINTER tdesc_t that could not be
83*7c478bd9Sstevel@tonic-gate  * resolved would have its &tdesc_t->t_tdesc added to md_tdtbr.
84*7c478bd9Sstevel@tonic-gate  *
85*7c478bd9Sstevel@tonic-gate  * 3. Creating new iidesc_t nodes (the md_iitba list)
86*7c478bd9Sstevel@tonic-gate  *
87*7c478bd9Sstevel@tonic-gate  * When we have completed step 2, all tdesc_t nodes have been created (or
88*7c478bd9Sstevel@tonic-gate  * already existed) in the parent.  Some of them may have incorrect links (the
89*7c478bd9Sstevel@tonic-gate  * members of the md_tdtbr list), but they've all been created.  As such, we can
90*7c478bd9Sstevel@tonic-gate  * create all of the iidesc_t nodes, as we can attach the tdesc_t subgraph
91*7c478bd9Sstevel@tonic-gate  * pointers correctly.  We create each node, and attach the pointers to the
92*7c478bd9Sstevel@tonic-gate  * appropriate parts of the parent tdesc_t graph.
93*7c478bd9Sstevel@tonic-gate  *
94*7c478bd9Sstevel@tonic-gate  * 4. Resolving newly-created tdesc_t node links (the md_tdtbr list)
95*7c478bd9Sstevel@tonic-gate  *
96*7c478bd9Sstevel@tonic-gate  * As in step 3, we rely on the fact that all of the tdesc_t nodes have been
97*7c478bd9Sstevel@tonic-gate  * created.  Each entry in the md_tdtbr list is a pointer to where a link into
98*7c478bd9Sstevel@tonic-gate  * the parent will be established.  As saved in the md_tdtbr list, these
99*7c478bd9Sstevel@tonic-gate  * pointers point into the child tdesc_t subgraph.  We can thus get the target
100*7c478bd9Sstevel@tonic-gate  * type ID from the child, look at the ID mapping to determine the desired link
101*7c478bd9Sstevel@tonic-gate  * target, and redirect the link accordingly.
102*7c478bd9Sstevel@tonic-gate  *
103*7c478bd9Sstevel@tonic-gate  * 5. Parent => child forward declaration resolution
104*7c478bd9Sstevel@tonic-gate  *
105*7c478bd9Sstevel@tonic-gate  * If entries were made in the md_fdida list in step 1, we have forward
106*7c478bd9Sstevel@tonic-gate  * declarations in the parent that need to be resolved to their definitions
107*7c478bd9Sstevel@tonic-gate  * re-created in step 2 from the child.  Using the md_fdida list, we can locate
108*7c478bd9Sstevel@tonic-gate  * the definition for the forward declaration, and we can redirect all inbound
109*7c478bd9Sstevel@tonic-gate  * edges to the forward declaration node to the actual definition.
110*7c478bd9Sstevel@tonic-gate  *
111*7c478bd9Sstevel@tonic-gate  * A pox on the house of anyone who changes the algorithm without updating
112*7c478bd9Sstevel@tonic-gate  * this comment.
113*7c478bd9Sstevel@tonic-gate  */
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate #include <stdio.h>
116*7c478bd9Sstevel@tonic-gate #include <strings.h>
117*7c478bd9Sstevel@tonic-gate #include <assert.h>
118*7c478bd9Sstevel@tonic-gate #include <pthread.h>
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate #include "ctf_headers.h"
121*7c478bd9Sstevel@tonic-gate #include "ctftools.h"
122*7c478bd9Sstevel@tonic-gate #include "list.h"
123*7c478bd9Sstevel@tonic-gate #include "alist.h"
124*7c478bd9Sstevel@tonic-gate #include "memory.h"
125*7c478bd9Sstevel@tonic-gate #include "traverse.h"
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate typedef struct equiv_data equiv_data_t;
128*7c478bd9Sstevel@tonic-gate typedef struct merge_cb_data merge_cb_data_t;
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate /*
131*7c478bd9Sstevel@tonic-gate  * There are two traversals in this file, for equivalency and for tdesc_t
132*7c478bd9Sstevel@tonic-gate  * re-creation, that do not fit into the tdtraverse() framework.  We have our
133*7c478bd9Sstevel@tonic-gate  * own traversal mechanism and ops vector here for those two cases.
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate typedef struct tdesc_ops {
136*7c478bd9Sstevel@tonic-gate 	char *name;
137*7c478bd9Sstevel@tonic-gate 	int (*equiv)(tdesc_t *, tdesc_t *, equiv_data_t *);
138*7c478bd9Sstevel@tonic-gate 	tdesc_t *(*conjure)(tdesc_t *, int, merge_cb_data_t *);
139*7c478bd9Sstevel@tonic-gate } tdesc_ops_t;
140*7c478bd9Sstevel@tonic-gate extern tdesc_ops_t tdesc_ops[];
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate /*
143*7c478bd9Sstevel@tonic-gate  * The workhorse structure of tdata_t merging.  Holds all lists of nodes to be
144*7c478bd9Sstevel@tonic-gate  * processed during various phases of the merge algorithm.
145*7c478bd9Sstevel@tonic-gate  */
146*7c478bd9Sstevel@tonic-gate struct merge_cb_data {
147*7c478bd9Sstevel@tonic-gate 	tdata_t *md_parent;
148*7c478bd9Sstevel@tonic-gate 	tdata_t *md_tgt;
149*7c478bd9Sstevel@tonic-gate 	alist_t *md_ta;		/* Type Association */
150*7c478bd9Sstevel@tonic-gate 	alist_t *md_fdida;	/* Forward -> Definition ID Association */
151*7c478bd9Sstevel@tonic-gate 	list_t	**md_iitba;	/* iidesc_t nodes To Be Added to the parent */
152*7c478bd9Sstevel@tonic-gate 	hash_t	*md_tdtba;	/* tdesc_t nodes To Be Added to the parent */
153*7c478bd9Sstevel@tonic-gate 	list_t	**md_tdtbr;	/* tdesc_t nodes To Be Remapped */
154*7c478bd9Sstevel@tonic-gate 	int md_flags;
155*7c478bd9Sstevel@tonic-gate }; /* merge_cb_data_t */
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate /*
158*7c478bd9Sstevel@tonic-gate  * When we first create a tdata_t from stabs data, we will have duplicate nodes.
159*7c478bd9Sstevel@tonic-gate  * Normal merges, however, assume that the child tdata_t is already self-unique,
160*7c478bd9Sstevel@tonic-gate  * and for speed reasons do not attempt to self-uniquify.  If this flag is set,
161*7c478bd9Sstevel@tonic-gate  * the merge algorithm will self-uniquify by avoiding the insertion of
162*7c478bd9Sstevel@tonic-gate  * duplicates in the md_tdtdba list.
163*7c478bd9Sstevel@tonic-gate  */
164*7c478bd9Sstevel@tonic-gate #define	MCD_F_SELFUNIQUIFY	0x1
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate /*
167*7c478bd9Sstevel@tonic-gate  * When we merge the CTF data for the modules, we don't want it to contain any
168*7c478bd9Sstevel@tonic-gate  * data that can be found in the reference module (usually genunix).  If this
169*7c478bd9Sstevel@tonic-gate  * flag is set, we're doing a merge between the fully merged tdata_t for this
170*7c478bd9Sstevel@tonic-gate  * module and the tdata_t for the reference module, with the data unique to this
171*7c478bd9Sstevel@tonic-gate  * module ending up in a third tdata_t.  It is this third tdata_t that will end
172*7c478bd9Sstevel@tonic-gate  * up in the .SUNW_ctf section for the module.
173*7c478bd9Sstevel@tonic-gate  */
174*7c478bd9Sstevel@tonic-gate #define	MCD_F_REFMERGE	0x2
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate /*
177*7c478bd9Sstevel@tonic-gate  * Mapping of child type IDs to parent type IDs
178*7c478bd9Sstevel@tonic-gate  */
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate static void
181*7c478bd9Sstevel@tonic-gate add_mapping(alist_t *ta, tid_t srcid, tid_t tgtid)
182*7c478bd9Sstevel@tonic-gate {
183*7c478bd9Sstevel@tonic-gate 	debug(3, "Adding mapping %u => %u\n", srcid, tgtid);
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	assert(!alist_find(ta, (void *)srcid, NULL));
186*7c478bd9Sstevel@tonic-gate 	assert(srcid != 0 && tgtid != 0);
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 	alist_add(ta, (void *)srcid, (void *)tgtid);
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate static tid_t
192*7c478bd9Sstevel@tonic-gate get_mapping(alist_t *ta, int srcid)
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate 	long ltgtid;
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	if (alist_find(ta, (void *)srcid, (void **)&ltgtid))
197*7c478bd9Sstevel@tonic-gate 		return ((int)ltgtid);
198*7c478bd9Sstevel@tonic-gate 	else
199*7c478bd9Sstevel@tonic-gate 		return (0);
200*7c478bd9Sstevel@tonic-gate }
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate /*
203*7c478bd9Sstevel@tonic-gate  * Determining equivalence of tdesc_t subgraphs
204*7c478bd9Sstevel@tonic-gate  */
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate struct equiv_data {
207*7c478bd9Sstevel@tonic-gate 	alist_t *ed_ta;
208*7c478bd9Sstevel@tonic-gate 	tdesc_t *ed_node;
209*7c478bd9Sstevel@tonic-gate 	tdesc_t *ed_tgt;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	int ed_clear_mark;
212*7c478bd9Sstevel@tonic-gate 	int ed_cur_mark;
213*7c478bd9Sstevel@tonic-gate 	int ed_selfuniquify;
214*7c478bd9Sstevel@tonic-gate }; /* equiv_data_t */
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate static int equiv_node(tdesc_t *, tdesc_t *, equiv_data_t *);
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
219*7c478bd9Sstevel@tonic-gate static int
220*7c478bd9Sstevel@tonic-gate equiv_intrinsic(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
221*7c478bd9Sstevel@tonic-gate {
222*7c478bd9Sstevel@tonic-gate 	intr_t *si = stdp->t_intr;
223*7c478bd9Sstevel@tonic-gate 	intr_t *ti = ttdp->t_intr;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	if (si->intr_type != ti->intr_type ||
226*7c478bd9Sstevel@tonic-gate 	    si->intr_signed != ti->intr_signed ||
227*7c478bd9Sstevel@tonic-gate 	    si->intr_offset != ti->intr_offset ||
228*7c478bd9Sstevel@tonic-gate 	    si->intr_nbits != ti->intr_nbits)
229*7c478bd9Sstevel@tonic-gate 		return (0);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	if (si->intr_type == INTR_INT &&
232*7c478bd9Sstevel@tonic-gate 	    si->intr_iformat != ti->intr_iformat)
233*7c478bd9Sstevel@tonic-gate 		return (0);
234*7c478bd9Sstevel@tonic-gate 	else if (si->intr_type == INTR_REAL &&
235*7c478bd9Sstevel@tonic-gate 	    si->intr_fformat != ti->intr_fformat)
236*7c478bd9Sstevel@tonic-gate 		return (0);
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	return (1);
239*7c478bd9Sstevel@tonic-gate }
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate static int
242*7c478bd9Sstevel@tonic-gate equiv_plain(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
243*7c478bd9Sstevel@tonic-gate {
244*7c478bd9Sstevel@tonic-gate 	return (equiv_node(stdp->t_tdesc, ttdp->t_tdesc, ed));
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate static int
248*7c478bd9Sstevel@tonic-gate equiv_function(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 	fndef_t *fn1 = stdp->t_fndef, *fn2 = ttdp->t_fndef;
251*7c478bd9Sstevel@tonic-gate 	int i;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	if (fn1->fn_nargs != fn2->fn_nargs ||
254*7c478bd9Sstevel@tonic-gate 	    fn1->fn_vargs != fn2->fn_vargs)
255*7c478bd9Sstevel@tonic-gate 		return (0);
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	if (!equiv_node(fn1->fn_ret, fn2->fn_ret, ed))
258*7c478bd9Sstevel@tonic-gate 		return (0);
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < fn1->fn_nargs; i++) {
261*7c478bd9Sstevel@tonic-gate 		if (!equiv_node(fn1->fn_args[i], fn2->fn_args[i], ed))
262*7c478bd9Sstevel@tonic-gate 			return (0);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	return (1);
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate static int
269*7c478bd9Sstevel@tonic-gate equiv_array(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
270*7c478bd9Sstevel@tonic-gate {
271*7c478bd9Sstevel@tonic-gate 	ardef_t *ar1 = stdp->t_ardef, *ar2 = ttdp->t_ardef;
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	if (!equiv_node(ar1->ad_contents, ar2->ad_contents, ed) ||
274*7c478bd9Sstevel@tonic-gate 	    !equiv_node(ar1->ad_idxtype, ar2->ad_idxtype, ed))
275*7c478bd9Sstevel@tonic-gate 		return (0);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	if (ar1->ad_nelems != ar2->ad_nelems)
278*7c478bd9Sstevel@tonic-gate 		return (0);
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	return (1);
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate static int
284*7c478bd9Sstevel@tonic-gate equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
287*7c478bd9Sstevel@tonic-gate 	mlist_t *olm1 = NULL;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	while (ml1 && ml2) {
290*7c478bd9Sstevel@tonic-gate 		if (ml1->ml_offset != ml2->ml_offset ||
291*7c478bd9Sstevel@tonic-gate 		    strcmp(ml1->ml_name, ml2->ml_name) != 0)
292*7c478bd9Sstevel@tonic-gate 			return (0);
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		/*
295*7c478bd9Sstevel@tonic-gate 		 * Don't do the recursive equivalency checking more than
296*7c478bd9Sstevel@tonic-gate 		 * we have to.
297*7c478bd9Sstevel@tonic-gate 		 */
298*7c478bd9Sstevel@tonic-gate 		if (olm1 == NULL || olm1->ml_type->t_id != ml1->ml_type->t_id) {
299*7c478bd9Sstevel@tonic-gate 			if (ml1->ml_size != ml2->ml_size ||
300*7c478bd9Sstevel@tonic-gate 			    !equiv_node(ml1->ml_type, ml2->ml_type, ed))
301*7c478bd9Sstevel@tonic-gate 				return (0);
302*7c478bd9Sstevel@tonic-gate 		}
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 		olm1 = ml1;
305*7c478bd9Sstevel@tonic-gate 		ml1 = ml1->ml_next;
306*7c478bd9Sstevel@tonic-gate 		ml2 = ml2->ml_next;
307*7c478bd9Sstevel@tonic-gate 	}
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	if (ml1 || ml2)
310*7c478bd9Sstevel@tonic-gate 		return (0);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	return (1);
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
316*7c478bd9Sstevel@tonic-gate static int
317*7c478bd9Sstevel@tonic-gate equiv_enum(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	elist_t *el1 = stdp->t_emem;
320*7c478bd9Sstevel@tonic-gate 	elist_t *el2 = ttdp->t_emem;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	while (el1 && el2) {
323*7c478bd9Sstevel@tonic-gate 		if (el1->el_number != el2->el_number ||
324*7c478bd9Sstevel@tonic-gate 		    strcmp(el1->el_name, el2->el_name) != 0)
325*7c478bd9Sstevel@tonic-gate 			return (0);
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 		el1 = el1->el_next;
328*7c478bd9Sstevel@tonic-gate 		el2 = el2->el_next;
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	if (el1 || el2)
332*7c478bd9Sstevel@tonic-gate 		return (0);
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	return (1);
335*7c478bd9Sstevel@tonic-gate }
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
338*7c478bd9Sstevel@tonic-gate static int
339*7c478bd9Sstevel@tonic-gate equiv_assert(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
340*7c478bd9Sstevel@tonic-gate {
341*7c478bd9Sstevel@tonic-gate 	/* foul, evil, and very bad - this is a "shouldn't happen" */
342*7c478bd9Sstevel@tonic-gate 	assert(1 == 0);
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	return (0);
345*7c478bd9Sstevel@tonic-gate }
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate static int
348*7c478bd9Sstevel@tonic-gate fwd_equiv(tdesc_t *ctdp, tdesc_t *mtdp)
349*7c478bd9Sstevel@tonic-gate {
350*7c478bd9Sstevel@tonic-gate 	tdesc_t *defn = (ctdp->t_type == FORWARD ? mtdp : ctdp);
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	return (defn->t_type == STRUCT || defn->t_type == UNION);
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate static int
356*7c478bd9Sstevel@tonic-gate equiv_node(tdesc_t *ctdp, tdesc_t *mtdp, equiv_data_t *ed)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	int (*equiv)();
359*7c478bd9Sstevel@tonic-gate 	int mapping;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	if (ctdp->t_emark > ed->ed_clear_mark ||
362*7c478bd9Sstevel@tonic-gate 	    mtdp->t_emark > ed->ed_clear_mark)
363*7c478bd9Sstevel@tonic-gate 		return (ctdp->t_emark == mtdp->t_emark);
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	/*
366*7c478bd9Sstevel@tonic-gate 	 * In normal (non-self-uniquify) mode, we don't want to do equivalency
367*7c478bd9Sstevel@tonic-gate 	 * checking on a subgraph that has already been checked.  If a mapping
368*7c478bd9Sstevel@tonic-gate 	 * has already been established for a given child node, we can simply
369*7c478bd9Sstevel@tonic-gate 	 * compare the mapping for the child node with the ID of the parent
370*7c478bd9Sstevel@tonic-gate 	 * node.  If we are in self-uniquify mode, then we're comparing two
371*7c478bd9Sstevel@tonic-gate 	 * subgraphs within the child graph, and thus need to ignore any
372*7c478bd9Sstevel@tonic-gate 	 * type mappings that have been created, as they are only valid into the
373*7c478bd9Sstevel@tonic-gate 	 * parent.
374*7c478bd9Sstevel@tonic-gate 	 */
375*7c478bd9Sstevel@tonic-gate 	if ((mapping = get_mapping(ed->ed_ta, ctdp->t_id)) > 0 &&
376*7c478bd9Sstevel@tonic-gate 	    mapping == mtdp->t_id && !ed->ed_selfuniquify)
377*7c478bd9Sstevel@tonic-gate 		return (1);
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	if (!streq(ctdp->t_name, mtdp->t_name))
380*7c478bd9Sstevel@tonic-gate 		return (0);
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	if (ctdp->t_type != mtdp->t_type) {
383*7c478bd9Sstevel@tonic-gate 		if (ctdp->t_type == FORWARD || mtdp->t_type == FORWARD)
384*7c478bd9Sstevel@tonic-gate 			return (fwd_equiv(ctdp, mtdp));
385*7c478bd9Sstevel@tonic-gate 		else
386*7c478bd9Sstevel@tonic-gate 			return (0);
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate 	ctdp->t_emark = ed->ed_cur_mark;
390*7c478bd9Sstevel@tonic-gate 	mtdp->t_emark = ed->ed_cur_mark;
391*7c478bd9Sstevel@tonic-gate 	ed->ed_cur_mark++;
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 	if ((equiv = tdesc_ops[ctdp->t_type].equiv) != NULL)
394*7c478bd9Sstevel@tonic-gate 		return (equiv(ctdp, mtdp, ed));
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	return (1);
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /*
400*7c478bd9Sstevel@tonic-gate  * We perform an equivalency check on two subgraphs by traversing through them
401*7c478bd9Sstevel@tonic-gate  * in lockstep.  If a given node is equivalent in both the parent and the child,
402*7c478bd9Sstevel@tonic-gate  * we mark it in both subgraphs, using the t_emark field, with a monotonically
403*7c478bd9Sstevel@tonic-gate  * increasing number.  If, in the course of the traversal, we reach a node that
404*7c478bd9Sstevel@tonic-gate  * we have visited and numbered during this equivalency check, we have a cycle.
405*7c478bd9Sstevel@tonic-gate  * If the previously-visited nodes don't have the same emark, then the edges
406*7c478bd9Sstevel@tonic-gate  * that brought us to these nodes are not equivalent, and so the check ends.
407*7c478bd9Sstevel@tonic-gate  * If the emarks are the same, the edges are equivalent.  We then backtrack and
408*7c478bd9Sstevel@tonic-gate  * continue the traversal.  If we have exhausted all edges in the subgraph, and
409*7c478bd9Sstevel@tonic-gate  * have not found any inequivalent nodes, then the subgraphs are equivalent.
410*7c478bd9Sstevel@tonic-gate  */
411*7c478bd9Sstevel@tonic-gate static int
412*7c478bd9Sstevel@tonic-gate equiv_cb(void *bucket, void *arg)
413*7c478bd9Sstevel@tonic-gate {
414*7c478bd9Sstevel@tonic-gate 	equiv_data_t *ed = arg;
415*7c478bd9Sstevel@tonic-gate 	tdesc_t *mtdp = bucket;
416*7c478bd9Sstevel@tonic-gate 	tdesc_t *ctdp = ed->ed_node;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	ed->ed_clear_mark = ed->ed_cur_mark + 1;
419*7c478bd9Sstevel@tonic-gate 	ed->ed_cur_mark = ed->ed_clear_mark + 1;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	if (equiv_node(ctdp, mtdp, ed)) {
422*7c478bd9Sstevel@tonic-gate 		debug(3, "equiv_node matched %d %d\n", ctdp->t_id, mtdp->t_id);
423*7c478bd9Sstevel@tonic-gate 		ed->ed_tgt = mtdp;
424*7c478bd9Sstevel@tonic-gate 		/* matched.  stop looking */
425*7c478bd9Sstevel@tonic-gate 		return (-1);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	return (0);
429*7c478bd9Sstevel@tonic-gate }
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
432*7c478bd9Sstevel@tonic-gate static int
433*7c478bd9Sstevel@tonic-gate map_td_tree_pre(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = private;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	if (get_mapping(mcd->md_ta, ctdp->t_id) > 0)
438*7c478bd9Sstevel@tonic-gate 		return (0);
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	return (1);
441*7c478bd9Sstevel@tonic-gate }
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
444*7c478bd9Sstevel@tonic-gate static int
445*7c478bd9Sstevel@tonic-gate map_td_tree_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
446*7c478bd9Sstevel@tonic-gate {
447*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = private;
448*7c478bd9Sstevel@tonic-gate 	equiv_data_t ed;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	ed.ed_ta = mcd->md_ta;
451*7c478bd9Sstevel@tonic-gate 	ed.ed_clear_mark = mcd->md_parent->td_curemark;
452*7c478bd9Sstevel@tonic-gate 	ed.ed_cur_mark = mcd->md_parent->td_curemark + 1;
453*7c478bd9Sstevel@tonic-gate 	ed.ed_node = ctdp;
454*7c478bd9Sstevel@tonic-gate 	ed.ed_selfuniquify = 0;
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	debug(3, "map_td_tree_post on %d %s\n", ctdp->t_id,
457*7c478bd9Sstevel@tonic-gate 	    ctdp->t_name == NULL ? "(anon)" : ctdp->t_name);
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 	if (hash_find_iter(mcd->md_parent->td_layouthash, ctdp,
460*7c478bd9Sstevel@tonic-gate 	    equiv_cb, &ed) < 0) {
461*7c478bd9Sstevel@tonic-gate 		/* We found an equivalent node */
462*7c478bd9Sstevel@tonic-gate 		if (ed.ed_tgt->t_type == FORWARD && ctdp->t_type != FORWARD) {
463*7c478bd9Sstevel@tonic-gate 			int id = mcd->md_tgt->td_nextid++;
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 			debug(3, "Creating new defn type %d\n", id);
466*7c478bd9Sstevel@tonic-gate 			add_mapping(mcd->md_ta, ctdp->t_id, id);
467*7c478bd9Sstevel@tonic-gate 			alist_add(mcd->md_fdida, (void *)(ulong_t)ed.ed_tgt,
468*7c478bd9Sstevel@tonic-gate 			    (void *)(ulong_t)id);
469*7c478bd9Sstevel@tonic-gate 			hash_add(mcd->md_tdtba, ctdp);
470*7c478bd9Sstevel@tonic-gate 		} else
471*7c478bd9Sstevel@tonic-gate 			add_mapping(mcd->md_ta, ctdp->t_id, ed.ed_tgt->t_id);
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	} else if (debug_level > 1 && hash_iter(mcd->md_parent->td_idhash,
474*7c478bd9Sstevel@tonic-gate 	    equiv_cb, &ed) < 0) {
475*7c478bd9Sstevel@tonic-gate 		/*
476*7c478bd9Sstevel@tonic-gate 		 * We didn't find an equivalent node by looking through the
477*7c478bd9Sstevel@tonic-gate 		 * layout hash, but we somehow found it by performing an
478*7c478bd9Sstevel@tonic-gate 		 * exhaustive search through the entire graph.  This usually
479*7c478bd9Sstevel@tonic-gate 		 * means that the "name" hash function is broken.
480*7c478bd9Sstevel@tonic-gate 		 */
481*7c478bd9Sstevel@tonic-gate 		terminate("Second pass for %d (%s) == %d\n", ctdp->t_id,
482*7c478bd9Sstevel@tonic-gate 		    (ctdp->t_name ? ctdp->t_name : "(anon)"), ed.ed_tgt->t_id);
483*7c478bd9Sstevel@tonic-gate 	} else {
484*7c478bd9Sstevel@tonic-gate 		int id = mcd->md_tgt->td_nextid++;
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 		debug(3, "Creating new type %d\n", id);
487*7c478bd9Sstevel@tonic-gate 		add_mapping(mcd->md_ta, ctdp->t_id, id);
488*7c478bd9Sstevel@tonic-gate 		hash_add(mcd->md_tdtba, ctdp);
489*7c478bd9Sstevel@tonic-gate 	}
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	mcd->md_parent->td_curemark = ed.ed_cur_mark + 1;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	return (1);
494*7c478bd9Sstevel@tonic-gate }
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
497*7c478bd9Sstevel@tonic-gate static int
498*7c478bd9Sstevel@tonic-gate map_td_tree_self_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private)
499*7c478bd9Sstevel@tonic-gate {
500*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = private;
501*7c478bd9Sstevel@tonic-gate 	equiv_data_t ed;
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	ed.ed_ta = mcd->md_ta;
504*7c478bd9Sstevel@tonic-gate 	ed.ed_clear_mark = mcd->md_parent->td_curemark;
505*7c478bd9Sstevel@tonic-gate 	ed.ed_cur_mark = mcd->md_parent->td_curemark + 1;
506*7c478bd9Sstevel@tonic-gate 	ed.ed_node = ctdp;
507*7c478bd9Sstevel@tonic-gate 	ed.ed_selfuniquify = 1;
508*7c478bd9Sstevel@tonic-gate 	ed.ed_tgt = NULL;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	if (hash_find_iter(mcd->md_tdtba, ctdp, equiv_cb, &ed) < 0) {
511*7c478bd9Sstevel@tonic-gate 		debug(3, "Self check found %d in %d\n", ctdp->t_id,
512*7c478bd9Sstevel@tonic-gate 		    ed.ed_tgt->t_id);
513*7c478bd9Sstevel@tonic-gate 		add_mapping(mcd->md_ta, ctdp->t_id,
514*7c478bd9Sstevel@tonic-gate 		    get_mapping(mcd->md_ta, ed.ed_tgt->t_id));
515*7c478bd9Sstevel@tonic-gate 	} else if (debug_level > 1 && hash_iter(mcd->md_tdtba,
516*7c478bd9Sstevel@tonic-gate 	    equiv_cb, &ed) < 0) {
517*7c478bd9Sstevel@tonic-gate 		/*
518*7c478bd9Sstevel@tonic-gate 		 * We didn't find an equivalent node using the quick way (going
519*7c478bd9Sstevel@tonic-gate 		 * through the hash normally), but we did find it by iterating
520*7c478bd9Sstevel@tonic-gate 		 * through the entire hash.  This usually means that the hash
521*7c478bd9Sstevel@tonic-gate 		 * function is broken.
522*7c478bd9Sstevel@tonic-gate 		 */
523*7c478bd9Sstevel@tonic-gate 		terminate("Self-unique second pass for %d (%s) == %d\n",
524*7c478bd9Sstevel@tonic-gate 		    ctdp->t_id, (ctdp->t_name ? ctdp->t_name : "(anon)"),
525*7c478bd9Sstevel@tonic-gate 		    ed.ed_tgt->t_id);
526*7c478bd9Sstevel@tonic-gate 	} else {
527*7c478bd9Sstevel@tonic-gate 		int id = mcd->md_tgt->td_nextid++;
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 		debug(3, "Creating new type %d\n", id);
530*7c478bd9Sstevel@tonic-gate 		add_mapping(mcd->md_ta, ctdp->t_id, id);
531*7c478bd9Sstevel@tonic-gate 		hash_add(mcd->md_tdtba, ctdp);
532*7c478bd9Sstevel@tonic-gate 	}
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	mcd->md_parent->td_curemark = ed.ed_cur_mark + 1;
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	return (1);
537*7c478bd9Sstevel@tonic-gate }
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_pre[] = {
540*7c478bd9Sstevel@tonic-gate 	NULL,
541*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* intrinsic */
542*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* pointer */
543*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* array */
544*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* function */
545*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* struct */
546*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* union */
547*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* enum */
548*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* forward */
549*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* typedef */
550*7c478bd9Sstevel@tonic-gate 	tdtrav_assert,		/* typedef_unres */
551*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* volatile */
552*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre,	/* const */
553*7c478bd9Sstevel@tonic-gate 	map_td_tree_pre		/* restrict */
554*7c478bd9Sstevel@tonic-gate };
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_post[] = {
557*7c478bd9Sstevel@tonic-gate 	NULL,
558*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* intrinsic */
559*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* pointer */
560*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* array */
561*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* function */
562*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* struct */
563*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* union */
564*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* enum */
565*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* forward */
566*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* typedef */
567*7c478bd9Sstevel@tonic-gate 	tdtrav_assert,		/* typedef_unres */
568*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* volatile */
569*7c478bd9Sstevel@tonic-gate 	map_td_tree_post,	/* const */
570*7c478bd9Sstevel@tonic-gate 	map_td_tree_post	/* restrict */
571*7c478bd9Sstevel@tonic-gate };
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_self_post[] = {
574*7c478bd9Sstevel@tonic-gate 	NULL,
575*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* intrinsic */
576*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* pointer */
577*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* array */
578*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* function */
579*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* struct */
580*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* union */
581*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* enum */
582*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* forward */
583*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* typedef */
584*7c478bd9Sstevel@tonic-gate 	tdtrav_assert,		/* typedef_unres */
585*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* volatile */
586*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post,	/* const */
587*7c478bd9Sstevel@tonic-gate 	map_td_tree_self_post	/* restrict */
588*7c478bd9Sstevel@tonic-gate };
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate /*
591*7c478bd9Sstevel@tonic-gate  * Determining equivalence of iidesc_t nodes
592*7c478bd9Sstevel@tonic-gate  */
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate typedef struct iifind_data {
595*7c478bd9Sstevel@tonic-gate 	iidesc_t *iif_template;
596*7c478bd9Sstevel@tonic-gate 	alist_t *iif_ta;
597*7c478bd9Sstevel@tonic-gate 	int iif_newidx;
598*7c478bd9Sstevel@tonic-gate 	int iif_refmerge;
599*7c478bd9Sstevel@tonic-gate } iifind_data_t;
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate /*
602*7c478bd9Sstevel@tonic-gate  * Check to see if this iidesc_t (node) - the current one on the list we're
603*7c478bd9Sstevel@tonic-gate  * iterating through - matches the target one (iif->iif_template).  Return -1
604*7c478bd9Sstevel@tonic-gate  * if it matches, to stop the iteration.
605*7c478bd9Sstevel@tonic-gate  */
606*7c478bd9Sstevel@tonic-gate static int
607*7c478bd9Sstevel@tonic-gate iidesc_match(void *data, void *arg)
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate 	iidesc_t *node = data;
610*7c478bd9Sstevel@tonic-gate 	iifind_data_t *iif = arg;
611*7c478bd9Sstevel@tonic-gate 	int i;
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	if (node->ii_type != iif->iif_template->ii_type ||
614*7c478bd9Sstevel@tonic-gate 	    !streq(node->ii_name, iif->iif_template->ii_name) ||
615*7c478bd9Sstevel@tonic-gate 	    node->ii_dtype->t_id != iif->iif_newidx)
616*7c478bd9Sstevel@tonic-gate 		return (0);
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	if ((node->ii_type == II_SVAR || node->ii_type == II_SFUN) &&
619*7c478bd9Sstevel@tonic-gate 	    !streq(node->ii_owner, iif->iif_template->ii_owner))
620*7c478bd9Sstevel@tonic-gate 		return (0);
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	if (node->ii_nargs != iif->iif_template->ii_nargs)
623*7c478bd9Sstevel@tonic-gate 		return (0);
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < node->ii_nargs; i++) {
626*7c478bd9Sstevel@tonic-gate 		if (get_mapping(iif->iif_ta,
627*7c478bd9Sstevel@tonic-gate 		    iif->iif_template->ii_args[i]->t_id) !=
628*7c478bd9Sstevel@tonic-gate 		    node->ii_args[i]->t_id)
629*7c478bd9Sstevel@tonic-gate 			return (0);
630*7c478bd9Sstevel@tonic-gate 	}
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 	if (iif->iif_refmerge) {
633*7c478bd9Sstevel@tonic-gate 		switch (iif->iif_template->ii_type) {
634*7c478bd9Sstevel@tonic-gate 		case II_GFUN:
635*7c478bd9Sstevel@tonic-gate 		case II_SFUN:
636*7c478bd9Sstevel@tonic-gate 		case II_GVAR:
637*7c478bd9Sstevel@tonic-gate 		case II_SVAR:
638*7c478bd9Sstevel@tonic-gate 			debug(3, "suppressing duping of %d %s from %s\n",
639*7c478bd9Sstevel@tonic-gate 			    iif->iif_template->ii_type,
640*7c478bd9Sstevel@tonic-gate 			    iif->iif_template->ii_name,
641*7c478bd9Sstevel@tonic-gate 			    (iif->iif_template->ii_owner ?
642*7c478bd9Sstevel@tonic-gate 			    iif->iif_template->ii_owner : "NULL"));
643*7c478bd9Sstevel@tonic-gate 			return (0);
644*7c478bd9Sstevel@tonic-gate 		case II_NOT:
645*7c478bd9Sstevel@tonic-gate 		case II_PSYM:
646*7c478bd9Sstevel@tonic-gate 		case II_SOU:
647*7c478bd9Sstevel@tonic-gate 		case II_TYPE:
648*7c478bd9Sstevel@tonic-gate 			break;
649*7c478bd9Sstevel@tonic-gate 		}
650*7c478bd9Sstevel@tonic-gate 	}
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	return (-1);
653*7c478bd9Sstevel@tonic-gate }
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate static int
656*7c478bd9Sstevel@tonic-gate merge_type_cb(void *data, void *arg)
657*7c478bd9Sstevel@tonic-gate {
658*7c478bd9Sstevel@tonic-gate 	iidesc_t *sii = data;
659*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = arg;
660*7c478bd9Sstevel@tonic-gate 	iifind_data_t iif;
661*7c478bd9Sstevel@tonic-gate 	tdtrav_cb_f *post;
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	post = (mcd->md_flags & MCD_F_SELFUNIQUIFY ? map_self_post : map_post);
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	/* Map the tdesc nodes */
666*7c478bd9Sstevel@tonic-gate 	(void) iitraverse(sii, &mcd->md_parent->td_curvgen, NULL, map_pre, post,
667*7c478bd9Sstevel@tonic-gate 	    mcd);
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	/* Map the iidesc nodes */
670*7c478bd9Sstevel@tonic-gate 	iif.iif_template = sii;
671*7c478bd9Sstevel@tonic-gate 	iif.iif_ta = mcd->md_ta;
672*7c478bd9Sstevel@tonic-gate 	iif.iif_newidx = get_mapping(mcd->md_ta, sii->ii_dtype->t_id);
673*7c478bd9Sstevel@tonic-gate 	iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE);
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	if (hash_match(mcd->md_parent->td_iihash, sii, iidesc_match,
676*7c478bd9Sstevel@tonic-gate 	    &iif) == 1)
677*7c478bd9Sstevel@tonic-gate 		/* successfully mapped */
678*7c478bd9Sstevel@tonic-gate 		return (1);
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	debug(3, "tba %s (%d)\n", (sii->ii_name ? sii->ii_name : "(anon)"),
681*7c478bd9Sstevel@tonic-gate 	    sii->ii_type);
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	list_add(mcd->md_iitba, sii);
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 	return (0);
686*7c478bd9Sstevel@tonic-gate }
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate static int
689*7c478bd9Sstevel@tonic-gate remap_node(tdesc_t **tgtp, tdesc_t *oldtgt, int selftid, tdesc_t *newself,
690*7c478bd9Sstevel@tonic-gate     merge_cb_data_t *mcd)
691*7c478bd9Sstevel@tonic-gate {
692*7c478bd9Sstevel@tonic-gate 	tdesc_t *tgt = NULL;
693*7c478bd9Sstevel@tonic-gate 	tdesc_t template;
694*7c478bd9Sstevel@tonic-gate 	int oldid = oldtgt->t_id;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	if (oldid == selftid) {
697*7c478bd9Sstevel@tonic-gate 		*tgtp = newself;
698*7c478bd9Sstevel@tonic-gate 		return (1);
699*7c478bd9Sstevel@tonic-gate 	}
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	if ((template.t_id = get_mapping(mcd->md_ta, oldid)) == 0)
702*7c478bd9Sstevel@tonic-gate 		terminate("failed to get mapping for tid %d\n", oldid);
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	if (!hash_find(mcd->md_parent->td_idhash, (void *)&template,
705*7c478bd9Sstevel@tonic-gate 	    (void *)&tgt) && (!(mcd->md_flags & MCD_F_REFMERGE) ||
706*7c478bd9Sstevel@tonic-gate 	    !hash_find(mcd->md_tgt->td_idhash, (void *)&template,
707*7c478bd9Sstevel@tonic-gate 	    (void *)&tgt))) {
708*7c478bd9Sstevel@tonic-gate 		debug(3, "Remap couldn't find %d (from %d)\n", template.t_id,
709*7c478bd9Sstevel@tonic-gate 		    oldid);
710*7c478bd9Sstevel@tonic-gate 		*tgtp = oldtgt;
711*7c478bd9Sstevel@tonic-gate 		list_add(mcd->md_tdtbr, tgtp);
712*7c478bd9Sstevel@tonic-gate 		return (0);
713*7c478bd9Sstevel@tonic-gate 	}
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 	*tgtp = tgt;
716*7c478bd9Sstevel@tonic-gate 	return (1);
717*7c478bd9Sstevel@tonic-gate }
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate static tdesc_t *
720*7c478bd9Sstevel@tonic-gate conjure_template(tdesc_t *old, int newselfid)
721*7c478bd9Sstevel@tonic-gate {
722*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = xcalloc(sizeof (tdesc_t));
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 	new->t_name = old->t_name ? xstrdup(old->t_name) : NULL;
725*7c478bd9Sstevel@tonic-gate 	new->t_type = old->t_type;
726*7c478bd9Sstevel@tonic-gate 	new->t_size = old->t_size;
727*7c478bd9Sstevel@tonic-gate 	new->t_id = newselfid;
728*7c478bd9Sstevel@tonic-gate 	new->t_flags = old->t_flags;
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	return (new);
731*7c478bd9Sstevel@tonic-gate }
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
734*7c478bd9Sstevel@tonic-gate static tdesc_t *
735*7c478bd9Sstevel@tonic-gate conjure_intrinsic(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
736*7c478bd9Sstevel@tonic-gate {
737*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	new->t_intr = xmalloc(sizeof (intr_t));
740*7c478bd9Sstevel@tonic-gate 	bcopy(old->t_intr, new->t_intr, sizeof (intr_t));
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	return (new);
743*7c478bd9Sstevel@tonic-gate }
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate static tdesc_t *
746*7c478bd9Sstevel@tonic-gate conjure_plain(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
747*7c478bd9Sstevel@tonic-gate {
748*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	(void) remap_node(&new->t_tdesc, old->t_tdesc, old->t_id, new, mcd);
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate 	return (new);
753*7c478bd9Sstevel@tonic-gate }
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate static tdesc_t *
756*7c478bd9Sstevel@tonic-gate conjure_function(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
757*7c478bd9Sstevel@tonic-gate {
758*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
759*7c478bd9Sstevel@tonic-gate 	fndef_t *nfn = xmalloc(sizeof (fndef_t));
760*7c478bd9Sstevel@tonic-gate 	fndef_t *ofn = old->t_fndef;
761*7c478bd9Sstevel@tonic-gate 	int i;
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 	(void) remap_node(&nfn->fn_ret, ofn->fn_ret, old->t_id, new, mcd);
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	nfn->fn_nargs = ofn->fn_nargs;
766*7c478bd9Sstevel@tonic-gate 	nfn->fn_vargs = ofn->fn_vargs;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 	if (nfn->fn_nargs > 0)
769*7c478bd9Sstevel@tonic-gate 		nfn->fn_args = xcalloc(sizeof (tdesc_t *) * ofn->fn_nargs);
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ofn->fn_nargs; i++) {
772*7c478bd9Sstevel@tonic-gate 		(void) remap_node(&nfn->fn_args[i], ofn->fn_args[i], old->t_id,
773*7c478bd9Sstevel@tonic-gate 		    new, mcd);
774*7c478bd9Sstevel@tonic-gate 	}
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	new->t_fndef = nfn;
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	return (new);
779*7c478bd9Sstevel@tonic-gate }
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate static tdesc_t *
782*7c478bd9Sstevel@tonic-gate conjure_array(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
783*7c478bd9Sstevel@tonic-gate {
784*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
785*7c478bd9Sstevel@tonic-gate 	ardef_t *nar = xmalloc(sizeof (ardef_t));
786*7c478bd9Sstevel@tonic-gate 	ardef_t *oar = old->t_ardef;
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	(void) remap_node(&nar->ad_contents, oar->ad_contents, old->t_id, new,
789*7c478bd9Sstevel@tonic-gate 	    mcd);
790*7c478bd9Sstevel@tonic-gate 	(void) remap_node(&nar->ad_idxtype, oar->ad_idxtype, old->t_id, new,
791*7c478bd9Sstevel@tonic-gate 	    mcd);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	nar->ad_nelems = oar->ad_nelems;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	new->t_ardef = nar;
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	return (new);
798*7c478bd9Sstevel@tonic-gate }
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate static tdesc_t *
801*7c478bd9Sstevel@tonic-gate conjure_su(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
802*7c478bd9Sstevel@tonic-gate {
803*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
804*7c478bd9Sstevel@tonic-gate 	mlist_t *omem, **nmemp;
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 	for (omem = old->t_members, nmemp = &new->t_members;
807*7c478bd9Sstevel@tonic-gate 	    omem; omem = omem->ml_next, nmemp = &((*nmemp)->ml_next)) {
808*7c478bd9Sstevel@tonic-gate 		*nmemp = xmalloc(sizeof (mlist_t));
809*7c478bd9Sstevel@tonic-gate 		(*nmemp)->ml_offset = omem->ml_offset;
810*7c478bd9Sstevel@tonic-gate 		(*nmemp)->ml_size = omem->ml_size;
811*7c478bd9Sstevel@tonic-gate 		(*nmemp)->ml_name = xstrdup(omem->ml_name);
812*7c478bd9Sstevel@tonic-gate 		(void) remap_node(&((*nmemp)->ml_type), omem->ml_type,
813*7c478bd9Sstevel@tonic-gate 		    old->t_id, new, mcd);
814*7c478bd9Sstevel@tonic-gate 	}
815*7c478bd9Sstevel@tonic-gate 	*nmemp = NULL;
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	return (new);
818*7c478bd9Sstevel@tonic-gate }
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
821*7c478bd9Sstevel@tonic-gate static tdesc_t *
822*7c478bd9Sstevel@tonic-gate conjure_enum(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
823*7c478bd9Sstevel@tonic-gate {
824*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
825*7c478bd9Sstevel@tonic-gate 	elist_t *oel, **nelp;
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 	for (oel = old->t_emem, nelp = &new->t_emem;
828*7c478bd9Sstevel@tonic-gate 	    oel; oel = oel->el_next, nelp = &((*nelp)->el_next)) {
829*7c478bd9Sstevel@tonic-gate 		*nelp = xmalloc(sizeof (elist_t));
830*7c478bd9Sstevel@tonic-gate 		(*nelp)->el_name = xstrdup(oel->el_name);
831*7c478bd9Sstevel@tonic-gate 		(*nelp)->el_number = oel->el_number;
832*7c478bd9Sstevel@tonic-gate 	}
833*7c478bd9Sstevel@tonic-gate 	*nelp = NULL;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 	return (new);
836*7c478bd9Sstevel@tonic-gate }
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
839*7c478bd9Sstevel@tonic-gate static tdesc_t *
840*7c478bd9Sstevel@tonic-gate conjure_forward(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
841*7c478bd9Sstevel@tonic-gate {
842*7c478bd9Sstevel@tonic-gate 	tdesc_t *new = conjure_template(old, newselfid);
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate 	list_add(&mcd->md_tgt->td_fwdlist, new);
845*7c478bd9Sstevel@tonic-gate 
846*7c478bd9Sstevel@tonic-gate 	return (new);
847*7c478bd9Sstevel@tonic-gate }
848*7c478bd9Sstevel@tonic-gate 
849*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
850*7c478bd9Sstevel@tonic-gate static tdesc_t *
851*7c478bd9Sstevel@tonic-gate conjure_assert(tdesc_t *old, int newselfid, merge_cb_data_t *mcd)
852*7c478bd9Sstevel@tonic-gate {
853*7c478bd9Sstevel@tonic-gate 	assert(1 == 0);
854*7c478bd9Sstevel@tonic-gate 	return (NULL);
855*7c478bd9Sstevel@tonic-gate }
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate static iidesc_t *
858*7c478bd9Sstevel@tonic-gate conjure_iidesc(iidesc_t *old, merge_cb_data_t *mcd)
859*7c478bd9Sstevel@tonic-gate {
860*7c478bd9Sstevel@tonic-gate 	iidesc_t *new = iidesc_dup(old);
861*7c478bd9Sstevel@tonic-gate 	int i;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	(void) remap_node(&new->ii_dtype, old->ii_dtype, -1, NULL, mcd);
864*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < new->ii_nargs; i++) {
865*7c478bd9Sstevel@tonic-gate 		(void) remap_node(&new->ii_args[i], old->ii_args[i], -1, NULL,
866*7c478bd9Sstevel@tonic-gate 		    mcd);
867*7c478bd9Sstevel@tonic-gate 	}
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	return (new);
870*7c478bd9Sstevel@tonic-gate }
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate static int
873*7c478bd9Sstevel@tonic-gate fwd_redir(tdesc_t *fwd, tdesc_t **fwdp, void *private)
874*7c478bd9Sstevel@tonic-gate {
875*7c478bd9Sstevel@tonic-gate 	alist_t *map = private;
876*7c478bd9Sstevel@tonic-gate 	tdesc_t *defn;
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	if (!alist_find(map, (void *)fwd, (void **)&defn))
879*7c478bd9Sstevel@tonic-gate 		return (0);
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 	debug(3, "Redirecting an edge to %s\n",
882*7c478bd9Sstevel@tonic-gate 	    (defn->t_name ? defn->t_name : "(anon)"));
883*7c478bd9Sstevel@tonic-gate 
884*7c478bd9Sstevel@tonic-gate 	*fwdp = defn;
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 	return (1);
887*7c478bd9Sstevel@tonic-gate }
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate static tdtrav_cb_f fwd_redir_cbs[] = {
890*7c478bd9Sstevel@tonic-gate 	NULL,
891*7c478bd9Sstevel@tonic-gate 	NULL,			/* intrinsic */
892*7c478bd9Sstevel@tonic-gate 	NULL,			/* pointer */
893*7c478bd9Sstevel@tonic-gate 	NULL,			/* array */
894*7c478bd9Sstevel@tonic-gate 	NULL,			/* function */
895*7c478bd9Sstevel@tonic-gate 	NULL,			/* struct */
896*7c478bd9Sstevel@tonic-gate 	NULL,			/* union */
897*7c478bd9Sstevel@tonic-gate 	NULL,			/* enum */
898*7c478bd9Sstevel@tonic-gate 	fwd_redir,		/* forward */
899*7c478bd9Sstevel@tonic-gate 	NULL,			/* typedef */
900*7c478bd9Sstevel@tonic-gate 	tdtrav_assert,		/* typedef_unres */
901*7c478bd9Sstevel@tonic-gate 	NULL,			/* volatile */
902*7c478bd9Sstevel@tonic-gate 	NULL,			/* const */
903*7c478bd9Sstevel@tonic-gate 	NULL			/* restrict */
904*7c478bd9Sstevel@tonic-gate };
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate typedef struct redir_mstr_data {
907*7c478bd9Sstevel@tonic-gate 	tdata_t *rmd_tgt;
908*7c478bd9Sstevel@tonic-gate 	alist_t *rmd_map;
909*7c478bd9Sstevel@tonic-gate } redir_mstr_data_t;
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate static int
912*7c478bd9Sstevel@tonic-gate redir_mstr_fwd_cb(void *name, void *value, void *arg)
913*7c478bd9Sstevel@tonic-gate {
914*7c478bd9Sstevel@tonic-gate 	tdesc_t *fwd = name;
915*7c478bd9Sstevel@tonic-gate 	int defnid = (int)value;
916*7c478bd9Sstevel@tonic-gate 	redir_mstr_data_t *rmd = arg;
917*7c478bd9Sstevel@tonic-gate 	tdesc_t template;
918*7c478bd9Sstevel@tonic-gate 	tdesc_t *defn;
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	template.t_id = defnid;
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate 	if (!hash_find(rmd->rmd_tgt->td_idhash, (void *)&template,
923*7c478bd9Sstevel@tonic-gate 	    (void *)&defn)) {
924*7c478bd9Sstevel@tonic-gate 		terminate("Couldn't unforward %d (%s)\n", defnid,
925*7c478bd9Sstevel@tonic-gate 		    (defn->t_name ? defn->t_name : "(anon)"));
926*7c478bd9Sstevel@tonic-gate 	}
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	debug(3, "Forward map: resolved %d to %s\n",
929*7c478bd9Sstevel@tonic-gate 	    defnid, (defn->t_name ? defn->t_name : "(anon)"));
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	alist_add(rmd->rmd_map, (void *)fwd, (void *)defn);
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 	return (1);
934*7c478bd9Sstevel@tonic-gate }
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate static void
937*7c478bd9Sstevel@tonic-gate redir_mstr_fwds(merge_cb_data_t *mcd)
938*7c478bd9Sstevel@tonic-gate {
939*7c478bd9Sstevel@tonic-gate 	redir_mstr_data_t rmd;
940*7c478bd9Sstevel@tonic-gate 	alist_t *map = alist_new(NULL, NULL);
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate 	rmd.rmd_tgt = mcd->md_tgt;
943*7c478bd9Sstevel@tonic-gate 	rmd.rmd_map = map;
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate 	if (alist_iter(mcd->md_fdida, redir_mstr_fwd_cb, &rmd)) {
946*7c478bd9Sstevel@tonic-gate 		(void) iitraverse_hash(mcd->md_tgt->td_iihash,
947*7c478bd9Sstevel@tonic-gate 		    &mcd->md_tgt->td_curvgen, fwd_redir_cbs, NULL, NULL, map);
948*7c478bd9Sstevel@tonic-gate 	}
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 	alist_free(map);
951*7c478bd9Sstevel@tonic-gate }
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate static int
954*7c478bd9Sstevel@tonic-gate add_iitba_cb(void *data, void *private)
955*7c478bd9Sstevel@tonic-gate {
956*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = private;
957*7c478bd9Sstevel@tonic-gate 	iidesc_t *tba = data;
958*7c478bd9Sstevel@tonic-gate 	iidesc_t *new;
959*7c478bd9Sstevel@tonic-gate 	iifind_data_t iif;
960*7c478bd9Sstevel@tonic-gate 	int newidx;
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 	newidx = get_mapping(mcd->md_ta, tba->ii_dtype->t_id);
963*7c478bd9Sstevel@tonic-gate 	assert(newidx != -1);
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	(void) list_remove(mcd->md_iitba, data, NULL, NULL);
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	iif.iif_template = tba;
968*7c478bd9Sstevel@tonic-gate 	iif.iif_ta = mcd->md_ta;
969*7c478bd9Sstevel@tonic-gate 	iif.iif_newidx = newidx;
970*7c478bd9Sstevel@tonic-gate 	iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE);
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 	if (hash_match(mcd->md_parent->td_iihash, tba, iidesc_match,
973*7c478bd9Sstevel@tonic-gate 	    &iif) == 1) {
974*7c478bd9Sstevel@tonic-gate 		debug(3, "iidesc_t %s already exists\n",
975*7c478bd9Sstevel@tonic-gate 		    (tba->ii_name ? tba->ii_name : "(anon)"));
976*7c478bd9Sstevel@tonic-gate 		return (1);
977*7c478bd9Sstevel@tonic-gate 	}
978*7c478bd9Sstevel@tonic-gate 
979*7c478bd9Sstevel@tonic-gate 	new = conjure_iidesc(tba, mcd);
980*7c478bd9Sstevel@tonic-gate 	hash_add(mcd->md_tgt->td_iihash, new);
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate 	return (1);
983*7c478bd9Sstevel@tonic-gate }
984*7c478bd9Sstevel@tonic-gate 
985*7c478bd9Sstevel@tonic-gate static int
986*7c478bd9Sstevel@tonic-gate add_tdesc(tdesc_t *oldtdp, int newid, merge_cb_data_t *mcd)
987*7c478bd9Sstevel@tonic-gate {
988*7c478bd9Sstevel@tonic-gate 	tdesc_t *newtdp;
989*7c478bd9Sstevel@tonic-gate 	tdesc_t template;
990*7c478bd9Sstevel@tonic-gate 
991*7c478bd9Sstevel@tonic-gate 	template.t_id = newid;
992*7c478bd9Sstevel@tonic-gate 	assert(hash_find(mcd->md_parent->td_idhash,
993*7c478bd9Sstevel@tonic-gate 	    (void *)&template, NULL) == 0);
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 	debug(3, "trying to conjure %d %s (%d) as %d\n",
996*7c478bd9Sstevel@tonic-gate 	    oldtdp->t_type, (oldtdp->t_name ? oldtdp->t_name : "(anon)"),
997*7c478bd9Sstevel@tonic-gate 	    oldtdp->t_id, newid);
998*7c478bd9Sstevel@tonic-gate 
999*7c478bd9Sstevel@tonic-gate 	if ((newtdp = tdesc_ops[oldtdp->t_type].conjure(oldtdp, newid,
1000*7c478bd9Sstevel@tonic-gate 	    mcd)) == NULL)
1001*7c478bd9Sstevel@tonic-gate 		/* couldn't map everything */
1002*7c478bd9Sstevel@tonic-gate 		return (0);
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 	debug(3, "succeeded\n");
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 	hash_add(mcd->md_tgt->td_idhash, newtdp);
1007*7c478bd9Sstevel@tonic-gate 	hash_add(mcd->md_tgt->td_layouthash, newtdp);
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 	return (1);
1010*7c478bd9Sstevel@tonic-gate }
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate static int
1013*7c478bd9Sstevel@tonic-gate add_tdtba_cb(void *data, void *arg)
1014*7c478bd9Sstevel@tonic-gate {
1015*7c478bd9Sstevel@tonic-gate 	tdesc_t *tdp = data;
1016*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = arg;
1017*7c478bd9Sstevel@tonic-gate 	int newid;
1018*7c478bd9Sstevel@tonic-gate 	int rc;
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	newid = get_mapping(mcd->md_ta, tdp->t_id);
1021*7c478bd9Sstevel@tonic-gate 	assert(newid != -1);
1022*7c478bd9Sstevel@tonic-gate 
1023*7c478bd9Sstevel@tonic-gate 	if ((rc = add_tdesc(tdp, newid, mcd)))
1024*7c478bd9Sstevel@tonic-gate 		hash_remove(mcd->md_tdtba, (void *)tdp);
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 	return (rc);
1027*7c478bd9Sstevel@tonic-gate }
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate static int
1030*7c478bd9Sstevel@tonic-gate add_tdtbr_cb(void *data, void *arg)
1031*7c478bd9Sstevel@tonic-gate {
1032*7c478bd9Sstevel@tonic-gate 	tdesc_t **tdpp = data;
1033*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t *mcd = arg;
1034*7c478bd9Sstevel@tonic-gate 
1035*7c478bd9Sstevel@tonic-gate 	debug(3, "Remapping %s (%d)\n",
1036*7c478bd9Sstevel@tonic-gate 	    ((*tdpp)->t_name ? (*tdpp)->t_name : "(anon)"), (*tdpp)->t_id);
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 	if (!remap_node(tdpp, *tdpp, -1, NULL, mcd))
1039*7c478bd9Sstevel@tonic-gate 		return (0);
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate 	(void) list_remove(mcd->md_tdtbr, (void *)tdpp, NULL, NULL);
1042*7c478bd9Sstevel@tonic-gate 	return (1);
1043*7c478bd9Sstevel@tonic-gate }
1044*7c478bd9Sstevel@tonic-gate 
1045*7c478bd9Sstevel@tonic-gate static void
1046*7c478bd9Sstevel@tonic-gate merge_types(hash_t *src, merge_cb_data_t *mcd)
1047*7c478bd9Sstevel@tonic-gate {
1048*7c478bd9Sstevel@tonic-gate 	list_t *iitba = NULL;
1049*7c478bd9Sstevel@tonic-gate 	list_t *tdtbr = NULL;
1050*7c478bd9Sstevel@tonic-gate 	int iirc, tdrc;
1051*7c478bd9Sstevel@tonic-gate 
1052*7c478bd9Sstevel@tonic-gate 	mcd->md_iitba = &iitba;
1053*7c478bd9Sstevel@tonic-gate 	mcd->md_tdtba = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash,
1054*7c478bd9Sstevel@tonic-gate 	    tdesc_layoutcmp);
1055*7c478bd9Sstevel@tonic-gate 	mcd->md_tdtbr = &tdtbr;
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	(void) hash_iter(src, merge_type_cb, mcd);
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 	tdrc = hash_iter(mcd->md_tdtba, add_tdtba_cb, (void *)mcd);
1060*7c478bd9Sstevel@tonic-gate 	debug(3, "add_tdtba_cb added %d items\n", tdrc);
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate 	iirc = list_iter(*mcd->md_iitba, add_iitba_cb, (void *)mcd);
1063*7c478bd9Sstevel@tonic-gate 	debug(3, "add_iitba_cb added %d items\n", iirc);
1064*7c478bd9Sstevel@tonic-gate 
1065*7c478bd9Sstevel@tonic-gate 	assert(list_count(*mcd->md_iitba) == 0 &&
1066*7c478bd9Sstevel@tonic-gate 	    hash_count(mcd->md_tdtba) == 0);
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 	tdrc = list_iter(*mcd->md_tdtbr, add_tdtbr_cb, (void *)mcd);
1069*7c478bd9Sstevel@tonic-gate 	debug(3, "add_tdtbr_cb added %d items\n", tdrc);
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 	if (list_count(*mcd->md_tdtbr) != 0)
1072*7c478bd9Sstevel@tonic-gate 		terminate("Couldn't remap all nodes\n");
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 	/*
1075*7c478bd9Sstevel@tonic-gate 	 * We now have an alist of master forwards and the ids of the new master
1076*7c478bd9Sstevel@tonic-gate 	 * definitions for those forwards in mcd->md_fdida.  By this point,
1077*7c478bd9Sstevel@tonic-gate 	 * we're guaranteed that all of the master definitions referenced in
1078*7c478bd9Sstevel@tonic-gate 	 * fdida have been added to the master tree.  We now traverse through
1079*7c478bd9Sstevel@tonic-gate 	 * the master tree, redirecting all edges inbound to forwards that have
1080*7c478bd9Sstevel@tonic-gate 	 * definitions to those definitions.
1081*7c478bd9Sstevel@tonic-gate 	 */
1082*7c478bd9Sstevel@tonic-gate 	if (mcd->md_parent == mcd->md_tgt) {
1083*7c478bd9Sstevel@tonic-gate 		redir_mstr_fwds(mcd);
1084*7c478bd9Sstevel@tonic-gate 	}
1085*7c478bd9Sstevel@tonic-gate }
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate void
1088*7c478bd9Sstevel@tonic-gate merge_into_master(tdata_t *cur, tdata_t *mstr, tdata_t *tgt, int selfuniquify)
1089*7c478bd9Sstevel@tonic-gate {
1090*7c478bd9Sstevel@tonic-gate 	merge_cb_data_t mcd;
1091*7c478bd9Sstevel@tonic-gate 
1092*7c478bd9Sstevel@tonic-gate 	cur->td_ref++;
1093*7c478bd9Sstevel@tonic-gate 	mstr->td_ref++;
1094*7c478bd9Sstevel@tonic-gate 	if (tgt)
1095*7c478bd9Sstevel@tonic-gate 		tgt->td_ref++;
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	assert(cur->td_ref == 1 && mstr->td_ref == 1 &&
1098*7c478bd9Sstevel@tonic-gate 	    (tgt == NULL || tgt->td_ref == 1));
1099*7c478bd9Sstevel@tonic-gate 
1100*7c478bd9Sstevel@tonic-gate 	mcd.md_parent = mstr;
1101*7c478bd9Sstevel@tonic-gate 	mcd.md_tgt = (tgt ? tgt : mstr);
1102*7c478bd9Sstevel@tonic-gate 	mcd.md_ta = alist_new(NULL, NULL);
1103*7c478bd9Sstevel@tonic-gate 	mcd.md_fdida = alist_new(NULL, NULL);
1104*7c478bd9Sstevel@tonic-gate 	mcd.md_flags = 0;
1105*7c478bd9Sstevel@tonic-gate 
1106*7c478bd9Sstevel@tonic-gate 	if (selfuniquify)
1107*7c478bd9Sstevel@tonic-gate 		mcd.md_flags |= MCD_F_SELFUNIQUIFY;
1108*7c478bd9Sstevel@tonic-gate 	if (tgt)
1109*7c478bd9Sstevel@tonic-gate 		mcd.md_flags |= MCD_F_REFMERGE;
1110*7c478bd9Sstevel@tonic-gate 
1111*7c478bd9Sstevel@tonic-gate 	mstr->td_curvgen = MAX(mstr->td_curvgen, cur->td_curvgen);
1112*7c478bd9Sstevel@tonic-gate 	mstr->td_curemark = MAX(mstr->td_curemark, cur->td_curemark);
1113*7c478bd9Sstevel@tonic-gate 
1114*7c478bd9Sstevel@tonic-gate 	merge_types(cur->td_iihash, &mcd);
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate 	if (debug_level >= 3) {
1117*7c478bd9Sstevel@tonic-gate 		debug(3, "Type association stats\n");
1118*7c478bd9Sstevel@tonic-gate 		alist_stats(mcd.md_ta, 0);
1119*7c478bd9Sstevel@tonic-gate 		debug(3, "Layout hash stats\n");
1120*7c478bd9Sstevel@tonic-gate 		hash_stats(mcd.md_tgt->td_layouthash, 1);
1121*7c478bd9Sstevel@tonic-gate 	}
1122*7c478bd9Sstevel@tonic-gate 
1123*7c478bd9Sstevel@tonic-gate 	alist_free(mcd.md_fdida);
1124*7c478bd9Sstevel@tonic-gate 	alist_free(mcd.md_ta);
1125*7c478bd9Sstevel@tonic-gate 
1126*7c478bd9Sstevel@tonic-gate 	cur->td_ref--;
1127*7c478bd9Sstevel@tonic-gate 	mstr->td_ref--;
1128*7c478bd9Sstevel@tonic-gate 	if (tgt)
1129*7c478bd9Sstevel@tonic-gate 		tgt->td_ref--;
1130*7c478bd9Sstevel@tonic-gate }
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate tdesc_ops_t tdesc_ops[] = {
1133*7c478bd9Sstevel@tonic-gate 	{ "ERROR! BAD tdesc TYPE", NULL, NULL },
1134*7c478bd9Sstevel@tonic-gate 	{ "intrinsic",		equiv_intrinsic,	conjure_intrinsic },
1135*7c478bd9Sstevel@tonic-gate 	{ "pointer", 		equiv_plain,		conjure_plain },
1136*7c478bd9Sstevel@tonic-gate 	{ "array", 		equiv_array,		conjure_array },
1137*7c478bd9Sstevel@tonic-gate 	{ "function", 		equiv_function,		conjure_function },
1138*7c478bd9Sstevel@tonic-gate 	{ "struct",		equiv_su,		conjure_su },
1139*7c478bd9Sstevel@tonic-gate 	{ "union",		equiv_su,		conjure_su },
1140*7c478bd9Sstevel@tonic-gate 	{ "enum",		equiv_enum,		conjure_enum },
1141*7c478bd9Sstevel@tonic-gate 	{ "forward",		NULL,			conjure_forward },
1142*7c478bd9Sstevel@tonic-gate 	{ "typedef",		equiv_plain,		conjure_plain },
1143*7c478bd9Sstevel@tonic-gate 	{ "typedef_unres",	equiv_assert,		conjure_assert },
1144*7c478bd9Sstevel@tonic-gate 	{ "volatile",		equiv_plain,		conjure_plain },
1145*7c478bd9Sstevel@tonic-gate 	{ "const", 		equiv_plain,		conjure_plain },
1146*7c478bd9Sstevel@tonic-gate 	{ "restrict",		equiv_plain,		conjure_plain }
1147*7c478bd9Sstevel@tonic-gate };
1148