~ubuntu-branches/ubuntu/trusty/ctfutils/trusty

« back to all changes in this revision

Viewing changes to cddl/contrib/opensolaris/tools/ctf/cvt/merge.c

  • Committer: Package Import Robot
  • Author(s): Robert Millan
  • Date: 2013-11-09 17:07:06 UTC
  • Revision ID: package-import@ubuntu.com-20131109170706-kacr6nvpkbhxsk81
Tags: upstream-9.2
ImportĀ upstreamĀ versionĀ 9.2

Show diffs side-by-side

added added

removed removed

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