1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Routines for manipulating tdesc and tdata structures 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <stdio.h> 34*0Sstevel@tonic-gate #include <stdlib.h> 35*0Sstevel@tonic-gate #include <strings.h> 36*0Sstevel@tonic-gate #include <pthread.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include "ctftools.h" 39*0Sstevel@tonic-gate #include "memory.h" 40*0Sstevel@tonic-gate #include "traverse.h" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * The layout hash is used during the equivalency checking. We have a node in 44*0Sstevel@tonic-gate * the child graph that may be equivalent to a node in the parent graph. To 45*0Sstevel@tonic-gate * find the corresponding node (if any) in the parent, we need a quick way to 46*0Sstevel@tonic-gate * get to all nodes in the parent that look like the node in the child. Since a 47*0Sstevel@tonic-gate * large number of nodes don't have names, we need to incorporate the layout of 48*0Sstevel@tonic-gate * the node into the hash. If we don't, we'll end up with the vast majority of 49*0Sstevel@tonic-gate * nodes in bucket zero, with one or two nodes in each of the remaining buckets. 50*0Sstevel@tonic-gate * 51*0Sstevel@tonic-gate * There are a couple of constraints, both of which concern forward 52*0Sstevel@tonic-gate * declarations. Recall that a forward declaration tdesc is equivalent to a 53*0Sstevel@tonic-gate * tdesc that actually defines the structure or union. As such, we cannot 54*0Sstevel@tonic-gate * incorporate anything into the hash for a named struct or union node that 55*0Sstevel@tonic-gate * couldn't be found by looking at the forward, and vice versa. 56*0Sstevel@tonic-gate */ 57*0Sstevel@tonic-gate int 58*0Sstevel@tonic-gate tdesc_layouthash(int nbuckets, void *node) 59*0Sstevel@tonic-gate { 60*0Sstevel@tonic-gate tdesc_t *tdp = node; 61*0Sstevel@tonic-gate char *name = NULL; 62*0Sstevel@tonic-gate ulong_t h = 0; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate if (tdp->t_name) 65*0Sstevel@tonic-gate name = tdp->t_name; 66*0Sstevel@tonic-gate else { 67*0Sstevel@tonic-gate switch (tdp->t_type) { 68*0Sstevel@tonic-gate case POINTER: 69*0Sstevel@tonic-gate case TYPEDEF: 70*0Sstevel@tonic-gate case VOLATILE: 71*0Sstevel@tonic-gate case CONST: 72*0Sstevel@tonic-gate case RESTRICT: 73*0Sstevel@tonic-gate name = tdp->t_tdesc->t_name; 74*0Sstevel@tonic-gate break; 75*0Sstevel@tonic-gate case FUNCTION: 76*0Sstevel@tonic-gate h = tdp->t_fndef->fn_nargs + 77*0Sstevel@tonic-gate tdp->t_fndef->fn_vargs; 78*0Sstevel@tonic-gate name = tdp->t_fndef->fn_ret->t_name; 79*0Sstevel@tonic-gate break; 80*0Sstevel@tonic-gate case ARRAY: 81*0Sstevel@tonic-gate h = tdp->t_ardef->ad_nelems; 82*0Sstevel@tonic-gate name = tdp->t_ardef->ad_contents->t_name; 83*0Sstevel@tonic-gate break; 84*0Sstevel@tonic-gate case STRUCT: 85*0Sstevel@tonic-gate case UNION: 86*0Sstevel@tonic-gate /* 87*0Sstevel@tonic-gate * Unnamed structures, which cannot have forward 88*0Sstevel@tonic-gate * declarations pointing to them. We can therefore 89*0Sstevel@tonic-gate * incorporate the name of the first member into 90*0Sstevel@tonic-gate * the hash value. 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate name = tdp->t_members->ml_name; 93*0Sstevel@tonic-gate break; 94*0Sstevel@tonic-gate case ENUM: 95*0Sstevel@tonic-gate /* Use the first element in the hash value */ 96*0Sstevel@tonic-gate name = tdp->t_emem->el_name; 97*0Sstevel@tonic-gate break; 98*0Sstevel@tonic-gate default: 99*0Sstevel@tonic-gate /* 100*0Sstevel@tonic-gate * Intrinsics, forwards, and typedefs all have 101*0Sstevel@tonic-gate * names. 102*0Sstevel@tonic-gate */ 103*0Sstevel@tonic-gate warning("Unexpected unnamed %d tdesc (ID %d)\n", 104*0Sstevel@tonic-gate tdp->t_type, tdp->t_id); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate if (name) 109*0Sstevel@tonic-gate return (hash_name(nbuckets, name)); 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate return (h % nbuckets); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate int 115*0Sstevel@tonic-gate tdesc_layoutcmp(void *arg1, void *arg2) 116*0Sstevel@tonic-gate { 117*0Sstevel@tonic-gate tdesc_t *tdp1 = arg1, *tdp2 = arg2; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate if (tdp1->t_name == NULL) { 120*0Sstevel@tonic-gate if (tdp2->t_name == NULL) 121*0Sstevel@tonic-gate return (0); 122*0Sstevel@tonic-gate else 123*0Sstevel@tonic-gate return (-1); 124*0Sstevel@tonic-gate } else if (tdp2->t_name == NULL) 125*0Sstevel@tonic-gate return (1); 126*0Sstevel@tonic-gate else 127*0Sstevel@tonic-gate return (strcmp(tdp1->t_name, tdp2->t_name)); 128*0Sstevel@tonic-gate } 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate int 131*0Sstevel@tonic-gate tdesc_idhash(int nbuckets, void *data) 132*0Sstevel@tonic-gate { 133*0Sstevel@tonic-gate tdesc_t *tdp = data; 134*0Sstevel@tonic-gate 135*0Sstevel@tonic-gate return (tdp->t_id % nbuckets); 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate int 139*0Sstevel@tonic-gate tdesc_idcmp(void *arg1, void *arg2) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate tdesc_t *tdp1 = arg1, *tdp2 = arg2; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate if (tdp1->t_id == tdp2->t_id) 144*0Sstevel@tonic-gate return (0); 145*0Sstevel@tonic-gate else 146*0Sstevel@tonic-gate return (tdp1->t_id > tdp2->t_id ? 1 : -1); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate int 150*0Sstevel@tonic-gate tdesc_namehash(int nbuckets, void *data) 151*0Sstevel@tonic-gate { 152*0Sstevel@tonic-gate tdesc_t *tdp = data; 153*0Sstevel@tonic-gate ulong_t h, g; 154*0Sstevel@tonic-gate char *c; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate if (tdp->t_name == NULL) 157*0Sstevel@tonic-gate return (0); 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate for (h = 0, c = tdp->t_name; *c; c++) { 160*0Sstevel@tonic-gate h = (h << 4) + *c; 161*0Sstevel@tonic-gate if ((g = (h & 0xf0000000)) != 0) { 162*0Sstevel@tonic-gate h ^= (g >> 24); 163*0Sstevel@tonic-gate h ^= g; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate return (h % nbuckets); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate int 171*0Sstevel@tonic-gate tdesc_namecmp(void *arg1, void *arg2) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate tdesc_t *tdp1 = arg1, *tdp2 = arg2; 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate return (!streq(tdp1->t_name, tdp2->t_name)); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate /*ARGSUSED1*/ 179*0Sstevel@tonic-gate int 180*0Sstevel@tonic-gate tdesc_print(void *data, void *private) 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate tdesc_t *tdp = data; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate printf("%7d %s\n", tdp->t_id, (tdp->t_name ? tdp->t_name : "(anon)")); 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate return (1); 187*0Sstevel@tonic-gate } 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate static void 190*0Sstevel@tonic-gate free_intr(tdesc_t *tdp) 191*0Sstevel@tonic-gate { 192*0Sstevel@tonic-gate free(tdp->t_intr); 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate static void 196*0Sstevel@tonic-gate free_ardef(tdesc_t *tdp) 197*0Sstevel@tonic-gate { 198*0Sstevel@tonic-gate free(tdp->t_ardef); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate static void 202*0Sstevel@tonic-gate free_mlist(tdesc_t *tdp) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate mlist_t *ml = tdp->t_members; 205*0Sstevel@tonic-gate mlist_t *oml; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate while (ml) { 208*0Sstevel@tonic-gate oml = ml; 209*0Sstevel@tonic-gate ml = ml->ml_next; 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate if (oml->ml_name) 212*0Sstevel@tonic-gate free(oml->ml_name); 213*0Sstevel@tonic-gate free(oml); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate static void 218*0Sstevel@tonic-gate free_elist(tdesc_t *tdp) 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate elist_t *el = tdp->t_emem; 221*0Sstevel@tonic-gate elist_t *oel; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate while (el) { 224*0Sstevel@tonic-gate oel = el; 225*0Sstevel@tonic-gate el = el->el_next; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate if (oel->el_name) 228*0Sstevel@tonic-gate free(oel->el_name); 229*0Sstevel@tonic-gate free(oel); 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate static void (*free_cbs[])(tdesc_t *) = { 234*0Sstevel@tonic-gate NULL, 235*0Sstevel@tonic-gate free_intr, 236*0Sstevel@tonic-gate NULL, 237*0Sstevel@tonic-gate free_ardef, 238*0Sstevel@tonic-gate NULL, 239*0Sstevel@tonic-gate free_mlist, 240*0Sstevel@tonic-gate free_mlist, 241*0Sstevel@tonic-gate free_elist, 242*0Sstevel@tonic-gate NULL, 243*0Sstevel@tonic-gate NULL, 244*0Sstevel@tonic-gate NULL, 245*0Sstevel@tonic-gate NULL, 246*0Sstevel@tonic-gate NULL, 247*0Sstevel@tonic-gate NULL 248*0Sstevel@tonic-gate }; 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate /*ARGSUSED1*/ 251*0Sstevel@tonic-gate static int 252*0Sstevel@tonic-gate tdesc_free_cb(tdesc_t *tdp, void *private) 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate if (tdp->t_name) 255*0Sstevel@tonic-gate free(tdp->t_name); 256*0Sstevel@tonic-gate if (free_cbs[tdp->t_type]) 257*0Sstevel@tonic-gate free_cbs[tdp->t_type](tdp); 258*0Sstevel@tonic-gate free(tdp); 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate return (1); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate void 264*0Sstevel@tonic-gate tdesc_free(tdesc_t *tdp) 265*0Sstevel@tonic-gate { 266*0Sstevel@tonic-gate (void) tdesc_free_cb(tdp, NULL); 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate static int 270*0Sstevel@tonic-gate tdata_label_cmp(labelent_t *le1, labelent_t *le2) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate return (le1->le_idx - le2->le_idx); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate void 276*0Sstevel@tonic-gate tdata_label_add(tdata_t *td, char *label, int idx) 277*0Sstevel@tonic-gate { 278*0Sstevel@tonic-gate labelent_t *le = xmalloc(sizeof (*le)); 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate le->le_name = xstrdup(label); 281*0Sstevel@tonic-gate le->le_idx = (idx == -1 ? td->td_nextid - 1 : idx); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate slist_add(&td->td_labels, le, (int (*)())tdata_label_cmp); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate static int 287*0Sstevel@tonic-gate tdata_label_top_cb(void *data, void *arg) 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate labelent_t *le = data; 290*0Sstevel@tonic-gate labelent_t **topp = arg; 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate *topp = le; 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate return (1); 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate labelent_t * 298*0Sstevel@tonic-gate tdata_label_top(tdata_t *td) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate labelent_t *top = NULL; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate (void) list_iter(td->td_labels, tdata_label_top_cb, &top); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate return (top); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate static int 308*0Sstevel@tonic-gate tdata_label_find_cb(labelent_t *le, labelent_t *tmpl) 309*0Sstevel@tonic-gate { 310*0Sstevel@tonic-gate return (streq(le->le_name, tmpl->le_name)); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate int 314*0Sstevel@tonic-gate tdata_label_find(tdata_t *td, char *label) 315*0Sstevel@tonic-gate { 316*0Sstevel@tonic-gate labelent_t let; 317*0Sstevel@tonic-gate labelent_t *ret; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if (streq(label, "BASE")) { 320*0Sstevel@tonic-gate ret = (labelent_t *)list_first(td->td_labels); 321*0Sstevel@tonic-gate return (ret ? ret->le_idx : -1); 322*0Sstevel@tonic-gate } 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate let.le_name = label; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate if (!(ret = (labelent_t *)list_find(td->td_labels, &let, 327*0Sstevel@tonic-gate (int (*)())tdata_label_find_cb))) 328*0Sstevel@tonic-gate return (-1); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate return (ret->le_idx); 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate static int 334*0Sstevel@tonic-gate tdata_label_newmax_cb(void *data, void *arg) 335*0Sstevel@tonic-gate { 336*0Sstevel@tonic-gate labelent_t *le = data; 337*0Sstevel@tonic-gate int *newmaxp = arg; 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate if (le->le_idx > *newmaxp) { 340*0Sstevel@tonic-gate le->le_idx = *newmaxp; 341*0Sstevel@tonic-gate return (1); 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate return (0); 345*0Sstevel@tonic-gate } 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate void 348*0Sstevel@tonic-gate tdata_label_newmax(tdata_t *td, int newmax) 349*0Sstevel@tonic-gate { 350*0Sstevel@tonic-gate (void) list_iter(td->td_labels, tdata_label_newmax_cb, &newmax); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate /*ARGSUSED1*/ 354*0Sstevel@tonic-gate static void 355*0Sstevel@tonic-gate tdata_label_free_cb(labelent_t *le, void *private) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate if (le->le_name) 358*0Sstevel@tonic-gate free(le->le_name); 359*0Sstevel@tonic-gate free(le); 360*0Sstevel@tonic-gate } 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate void 363*0Sstevel@tonic-gate tdata_label_free(tdata_t *td) 364*0Sstevel@tonic-gate { 365*0Sstevel@tonic-gate list_free(td->td_labels, (void (*)())tdata_label_free_cb, NULL); 366*0Sstevel@tonic-gate td->td_labels = NULL; 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate tdata_t * 370*0Sstevel@tonic-gate tdata_new(void) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate tdata_t *new = xcalloc(sizeof (tdata_t)); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate new->td_layouthash = hash_new(TDATA_LAYOUT_HASH_SIZE, tdesc_layouthash, 375*0Sstevel@tonic-gate tdesc_layoutcmp); 376*0Sstevel@tonic-gate new->td_idhash = hash_new(TDATA_ID_HASH_SIZE, tdesc_idhash, 377*0Sstevel@tonic-gate tdesc_idcmp); 378*0Sstevel@tonic-gate /* 379*0Sstevel@tonic-gate * This is also traversed as a list, but amortized O(1) 380*0Sstevel@tonic-gate * lookup massively impacts part of the merge phase, so 381*0Sstevel@tonic-gate * we store the iidescs as a hash. 382*0Sstevel@tonic-gate */ 383*0Sstevel@tonic-gate new->td_iihash = hash_new(IIDESC_HASH_SIZE, iidesc_hash, NULL); 384*0Sstevel@tonic-gate new->td_nextid = 1; 385*0Sstevel@tonic-gate new->td_curvgen = 1; 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate pthread_mutex_init(&new->td_mergelock, NULL); 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate return (new); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate void 393*0Sstevel@tonic-gate tdata_free(tdata_t *td) 394*0Sstevel@tonic-gate { 395*0Sstevel@tonic-gate hash_free(td->td_iihash, (void (*)())iidesc_free, NULL); 396*0Sstevel@tonic-gate hash_free(td->td_layouthash, (void (*)())tdesc_free_cb, NULL); 397*0Sstevel@tonic-gate hash_free(td->td_idhash, NULL, NULL); 398*0Sstevel@tonic-gate list_free(td->td_fwdlist, NULL, NULL); 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate tdata_label_free(td); 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate free(td->td_parlabel); 403*0Sstevel@tonic-gate free(td->td_parname); 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate pthread_mutex_destroy(&td->td_mergelock); 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate free(td); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /*ARGSUSED1*/ 411*0Sstevel@tonic-gate static int 412*0Sstevel@tonic-gate build_hashes(tdesc_t *ctdp, tdesc_t **ctdpp, void *private) 413*0Sstevel@tonic-gate { 414*0Sstevel@tonic-gate tdata_t *td = private; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate hash_add(td->td_idhash, ctdp); 417*0Sstevel@tonic-gate hash_add(td->td_layouthash, ctdp); 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate return (1); 420*0Sstevel@tonic-gate } 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate static tdtrav_cb_f build_hashes_cbs[] = { 423*0Sstevel@tonic-gate NULL, 424*0Sstevel@tonic-gate build_hashes, /* intrinsic */ 425*0Sstevel@tonic-gate build_hashes, /* pointer */ 426*0Sstevel@tonic-gate build_hashes, /* array */ 427*0Sstevel@tonic-gate build_hashes, /* function */ 428*0Sstevel@tonic-gate build_hashes, /* struct */ 429*0Sstevel@tonic-gate build_hashes, /* union */ 430*0Sstevel@tonic-gate build_hashes, /* enum */ 431*0Sstevel@tonic-gate build_hashes, /* forward */ 432*0Sstevel@tonic-gate build_hashes, /* typedef */ 433*0Sstevel@tonic-gate tdtrav_assert, /* typedef_unres */ 434*0Sstevel@tonic-gate build_hashes, /* volatile */ 435*0Sstevel@tonic-gate build_hashes, /* const */ 436*0Sstevel@tonic-gate build_hashes /* restrict */ 437*0Sstevel@tonic-gate }; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate static void 440*0Sstevel@tonic-gate tdata_build_hashes_common(tdata_t *td, hash_t *hash) 441*0Sstevel@tonic-gate { 442*0Sstevel@tonic-gate (void) iitraverse_hash(hash, &td->td_curvgen, NULL, NULL, 443*0Sstevel@tonic-gate build_hashes_cbs, td); 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate void 447*0Sstevel@tonic-gate tdata_build_hashes(tdata_t *td) 448*0Sstevel@tonic-gate { 449*0Sstevel@tonic-gate tdata_build_hashes_common(td, td->td_iihash); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* Merge td2 into td1. td2 is destroyed by the merge */ 453*0Sstevel@tonic-gate void 454*0Sstevel@tonic-gate tdata_merge(tdata_t *td1, tdata_t *td2) 455*0Sstevel@tonic-gate { 456*0Sstevel@tonic-gate td1->td_curemark = MAX(td1->td_curemark, td2->td_curemark); 457*0Sstevel@tonic-gate td1->td_curvgen = MAX(td1->td_curvgen, td2->td_curvgen); 458*0Sstevel@tonic-gate td1->td_nextid = MAX(td1->td_nextid, td2->td_nextid); 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate hash_merge(td1->td_iihash, td2->td_iihash); 461*0Sstevel@tonic-gate 462*0Sstevel@tonic-gate /* Add td2's type tree to the hashes */ 463*0Sstevel@tonic-gate tdata_build_hashes_common(td1, td2->td_iihash); 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate list_concat(&td1->td_fwdlist, td2->td_fwdlist); 466*0Sstevel@tonic-gate td2->td_fwdlist = NULL; 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate slist_merge(&td1->td_labels, td2->td_labels, 469*0Sstevel@tonic-gate (int (*)())tdata_label_cmp); 470*0Sstevel@tonic-gate td2->td_labels = NULL; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* free the td2 hashes (data is now part of td1) */ 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate hash_free(td2->td_layouthash, NULL, NULL); 475*0Sstevel@tonic-gate td2->td_layouthash = NULL; 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate hash_free(td2->td_iihash, NULL, NULL); 478*0Sstevel@tonic-gate td2->td_iihash = NULL; 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate tdata_free(td2); 481*0Sstevel@tonic-gate } 482