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