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