10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1882Sjohnlev * Common Development and Distribution License (the "License"). 6*1882Sjohnlev * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1882Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * This file contains routines that merge one tdata_t tree, called the child, 300Sstevel@tonic-gate * into another, called the parent. Note that these names are used mainly for 310Sstevel@tonic-gate * convenience and to represent the direction of the merge. They are not meant 320Sstevel@tonic-gate * to imply any relationship between the tdata_t graphs prior to the merge. 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * tdata_t structures contain two main elements - a hash of iidesc_t nodes, and 350Sstevel@tonic-gate * a directed graph of tdesc_t nodes, pointed to by the iidesc_t nodes. Simply 360Sstevel@tonic-gate * put, we merge the tdesc_t graphs, followed by the iidesc_t nodes, and then we 370Sstevel@tonic-gate * clean up loose ends. 380Sstevel@tonic-gate * 390Sstevel@tonic-gate * The algorithm is as follows: 400Sstevel@tonic-gate * 410Sstevel@tonic-gate * 1. Mapping iidesc_t nodes 420Sstevel@tonic-gate * 430Sstevel@tonic-gate * For each child iidesc_t node, we first try to map its tdesc_t subgraph 440Sstevel@tonic-gate * against the tdesc_t graph in the parent. For each node in the child subgraph 450Sstevel@tonic-gate * that exists in the parent, a mapping between the two (between their type IDs) 460Sstevel@tonic-gate * is established. For the child nodes that cannot be mapped onto existing 470Sstevel@tonic-gate * parent nodes, a mapping is established between the child node ID and a 480Sstevel@tonic-gate * newly-allocated ID that the node will use when it is re-created in the 490Sstevel@tonic-gate * parent. These unmappable nodes are added to the md_tdtba (tdesc_t To Be 500Sstevel@tonic-gate * Added) hash, which tracks nodes that need to be created in the parent. 510Sstevel@tonic-gate * 520Sstevel@tonic-gate * If all of the nodes in the subgraph for an iidesc_t in the child can be 530Sstevel@tonic-gate * mapped to existing nodes in the parent, then we can try to map the child 540Sstevel@tonic-gate * iidesc_t onto an iidesc_t in the parent. If we cannot find an equivalent 550Sstevel@tonic-gate * iidesc_t, or if we were not able to completely map the tdesc_t subgraph(s), 560Sstevel@tonic-gate * then we add this iidesc_t to the md_iitba (iidesc_t To Be Added) list. This 570Sstevel@tonic-gate * list tracks iidesc_t nodes that are to be created in the parent. 580Sstevel@tonic-gate * 590Sstevel@tonic-gate * While visiting the tdesc_t nodes, we may discover a forward declaration (a 600Sstevel@tonic-gate * FORWARD tdesc_t) in the parent that is resolved in the child. That is, there 610Sstevel@tonic-gate * may be a structure or union definition in the child with the same name as the 620Sstevel@tonic-gate * forward declaration in the parent. If we find such a node, we record an 630Sstevel@tonic-gate * association in the md_fdida (Forward => Definition ID Association) list 640Sstevel@tonic-gate * between the parent ID of the forward declaration and the ID that the 650Sstevel@tonic-gate * definition will use when re-created in the parent. 660Sstevel@tonic-gate * 670Sstevel@tonic-gate * 2. Creating new tdesc_t nodes (the md_tdtba hash) 680Sstevel@tonic-gate * 690Sstevel@tonic-gate * We have now attempted to map all tdesc_t nodes from the child into the 700Sstevel@tonic-gate * parent, and have, in md_tdtba, a hash of all tdesc_t nodes that need to be 710Sstevel@tonic-gate * created (or, as we so wittily call it, conjured) in the parent. We iterate 720Sstevel@tonic-gate * through this hash, creating the indicated tdesc_t nodes. For a given tdesc_t 730Sstevel@tonic-gate * node, conjuring requires two steps - the copying of the common tdesc_t data 740Sstevel@tonic-gate * (name, type, etc) from the child node, and the creation of links from the 750Sstevel@tonic-gate * newly-created node to the parent equivalents of other tdesc_t nodes pointed 760Sstevel@tonic-gate * to by node being conjured. Note that in some cases, the targets of these 770Sstevel@tonic-gate * links will be on the md_tdtba hash themselves, and may not have been created 780Sstevel@tonic-gate * yet. As such, we can't establish the links from these new nodes into the 790Sstevel@tonic-gate * parent graph. We therefore conjure them with links to nodes in the *child* 800Sstevel@tonic-gate * graph, and add pointers to the links to be created to the md_tdtbr (tdesc_t 810Sstevel@tonic-gate * To Be Remapped) hash. For example, a POINTER tdesc_t that could not be 820Sstevel@tonic-gate * resolved would have its &tdesc_t->t_tdesc added to md_tdtbr. 830Sstevel@tonic-gate * 840Sstevel@tonic-gate * 3. Creating new iidesc_t nodes (the md_iitba list) 850Sstevel@tonic-gate * 860Sstevel@tonic-gate * When we have completed step 2, all tdesc_t nodes have been created (or 870Sstevel@tonic-gate * already existed) in the parent. Some of them may have incorrect links (the 880Sstevel@tonic-gate * members of the md_tdtbr list), but they've all been created. As such, we can 890Sstevel@tonic-gate * create all of the iidesc_t nodes, as we can attach the tdesc_t subgraph 900Sstevel@tonic-gate * pointers correctly. We create each node, and attach the pointers to the 910Sstevel@tonic-gate * appropriate parts of the parent tdesc_t graph. 920Sstevel@tonic-gate * 930Sstevel@tonic-gate * 4. Resolving newly-created tdesc_t node links (the md_tdtbr list) 940Sstevel@tonic-gate * 950Sstevel@tonic-gate * As in step 3, we rely on the fact that all of the tdesc_t nodes have been 960Sstevel@tonic-gate * created. Each entry in the md_tdtbr list is a pointer to where a link into 970Sstevel@tonic-gate * the parent will be established. As saved in the md_tdtbr list, these 980Sstevel@tonic-gate * pointers point into the child tdesc_t subgraph. We can thus get the target 990Sstevel@tonic-gate * type ID from the child, look at the ID mapping to determine the desired link 1000Sstevel@tonic-gate * target, and redirect the link accordingly. 1010Sstevel@tonic-gate * 1020Sstevel@tonic-gate * 5. Parent => child forward declaration resolution 1030Sstevel@tonic-gate * 1040Sstevel@tonic-gate * If entries were made in the md_fdida list in step 1, we have forward 1050Sstevel@tonic-gate * declarations in the parent that need to be resolved to their definitions 1060Sstevel@tonic-gate * re-created in step 2 from the child. Using the md_fdida list, we can locate 1070Sstevel@tonic-gate * the definition for the forward declaration, and we can redirect all inbound 1080Sstevel@tonic-gate * edges to the forward declaration node to the actual definition. 1090Sstevel@tonic-gate * 1100Sstevel@tonic-gate * A pox on the house of anyone who changes the algorithm without updating 1110Sstevel@tonic-gate * this comment. 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate #include <stdio.h> 1150Sstevel@tonic-gate #include <strings.h> 1160Sstevel@tonic-gate #include <assert.h> 1170Sstevel@tonic-gate #include <pthread.h> 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate #include "ctf_headers.h" 1200Sstevel@tonic-gate #include "ctftools.h" 1210Sstevel@tonic-gate #include "list.h" 1220Sstevel@tonic-gate #include "alist.h" 1230Sstevel@tonic-gate #include "memory.h" 1240Sstevel@tonic-gate #include "traverse.h" 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate typedef struct equiv_data equiv_data_t; 1270Sstevel@tonic-gate typedef struct merge_cb_data merge_cb_data_t; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate /* 1300Sstevel@tonic-gate * There are two traversals in this file, for equivalency and for tdesc_t 1310Sstevel@tonic-gate * re-creation, that do not fit into the tdtraverse() framework. We have our 1320Sstevel@tonic-gate * own traversal mechanism and ops vector here for those two cases. 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate typedef struct tdesc_ops { 1350Sstevel@tonic-gate char *name; 1360Sstevel@tonic-gate int (*equiv)(tdesc_t *, tdesc_t *, equiv_data_t *); 1370Sstevel@tonic-gate tdesc_t *(*conjure)(tdesc_t *, int, merge_cb_data_t *); 1380Sstevel@tonic-gate } tdesc_ops_t; 1390Sstevel@tonic-gate extern tdesc_ops_t tdesc_ops[]; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* 1420Sstevel@tonic-gate * The workhorse structure of tdata_t merging. Holds all lists of nodes to be 1430Sstevel@tonic-gate * processed during various phases of the merge algorithm. 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate struct merge_cb_data { 1460Sstevel@tonic-gate tdata_t *md_parent; 1470Sstevel@tonic-gate tdata_t *md_tgt; 1480Sstevel@tonic-gate alist_t *md_ta; /* Type Association */ 1490Sstevel@tonic-gate alist_t *md_fdida; /* Forward -> Definition ID Association */ 1500Sstevel@tonic-gate list_t **md_iitba; /* iidesc_t nodes To Be Added to the parent */ 1510Sstevel@tonic-gate hash_t *md_tdtba; /* tdesc_t nodes To Be Added to the parent */ 1520Sstevel@tonic-gate list_t **md_tdtbr; /* tdesc_t nodes To Be Remapped */ 1530Sstevel@tonic-gate int md_flags; 1540Sstevel@tonic-gate }; /* merge_cb_data_t */ 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate /* 1570Sstevel@tonic-gate * When we first create a tdata_t from stabs data, we will have duplicate nodes. 1580Sstevel@tonic-gate * Normal merges, however, assume that the child tdata_t is already self-unique, 1590Sstevel@tonic-gate * and for speed reasons do not attempt to self-uniquify. If this flag is set, 1600Sstevel@tonic-gate * the merge algorithm will self-uniquify by avoiding the insertion of 1610Sstevel@tonic-gate * duplicates in the md_tdtdba list. 1620Sstevel@tonic-gate */ 1630Sstevel@tonic-gate #define MCD_F_SELFUNIQUIFY 0x1 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate /* 1660Sstevel@tonic-gate * When we merge the CTF data for the modules, we don't want it to contain any 1670Sstevel@tonic-gate * data that can be found in the reference module (usually genunix). If this 1680Sstevel@tonic-gate * flag is set, we're doing a merge between the fully merged tdata_t for this 1690Sstevel@tonic-gate * module and the tdata_t for the reference module, with the data unique to this 1700Sstevel@tonic-gate * module ending up in a third tdata_t. It is this third tdata_t that will end 1710Sstevel@tonic-gate * up in the .SUNW_ctf section for the module. 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate #define MCD_F_REFMERGE 0x2 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* 1760Sstevel@tonic-gate * Mapping of child type IDs to parent type IDs 1770Sstevel@tonic-gate */ 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate static void 1800Sstevel@tonic-gate add_mapping(alist_t *ta, tid_t srcid, tid_t tgtid) 1810Sstevel@tonic-gate { 1820Sstevel@tonic-gate debug(3, "Adding mapping %u => %u\n", srcid, tgtid); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate assert(!alist_find(ta, (void *)srcid, NULL)); 1850Sstevel@tonic-gate assert(srcid != 0 && tgtid != 0); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate alist_add(ta, (void *)srcid, (void *)tgtid); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate static tid_t 1910Sstevel@tonic-gate get_mapping(alist_t *ta, int srcid) 1920Sstevel@tonic-gate { 1930Sstevel@tonic-gate long ltgtid; 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (alist_find(ta, (void *)srcid, (void **)<gtid)) 1960Sstevel@tonic-gate return ((int)ltgtid); 1970Sstevel@tonic-gate else 1980Sstevel@tonic-gate return (0); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * Determining equivalence of tdesc_t subgraphs 2030Sstevel@tonic-gate */ 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate struct equiv_data { 2060Sstevel@tonic-gate alist_t *ed_ta; 2070Sstevel@tonic-gate tdesc_t *ed_node; 2080Sstevel@tonic-gate tdesc_t *ed_tgt; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate int ed_clear_mark; 2110Sstevel@tonic-gate int ed_cur_mark; 2120Sstevel@tonic-gate int ed_selfuniquify; 2130Sstevel@tonic-gate }; /* equiv_data_t */ 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate static int equiv_node(tdesc_t *, tdesc_t *, equiv_data_t *); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /*ARGSUSED2*/ 2180Sstevel@tonic-gate static int 2190Sstevel@tonic-gate equiv_intrinsic(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2200Sstevel@tonic-gate { 2210Sstevel@tonic-gate intr_t *si = stdp->t_intr; 2220Sstevel@tonic-gate intr_t *ti = ttdp->t_intr; 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate if (si->intr_type != ti->intr_type || 2250Sstevel@tonic-gate si->intr_signed != ti->intr_signed || 2260Sstevel@tonic-gate si->intr_offset != ti->intr_offset || 2270Sstevel@tonic-gate si->intr_nbits != ti->intr_nbits) 2280Sstevel@tonic-gate return (0); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (si->intr_type == INTR_INT && 2310Sstevel@tonic-gate si->intr_iformat != ti->intr_iformat) 2320Sstevel@tonic-gate return (0); 2330Sstevel@tonic-gate else if (si->intr_type == INTR_REAL && 2340Sstevel@tonic-gate si->intr_fformat != ti->intr_fformat) 2350Sstevel@tonic-gate return (0); 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate return (1); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate static int 2410Sstevel@tonic-gate equiv_plain(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate return (equiv_node(stdp->t_tdesc, ttdp->t_tdesc, ed)); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate static int 2470Sstevel@tonic-gate equiv_function(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2480Sstevel@tonic-gate { 2490Sstevel@tonic-gate fndef_t *fn1 = stdp->t_fndef, *fn2 = ttdp->t_fndef; 2500Sstevel@tonic-gate int i; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (fn1->fn_nargs != fn2->fn_nargs || 2530Sstevel@tonic-gate fn1->fn_vargs != fn2->fn_vargs) 2540Sstevel@tonic-gate return (0); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate if (!equiv_node(fn1->fn_ret, fn2->fn_ret, ed)) 2570Sstevel@tonic-gate return (0); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate for (i = 0; i < fn1->fn_nargs; i++) { 2600Sstevel@tonic-gate if (!equiv_node(fn1->fn_args[i], fn2->fn_args[i], ed)) 2610Sstevel@tonic-gate return (0); 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate return (1); 2650Sstevel@tonic-gate } 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate static int 2680Sstevel@tonic-gate equiv_array(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2690Sstevel@tonic-gate { 2700Sstevel@tonic-gate ardef_t *ar1 = stdp->t_ardef, *ar2 = ttdp->t_ardef; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate if (!equiv_node(ar1->ad_contents, ar2->ad_contents, ed) || 2730Sstevel@tonic-gate !equiv_node(ar1->ad_idxtype, ar2->ad_idxtype, ed)) 2740Sstevel@tonic-gate return (0); 2750Sstevel@tonic-gate 2760Sstevel@tonic-gate if (ar1->ad_nelems != ar2->ad_nelems) 2770Sstevel@tonic-gate return (0); 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate return (1); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate static int 2830Sstevel@tonic-gate equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2840Sstevel@tonic-gate { 2850Sstevel@tonic-gate mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members; 2860Sstevel@tonic-gate mlist_t *olm1 = NULL; 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate while (ml1 && ml2) { 2890Sstevel@tonic-gate if (ml1->ml_offset != ml2->ml_offset || 2900Sstevel@tonic-gate strcmp(ml1->ml_name, ml2->ml_name) != 0) 2910Sstevel@tonic-gate return (0); 2920Sstevel@tonic-gate 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * Don't do the recursive equivalency checking more than 2950Sstevel@tonic-gate * we have to. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate if (olm1 == NULL || olm1->ml_type->t_id != ml1->ml_type->t_id) { 2980Sstevel@tonic-gate if (ml1->ml_size != ml2->ml_size || 2990Sstevel@tonic-gate !equiv_node(ml1->ml_type, ml2->ml_type, ed)) 3000Sstevel@tonic-gate return (0); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate olm1 = ml1; 3040Sstevel@tonic-gate ml1 = ml1->ml_next; 3050Sstevel@tonic-gate ml2 = ml2->ml_next; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate if (ml1 || ml2) 3090Sstevel@tonic-gate return (0); 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate return (1); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /*ARGSUSED2*/ 3150Sstevel@tonic-gate static int 3160Sstevel@tonic-gate equiv_enum(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 3170Sstevel@tonic-gate { 3180Sstevel@tonic-gate elist_t *el1 = stdp->t_emem; 3190Sstevel@tonic-gate elist_t *el2 = ttdp->t_emem; 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate while (el1 && el2) { 3220Sstevel@tonic-gate if (el1->el_number != el2->el_number || 3230Sstevel@tonic-gate strcmp(el1->el_name, el2->el_name) != 0) 3240Sstevel@tonic-gate return (0); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate el1 = el1->el_next; 3270Sstevel@tonic-gate el2 = el2->el_next; 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate if (el1 || el2) 3310Sstevel@tonic-gate return (0); 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate return (1); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /*ARGSUSED*/ 3370Sstevel@tonic-gate static int 3380Sstevel@tonic-gate equiv_assert(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate /* foul, evil, and very bad - this is a "shouldn't happen" */ 3410Sstevel@tonic-gate assert(1 == 0); 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate return (0); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate static int 3470Sstevel@tonic-gate fwd_equiv(tdesc_t *ctdp, tdesc_t *mtdp) 3480Sstevel@tonic-gate { 3490Sstevel@tonic-gate tdesc_t *defn = (ctdp->t_type == FORWARD ? mtdp : ctdp); 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate return (defn->t_type == STRUCT || defn->t_type == UNION); 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate static int 3550Sstevel@tonic-gate equiv_node(tdesc_t *ctdp, tdesc_t *mtdp, equiv_data_t *ed) 3560Sstevel@tonic-gate { 3570Sstevel@tonic-gate int (*equiv)(); 3580Sstevel@tonic-gate int mapping; 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate if (ctdp->t_emark > ed->ed_clear_mark || 3610Sstevel@tonic-gate mtdp->t_emark > ed->ed_clear_mark) 3620Sstevel@tonic-gate return (ctdp->t_emark == mtdp->t_emark); 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate /* 3650Sstevel@tonic-gate * In normal (non-self-uniquify) mode, we don't want to do equivalency 3660Sstevel@tonic-gate * checking on a subgraph that has already been checked. If a mapping 3670Sstevel@tonic-gate * has already been established for a given child node, we can simply 3680Sstevel@tonic-gate * compare the mapping for the child node with the ID of the parent 3690Sstevel@tonic-gate * node. If we are in self-uniquify mode, then we're comparing two 3700Sstevel@tonic-gate * subgraphs within the child graph, and thus need to ignore any 3710Sstevel@tonic-gate * type mappings that have been created, as they are only valid into the 3720Sstevel@tonic-gate * parent. 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate if ((mapping = get_mapping(ed->ed_ta, ctdp->t_id)) > 0 && 3750Sstevel@tonic-gate mapping == mtdp->t_id && !ed->ed_selfuniquify) 3760Sstevel@tonic-gate return (1); 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate if (!streq(ctdp->t_name, mtdp->t_name)) 3790Sstevel@tonic-gate return (0); 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate if (ctdp->t_type != mtdp->t_type) { 3820Sstevel@tonic-gate if (ctdp->t_type == FORWARD || mtdp->t_type == FORWARD) 3830Sstevel@tonic-gate return (fwd_equiv(ctdp, mtdp)); 3840Sstevel@tonic-gate else 3850Sstevel@tonic-gate return (0); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate ctdp->t_emark = ed->ed_cur_mark; 3890Sstevel@tonic-gate mtdp->t_emark = ed->ed_cur_mark; 3900Sstevel@tonic-gate ed->ed_cur_mark++; 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate if ((equiv = tdesc_ops[ctdp->t_type].equiv) != NULL) 3930Sstevel@tonic-gate return (equiv(ctdp, mtdp, ed)); 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate return (1); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * We perform an equivalency check on two subgraphs by traversing through them 4000Sstevel@tonic-gate * in lockstep. If a given node is equivalent in both the parent and the child, 4010Sstevel@tonic-gate * we mark it in both subgraphs, using the t_emark field, with a monotonically 4020Sstevel@tonic-gate * increasing number. If, in the course of the traversal, we reach a node that 4030Sstevel@tonic-gate * we have visited and numbered during this equivalency check, we have a cycle. 4040Sstevel@tonic-gate * If the previously-visited nodes don't have the same emark, then the edges 4050Sstevel@tonic-gate * that brought us to these nodes are not equivalent, and so the check ends. 4060Sstevel@tonic-gate * If the emarks are the same, the edges are equivalent. We then backtrack and 4070Sstevel@tonic-gate * continue the traversal. If we have exhausted all edges in the subgraph, and 4080Sstevel@tonic-gate * have not found any inequivalent nodes, then the subgraphs are equivalent. 4090Sstevel@tonic-gate */ 4100Sstevel@tonic-gate static int 4110Sstevel@tonic-gate equiv_cb(void *bucket, void *arg) 4120Sstevel@tonic-gate { 4130Sstevel@tonic-gate equiv_data_t *ed = arg; 4140Sstevel@tonic-gate tdesc_t *mtdp = bucket; 4150Sstevel@tonic-gate tdesc_t *ctdp = ed->ed_node; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate ed->ed_clear_mark = ed->ed_cur_mark + 1; 4180Sstevel@tonic-gate ed->ed_cur_mark = ed->ed_clear_mark + 1; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate if (equiv_node(ctdp, mtdp, ed)) { 4210Sstevel@tonic-gate debug(3, "equiv_node matched %d %d\n", ctdp->t_id, mtdp->t_id); 4220Sstevel@tonic-gate ed->ed_tgt = mtdp; 4230Sstevel@tonic-gate /* matched. stop looking */ 4240Sstevel@tonic-gate return (-1); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate return (0); 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate /*ARGSUSED1*/ 4310Sstevel@tonic-gate static int 4320Sstevel@tonic-gate map_td_tree_pre(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4330Sstevel@tonic-gate { 4340Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate if (get_mapping(mcd->md_ta, ctdp->t_id) > 0) 4370Sstevel@tonic-gate return (0); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate return (1); 4400Sstevel@tonic-gate } 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate /*ARGSUSED1*/ 4430Sstevel@tonic-gate static int 4440Sstevel@tonic-gate map_td_tree_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4450Sstevel@tonic-gate { 4460Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4470Sstevel@tonic-gate equiv_data_t ed; 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 4500Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 4510Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 4520Sstevel@tonic-gate ed.ed_node = ctdp; 4530Sstevel@tonic-gate ed.ed_selfuniquify = 0; 4540Sstevel@tonic-gate 455*1882Sjohnlev debug(3, "map_td_tree_post on %d %s\n", ctdp->t_id, tdesc_name(ctdp)); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate if (hash_find_iter(mcd->md_parent->td_layouthash, ctdp, 4580Sstevel@tonic-gate equiv_cb, &ed) < 0) { 4590Sstevel@tonic-gate /* We found an equivalent node */ 4600Sstevel@tonic-gate if (ed.ed_tgt->t_type == FORWARD && ctdp->t_type != FORWARD) { 4610Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate debug(3, "Creating new defn type %d\n", id); 4640Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 4650Sstevel@tonic-gate alist_add(mcd->md_fdida, (void *)(ulong_t)ed.ed_tgt, 4660Sstevel@tonic-gate (void *)(ulong_t)id); 4670Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 4680Sstevel@tonic-gate } else 4690Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, ed.ed_tgt->t_id); 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_parent->td_idhash, 4720Sstevel@tonic-gate equiv_cb, &ed) < 0) { 4730Sstevel@tonic-gate /* 4740Sstevel@tonic-gate * We didn't find an equivalent node by looking through the 4750Sstevel@tonic-gate * layout hash, but we somehow found it by performing an 4760Sstevel@tonic-gate * exhaustive search through the entire graph. This usually 4770Sstevel@tonic-gate * means that the "name" hash function is broken. 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate terminate("Second pass for %d (%s) == %d\n", ctdp->t_id, 480*1882Sjohnlev tdesc_name(ctdp), ed.ed_tgt->t_id); 4810Sstevel@tonic-gate } else { 4820Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 4850Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 4860Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate return (1); 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate /*ARGSUSED1*/ 4950Sstevel@tonic-gate static int 4960Sstevel@tonic-gate map_td_tree_self_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4990Sstevel@tonic-gate equiv_data_t ed; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 5020Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 5030Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 5040Sstevel@tonic-gate ed.ed_node = ctdp; 5050Sstevel@tonic-gate ed.ed_selfuniquify = 1; 5060Sstevel@tonic-gate ed.ed_tgt = NULL; 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate if (hash_find_iter(mcd->md_tdtba, ctdp, equiv_cb, &ed) < 0) { 5090Sstevel@tonic-gate debug(3, "Self check found %d in %d\n", ctdp->t_id, 5100Sstevel@tonic-gate ed.ed_tgt->t_id); 5110Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, 5120Sstevel@tonic-gate get_mapping(mcd->md_ta, ed.ed_tgt->t_id)); 5130Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_tdtba, 5140Sstevel@tonic-gate equiv_cb, &ed) < 0) { 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * We didn't find an equivalent node using the quick way (going 5170Sstevel@tonic-gate * through the hash normally), but we did find it by iterating 5180Sstevel@tonic-gate * through the entire hash. This usually means that the hash 5190Sstevel@tonic-gate * function is broken. 5200Sstevel@tonic-gate */ 5210Sstevel@tonic-gate terminate("Self-unique second pass for %d (%s) == %d\n", 522*1882Sjohnlev ctdp->t_id, tdesc_name(ctdp), ed.ed_tgt->t_id); 5230Sstevel@tonic-gate } else { 5240Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 5270Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 5280Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate return (1); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate static tdtrav_cb_f map_pre[] = { 5370Sstevel@tonic-gate NULL, 5380Sstevel@tonic-gate map_td_tree_pre, /* intrinsic */ 5390Sstevel@tonic-gate map_td_tree_pre, /* pointer */ 5400Sstevel@tonic-gate map_td_tree_pre, /* array */ 5410Sstevel@tonic-gate map_td_tree_pre, /* function */ 5420Sstevel@tonic-gate map_td_tree_pre, /* struct */ 5430Sstevel@tonic-gate map_td_tree_pre, /* union */ 5440Sstevel@tonic-gate map_td_tree_pre, /* enum */ 5450Sstevel@tonic-gate map_td_tree_pre, /* forward */ 5460Sstevel@tonic-gate map_td_tree_pre, /* typedef */ 5470Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5480Sstevel@tonic-gate map_td_tree_pre, /* volatile */ 5490Sstevel@tonic-gate map_td_tree_pre, /* const */ 5500Sstevel@tonic-gate map_td_tree_pre /* restrict */ 5510Sstevel@tonic-gate }; 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate static tdtrav_cb_f map_post[] = { 5540Sstevel@tonic-gate NULL, 5550Sstevel@tonic-gate map_td_tree_post, /* intrinsic */ 5560Sstevel@tonic-gate map_td_tree_post, /* pointer */ 5570Sstevel@tonic-gate map_td_tree_post, /* array */ 5580Sstevel@tonic-gate map_td_tree_post, /* function */ 5590Sstevel@tonic-gate map_td_tree_post, /* struct */ 5600Sstevel@tonic-gate map_td_tree_post, /* union */ 5610Sstevel@tonic-gate map_td_tree_post, /* enum */ 5620Sstevel@tonic-gate map_td_tree_post, /* forward */ 5630Sstevel@tonic-gate map_td_tree_post, /* typedef */ 5640Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5650Sstevel@tonic-gate map_td_tree_post, /* volatile */ 5660Sstevel@tonic-gate map_td_tree_post, /* const */ 5670Sstevel@tonic-gate map_td_tree_post /* restrict */ 5680Sstevel@tonic-gate }; 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate static tdtrav_cb_f map_self_post[] = { 5710Sstevel@tonic-gate NULL, 5720Sstevel@tonic-gate map_td_tree_self_post, /* intrinsic */ 5730Sstevel@tonic-gate map_td_tree_self_post, /* pointer */ 5740Sstevel@tonic-gate map_td_tree_self_post, /* array */ 5750Sstevel@tonic-gate map_td_tree_self_post, /* function */ 5760Sstevel@tonic-gate map_td_tree_self_post, /* struct */ 5770Sstevel@tonic-gate map_td_tree_self_post, /* union */ 5780Sstevel@tonic-gate map_td_tree_self_post, /* enum */ 5790Sstevel@tonic-gate map_td_tree_self_post, /* forward */ 5800Sstevel@tonic-gate map_td_tree_self_post, /* typedef */ 5810Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5820Sstevel@tonic-gate map_td_tree_self_post, /* volatile */ 5830Sstevel@tonic-gate map_td_tree_self_post, /* const */ 5840Sstevel@tonic-gate map_td_tree_self_post /* restrict */ 5850Sstevel@tonic-gate }; 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate /* 5880Sstevel@tonic-gate * Determining equivalence of iidesc_t nodes 5890Sstevel@tonic-gate */ 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate typedef struct iifind_data { 5920Sstevel@tonic-gate iidesc_t *iif_template; 5930Sstevel@tonic-gate alist_t *iif_ta; 5940Sstevel@tonic-gate int iif_newidx; 5950Sstevel@tonic-gate int iif_refmerge; 5960Sstevel@tonic-gate } iifind_data_t; 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate /* 5990Sstevel@tonic-gate * Check to see if this iidesc_t (node) - the current one on the list we're 6000Sstevel@tonic-gate * iterating through - matches the target one (iif->iif_template). Return -1 6010Sstevel@tonic-gate * if it matches, to stop the iteration. 6020Sstevel@tonic-gate */ 6030Sstevel@tonic-gate static int 6040Sstevel@tonic-gate iidesc_match(void *data, void *arg) 6050Sstevel@tonic-gate { 6060Sstevel@tonic-gate iidesc_t *node = data; 6070Sstevel@tonic-gate iifind_data_t *iif = arg; 6080Sstevel@tonic-gate int i; 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate if (node->ii_type != iif->iif_template->ii_type || 6110Sstevel@tonic-gate !streq(node->ii_name, iif->iif_template->ii_name) || 6120Sstevel@tonic-gate node->ii_dtype->t_id != iif->iif_newidx) 6130Sstevel@tonic-gate return (0); 6140Sstevel@tonic-gate 6150Sstevel@tonic-gate if ((node->ii_type == II_SVAR || node->ii_type == II_SFUN) && 6160Sstevel@tonic-gate !streq(node->ii_owner, iif->iif_template->ii_owner)) 6170Sstevel@tonic-gate return (0); 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate if (node->ii_nargs != iif->iif_template->ii_nargs) 6200Sstevel@tonic-gate return (0); 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate for (i = 0; i < node->ii_nargs; i++) { 6230Sstevel@tonic-gate if (get_mapping(iif->iif_ta, 6240Sstevel@tonic-gate iif->iif_template->ii_args[i]->t_id) != 6250Sstevel@tonic-gate node->ii_args[i]->t_id) 6260Sstevel@tonic-gate return (0); 6270Sstevel@tonic-gate } 6280Sstevel@tonic-gate 6290Sstevel@tonic-gate if (iif->iif_refmerge) { 6300Sstevel@tonic-gate switch (iif->iif_template->ii_type) { 6310Sstevel@tonic-gate case II_GFUN: 6320Sstevel@tonic-gate case II_SFUN: 6330Sstevel@tonic-gate case II_GVAR: 6340Sstevel@tonic-gate case II_SVAR: 6350Sstevel@tonic-gate debug(3, "suppressing duping of %d %s from %s\n", 6360Sstevel@tonic-gate iif->iif_template->ii_type, 6370Sstevel@tonic-gate iif->iif_template->ii_name, 6380Sstevel@tonic-gate (iif->iif_template->ii_owner ? 6390Sstevel@tonic-gate iif->iif_template->ii_owner : "NULL")); 6400Sstevel@tonic-gate return (0); 6410Sstevel@tonic-gate case II_NOT: 6420Sstevel@tonic-gate case II_PSYM: 6430Sstevel@tonic-gate case II_SOU: 6440Sstevel@tonic-gate case II_TYPE: 6450Sstevel@tonic-gate break; 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate return (-1); 6500Sstevel@tonic-gate } 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate static int 6530Sstevel@tonic-gate merge_type_cb(void *data, void *arg) 6540Sstevel@tonic-gate { 6550Sstevel@tonic-gate iidesc_t *sii = data; 6560Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 6570Sstevel@tonic-gate iifind_data_t iif; 6580Sstevel@tonic-gate tdtrav_cb_f *post; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate post = (mcd->md_flags & MCD_F_SELFUNIQUIFY ? map_self_post : map_post); 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate /* Map the tdesc nodes */ 6630Sstevel@tonic-gate (void) iitraverse(sii, &mcd->md_parent->td_curvgen, NULL, map_pre, post, 6640Sstevel@tonic-gate mcd); 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /* Map the iidesc nodes */ 6670Sstevel@tonic-gate iif.iif_template = sii; 6680Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 6690Sstevel@tonic-gate iif.iif_newidx = get_mapping(mcd->md_ta, sii->ii_dtype->t_id); 6700Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, sii, iidesc_match, 6730Sstevel@tonic-gate &iif) == 1) 6740Sstevel@tonic-gate /* successfully mapped */ 6750Sstevel@tonic-gate return (1); 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate debug(3, "tba %s (%d)\n", (sii->ii_name ? sii->ii_name : "(anon)"), 6780Sstevel@tonic-gate sii->ii_type); 6790Sstevel@tonic-gate 6800Sstevel@tonic-gate list_add(mcd->md_iitba, sii); 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate return (0); 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate static int 6860Sstevel@tonic-gate remap_node(tdesc_t **tgtp, tdesc_t *oldtgt, int selftid, tdesc_t *newself, 6870Sstevel@tonic-gate merge_cb_data_t *mcd) 6880Sstevel@tonic-gate { 6890Sstevel@tonic-gate tdesc_t *tgt = NULL; 6900Sstevel@tonic-gate tdesc_t template; 6910Sstevel@tonic-gate int oldid = oldtgt->t_id; 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate if (oldid == selftid) { 6940Sstevel@tonic-gate *tgtp = newself; 6950Sstevel@tonic-gate return (1); 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate if ((template.t_id = get_mapping(mcd->md_ta, oldid)) == 0) 6990Sstevel@tonic-gate terminate("failed to get mapping for tid %d\n", oldid); 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate if (!hash_find(mcd->md_parent->td_idhash, (void *)&template, 7020Sstevel@tonic-gate (void *)&tgt) && (!(mcd->md_flags & MCD_F_REFMERGE) || 7030Sstevel@tonic-gate !hash_find(mcd->md_tgt->td_idhash, (void *)&template, 7040Sstevel@tonic-gate (void *)&tgt))) { 7050Sstevel@tonic-gate debug(3, "Remap couldn't find %d (from %d)\n", template.t_id, 7060Sstevel@tonic-gate oldid); 7070Sstevel@tonic-gate *tgtp = oldtgt; 7080Sstevel@tonic-gate list_add(mcd->md_tdtbr, tgtp); 7090Sstevel@tonic-gate return (0); 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate *tgtp = tgt; 7130Sstevel@tonic-gate return (1); 7140Sstevel@tonic-gate } 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate static tdesc_t * 7170Sstevel@tonic-gate conjure_template(tdesc_t *old, int newselfid) 7180Sstevel@tonic-gate { 7190Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate new->t_name = old->t_name ? xstrdup(old->t_name) : NULL; 7220Sstevel@tonic-gate new->t_type = old->t_type; 7230Sstevel@tonic-gate new->t_size = old->t_size; 7240Sstevel@tonic-gate new->t_id = newselfid; 7250Sstevel@tonic-gate new->t_flags = old->t_flags; 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate return (new); 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate /*ARGSUSED2*/ 7310Sstevel@tonic-gate static tdesc_t * 7320Sstevel@tonic-gate conjure_intrinsic(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7330Sstevel@tonic-gate { 7340Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate new->t_intr = xmalloc(sizeof (intr_t)); 7370Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate return (new); 7400Sstevel@tonic-gate } 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate static tdesc_t * 7430Sstevel@tonic-gate conjure_plain(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7440Sstevel@tonic-gate { 7450Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate (void) remap_node(&new->t_tdesc, old->t_tdesc, old->t_id, new, mcd); 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate return (new); 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate static tdesc_t * 7530Sstevel@tonic-gate conjure_function(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7540Sstevel@tonic-gate { 7550Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7560Sstevel@tonic-gate fndef_t *nfn = xmalloc(sizeof (fndef_t)); 7570Sstevel@tonic-gate fndef_t *ofn = old->t_fndef; 7580Sstevel@tonic-gate int i; 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate (void) remap_node(&nfn->fn_ret, ofn->fn_ret, old->t_id, new, mcd); 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate nfn->fn_nargs = ofn->fn_nargs; 7630Sstevel@tonic-gate nfn->fn_vargs = ofn->fn_vargs; 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate if (nfn->fn_nargs > 0) 7660Sstevel@tonic-gate nfn->fn_args = xcalloc(sizeof (tdesc_t *) * ofn->fn_nargs); 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate for (i = 0; i < ofn->fn_nargs; i++) { 7690Sstevel@tonic-gate (void) remap_node(&nfn->fn_args[i], ofn->fn_args[i], old->t_id, 7700Sstevel@tonic-gate new, mcd); 7710Sstevel@tonic-gate } 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate new->t_fndef = nfn; 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate return (new); 7760Sstevel@tonic-gate } 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate static tdesc_t * 7790Sstevel@tonic-gate conjure_array(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7800Sstevel@tonic-gate { 7810Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7820Sstevel@tonic-gate ardef_t *nar = xmalloc(sizeof (ardef_t)); 7830Sstevel@tonic-gate ardef_t *oar = old->t_ardef; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate (void) remap_node(&nar->ad_contents, oar->ad_contents, old->t_id, new, 7860Sstevel@tonic-gate mcd); 7870Sstevel@tonic-gate (void) remap_node(&nar->ad_idxtype, oar->ad_idxtype, old->t_id, new, 7880Sstevel@tonic-gate mcd); 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate nar->ad_nelems = oar->ad_nelems; 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate new->t_ardef = nar; 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate return (new); 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate static tdesc_t * 7980Sstevel@tonic-gate conjure_su(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7990Sstevel@tonic-gate { 8000Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8010Sstevel@tonic-gate mlist_t *omem, **nmemp; 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate for (omem = old->t_members, nmemp = &new->t_members; 8040Sstevel@tonic-gate omem; omem = omem->ml_next, nmemp = &((*nmemp)->ml_next)) { 8050Sstevel@tonic-gate *nmemp = xmalloc(sizeof (mlist_t)); 8060Sstevel@tonic-gate (*nmemp)->ml_offset = omem->ml_offset; 8070Sstevel@tonic-gate (*nmemp)->ml_size = omem->ml_size; 8080Sstevel@tonic-gate (*nmemp)->ml_name = xstrdup(omem->ml_name); 8090Sstevel@tonic-gate (void) remap_node(&((*nmemp)->ml_type), omem->ml_type, 8100Sstevel@tonic-gate old->t_id, new, mcd); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate *nmemp = NULL; 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate return (new); 8150Sstevel@tonic-gate } 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate /*ARGSUSED2*/ 8180Sstevel@tonic-gate static tdesc_t * 8190Sstevel@tonic-gate conjure_enum(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8200Sstevel@tonic-gate { 8210Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8220Sstevel@tonic-gate elist_t *oel, **nelp; 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate for (oel = old->t_emem, nelp = &new->t_emem; 8250Sstevel@tonic-gate oel; oel = oel->el_next, nelp = &((*nelp)->el_next)) { 8260Sstevel@tonic-gate *nelp = xmalloc(sizeof (elist_t)); 8270Sstevel@tonic-gate (*nelp)->el_name = xstrdup(oel->el_name); 8280Sstevel@tonic-gate (*nelp)->el_number = oel->el_number; 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate *nelp = NULL; 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate return (new); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate /*ARGSUSED2*/ 8360Sstevel@tonic-gate static tdesc_t * 8370Sstevel@tonic-gate conjure_forward(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8380Sstevel@tonic-gate { 8390Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate list_add(&mcd->md_tgt->td_fwdlist, new); 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate return (new); 8440Sstevel@tonic-gate } 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate /*ARGSUSED*/ 8470Sstevel@tonic-gate static tdesc_t * 8480Sstevel@tonic-gate conjure_assert(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8490Sstevel@tonic-gate { 8500Sstevel@tonic-gate assert(1 == 0); 8510Sstevel@tonic-gate return (NULL); 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate static iidesc_t * 8550Sstevel@tonic-gate conjure_iidesc(iidesc_t *old, merge_cb_data_t *mcd) 8560Sstevel@tonic-gate { 8570Sstevel@tonic-gate iidesc_t *new = iidesc_dup(old); 8580Sstevel@tonic-gate int i; 8590Sstevel@tonic-gate 8600Sstevel@tonic-gate (void) remap_node(&new->ii_dtype, old->ii_dtype, -1, NULL, mcd); 8610Sstevel@tonic-gate for (i = 0; i < new->ii_nargs; i++) { 8620Sstevel@tonic-gate (void) remap_node(&new->ii_args[i], old->ii_args[i], -1, NULL, 8630Sstevel@tonic-gate mcd); 8640Sstevel@tonic-gate } 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate return (new); 8670Sstevel@tonic-gate } 8680Sstevel@tonic-gate 8690Sstevel@tonic-gate static int 8700Sstevel@tonic-gate fwd_redir(tdesc_t *fwd, tdesc_t **fwdp, void *private) 8710Sstevel@tonic-gate { 8720Sstevel@tonic-gate alist_t *map = private; 8730Sstevel@tonic-gate tdesc_t *defn; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate if (!alist_find(map, (void *)fwd, (void **)&defn)) 8760Sstevel@tonic-gate return (0); 8770Sstevel@tonic-gate 878*1882Sjohnlev debug(3, "Redirecting an edge to %s\n", tdesc_name(defn)); 8790Sstevel@tonic-gate 8800Sstevel@tonic-gate *fwdp = defn; 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate return (1); 8830Sstevel@tonic-gate } 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate static tdtrav_cb_f fwd_redir_cbs[] = { 8860Sstevel@tonic-gate NULL, 8870Sstevel@tonic-gate NULL, /* intrinsic */ 8880Sstevel@tonic-gate NULL, /* pointer */ 8890Sstevel@tonic-gate NULL, /* array */ 8900Sstevel@tonic-gate NULL, /* function */ 8910Sstevel@tonic-gate NULL, /* struct */ 8920Sstevel@tonic-gate NULL, /* union */ 8930Sstevel@tonic-gate NULL, /* enum */ 8940Sstevel@tonic-gate fwd_redir, /* forward */ 8950Sstevel@tonic-gate NULL, /* typedef */ 8960Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 8970Sstevel@tonic-gate NULL, /* volatile */ 8980Sstevel@tonic-gate NULL, /* const */ 8990Sstevel@tonic-gate NULL /* restrict */ 9000Sstevel@tonic-gate }; 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate typedef struct redir_mstr_data { 9030Sstevel@tonic-gate tdata_t *rmd_tgt; 9040Sstevel@tonic-gate alist_t *rmd_map; 9050Sstevel@tonic-gate } redir_mstr_data_t; 9060Sstevel@tonic-gate 9070Sstevel@tonic-gate static int 9080Sstevel@tonic-gate redir_mstr_fwd_cb(void *name, void *value, void *arg) 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate tdesc_t *fwd = name; 9110Sstevel@tonic-gate int defnid = (int)value; 9120Sstevel@tonic-gate redir_mstr_data_t *rmd = arg; 9130Sstevel@tonic-gate tdesc_t template; 9140Sstevel@tonic-gate tdesc_t *defn; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate template.t_id = defnid; 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate if (!hash_find(rmd->rmd_tgt->td_idhash, (void *)&template, 9190Sstevel@tonic-gate (void *)&defn)) { 9200Sstevel@tonic-gate terminate("Couldn't unforward %d (%s)\n", defnid, 921*1882Sjohnlev tdesc_name(defn)); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate 924*1882Sjohnlev debug(3, "Forward map: resolved %d to %s\n", defnid, tdesc_name(defn)); 9250Sstevel@tonic-gate 9260Sstevel@tonic-gate alist_add(rmd->rmd_map, (void *)fwd, (void *)defn); 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate return (1); 9290Sstevel@tonic-gate } 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate static void 9320Sstevel@tonic-gate redir_mstr_fwds(merge_cb_data_t *mcd) 9330Sstevel@tonic-gate { 9340Sstevel@tonic-gate redir_mstr_data_t rmd; 9350Sstevel@tonic-gate alist_t *map = alist_new(NULL, NULL); 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate rmd.rmd_tgt = mcd->md_tgt; 9380Sstevel@tonic-gate rmd.rmd_map = map; 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate if (alist_iter(mcd->md_fdida, redir_mstr_fwd_cb, &rmd)) { 9410Sstevel@tonic-gate (void) iitraverse_hash(mcd->md_tgt->td_iihash, 9420Sstevel@tonic-gate &mcd->md_tgt->td_curvgen, fwd_redir_cbs, NULL, NULL, map); 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate alist_free(map); 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate static int 9490Sstevel@tonic-gate add_iitba_cb(void *data, void *private) 9500Sstevel@tonic-gate { 9510Sstevel@tonic-gate merge_cb_data_t *mcd = private; 9520Sstevel@tonic-gate iidesc_t *tba = data; 9530Sstevel@tonic-gate iidesc_t *new; 9540Sstevel@tonic-gate iifind_data_t iif; 9550Sstevel@tonic-gate int newidx; 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate newidx = get_mapping(mcd->md_ta, tba->ii_dtype->t_id); 9580Sstevel@tonic-gate assert(newidx != -1); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate (void) list_remove(mcd->md_iitba, data, NULL, NULL); 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate iif.iif_template = tba; 9630Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 9640Sstevel@tonic-gate iif.iif_newidx = newidx; 9650Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, tba, iidesc_match, 9680Sstevel@tonic-gate &iif) == 1) { 9690Sstevel@tonic-gate debug(3, "iidesc_t %s already exists\n", 9700Sstevel@tonic-gate (tba->ii_name ? tba->ii_name : "(anon)")); 9710Sstevel@tonic-gate return (1); 9720Sstevel@tonic-gate } 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate new = conjure_iidesc(tba, mcd); 9750Sstevel@tonic-gate hash_add(mcd->md_tgt->td_iihash, new); 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate return (1); 9780Sstevel@tonic-gate } 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate static int 9810Sstevel@tonic-gate add_tdesc(tdesc_t *oldtdp, int newid, merge_cb_data_t *mcd) 9820Sstevel@tonic-gate { 9830Sstevel@tonic-gate tdesc_t *newtdp; 9840Sstevel@tonic-gate tdesc_t template; 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate template.t_id = newid; 9870Sstevel@tonic-gate assert(hash_find(mcd->md_parent->td_idhash, 9880Sstevel@tonic-gate (void *)&template, NULL) == 0); 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate debug(3, "trying to conjure %d %s (%d) as %d\n", 991*1882Sjohnlev oldtdp->t_type, tdesc_name(oldtdp), oldtdp->t_id, newid); 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate if ((newtdp = tdesc_ops[oldtdp->t_type].conjure(oldtdp, newid, 9940Sstevel@tonic-gate mcd)) == NULL) 9950Sstevel@tonic-gate /* couldn't map everything */ 9960Sstevel@tonic-gate return (0); 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate debug(3, "succeeded\n"); 9990Sstevel@tonic-gate 10000Sstevel@tonic-gate hash_add(mcd->md_tgt->td_idhash, newtdp); 10010Sstevel@tonic-gate hash_add(mcd->md_tgt->td_layouthash, newtdp); 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate return (1); 10040Sstevel@tonic-gate } 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate static int 10070Sstevel@tonic-gate add_tdtba_cb(void *data, void *arg) 10080Sstevel@tonic-gate { 10090Sstevel@tonic-gate tdesc_t *tdp = data; 10100Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 10110Sstevel@tonic-gate int newid; 10120Sstevel@tonic-gate int rc; 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate newid = get_mapping(mcd->md_ta, tdp->t_id); 10150Sstevel@tonic-gate assert(newid != -1); 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate if ((rc = add_tdesc(tdp, newid, mcd))) 10180Sstevel@tonic-gate hash_remove(mcd->md_tdtba, (void *)tdp); 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate return (rc); 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate static int 10240Sstevel@tonic-gate add_tdtbr_cb(void *data, void *arg) 10250Sstevel@tonic-gate { 10260Sstevel@tonic-gate tdesc_t **tdpp = data; 10270Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 10280Sstevel@tonic-gate 1029*1882Sjohnlev debug(3, "Remapping %s (%d)\n", tdesc_name(*tdpp), (*tdpp)->t_id); 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate if (!remap_node(tdpp, *tdpp, -1, NULL, mcd)) 10320Sstevel@tonic-gate return (0); 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate (void) list_remove(mcd->md_tdtbr, (void *)tdpp, NULL, NULL); 10350Sstevel@tonic-gate return (1); 10360Sstevel@tonic-gate } 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate static void 10390Sstevel@tonic-gate merge_types(hash_t *src, merge_cb_data_t *mcd) 10400Sstevel@tonic-gate { 10410Sstevel@tonic-gate list_t *iitba = NULL; 10420Sstevel@tonic-gate list_t *tdtbr = NULL; 10430Sstevel@tonic-gate int iirc, tdrc; 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate mcd->md_iitba = &iitba; 10460Sstevel@tonic-gate mcd->md_tdtba = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash, 10470Sstevel@tonic-gate tdesc_layoutcmp); 10480Sstevel@tonic-gate mcd->md_tdtbr = &tdtbr; 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate (void) hash_iter(src, merge_type_cb, mcd); 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate tdrc = hash_iter(mcd->md_tdtba, add_tdtba_cb, (void *)mcd); 10530Sstevel@tonic-gate debug(3, "add_tdtba_cb added %d items\n", tdrc); 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate iirc = list_iter(*mcd->md_iitba, add_iitba_cb, (void *)mcd); 10560Sstevel@tonic-gate debug(3, "add_iitba_cb added %d items\n", iirc); 10570Sstevel@tonic-gate 10580Sstevel@tonic-gate assert(list_count(*mcd->md_iitba) == 0 && 10590Sstevel@tonic-gate hash_count(mcd->md_tdtba) == 0); 10600Sstevel@tonic-gate 10610Sstevel@tonic-gate tdrc = list_iter(*mcd->md_tdtbr, add_tdtbr_cb, (void *)mcd); 10620Sstevel@tonic-gate debug(3, "add_tdtbr_cb added %d items\n", tdrc); 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate if (list_count(*mcd->md_tdtbr) != 0) 10650Sstevel@tonic-gate terminate("Couldn't remap all nodes\n"); 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate /* 10680Sstevel@tonic-gate * We now have an alist of master forwards and the ids of the new master 10690Sstevel@tonic-gate * definitions for those forwards in mcd->md_fdida. By this point, 10700Sstevel@tonic-gate * we're guaranteed that all of the master definitions referenced in 10710Sstevel@tonic-gate * fdida have been added to the master tree. We now traverse through 10720Sstevel@tonic-gate * the master tree, redirecting all edges inbound to forwards that have 10730Sstevel@tonic-gate * definitions to those definitions. 10740Sstevel@tonic-gate */ 10750Sstevel@tonic-gate if (mcd->md_parent == mcd->md_tgt) { 10760Sstevel@tonic-gate redir_mstr_fwds(mcd); 10770Sstevel@tonic-gate } 10780Sstevel@tonic-gate } 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate void 10810Sstevel@tonic-gate merge_into_master(tdata_t *cur, tdata_t *mstr, tdata_t *tgt, int selfuniquify) 10820Sstevel@tonic-gate { 10830Sstevel@tonic-gate merge_cb_data_t mcd; 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate cur->td_ref++; 10860Sstevel@tonic-gate mstr->td_ref++; 10870Sstevel@tonic-gate if (tgt) 10880Sstevel@tonic-gate tgt->td_ref++; 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate assert(cur->td_ref == 1 && mstr->td_ref == 1 && 10910Sstevel@tonic-gate (tgt == NULL || tgt->td_ref == 1)); 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate mcd.md_parent = mstr; 10940Sstevel@tonic-gate mcd.md_tgt = (tgt ? tgt : mstr); 10950Sstevel@tonic-gate mcd.md_ta = alist_new(NULL, NULL); 10960Sstevel@tonic-gate mcd.md_fdida = alist_new(NULL, NULL); 10970Sstevel@tonic-gate mcd.md_flags = 0; 10980Sstevel@tonic-gate 10990Sstevel@tonic-gate if (selfuniquify) 11000Sstevel@tonic-gate mcd.md_flags |= MCD_F_SELFUNIQUIFY; 11010Sstevel@tonic-gate if (tgt) 11020Sstevel@tonic-gate mcd.md_flags |= MCD_F_REFMERGE; 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate mstr->td_curvgen = MAX(mstr->td_curvgen, cur->td_curvgen); 11050Sstevel@tonic-gate mstr->td_curemark = MAX(mstr->td_curemark, cur->td_curemark); 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate merge_types(cur->td_iihash, &mcd); 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate if (debug_level >= 3) { 11100Sstevel@tonic-gate debug(3, "Type association stats\n"); 11110Sstevel@tonic-gate alist_stats(mcd.md_ta, 0); 11120Sstevel@tonic-gate debug(3, "Layout hash stats\n"); 11130Sstevel@tonic-gate hash_stats(mcd.md_tgt->td_layouthash, 1); 11140Sstevel@tonic-gate } 11150Sstevel@tonic-gate 11160Sstevel@tonic-gate alist_free(mcd.md_fdida); 11170Sstevel@tonic-gate alist_free(mcd.md_ta); 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate cur->td_ref--; 11200Sstevel@tonic-gate mstr->td_ref--; 11210Sstevel@tonic-gate if (tgt) 11220Sstevel@tonic-gate tgt->td_ref--; 11230Sstevel@tonic-gate } 11240Sstevel@tonic-gate 11250Sstevel@tonic-gate tdesc_ops_t tdesc_ops[] = { 11260Sstevel@tonic-gate { "ERROR! BAD tdesc TYPE", NULL, NULL }, 11270Sstevel@tonic-gate { "intrinsic", equiv_intrinsic, conjure_intrinsic }, 11280Sstevel@tonic-gate { "pointer", equiv_plain, conjure_plain }, 11290Sstevel@tonic-gate { "array", equiv_array, conjure_array }, 11300Sstevel@tonic-gate { "function", equiv_function, conjure_function }, 11310Sstevel@tonic-gate { "struct", equiv_su, conjure_su }, 11320Sstevel@tonic-gate { "union", equiv_su, conjure_su }, 11330Sstevel@tonic-gate { "enum", equiv_enum, conjure_enum }, 11340Sstevel@tonic-gate { "forward", NULL, conjure_forward }, 11350Sstevel@tonic-gate { "typedef", equiv_plain, conjure_plain }, 11360Sstevel@tonic-gate { "typedef_unres", equiv_assert, conjure_assert }, 11370Sstevel@tonic-gate { "volatile", equiv_plain, conjure_plain }, 11380Sstevel@tonic-gate { "const", equiv_plain, conjure_plain }, 11390Sstevel@tonic-gate { "restrict", equiv_plain, conjure_plain } 11400Sstevel@tonic-gate }; 1141