17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54d232658Sjohnlev * Common Development and Distribution License (the "License"). 64d232658Sjohnlev * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 224d232658Sjohnlev * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This file contains routines that merge one tdata_t tree, called the child, 307c478bd9Sstevel@tonic-gate * into another, called the parent. Note that these names are used mainly for 317c478bd9Sstevel@tonic-gate * convenience and to represent the direction of the merge. They are not meant 327c478bd9Sstevel@tonic-gate * to imply any relationship between the tdata_t graphs prior to the merge. 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * tdata_t structures contain two main elements - a hash of iidesc_t nodes, and 357c478bd9Sstevel@tonic-gate * a directed graph of tdesc_t nodes, pointed to by the iidesc_t nodes. Simply 367c478bd9Sstevel@tonic-gate * put, we merge the tdesc_t graphs, followed by the iidesc_t nodes, and then we 377c478bd9Sstevel@tonic-gate * clean up loose ends. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * The algorithm is as follows: 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * 1. Mapping iidesc_t nodes 427c478bd9Sstevel@tonic-gate * 437c478bd9Sstevel@tonic-gate * For each child iidesc_t node, we first try to map its tdesc_t subgraph 447c478bd9Sstevel@tonic-gate * against the tdesc_t graph in the parent. For each node in the child subgraph 457c478bd9Sstevel@tonic-gate * that exists in the parent, a mapping between the two (between their type IDs) 467c478bd9Sstevel@tonic-gate * is established. For the child nodes that cannot be mapped onto existing 477c478bd9Sstevel@tonic-gate * parent nodes, a mapping is established between the child node ID and a 487c478bd9Sstevel@tonic-gate * newly-allocated ID that the node will use when it is re-created in the 497c478bd9Sstevel@tonic-gate * parent. These unmappable nodes are added to the md_tdtba (tdesc_t To Be 507c478bd9Sstevel@tonic-gate * Added) hash, which tracks nodes that need to be created in the parent. 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * If all of the nodes in the subgraph for an iidesc_t in the child can be 537c478bd9Sstevel@tonic-gate * mapped to existing nodes in the parent, then we can try to map the child 547c478bd9Sstevel@tonic-gate * iidesc_t onto an iidesc_t in the parent. If we cannot find an equivalent 557c478bd9Sstevel@tonic-gate * iidesc_t, or if we were not able to completely map the tdesc_t subgraph(s), 567c478bd9Sstevel@tonic-gate * then we add this iidesc_t to the md_iitba (iidesc_t To Be Added) list. This 577c478bd9Sstevel@tonic-gate * list tracks iidesc_t nodes that are to be created in the parent. 587c478bd9Sstevel@tonic-gate * 597c478bd9Sstevel@tonic-gate * While visiting the tdesc_t nodes, we may discover a forward declaration (a 607c478bd9Sstevel@tonic-gate * FORWARD tdesc_t) in the parent that is resolved in the child. That is, there 617c478bd9Sstevel@tonic-gate * may be a structure or union definition in the child with the same name as the 627c478bd9Sstevel@tonic-gate * forward declaration in the parent. If we find such a node, we record an 637c478bd9Sstevel@tonic-gate * association in the md_fdida (Forward => Definition ID Association) list 647c478bd9Sstevel@tonic-gate * between the parent ID of the forward declaration and the ID that the 657c478bd9Sstevel@tonic-gate * definition will use when re-created in the parent. 667c478bd9Sstevel@tonic-gate * 677c478bd9Sstevel@tonic-gate * 2. Creating new tdesc_t nodes (the md_tdtba hash) 687c478bd9Sstevel@tonic-gate * 697c478bd9Sstevel@tonic-gate * We have now attempted to map all tdesc_t nodes from the child into the 707c478bd9Sstevel@tonic-gate * parent, and have, in md_tdtba, a hash of all tdesc_t nodes that need to be 717c478bd9Sstevel@tonic-gate * created (or, as we so wittily call it, conjured) in the parent. We iterate 727c478bd9Sstevel@tonic-gate * through this hash, creating the indicated tdesc_t nodes. For a given tdesc_t 737c478bd9Sstevel@tonic-gate * node, conjuring requires two steps - the copying of the common tdesc_t data 747c478bd9Sstevel@tonic-gate * (name, type, etc) from the child node, and the creation of links from the 757c478bd9Sstevel@tonic-gate * newly-created node to the parent equivalents of other tdesc_t nodes pointed 767c478bd9Sstevel@tonic-gate * to by node being conjured. Note that in some cases, the targets of these 777c478bd9Sstevel@tonic-gate * links will be on the md_tdtba hash themselves, and may not have been created 787c478bd9Sstevel@tonic-gate * yet. As such, we can't establish the links from these new nodes into the 797c478bd9Sstevel@tonic-gate * parent graph. We therefore conjure them with links to nodes in the *child* 807c478bd9Sstevel@tonic-gate * graph, and add pointers to the links to be created to the md_tdtbr (tdesc_t 817c478bd9Sstevel@tonic-gate * To Be Remapped) hash. For example, a POINTER tdesc_t that could not be 827c478bd9Sstevel@tonic-gate * resolved would have its &tdesc_t->t_tdesc added to md_tdtbr. 837c478bd9Sstevel@tonic-gate * 847c478bd9Sstevel@tonic-gate * 3. Creating new iidesc_t nodes (the md_iitba list) 857c478bd9Sstevel@tonic-gate * 867c478bd9Sstevel@tonic-gate * When we have completed step 2, all tdesc_t nodes have been created (or 877c478bd9Sstevel@tonic-gate * already existed) in the parent. Some of them may have incorrect links (the 887c478bd9Sstevel@tonic-gate * members of the md_tdtbr list), but they've all been created. As such, we can 897c478bd9Sstevel@tonic-gate * create all of the iidesc_t nodes, as we can attach the tdesc_t subgraph 907c478bd9Sstevel@tonic-gate * pointers correctly. We create each node, and attach the pointers to the 917c478bd9Sstevel@tonic-gate * appropriate parts of the parent tdesc_t graph. 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * 4. Resolving newly-created tdesc_t node links (the md_tdtbr list) 947c478bd9Sstevel@tonic-gate * 957c478bd9Sstevel@tonic-gate * As in step 3, we rely on the fact that all of the tdesc_t nodes have been 967c478bd9Sstevel@tonic-gate * created. Each entry in the md_tdtbr list is a pointer to where a link into 977c478bd9Sstevel@tonic-gate * the parent will be established. As saved in the md_tdtbr list, these 987c478bd9Sstevel@tonic-gate * pointers point into the child tdesc_t subgraph. We can thus get the target 997c478bd9Sstevel@tonic-gate * type ID from the child, look at the ID mapping to determine the desired link 1007c478bd9Sstevel@tonic-gate * target, and redirect the link accordingly. 1017c478bd9Sstevel@tonic-gate * 1027c478bd9Sstevel@tonic-gate * 5. Parent => child forward declaration resolution 1037c478bd9Sstevel@tonic-gate * 1047c478bd9Sstevel@tonic-gate * If entries were made in the md_fdida list in step 1, we have forward 1057c478bd9Sstevel@tonic-gate * declarations in the parent that need to be resolved to their definitions 1067c478bd9Sstevel@tonic-gate * re-created in step 2 from the child. Using the md_fdida list, we can locate 1077c478bd9Sstevel@tonic-gate * the definition for the forward declaration, and we can redirect all inbound 1087c478bd9Sstevel@tonic-gate * edges to the forward declaration node to the actual definition. 1097c478bd9Sstevel@tonic-gate * 1107c478bd9Sstevel@tonic-gate * A pox on the house of anyone who changes the algorithm without updating 1117c478bd9Sstevel@tonic-gate * this comment. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate #include <stdio.h> 1157c478bd9Sstevel@tonic-gate #include <strings.h> 1167c478bd9Sstevel@tonic-gate #include <assert.h> 1177c478bd9Sstevel@tonic-gate #include <pthread.h> 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate #include "ctf_headers.h" 1207c478bd9Sstevel@tonic-gate #include "ctftools.h" 1217c478bd9Sstevel@tonic-gate #include "list.h" 1227c478bd9Sstevel@tonic-gate #include "alist.h" 1237c478bd9Sstevel@tonic-gate #include "memory.h" 1247c478bd9Sstevel@tonic-gate #include "traverse.h" 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate typedef struct equiv_data equiv_data_t; 1277c478bd9Sstevel@tonic-gate typedef struct merge_cb_data merge_cb_data_t; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate * There are two traversals in this file, for equivalency and for tdesc_t 1317c478bd9Sstevel@tonic-gate * re-creation, that do not fit into the tdtraverse() framework. We have our 1327c478bd9Sstevel@tonic-gate * own traversal mechanism and ops vector here for those two cases. 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate typedef struct tdesc_ops { 1357c478bd9Sstevel@tonic-gate char *name; 1367c478bd9Sstevel@tonic-gate int (*equiv)(tdesc_t *, tdesc_t *, equiv_data_t *); 1377c478bd9Sstevel@tonic-gate tdesc_t *(*conjure)(tdesc_t *, int, merge_cb_data_t *); 1387c478bd9Sstevel@tonic-gate } tdesc_ops_t; 1397c478bd9Sstevel@tonic-gate extern tdesc_ops_t tdesc_ops[]; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * The workhorse structure of tdata_t merging. Holds all lists of nodes to be 1437c478bd9Sstevel@tonic-gate * processed during various phases of the merge algorithm. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate struct merge_cb_data { 1467c478bd9Sstevel@tonic-gate tdata_t *md_parent; 1477c478bd9Sstevel@tonic-gate tdata_t *md_tgt; 1487c478bd9Sstevel@tonic-gate alist_t *md_ta; /* Type Association */ 1497c478bd9Sstevel@tonic-gate alist_t *md_fdida; /* Forward -> Definition ID Association */ 1507c478bd9Sstevel@tonic-gate list_t **md_iitba; /* iidesc_t nodes To Be Added to the parent */ 1517c478bd9Sstevel@tonic-gate hash_t *md_tdtba; /* tdesc_t nodes To Be Added to the parent */ 1527c478bd9Sstevel@tonic-gate list_t **md_tdtbr; /* tdesc_t nodes To Be Remapped */ 1537c478bd9Sstevel@tonic-gate int md_flags; 1547c478bd9Sstevel@tonic-gate }; /* merge_cb_data_t */ 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* 1577c478bd9Sstevel@tonic-gate * When we first create a tdata_t from stabs data, we will have duplicate nodes. 1587c478bd9Sstevel@tonic-gate * Normal merges, however, assume that the child tdata_t is already self-unique, 1597c478bd9Sstevel@tonic-gate * and for speed reasons do not attempt to self-uniquify. If this flag is set, 1607c478bd9Sstevel@tonic-gate * the merge algorithm will self-uniquify by avoiding the insertion of 1617c478bd9Sstevel@tonic-gate * duplicates in the md_tdtdba list. 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate #define MCD_F_SELFUNIQUIFY 0x1 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * When we merge the CTF data for the modules, we don't want it to contain any 1677c478bd9Sstevel@tonic-gate * data that can be found in the reference module (usually genunix). If this 1687c478bd9Sstevel@tonic-gate * flag is set, we're doing a merge between the fully merged tdata_t for this 1697c478bd9Sstevel@tonic-gate * module and the tdata_t for the reference module, with the data unique to this 1707c478bd9Sstevel@tonic-gate * module ending up in a third tdata_t. It is this third tdata_t that will end 1717c478bd9Sstevel@tonic-gate * up in the .SUNW_ctf section for the module. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate #define MCD_F_REFMERGE 0x2 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Mapping of child type IDs to parent type IDs 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static void 1807c478bd9Sstevel@tonic-gate add_mapping(alist_t *ta, tid_t srcid, tid_t tgtid) 1817c478bd9Sstevel@tonic-gate { 1827c478bd9Sstevel@tonic-gate debug(3, "Adding mapping %u => %u\n", srcid, tgtid); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate assert(!alist_find(ta, (void *)srcid, NULL)); 1857c478bd9Sstevel@tonic-gate assert(srcid != 0 && tgtid != 0); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate alist_add(ta, (void *)srcid, (void *)tgtid); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate static tid_t 1917c478bd9Sstevel@tonic-gate get_mapping(alist_t *ta, int srcid) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate long ltgtid; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate if (alist_find(ta, (void *)srcid, (void **)<gtid)) 1967c478bd9Sstevel@tonic-gate return ((int)ltgtid); 1977c478bd9Sstevel@tonic-gate else 1987c478bd9Sstevel@tonic-gate return (0); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Determining equivalence of tdesc_t subgraphs 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate struct equiv_data { 2067c478bd9Sstevel@tonic-gate alist_t *ed_ta; 2077c478bd9Sstevel@tonic-gate tdesc_t *ed_node; 2087c478bd9Sstevel@tonic-gate tdesc_t *ed_tgt; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate int ed_clear_mark; 2117c478bd9Sstevel@tonic-gate int ed_cur_mark; 2127c478bd9Sstevel@tonic-gate int ed_selfuniquify; 2137c478bd9Sstevel@tonic-gate }; /* equiv_data_t */ 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate static int equiv_node(tdesc_t *, tdesc_t *, equiv_data_t *); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 2187c478bd9Sstevel@tonic-gate static int 2197c478bd9Sstevel@tonic-gate equiv_intrinsic(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate intr_t *si = stdp->t_intr; 2227c478bd9Sstevel@tonic-gate intr_t *ti = ttdp->t_intr; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate if (si->intr_type != ti->intr_type || 2257c478bd9Sstevel@tonic-gate si->intr_signed != ti->intr_signed || 2267c478bd9Sstevel@tonic-gate si->intr_offset != ti->intr_offset || 2277c478bd9Sstevel@tonic-gate si->intr_nbits != ti->intr_nbits) 2287c478bd9Sstevel@tonic-gate return (0); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if (si->intr_type == INTR_INT && 2317c478bd9Sstevel@tonic-gate si->intr_iformat != ti->intr_iformat) 2327c478bd9Sstevel@tonic-gate return (0); 2337c478bd9Sstevel@tonic-gate else if (si->intr_type == INTR_REAL && 2347c478bd9Sstevel@tonic-gate si->intr_fformat != ti->intr_fformat) 2357c478bd9Sstevel@tonic-gate return (0); 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate return (1); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate static int 2417c478bd9Sstevel@tonic-gate equiv_plain(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate return (equiv_node(stdp->t_tdesc, ttdp->t_tdesc, ed)); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate static int 2477c478bd9Sstevel@tonic-gate equiv_function(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate fndef_t *fn1 = stdp->t_fndef, *fn2 = ttdp->t_fndef; 2507c478bd9Sstevel@tonic-gate int i; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (fn1->fn_nargs != fn2->fn_nargs || 2537c478bd9Sstevel@tonic-gate fn1->fn_vargs != fn2->fn_vargs) 2547c478bd9Sstevel@tonic-gate return (0); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if (!equiv_node(fn1->fn_ret, fn2->fn_ret, ed)) 2577c478bd9Sstevel@tonic-gate return (0); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate for (i = 0; i < fn1->fn_nargs; i++) { 2607c478bd9Sstevel@tonic-gate if (!equiv_node(fn1->fn_args[i], fn2->fn_args[i], ed)) 2617c478bd9Sstevel@tonic-gate return (0); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate return (1); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate static int 2687c478bd9Sstevel@tonic-gate equiv_array(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate ardef_t *ar1 = stdp->t_ardef, *ar2 = ttdp->t_ardef; 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (!equiv_node(ar1->ad_contents, ar2->ad_contents, ed) || 2737c478bd9Sstevel@tonic-gate !equiv_node(ar1->ad_idxtype, ar2->ad_idxtype, ed)) 2747c478bd9Sstevel@tonic-gate return (0); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (ar1->ad_nelems != ar2->ad_nelems) 2777c478bd9Sstevel@tonic-gate return (0); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate return (1); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate static int 2837c478bd9Sstevel@tonic-gate equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members; 2867c478bd9Sstevel@tonic-gate mlist_t *olm1 = NULL; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate while (ml1 && ml2) { 2897c478bd9Sstevel@tonic-gate if (ml1->ml_offset != ml2->ml_offset || 2907c478bd9Sstevel@tonic-gate strcmp(ml1->ml_name, ml2->ml_name) != 0) 2917c478bd9Sstevel@tonic-gate return (0); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * Don't do the recursive equivalency checking more than 2957c478bd9Sstevel@tonic-gate * we have to. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate if (olm1 == NULL || olm1->ml_type->t_id != ml1->ml_type->t_id) { 2987c478bd9Sstevel@tonic-gate if (ml1->ml_size != ml2->ml_size || 2997c478bd9Sstevel@tonic-gate !equiv_node(ml1->ml_type, ml2->ml_type, ed)) 3007c478bd9Sstevel@tonic-gate return (0); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate olm1 = ml1; 3047c478bd9Sstevel@tonic-gate ml1 = ml1->ml_next; 3057c478bd9Sstevel@tonic-gate ml2 = ml2->ml_next; 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate if (ml1 || ml2) 3097c478bd9Sstevel@tonic-gate return (0); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate return (1); 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 3157c478bd9Sstevel@tonic-gate static int 3167c478bd9Sstevel@tonic-gate equiv_enum(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate elist_t *el1 = stdp->t_emem; 3197c478bd9Sstevel@tonic-gate elist_t *el2 = ttdp->t_emem; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate while (el1 && el2) { 3227c478bd9Sstevel@tonic-gate if (el1->el_number != el2->el_number || 3237c478bd9Sstevel@tonic-gate strcmp(el1->el_name, el2->el_name) != 0) 3247c478bd9Sstevel@tonic-gate return (0); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate el1 = el1->el_next; 3277c478bd9Sstevel@tonic-gate el2 = el2->el_next; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if (el1 || el2) 3317c478bd9Sstevel@tonic-gate return (0); 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate return (1); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3377c478bd9Sstevel@tonic-gate static int 3387c478bd9Sstevel@tonic-gate equiv_assert(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate /* foul, evil, and very bad - this is a "shouldn't happen" */ 3417c478bd9Sstevel@tonic-gate assert(1 == 0); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate return (0); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate static int 3477c478bd9Sstevel@tonic-gate fwd_equiv(tdesc_t *ctdp, tdesc_t *mtdp) 3487c478bd9Sstevel@tonic-gate { 3497c478bd9Sstevel@tonic-gate tdesc_t *defn = (ctdp->t_type == FORWARD ? mtdp : ctdp); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate return (defn->t_type == STRUCT || defn->t_type == UNION); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate static int 3557c478bd9Sstevel@tonic-gate equiv_node(tdesc_t *ctdp, tdesc_t *mtdp, equiv_data_t *ed) 3567c478bd9Sstevel@tonic-gate { 3577c478bd9Sstevel@tonic-gate int (*equiv)(); 3587c478bd9Sstevel@tonic-gate int mapping; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (ctdp->t_emark > ed->ed_clear_mark || 3617c478bd9Sstevel@tonic-gate mtdp->t_emark > ed->ed_clear_mark) 3627c478bd9Sstevel@tonic-gate return (ctdp->t_emark == mtdp->t_emark); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * In normal (non-self-uniquify) mode, we don't want to do equivalency 3667c478bd9Sstevel@tonic-gate * checking on a subgraph that has already been checked. If a mapping 3677c478bd9Sstevel@tonic-gate * has already been established for a given child node, we can simply 3687c478bd9Sstevel@tonic-gate * compare the mapping for the child node with the ID of the parent 3697c478bd9Sstevel@tonic-gate * node. If we are in self-uniquify mode, then we're comparing two 3707c478bd9Sstevel@tonic-gate * subgraphs within the child graph, and thus need to ignore any 3717c478bd9Sstevel@tonic-gate * type mappings that have been created, as they are only valid into the 3727c478bd9Sstevel@tonic-gate * parent. 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate if ((mapping = get_mapping(ed->ed_ta, ctdp->t_id)) > 0 && 3757c478bd9Sstevel@tonic-gate mapping == mtdp->t_id && !ed->ed_selfuniquify) 3767c478bd9Sstevel@tonic-gate return (1); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (!streq(ctdp->t_name, mtdp->t_name)) 3797c478bd9Sstevel@tonic-gate return (0); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (ctdp->t_type != mtdp->t_type) { 3827c478bd9Sstevel@tonic-gate if (ctdp->t_type == FORWARD || mtdp->t_type == FORWARD) 3837c478bd9Sstevel@tonic-gate return (fwd_equiv(ctdp, mtdp)); 3847c478bd9Sstevel@tonic-gate else 3857c478bd9Sstevel@tonic-gate return (0); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate ctdp->t_emark = ed->ed_cur_mark; 3897c478bd9Sstevel@tonic-gate mtdp->t_emark = ed->ed_cur_mark; 3907c478bd9Sstevel@tonic-gate ed->ed_cur_mark++; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate if ((equiv = tdesc_ops[ctdp->t_type].equiv) != NULL) 3937c478bd9Sstevel@tonic-gate return (equiv(ctdp, mtdp, ed)); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate return (1); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate /* 3997c478bd9Sstevel@tonic-gate * We perform an equivalency check on two subgraphs by traversing through them 4007c478bd9Sstevel@tonic-gate * in lockstep. If a given node is equivalent in both the parent and the child, 4017c478bd9Sstevel@tonic-gate * we mark it in both subgraphs, using the t_emark field, with a monotonically 4027c478bd9Sstevel@tonic-gate * increasing number. If, in the course of the traversal, we reach a node that 4037c478bd9Sstevel@tonic-gate * we have visited and numbered during this equivalency check, we have a cycle. 4047c478bd9Sstevel@tonic-gate * If the previously-visited nodes don't have the same emark, then the edges 4057c478bd9Sstevel@tonic-gate * that brought us to these nodes are not equivalent, and so the check ends. 4067c478bd9Sstevel@tonic-gate * If the emarks are the same, the edges are equivalent. We then backtrack and 4077c478bd9Sstevel@tonic-gate * continue the traversal. If we have exhausted all edges in the subgraph, and 4087c478bd9Sstevel@tonic-gate * have not found any inequivalent nodes, then the subgraphs are equivalent. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate static int 4117c478bd9Sstevel@tonic-gate equiv_cb(void *bucket, void *arg) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate equiv_data_t *ed = arg; 4147c478bd9Sstevel@tonic-gate tdesc_t *mtdp = bucket; 4157c478bd9Sstevel@tonic-gate tdesc_t *ctdp = ed->ed_node; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate ed->ed_clear_mark = ed->ed_cur_mark + 1; 4187c478bd9Sstevel@tonic-gate ed->ed_cur_mark = ed->ed_clear_mark + 1; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate if (equiv_node(ctdp, mtdp, ed)) { 4217c478bd9Sstevel@tonic-gate debug(3, "equiv_node matched %d %d\n", ctdp->t_id, mtdp->t_id); 4227c478bd9Sstevel@tonic-gate ed->ed_tgt = mtdp; 4237c478bd9Sstevel@tonic-gate /* matched. stop looking */ 4247c478bd9Sstevel@tonic-gate return (-1); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate return (0); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 4317c478bd9Sstevel@tonic-gate static int 4327c478bd9Sstevel@tonic-gate map_td_tree_pre(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate if (get_mapping(mcd->md_ta, ctdp->t_id) > 0) 4377c478bd9Sstevel@tonic-gate return (0); 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate return (1); 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 4437c478bd9Sstevel@tonic-gate static int 4447c478bd9Sstevel@tonic-gate map_td_tree_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4457c478bd9Sstevel@tonic-gate { 4467c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4477c478bd9Sstevel@tonic-gate equiv_data_t ed; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 4507c478bd9Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 4517c478bd9Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 4527c478bd9Sstevel@tonic-gate ed.ed_node = ctdp; 4537c478bd9Sstevel@tonic-gate ed.ed_selfuniquify = 0; 4547c478bd9Sstevel@tonic-gate 4554d232658Sjohnlev debug(3, "map_td_tree_post on %d %s\n", ctdp->t_id, tdesc_name(ctdp)); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (hash_find_iter(mcd->md_parent->td_layouthash, ctdp, 4587c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 4597c478bd9Sstevel@tonic-gate /* We found an equivalent node */ 4607c478bd9Sstevel@tonic-gate if (ed.ed_tgt->t_type == FORWARD && ctdp->t_type != FORWARD) { 4617c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate debug(3, "Creating new defn type %d\n", id); 4647c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 4657c478bd9Sstevel@tonic-gate alist_add(mcd->md_fdida, (void *)(ulong_t)ed.ed_tgt, 4667c478bd9Sstevel@tonic-gate (void *)(ulong_t)id); 4677c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 4687c478bd9Sstevel@tonic-gate } else 4697c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, ed.ed_tgt->t_id); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_parent->td_idhash, 4727c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * We didn't find an equivalent node by looking through the 4757c478bd9Sstevel@tonic-gate * layout hash, but we somehow found it by performing an 4767c478bd9Sstevel@tonic-gate * exhaustive search through the entire graph. This usually 4777c478bd9Sstevel@tonic-gate * means that the "name" hash function is broken. 4787c478bd9Sstevel@tonic-gate */ 479*c168da27Sjohnlev aborterr("Second pass for %d (%s) == %d\n", ctdp->t_id, 4804d232658Sjohnlev tdesc_name(ctdp), ed.ed_tgt->t_id); 4817c478bd9Sstevel@tonic-gate } else { 4827c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 4857c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 4867c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate return (1); 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 4957c478bd9Sstevel@tonic-gate static int 4967c478bd9Sstevel@tonic-gate map_td_tree_self_post(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 4997c478bd9Sstevel@tonic-gate equiv_data_t ed; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate ed.ed_ta = mcd->md_ta; 5027c478bd9Sstevel@tonic-gate ed.ed_clear_mark = mcd->md_parent->td_curemark; 5037c478bd9Sstevel@tonic-gate ed.ed_cur_mark = mcd->md_parent->td_curemark + 1; 5047c478bd9Sstevel@tonic-gate ed.ed_node = ctdp; 5057c478bd9Sstevel@tonic-gate ed.ed_selfuniquify = 1; 5067c478bd9Sstevel@tonic-gate ed.ed_tgt = NULL; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate if (hash_find_iter(mcd->md_tdtba, ctdp, equiv_cb, &ed) < 0) { 5097c478bd9Sstevel@tonic-gate debug(3, "Self check found %d in %d\n", ctdp->t_id, 5107c478bd9Sstevel@tonic-gate ed.ed_tgt->t_id); 5117c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, 5127c478bd9Sstevel@tonic-gate get_mapping(mcd->md_ta, ed.ed_tgt->t_id)); 5137c478bd9Sstevel@tonic-gate } else if (debug_level > 1 && hash_iter(mcd->md_tdtba, 5147c478bd9Sstevel@tonic-gate equiv_cb, &ed) < 0) { 5157c478bd9Sstevel@tonic-gate /* 5167c478bd9Sstevel@tonic-gate * We didn't find an equivalent node using the quick way (going 5177c478bd9Sstevel@tonic-gate * through the hash normally), but we did find it by iterating 5187c478bd9Sstevel@tonic-gate * through the entire hash. This usually means that the hash 5197c478bd9Sstevel@tonic-gate * function is broken. 5207c478bd9Sstevel@tonic-gate */ 521*c168da27Sjohnlev aborterr("Self-unique second pass for %d (%s) == %d\n", 5224d232658Sjohnlev ctdp->t_id, tdesc_name(ctdp), ed.ed_tgt->t_id); 5237c478bd9Sstevel@tonic-gate } else { 5247c478bd9Sstevel@tonic-gate int id = mcd->md_tgt->td_nextid++; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate debug(3, "Creating new type %d\n", id); 5277c478bd9Sstevel@tonic-gate add_mapping(mcd->md_ta, ctdp->t_id, id); 5287c478bd9Sstevel@tonic-gate hash_add(mcd->md_tdtba, ctdp); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate mcd->md_parent->td_curemark = ed.ed_cur_mark + 1; 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate return (1); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_pre[] = { 5377c478bd9Sstevel@tonic-gate NULL, 5387c478bd9Sstevel@tonic-gate map_td_tree_pre, /* intrinsic */ 5397c478bd9Sstevel@tonic-gate map_td_tree_pre, /* pointer */ 5407c478bd9Sstevel@tonic-gate map_td_tree_pre, /* array */ 5417c478bd9Sstevel@tonic-gate map_td_tree_pre, /* function */ 5427c478bd9Sstevel@tonic-gate map_td_tree_pre, /* struct */ 5437c478bd9Sstevel@tonic-gate map_td_tree_pre, /* union */ 5447c478bd9Sstevel@tonic-gate map_td_tree_pre, /* enum */ 5457c478bd9Sstevel@tonic-gate map_td_tree_pre, /* forward */ 5467c478bd9Sstevel@tonic-gate map_td_tree_pre, /* typedef */ 5477c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5487c478bd9Sstevel@tonic-gate map_td_tree_pre, /* volatile */ 5497c478bd9Sstevel@tonic-gate map_td_tree_pre, /* const */ 5507c478bd9Sstevel@tonic-gate map_td_tree_pre /* restrict */ 5517c478bd9Sstevel@tonic-gate }; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_post[] = { 5547c478bd9Sstevel@tonic-gate NULL, 5557c478bd9Sstevel@tonic-gate map_td_tree_post, /* intrinsic */ 5567c478bd9Sstevel@tonic-gate map_td_tree_post, /* pointer */ 5577c478bd9Sstevel@tonic-gate map_td_tree_post, /* array */ 5587c478bd9Sstevel@tonic-gate map_td_tree_post, /* function */ 5597c478bd9Sstevel@tonic-gate map_td_tree_post, /* struct */ 5607c478bd9Sstevel@tonic-gate map_td_tree_post, /* union */ 5617c478bd9Sstevel@tonic-gate map_td_tree_post, /* enum */ 5627c478bd9Sstevel@tonic-gate map_td_tree_post, /* forward */ 5637c478bd9Sstevel@tonic-gate map_td_tree_post, /* typedef */ 5647c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5657c478bd9Sstevel@tonic-gate map_td_tree_post, /* volatile */ 5667c478bd9Sstevel@tonic-gate map_td_tree_post, /* const */ 5677c478bd9Sstevel@tonic-gate map_td_tree_post /* restrict */ 5687c478bd9Sstevel@tonic-gate }; 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate static tdtrav_cb_f map_self_post[] = { 5717c478bd9Sstevel@tonic-gate NULL, 5727c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* intrinsic */ 5737c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* pointer */ 5747c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* array */ 5757c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* function */ 5767c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* struct */ 5777c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* union */ 5787c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* enum */ 5797c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* forward */ 5807c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* typedef */ 5817c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 5827c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* volatile */ 5837c478bd9Sstevel@tonic-gate map_td_tree_self_post, /* const */ 5847c478bd9Sstevel@tonic-gate map_td_tree_self_post /* restrict */ 5857c478bd9Sstevel@tonic-gate }; 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate /* 5887c478bd9Sstevel@tonic-gate * Determining equivalence of iidesc_t nodes 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate typedef struct iifind_data { 5927c478bd9Sstevel@tonic-gate iidesc_t *iif_template; 5937c478bd9Sstevel@tonic-gate alist_t *iif_ta; 5947c478bd9Sstevel@tonic-gate int iif_newidx; 5957c478bd9Sstevel@tonic-gate int iif_refmerge; 5967c478bd9Sstevel@tonic-gate } iifind_data_t; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate /* 5997c478bd9Sstevel@tonic-gate * Check to see if this iidesc_t (node) - the current one on the list we're 6007c478bd9Sstevel@tonic-gate * iterating through - matches the target one (iif->iif_template). Return -1 6017c478bd9Sstevel@tonic-gate * if it matches, to stop the iteration. 6027c478bd9Sstevel@tonic-gate */ 6037c478bd9Sstevel@tonic-gate static int 6047c478bd9Sstevel@tonic-gate iidesc_match(void *data, void *arg) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate iidesc_t *node = data; 6077c478bd9Sstevel@tonic-gate iifind_data_t *iif = arg; 6087c478bd9Sstevel@tonic-gate int i; 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (node->ii_type != iif->iif_template->ii_type || 6117c478bd9Sstevel@tonic-gate !streq(node->ii_name, iif->iif_template->ii_name) || 6127c478bd9Sstevel@tonic-gate node->ii_dtype->t_id != iif->iif_newidx) 6137c478bd9Sstevel@tonic-gate return (0); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate if ((node->ii_type == II_SVAR || node->ii_type == II_SFUN) && 6167c478bd9Sstevel@tonic-gate !streq(node->ii_owner, iif->iif_template->ii_owner)) 6177c478bd9Sstevel@tonic-gate return (0); 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate if (node->ii_nargs != iif->iif_template->ii_nargs) 6207c478bd9Sstevel@tonic-gate return (0); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate for (i = 0; i < node->ii_nargs; i++) { 6237c478bd9Sstevel@tonic-gate if (get_mapping(iif->iif_ta, 6247c478bd9Sstevel@tonic-gate iif->iif_template->ii_args[i]->t_id) != 6257c478bd9Sstevel@tonic-gate node->ii_args[i]->t_id) 6267c478bd9Sstevel@tonic-gate return (0); 6277c478bd9Sstevel@tonic-gate } 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (iif->iif_refmerge) { 6307c478bd9Sstevel@tonic-gate switch (iif->iif_template->ii_type) { 6317c478bd9Sstevel@tonic-gate case II_GFUN: 6327c478bd9Sstevel@tonic-gate case II_SFUN: 6337c478bd9Sstevel@tonic-gate case II_GVAR: 6347c478bd9Sstevel@tonic-gate case II_SVAR: 6357c478bd9Sstevel@tonic-gate debug(3, "suppressing duping of %d %s from %s\n", 6367c478bd9Sstevel@tonic-gate iif->iif_template->ii_type, 6377c478bd9Sstevel@tonic-gate iif->iif_template->ii_name, 6387c478bd9Sstevel@tonic-gate (iif->iif_template->ii_owner ? 6397c478bd9Sstevel@tonic-gate iif->iif_template->ii_owner : "NULL")); 6407c478bd9Sstevel@tonic-gate return (0); 6417c478bd9Sstevel@tonic-gate case II_NOT: 6427c478bd9Sstevel@tonic-gate case II_PSYM: 6437c478bd9Sstevel@tonic-gate case II_SOU: 6447c478bd9Sstevel@tonic-gate case II_TYPE: 6457c478bd9Sstevel@tonic-gate break; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate return (-1); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate static int 6537c478bd9Sstevel@tonic-gate merge_type_cb(void *data, void *arg) 6547c478bd9Sstevel@tonic-gate { 6557c478bd9Sstevel@tonic-gate iidesc_t *sii = data; 6567c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 6577c478bd9Sstevel@tonic-gate iifind_data_t iif; 6587c478bd9Sstevel@tonic-gate tdtrav_cb_f *post; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate post = (mcd->md_flags & MCD_F_SELFUNIQUIFY ? map_self_post : map_post); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* Map the tdesc nodes */ 6637c478bd9Sstevel@tonic-gate (void) iitraverse(sii, &mcd->md_parent->td_curvgen, NULL, map_pre, post, 6647c478bd9Sstevel@tonic-gate mcd); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* Map the iidesc nodes */ 6677c478bd9Sstevel@tonic-gate iif.iif_template = sii; 6687c478bd9Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 6697c478bd9Sstevel@tonic-gate iif.iif_newidx = get_mapping(mcd->md_ta, sii->ii_dtype->t_id); 6707c478bd9Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, sii, iidesc_match, 6737c478bd9Sstevel@tonic-gate &iif) == 1) 6747c478bd9Sstevel@tonic-gate /* successfully mapped */ 6757c478bd9Sstevel@tonic-gate return (1); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate debug(3, "tba %s (%d)\n", (sii->ii_name ? sii->ii_name : "(anon)"), 6787c478bd9Sstevel@tonic-gate sii->ii_type); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate list_add(mcd->md_iitba, sii); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate return (0); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate static int 6867c478bd9Sstevel@tonic-gate remap_node(tdesc_t **tgtp, tdesc_t *oldtgt, int selftid, tdesc_t *newself, 6877c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd) 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate tdesc_t *tgt = NULL; 6907c478bd9Sstevel@tonic-gate tdesc_t template; 6917c478bd9Sstevel@tonic-gate int oldid = oldtgt->t_id; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (oldid == selftid) { 6947c478bd9Sstevel@tonic-gate *tgtp = newself; 6957c478bd9Sstevel@tonic-gate return (1); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate if ((template.t_id = get_mapping(mcd->md_ta, oldid)) == 0) 699*c168da27Sjohnlev aborterr("failed to get mapping for tid %d\n", oldid); 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate if (!hash_find(mcd->md_parent->td_idhash, (void *)&template, 7027c478bd9Sstevel@tonic-gate (void *)&tgt) && (!(mcd->md_flags & MCD_F_REFMERGE) || 7037c478bd9Sstevel@tonic-gate !hash_find(mcd->md_tgt->td_idhash, (void *)&template, 7047c478bd9Sstevel@tonic-gate (void *)&tgt))) { 7057c478bd9Sstevel@tonic-gate debug(3, "Remap couldn't find %d (from %d)\n", template.t_id, 7067c478bd9Sstevel@tonic-gate oldid); 7077c478bd9Sstevel@tonic-gate *tgtp = oldtgt; 7087c478bd9Sstevel@tonic-gate list_add(mcd->md_tdtbr, tgtp); 7097c478bd9Sstevel@tonic-gate return (0); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate *tgtp = tgt; 7137c478bd9Sstevel@tonic-gate return (1); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate static tdesc_t * 7177c478bd9Sstevel@tonic-gate conjure_template(tdesc_t *old, int newselfid) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate tdesc_t *new = xcalloc(sizeof (tdesc_t)); 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate new->t_name = old->t_name ? xstrdup(old->t_name) : NULL; 7227c478bd9Sstevel@tonic-gate new->t_type = old->t_type; 7237c478bd9Sstevel@tonic-gate new->t_size = old->t_size; 7247c478bd9Sstevel@tonic-gate new->t_id = newselfid; 7257c478bd9Sstevel@tonic-gate new->t_flags = old->t_flags; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate return (new); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 7317c478bd9Sstevel@tonic-gate static tdesc_t * 7327c478bd9Sstevel@tonic-gate conjure_intrinsic(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7337c478bd9Sstevel@tonic-gate { 7347c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate new->t_intr = xmalloc(sizeof (intr_t)); 7377c478bd9Sstevel@tonic-gate bcopy(old->t_intr, new->t_intr, sizeof (intr_t)); 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate return (new); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate static tdesc_t * 7437c478bd9Sstevel@tonic-gate conjure_plain(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate (void) remap_node(&new->t_tdesc, old->t_tdesc, old->t_id, new, mcd); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate return (new); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate static tdesc_t * 7537c478bd9Sstevel@tonic-gate conjure_function(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7547c478bd9Sstevel@tonic-gate { 7557c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7567c478bd9Sstevel@tonic-gate fndef_t *nfn = xmalloc(sizeof (fndef_t)); 7577c478bd9Sstevel@tonic-gate fndef_t *ofn = old->t_fndef; 7587c478bd9Sstevel@tonic-gate int i; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate (void) remap_node(&nfn->fn_ret, ofn->fn_ret, old->t_id, new, mcd); 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate nfn->fn_nargs = ofn->fn_nargs; 7637c478bd9Sstevel@tonic-gate nfn->fn_vargs = ofn->fn_vargs; 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate if (nfn->fn_nargs > 0) 7667c478bd9Sstevel@tonic-gate nfn->fn_args = xcalloc(sizeof (tdesc_t *) * ofn->fn_nargs); 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate for (i = 0; i < ofn->fn_nargs; i++) { 7697c478bd9Sstevel@tonic-gate (void) remap_node(&nfn->fn_args[i], ofn->fn_args[i], old->t_id, 7707c478bd9Sstevel@tonic-gate new, mcd); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate new->t_fndef = nfn; 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate return (new); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate static tdesc_t * 7797c478bd9Sstevel@tonic-gate conjure_array(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7807c478bd9Sstevel@tonic-gate { 7817c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 7827c478bd9Sstevel@tonic-gate ardef_t *nar = xmalloc(sizeof (ardef_t)); 7837c478bd9Sstevel@tonic-gate ardef_t *oar = old->t_ardef; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate (void) remap_node(&nar->ad_contents, oar->ad_contents, old->t_id, new, 7867c478bd9Sstevel@tonic-gate mcd); 7877c478bd9Sstevel@tonic-gate (void) remap_node(&nar->ad_idxtype, oar->ad_idxtype, old->t_id, new, 7887c478bd9Sstevel@tonic-gate mcd); 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate nar->ad_nelems = oar->ad_nelems; 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate new->t_ardef = nar; 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate return (new); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate static tdesc_t * 7987c478bd9Sstevel@tonic-gate conjure_su(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 7997c478bd9Sstevel@tonic-gate { 8007c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8017c478bd9Sstevel@tonic-gate mlist_t *omem, **nmemp; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate for (omem = old->t_members, nmemp = &new->t_members; 8047c478bd9Sstevel@tonic-gate omem; omem = omem->ml_next, nmemp = &((*nmemp)->ml_next)) { 8057c478bd9Sstevel@tonic-gate *nmemp = xmalloc(sizeof (mlist_t)); 8067c478bd9Sstevel@tonic-gate (*nmemp)->ml_offset = omem->ml_offset; 8077c478bd9Sstevel@tonic-gate (*nmemp)->ml_size = omem->ml_size; 8087c478bd9Sstevel@tonic-gate (*nmemp)->ml_name = xstrdup(omem->ml_name); 8097c478bd9Sstevel@tonic-gate (void) remap_node(&((*nmemp)->ml_type), omem->ml_type, 8107c478bd9Sstevel@tonic-gate old->t_id, new, mcd); 8117c478bd9Sstevel@tonic-gate } 8127c478bd9Sstevel@tonic-gate *nmemp = NULL; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate return (new); 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 8187c478bd9Sstevel@tonic-gate static tdesc_t * 8197c478bd9Sstevel@tonic-gate conjure_enum(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8207c478bd9Sstevel@tonic-gate { 8217c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8227c478bd9Sstevel@tonic-gate elist_t *oel, **nelp; 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate for (oel = old->t_emem, nelp = &new->t_emem; 8257c478bd9Sstevel@tonic-gate oel; oel = oel->el_next, nelp = &((*nelp)->el_next)) { 8267c478bd9Sstevel@tonic-gate *nelp = xmalloc(sizeof (elist_t)); 8277c478bd9Sstevel@tonic-gate (*nelp)->el_name = xstrdup(oel->el_name); 8287c478bd9Sstevel@tonic-gate (*nelp)->el_number = oel->el_number; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate *nelp = NULL; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate return (new); 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /*ARGSUSED2*/ 8367c478bd9Sstevel@tonic-gate static tdesc_t * 8377c478bd9Sstevel@tonic-gate conjure_forward(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8387c478bd9Sstevel@tonic-gate { 8397c478bd9Sstevel@tonic-gate tdesc_t *new = conjure_template(old, newselfid); 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate list_add(&mcd->md_tgt->td_fwdlist, new); 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate return (new); 8447c478bd9Sstevel@tonic-gate } 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8477c478bd9Sstevel@tonic-gate static tdesc_t * 8487c478bd9Sstevel@tonic-gate conjure_assert(tdesc_t *old, int newselfid, merge_cb_data_t *mcd) 8497c478bd9Sstevel@tonic-gate { 8507c478bd9Sstevel@tonic-gate assert(1 == 0); 8517c478bd9Sstevel@tonic-gate return (NULL); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate static iidesc_t * 8557c478bd9Sstevel@tonic-gate conjure_iidesc(iidesc_t *old, merge_cb_data_t *mcd) 8567c478bd9Sstevel@tonic-gate { 8577c478bd9Sstevel@tonic-gate iidesc_t *new = iidesc_dup(old); 8587c478bd9Sstevel@tonic-gate int i; 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate (void) remap_node(&new->ii_dtype, old->ii_dtype, -1, NULL, mcd); 8617c478bd9Sstevel@tonic-gate for (i = 0; i < new->ii_nargs; i++) { 8627c478bd9Sstevel@tonic-gate (void) remap_node(&new->ii_args[i], old->ii_args[i], -1, NULL, 8637c478bd9Sstevel@tonic-gate mcd); 8647c478bd9Sstevel@tonic-gate } 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate return (new); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate static int 8707c478bd9Sstevel@tonic-gate fwd_redir(tdesc_t *fwd, tdesc_t **fwdp, void *private) 8717c478bd9Sstevel@tonic-gate { 8727c478bd9Sstevel@tonic-gate alist_t *map = private; 8737c478bd9Sstevel@tonic-gate tdesc_t *defn; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate if (!alist_find(map, (void *)fwd, (void **)&defn)) 8767c478bd9Sstevel@tonic-gate return (0); 8777c478bd9Sstevel@tonic-gate 8784d232658Sjohnlev debug(3, "Redirecting an edge to %s\n", tdesc_name(defn)); 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate *fwdp = defn; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate return (1); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate static tdtrav_cb_f fwd_redir_cbs[] = { 8867c478bd9Sstevel@tonic-gate NULL, 8877c478bd9Sstevel@tonic-gate NULL, /* intrinsic */ 8887c478bd9Sstevel@tonic-gate NULL, /* pointer */ 8897c478bd9Sstevel@tonic-gate NULL, /* array */ 8907c478bd9Sstevel@tonic-gate NULL, /* function */ 8917c478bd9Sstevel@tonic-gate NULL, /* struct */ 8927c478bd9Sstevel@tonic-gate NULL, /* union */ 8937c478bd9Sstevel@tonic-gate NULL, /* enum */ 8947c478bd9Sstevel@tonic-gate fwd_redir, /* forward */ 8957c478bd9Sstevel@tonic-gate NULL, /* typedef */ 8967c478bd9Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 8977c478bd9Sstevel@tonic-gate NULL, /* volatile */ 8987c478bd9Sstevel@tonic-gate NULL, /* const */ 8997c478bd9Sstevel@tonic-gate NULL /* restrict */ 9007c478bd9Sstevel@tonic-gate }; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate typedef struct redir_mstr_data { 9037c478bd9Sstevel@tonic-gate tdata_t *rmd_tgt; 9047c478bd9Sstevel@tonic-gate alist_t *rmd_map; 9057c478bd9Sstevel@tonic-gate } redir_mstr_data_t; 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate static int 9087c478bd9Sstevel@tonic-gate redir_mstr_fwd_cb(void *name, void *value, void *arg) 9097c478bd9Sstevel@tonic-gate { 9107c478bd9Sstevel@tonic-gate tdesc_t *fwd = name; 9117c478bd9Sstevel@tonic-gate int defnid = (int)value; 9127c478bd9Sstevel@tonic-gate redir_mstr_data_t *rmd = arg; 9137c478bd9Sstevel@tonic-gate tdesc_t template; 9147c478bd9Sstevel@tonic-gate tdesc_t *defn; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate template.t_id = defnid; 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate if (!hash_find(rmd->rmd_tgt->td_idhash, (void *)&template, 9197c478bd9Sstevel@tonic-gate (void *)&defn)) { 920*c168da27Sjohnlev aborterr("Couldn't unforward %d (%s)\n", defnid, 9214d232658Sjohnlev tdesc_name(defn)); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9244d232658Sjohnlev debug(3, "Forward map: resolved %d to %s\n", defnid, tdesc_name(defn)); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate alist_add(rmd->rmd_map, (void *)fwd, (void *)defn); 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate return (1); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate static void 9327c478bd9Sstevel@tonic-gate redir_mstr_fwds(merge_cb_data_t *mcd) 9337c478bd9Sstevel@tonic-gate { 9347c478bd9Sstevel@tonic-gate redir_mstr_data_t rmd; 9357c478bd9Sstevel@tonic-gate alist_t *map = alist_new(NULL, NULL); 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate rmd.rmd_tgt = mcd->md_tgt; 9387c478bd9Sstevel@tonic-gate rmd.rmd_map = map; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (alist_iter(mcd->md_fdida, redir_mstr_fwd_cb, &rmd)) { 9417c478bd9Sstevel@tonic-gate (void) iitraverse_hash(mcd->md_tgt->td_iihash, 9427c478bd9Sstevel@tonic-gate &mcd->md_tgt->td_curvgen, fwd_redir_cbs, NULL, NULL, map); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate alist_free(map); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate static int 9497c478bd9Sstevel@tonic-gate add_iitba_cb(void *data, void *private) 9507c478bd9Sstevel@tonic-gate { 9517c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = private; 9527c478bd9Sstevel@tonic-gate iidesc_t *tba = data; 9537c478bd9Sstevel@tonic-gate iidesc_t *new; 9547c478bd9Sstevel@tonic-gate iifind_data_t iif; 9557c478bd9Sstevel@tonic-gate int newidx; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate newidx = get_mapping(mcd->md_ta, tba->ii_dtype->t_id); 9587c478bd9Sstevel@tonic-gate assert(newidx != -1); 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate (void) list_remove(mcd->md_iitba, data, NULL, NULL); 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate iif.iif_template = tba; 9637c478bd9Sstevel@tonic-gate iif.iif_ta = mcd->md_ta; 9647c478bd9Sstevel@tonic-gate iif.iif_newidx = newidx; 9657c478bd9Sstevel@tonic-gate iif.iif_refmerge = (mcd->md_flags & MCD_F_REFMERGE); 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate if (hash_match(mcd->md_parent->td_iihash, tba, iidesc_match, 9687c478bd9Sstevel@tonic-gate &iif) == 1) { 9697c478bd9Sstevel@tonic-gate debug(3, "iidesc_t %s already exists\n", 9707c478bd9Sstevel@tonic-gate (tba->ii_name ? tba->ii_name : "(anon)")); 9717c478bd9Sstevel@tonic-gate return (1); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate new = conjure_iidesc(tba, mcd); 9757c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_iihash, new); 9767c478bd9Sstevel@tonic-gate 9777c478bd9Sstevel@tonic-gate return (1); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate static int 9817c478bd9Sstevel@tonic-gate add_tdesc(tdesc_t *oldtdp, int newid, merge_cb_data_t *mcd) 9827c478bd9Sstevel@tonic-gate { 9837c478bd9Sstevel@tonic-gate tdesc_t *newtdp; 9847c478bd9Sstevel@tonic-gate tdesc_t template; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate template.t_id = newid; 9877c478bd9Sstevel@tonic-gate assert(hash_find(mcd->md_parent->td_idhash, 9887c478bd9Sstevel@tonic-gate (void *)&template, NULL) == 0); 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate debug(3, "trying to conjure %d %s (%d) as %d\n", 9914d232658Sjohnlev oldtdp->t_type, tdesc_name(oldtdp), oldtdp->t_id, newid); 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate if ((newtdp = tdesc_ops[oldtdp->t_type].conjure(oldtdp, newid, 9947c478bd9Sstevel@tonic-gate mcd)) == NULL) 9957c478bd9Sstevel@tonic-gate /* couldn't map everything */ 9967c478bd9Sstevel@tonic-gate return (0); 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate debug(3, "succeeded\n"); 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_idhash, newtdp); 10017c478bd9Sstevel@tonic-gate hash_add(mcd->md_tgt->td_layouthash, newtdp); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate return (1); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate static int 10077c478bd9Sstevel@tonic-gate add_tdtba_cb(void *data, void *arg) 10087c478bd9Sstevel@tonic-gate { 10097c478bd9Sstevel@tonic-gate tdesc_t *tdp = data; 10107c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 10117c478bd9Sstevel@tonic-gate int newid; 10127c478bd9Sstevel@tonic-gate int rc; 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate newid = get_mapping(mcd->md_ta, tdp->t_id); 10157c478bd9Sstevel@tonic-gate assert(newid != -1); 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate if ((rc = add_tdesc(tdp, newid, mcd))) 10187c478bd9Sstevel@tonic-gate hash_remove(mcd->md_tdtba, (void *)tdp); 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate return (rc); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate static int 10247c478bd9Sstevel@tonic-gate add_tdtbr_cb(void *data, void *arg) 10257c478bd9Sstevel@tonic-gate { 10267c478bd9Sstevel@tonic-gate tdesc_t **tdpp = data; 10277c478bd9Sstevel@tonic-gate merge_cb_data_t *mcd = arg; 10287c478bd9Sstevel@tonic-gate 10294d232658Sjohnlev debug(3, "Remapping %s (%d)\n", tdesc_name(*tdpp), (*tdpp)->t_id); 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate if (!remap_node(tdpp, *tdpp, -1, NULL, mcd)) 10327c478bd9Sstevel@tonic-gate return (0); 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate (void) list_remove(mcd->md_tdtbr, (void *)tdpp, NULL, NULL); 10357c478bd9Sstevel@tonic-gate return (1); 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate static void 10397c478bd9Sstevel@tonic-gate merge_types(hash_t *src, merge_cb_data_t *mcd) 10407c478bd9Sstevel@tonic-gate { 10417c478bd9Sstevel@tonic-gate list_t *iitba = NULL; 10427c478bd9Sstevel@tonic-gate list_t *tdtbr = NULL; 10437c478bd9Sstevel@tonic-gate int iirc, tdrc; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate mcd->md_iitba = &iitba; 10467c478bd9Sstevel@tonic-gate mcd->md_tdtba = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash, 10477c478bd9Sstevel@tonic-gate tdesc_layoutcmp); 10487c478bd9Sstevel@tonic-gate mcd->md_tdtbr = &tdtbr; 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate (void) hash_iter(src, merge_type_cb, mcd); 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate tdrc = hash_iter(mcd->md_tdtba, add_tdtba_cb, (void *)mcd); 10537c478bd9Sstevel@tonic-gate debug(3, "add_tdtba_cb added %d items\n", tdrc); 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate iirc = list_iter(*mcd->md_iitba, add_iitba_cb, (void *)mcd); 10567c478bd9Sstevel@tonic-gate debug(3, "add_iitba_cb added %d items\n", iirc); 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate assert(list_count(*mcd->md_iitba) == 0 && 10597c478bd9Sstevel@tonic-gate hash_count(mcd->md_tdtba) == 0); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate tdrc = list_iter(*mcd->md_tdtbr, add_tdtbr_cb, (void *)mcd); 10627c478bd9Sstevel@tonic-gate debug(3, "add_tdtbr_cb added %d items\n", tdrc); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (list_count(*mcd->md_tdtbr) != 0) 1065*c168da27Sjohnlev aborterr("Couldn't remap all nodes\n"); 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate /* 10687c478bd9Sstevel@tonic-gate * We now have an alist of master forwards and the ids of the new master 10697c478bd9Sstevel@tonic-gate * definitions for those forwards in mcd->md_fdida. By this point, 10707c478bd9Sstevel@tonic-gate * we're guaranteed that all of the master definitions referenced in 10717c478bd9Sstevel@tonic-gate * fdida have been added to the master tree. We now traverse through 10727c478bd9Sstevel@tonic-gate * the master tree, redirecting all edges inbound to forwards that have 10737c478bd9Sstevel@tonic-gate * definitions to those definitions. 10747c478bd9Sstevel@tonic-gate */ 10757c478bd9Sstevel@tonic-gate if (mcd->md_parent == mcd->md_tgt) { 10767c478bd9Sstevel@tonic-gate redir_mstr_fwds(mcd); 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate void 10817c478bd9Sstevel@tonic-gate merge_into_master(tdata_t *cur, tdata_t *mstr, tdata_t *tgt, int selfuniquify) 10827c478bd9Sstevel@tonic-gate { 10837c478bd9Sstevel@tonic-gate merge_cb_data_t mcd; 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate cur->td_ref++; 10867c478bd9Sstevel@tonic-gate mstr->td_ref++; 10877c478bd9Sstevel@tonic-gate if (tgt) 10887c478bd9Sstevel@tonic-gate tgt->td_ref++; 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate assert(cur->td_ref == 1 && mstr->td_ref == 1 && 10917c478bd9Sstevel@tonic-gate (tgt == NULL || tgt->td_ref == 1)); 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate mcd.md_parent = mstr; 10947c478bd9Sstevel@tonic-gate mcd.md_tgt = (tgt ? tgt : mstr); 10957c478bd9Sstevel@tonic-gate mcd.md_ta = alist_new(NULL, NULL); 10967c478bd9Sstevel@tonic-gate mcd.md_fdida = alist_new(NULL, NULL); 10977c478bd9Sstevel@tonic-gate mcd.md_flags = 0; 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate if (selfuniquify) 11007c478bd9Sstevel@tonic-gate mcd.md_flags |= MCD_F_SELFUNIQUIFY; 11017c478bd9Sstevel@tonic-gate if (tgt) 11027c478bd9Sstevel@tonic-gate mcd.md_flags |= MCD_F_REFMERGE; 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate mstr->td_curvgen = MAX(mstr->td_curvgen, cur->td_curvgen); 11057c478bd9Sstevel@tonic-gate mstr->td_curemark = MAX(mstr->td_curemark, cur->td_curemark); 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate merge_types(cur->td_iihash, &mcd); 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate if (debug_level >= 3) { 11107c478bd9Sstevel@tonic-gate debug(3, "Type association stats\n"); 11117c478bd9Sstevel@tonic-gate alist_stats(mcd.md_ta, 0); 11127c478bd9Sstevel@tonic-gate debug(3, "Layout hash stats\n"); 11137c478bd9Sstevel@tonic-gate hash_stats(mcd.md_tgt->td_layouthash, 1); 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate alist_free(mcd.md_fdida); 11177c478bd9Sstevel@tonic-gate alist_free(mcd.md_ta); 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate cur->td_ref--; 11207c478bd9Sstevel@tonic-gate mstr->td_ref--; 11217c478bd9Sstevel@tonic-gate if (tgt) 11227c478bd9Sstevel@tonic-gate tgt->td_ref--; 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate tdesc_ops_t tdesc_ops[] = { 11267c478bd9Sstevel@tonic-gate { "ERROR! BAD tdesc TYPE", NULL, NULL }, 11277c478bd9Sstevel@tonic-gate { "intrinsic", equiv_intrinsic, conjure_intrinsic }, 11287c478bd9Sstevel@tonic-gate { "pointer", equiv_plain, conjure_plain }, 11297c478bd9Sstevel@tonic-gate { "array", equiv_array, conjure_array }, 11307c478bd9Sstevel@tonic-gate { "function", equiv_function, conjure_function }, 11317c478bd9Sstevel@tonic-gate { "struct", equiv_su, conjure_su }, 11327c478bd9Sstevel@tonic-gate { "union", equiv_su, conjure_su }, 11337c478bd9Sstevel@tonic-gate { "enum", equiv_enum, conjure_enum }, 11347c478bd9Sstevel@tonic-gate { "forward", NULL, conjure_forward }, 11357c478bd9Sstevel@tonic-gate { "typedef", equiv_plain, conjure_plain }, 11367c478bd9Sstevel@tonic-gate { "typedef_unres", equiv_assert, conjure_assert }, 11377c478bd9Sstevel@tonic-gate { "volatile", equiv_plain, conjure_plain }, 11387c478bd9Sstevel@tonic-gate { "const", equiv_plain, conjure_plain }, 11397c478bd9Sstevel@tonic-gate { "restrict", equiv_plain, conjure_plain } 11407c478bd9Sstevel@tonic-gate }; 1141