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