4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * DTrace Parsing Control Block
32 * A DTrace Parsing Control Block (PCB) contains all of the state that is used
33 * by a single pass of the D compiler, other than the global variables used by
34 * lex and yacc. The routines in this file are used to set up and tear down
35 * PCBs, which are kept on a stack pointed to by the libdtrace global 'yypcb'.
36 * The main engine of the compiler, dt_compile(), is located in dt_cc.c and is
37 * responsible for calling these routines to begin and end a compilation pass.
39 * Sun's lex/yacc are not MT-safe or re-entrant, but we permit limited nested
40 * use of dt_compile() once the entire parse tree has been constructed but has
41 * not yet executed the "cooking" pass (see dt_cc.c for more information). The
42 * PCB design also makes it easier to debug (since all global state is kept in
43 * one place) and could permit us to make the D compiler MT-safe or re-entrant
44 * in the future by adding locks to libdtrace or switching to Flex and Bison.
52 #include <dt_program.h>
53 #include <dt_provider.h>
57 * Initialize the specified PCB by zeroing it and filling in a few default
58 * members, and then pushing it on to the top of the PCB stack and setting
59 * yypcb to point to it. Increment the current handle's generation count.
62 dt_pcb_push(dtrace_hdl_t
*dtp
, dt_pcb_t
*pcb
)
65 * Since lex/yacc are not re-entrant and we don't implement state save,
66 * assert that if another PCB is active, it is from the same handle and
67 * has completed execution of yyparse(). If the first assertion fires,
68 * the caller is calling libdtrace without proper MT locking. If the
69 * second assertion fires, dt_compile() is being called recursively
70 * from an illegal location in libdtrace, or a dt_pcb_pop() is missing.
73 assert(yypcb
->pcb_hdl
== dtp
);
74 assert(yypcb
->pcb_yystate
== YYS_DONE
);
77 bzero(pcb
, sizeof (dt_pcb_t
));
79 dt_scope_create(&pcb
->pcb_dstack
);
80 dt_idstack_push(&pcb
->pcb_globals
, dtp
->dt_globals
);
81 dt_irlist_create(&pcb
->pcb_ir
);
84 pcb
->pcb_prev
= dtp
->dt_pcb
;
93 dt_pcb_pop_ident(dt_idhash_t
*dhp
, dt_ident_t
*idp
, void *arg
)
95 dtrace_hdl_t
*dtp
= arg
;
97 if (idp
->di_gen
== dtp
->dt_gen
)
98 dt_idhash_delete(dhp
, idp
);
104 * Pop the topmost PCB from the PCB stack and destroy any data structures that
105 * are associated with it. If 'err' is non-zero, destroy any intermediate
106 * state that is left behind as part of a compilation that has failed.
109 dt_pcb_pop(dtrace_hdl_t
*dtp
, int err
)
111 dt_pcb_t
*pcb
= yypcb
;
115 assert(pcb
== dtp
->dt_pcb
);
117 while (pcb
->pcb_dstack
.ds_next
!= NULL
)
118 (void) dt_scope_pop();
120 dt_scope_destroy(&pcb
->pcb_dstack
);
121 dt_irlist_destroy(&pcb
->pcb_ir
);
123 dt_node_link_free(&pcb
->pcb_list
);
124 dt_node_link_free(&pcb
->pcb_hold
);
127 dt_xlator_t
*dxp
, *nxp
;
128 dt_provider_t
*pvp
, *nvp
;
130 if (pcb
->pcb_prog
!= NULL
)
131 dt_program_destroy(dtp
, pcb
->pcb_prog
);
132 if (pcb
->pcb_stmt
!= NULL
)
133 dtrace_stmt_destroy(dtp
, pcb
->pcb_stmt
);
134 if (pcb
->pcb_ecbdesc
!= NULL
)
135 dt_ecbdesc_release(dtp
, pcb
->pcb_ecbdesc
);
137 for (dxp
= dt_list_next(&dtp
->dt_xlators
); dxp
; dxp
= nxp
) {
138 nxp
= dt_list_next(dxp
);
139 if (dxp
->dx_gen
== dtp
->dt_gen
)
140 dt_xlator_destroy(dtp
, dxp
);
143 for (pvp
= dt_list_next(&dtp
->dt_provlist
); pvp
; pvp
= nvp
) {
144 nvp
= dt_list_next(pvp
);
145 if (pvp
->pv_gen
== dtp
->dt_gen
)
146 dt_provider_destroy(dtp
, pvp
);
149 (void) dt_idhash_iter(dtp
->dt_aggs
, dt_pcb_pop_ident
, dtp
);
150 dt_idhash_update(dtp
->dt_aggs
);
152 (void) dt_idhash_iter(dtp
->dt_globals
, dt_pcb_pop_ident
, dtp
);
153 dt_idhash_update(dtp
->dt_globals
);
155 (void) dt_idhash_iter(dtp
->dt_tls
, dt_pcb_pop_ident
, dtp
);
156 dt_idhash_update(dtp
->dt_tls
);
158 (void) ctf_discard(dtp
->dt_cdefs
->dm_ctfp
);
159 (void) ctf_discard(dtp
->dt_ddefs
->dm_ctfp
);
162 if (pcb
->pcb_pragmas
!= NULL
)
163 dt_idhash_destroy(pcb
->pcb_pragmas
);
164 if (pcb
->pcb_locals
!= NULL
)
165 dt_idhash_destroy(pcb
->pcb_locals
);
166 if (pcb
->pcb_idents
!= NULL
)
167 dt_idhash_destroy(pcb
->pcb_idents
);
168 if (pcb
->pcb_inttab
!= NULL
)
169 dt_inttab_destroy(pcb
->pcb_inttab
);
170 if (pcb
->pcb_strtab
!= NULL
)
171 dt_strtab_destroy(pcb
->pcb_strtab
);
172 if (pcb
->pcb_regs
!= NULL
)
173 dt_regset_destroy(pcb
->pcb_regs
);
175 for (i
= 0; i
< pcb
->pcb_asxreflen
; i
++)
176 dt_free(dtp
, pcb
->pcb_asxrefs
[i
]);
178 dt_free(dtp
, pcb
->pcb_asxrefs
);
179 dt_difo_free(dtp
, pcb
->pcb_difo
);
181 free(pcb
->pcb_filetag
);
182 free(pcb
->pcb_sflagv
);
184 dtp
->dt_pcb
= pcb
->pcb_prev
;
185 bzero(pcb
, sizeof (dt_pcb_t
));