xref: /freebsd/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pcb.c (revision 6ff6d951ade3f3379932df7f878ef3ea272cfc59)
16ff6d951SJohn Birrell /*
26ff6d951SJohn Birrell  * CDDL HEADER START
36ff6d951SJohn Birrell  *
46ff6d951SJohn Birrell  * The contents of this file are subject to the terms of the
56ff6d951SJohn Birrell  * Common Development and Distribution License, Version 1.0 only
66ff6d951SJohn Birrell  * (the "License").  You may not use this file except in compliance
76ff6d951SJohn Birrell  * with the License.
86ff6d951SJohn Birrell  *
96ff6d951SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
106ff6d951SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
116ff6d951SJohn Birrell  * See the License for the specific language governing permissions
126ff6d951SJohn Birrell  * and limitations under the License.
136ff6d951SJohn Birrell  *
146ff6d951SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
156ff6d951SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
166ff6d951SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
176ff6d951SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
186ff6d951SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
196ff6d951SJohn Birrell  *
206ff6d951SJohn Birrell  * CDDL HEADER END
216ff6d951SJohn Birrell  */
226ff6d951SJohn Birrell /*
236ff6d951SJohn Birrell  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
246ff6d951SJohn Birrell  * Use is subject to license terms.
256ff6d951SJohn Birrell  */
266ff6d951SJohn Birrell 
276ff6d951SJohn Birrell #pragma ident	"%Z%%M%	%I%	%E% SMI"
286ff6d951SJohn Birrell 
296ff6d951SJohn Birrell /*
306ff6d951SJohn Birrell  * DTrace Parsing Control Block
316ff6d951SJohn Birrell  *
326ff6d951SJohn Birrell  * A DTrace Parsing Control Block (PCB) contains all of the state that is used
336ff6d951SJohn Birrell  * by a single pass of the D compiler, other than the global variables used by
346ff6d951SJohn Birrell  * lex and yacc.  The routines in this file are used to set up and tear down
356ff6d951SJohn Birrell  * PCBs, which are kept on a stack pointed to by the libdtrace global 'yypcb'.
366ff6d951SJohn Birrell  * The main engine of the compiler, dt_compile(), is located in dt_cc.c and is
376ff6d951SJohn Birrell  * responsible for calling these routines to begin and end a compilation pass.
386ff6d951SJohn Birrell  *
396ff6d951SJohn Birrell  * Sun's lex/yacc are not MT-safe or re-entrant, but we permit limited nested
406ff6d951SJohn Birrell  * use of dt_compile() once the entire parse tree has been constructed but has
416ff6d951SJohn Birrell  * not yet executed the "cooking" pass (see dt_cc.c for more information).  The
426ff6d951SJohn Birrell  * PCB design also makes it easier to debug (since all global state is kept in
436ff6d951SJohn Birrell  * one place) and could permit us to make the D compiler MT-safe or re-entrant
446ff6d951SJohn Birrell  * in the future by adding locks to libdtrace or switching to Flex and Bison.
456ff6d951SJohn Birrell  */
466ff6d951SJohn Birrell 
476ff6d951SJohn Birrell #include <strings.h>
486ff6d951SJohn Birrell #include <stdlib.h>
496ff6d951SJohn Birrell #include <assert.h>
506ff6d951SJohn Birrell 
516ff6d951SJohn Birrell #include <dt_impl.h>
526ff6d951SJohn Birrell #include <dt_program.h>
536ff6d951SJohn Birrell #include <dt_provider.h>
546ff6d951SJohn Birrell #include <dt_pcb.h>
556ff6d951SJohn Birrell 
566ff6d951SJohn Birrell /*
576ff6d951SJohn Birrell  * Initialize the specified PCB by zeroing it and filling in a few default
586ff6d951SJohn Birrell  * members, and then pushing it on to the top of the PCB stack and setting
596ff6d951SJohn Birrell  * yypcb to point to it.  Increment the current handle's generation count.
606ff6d951SJohn Birrell  */
616ff6d951SJohn Birrell void
dt_pcb_push(dtrace_hdl_t * dtp,dt_pcb_t * pcb)626ff6d951SJohn Birrell dt_pcb_push(dtrace_hdl_t *dtp, dt_pcb_t *pcb)
636ff6d951SJohn Birrell {
646ff6d951SJohn Birrell 	/*
656ff6d951SJohn Birrell 	 * Since lex/yacc are not re-entrant and we don't implement state save,
666ff6d951SJohn Birrell 	 * assert that if another PCB is active, it is from the same handle and
676ff6d951SJohn Birrell 	 * has completed execution of yyparse().  If the first assertion fires,
686ff6d951SJohn Birrell 	 * the caller is calling libdtrace without proper MT locking.  If the
696ff6d951SJohn Birrell 	 * second assertion fires, dt_compile() is being called recursively
706ff6d951SJohn Birrell 	 * from an illegal location in libdtrace, or a dt_pcb_pop() is missing.
716ff6d951SJohn Birrell 	 */
726ff6d951SJohn Birrell 	if (yypcb != NULL) {
736ff6d951SJohn Birrell 		assert(yypcb->pcb_hdl == dtp);
746ff6d951SJohn Birrell 		assert(yypcb->pcb_yystate == YYS_DONE);
756ff6d951SJohn Birrell 	}
766ff6d951SJohn Birrell 
776ff6d951SJohn Birrell 	bzero(pcb, sizeof (dt_pcb_t));
786ff6d951SJohn Birrell 
796ff6d951SJohn Birrell 	dt_scope_create(&pcb->pcb_dstack);
806ff6d951SJohn Birrell 	dt_idstack_push(&pcb->pcb_globals, dtp->dt_globals);
816ff6d951SJohn Birrell 	dt_irlist_create(&pcb->pcb_ir);
826ff6d951SJohn Birrell 
836ff6d951SJohn Birrell 	pcb->pcb_hdl = dtp;
846ff6d951SJohn Birrell 	pcb->pcb_prev = dtp->dt_pcb;
856ff6d951SJohn Birrell 
866ff6d951SJohn Birrell 	dtp->dt_pcb = pcb;
876ff6d951SJohn Birrell 	dtp->dt_gen++;
886ff6d951SJohn Birrell 
896ff6d951SJohn Birrell 	yyinit(pcb);
906ff6d951SJohn Birrell }
916ff6d951SJohn Birrell 
926ff6d951SJohn Birrell static int
dt_pcb_pop_ident(dt_idhash_t * dhp,dt_ident_t * idp,void * arg)936ff6d951SJohn Birrell dt_pcb_pop_ident(dt_idhash_t *dhp, dt_ident_t *idp, void *arg)
946ff6d951SJohn Birrell {
956ff6d951SJohn Birrell 	dtrace_hdl_t *dtp = arg;
966ff6d951SJohn Birrell 
976ff6d951SJohn Birrell 	if (idp->di_gen == dtp->dt_gen)
986ff6d951SJohn Birrell 		dt_idhash_delete(dhp, idp);
996ff6d951SJohn Birrell 
1006ff6d951SJohn Birrell 	return (0);
1016ff6d951SJohn Birrell }
1026ff6d951SJohn Birrell 
1036ff6d951SJohn Birrell /*
1046ff6d951SJohn Birrell  * Pop the topmost PCB from the PCB stack and destroy any data structures that
1056ff6d951SJohn Birrell  * are associated with it.  If 'err' is non-zero, destroy any intermediate
1066ff6d951SJohn Birrell  * state that is left behind as part of a compilation that has failed.
1076ff6d951SJohn Birrell  */
1086ff6d951SJohn Birrell void
dt_pcb_pop(dtrace_hdl_t * dtp,int err)1096ff6d951SJohn Birrell dt_pcb_pop(dtrace_hdl_t *dtp, int err)
1106ff6d951SJohn Birrell {
1116ff6d951SJohn Birrell 	dt_pcb_t *pcb = yypcb;
1126ff6d951SJohn Birrell 	uint_t i;
1136ff6d951SJohn Birrell 
1146ff6d951SJohn Birrell 	assert(pcb != NULL);
1156ff6d951SJohn Birrell 	assert(pcb == dtp->dt_pcb);
1166ff6d951SJohn Birrell 
1176ff6d951SJohn Birrell 	while (pcb->pcb_dstack.ds_next != NULL)
1186ff6d951SJohn Birrell 		(void) dt_scope_pop();
1196ff6d951SJohn Birrell 
1206ff6d951SJohn Birrell 	dt_scope_destroy(&pcb->pcb_dstack);
1216ff6d951SJohn Birrell 	dt_irlist_destroy(&pcb->pcb_ir);
1226ff6d951SJohn Birrell 
1236ff6d951SJohn Birrell 	dt_node_link_free(&pcb->pcb_list);
1246ff6d951SJohn Birrell 	dt_node_link_free(&pcb->pcb_hold);
1256ff6d951SJohn Birrell 
1266ff6d951SJohn Birrell 	if (err != 0) {
1276ff6d951SJohn Birrell 		dt_xlator_t *dxp, *nxp;
1286ff6d951SJohn Birrell 		dt_provider_t *pvp, *nvp;
1296ff6d951SJohn Birrell 
1306ff6d951SJohn Birrell 		if (pcb->pcb_prog != NULL)
1316ff6d951SJohn Birrell 			dt_program_destroy(dtp, pcb->pcb_prog);
1326ff6d951SJohn Birrell 		if (pcb->pcb_stmt != NULL)
1336ff6d951SJohn Birrell 			dtrace_stmt_destroy(dtp, pcb->pcb_stmt);
1346ff6d951SJohn Birrell 		if (pcb->pcb_ecbdesc != NULL)
1356ff6d951SJohn Birrell 			dt_ecbdesc_release(dtp, pcb->pcb_ecbdesc);
1366ff6d951SJohn Birrell 
1376ff6d951SJohn Birrell 		for (dxp = dt_list_next(&dtp->dt_xlators); dxp; dxp = nxp) {
1386ff6d951SJohn Birrell 			nxp = dt_list_next(dxp);
1396ff6d951SJohn Birrell 			if (dxp->dx_gen == dtp->dt_gen)
1406ff6d951SJohn Birrell 				dt_xlator_destroy(dtp, dxp);
1416ff6d951SJohn Birrell 		}
1426ff6d951SJohn Birrell 
1436ff6d951SJohn Birrell 		for (pvp = dt_list_next(&dtp->dt_provlist); pvp; pvp = nvp) {
1446ff6d951SJohn Birrell 			nvp = dt_list_next(pvp);
1456ff6d951SJohn Birrell 			if (pvp->pv_gen == dtp->dt_gen)
1466ff6d951SJohn Birrell 				dt_provider_destroy(dtp, pvp);
1476ff6d951SJohn Birrell 		}
1486ff6d951SJohn Birrell 
1496ff6d951SJohn Birrell 		(void) dt_idhash_iter(dtp->dt_aggs, dt_pcb_pop_ident, dtp);
1506ff6d951SJohn Birrell 		dt_idhash_update(dtp->dt_aggs);
1516ff6d951SJohn Birrell 
1526ff6d951SJohn Birrell 		(void) dt_idhash_iter(dtp->dt_globals, dt_pcb_pop_ident, dtp);
1536ff6d951SJohn Birrell 		dt_idhash_update(dtp->dt_globals);
1546ff6d951SJohn Birrell 
1556ff6d951SJohn Birrell 		(void) dt_idhash_iter(dtp->dt_tls, dt_pcb_pop_ident, dtp);
1566ff6d951SJohn Birrell 		dt_idhash_update(dtp->dt_tls);
1576ff6d951SJohn Birrell 
1586ff6d951SJohn Birrell 		(void) ctf_discard(dtp->dt_cdefs->dm_ctfp);
1596ff6d951SJohn Birrell 		(void) ctf_discard(dtp->dt_ddefs->dm_ctfp);
1606ff6d951SJohn Birrell 	}
1616ff6d951SJohn Birrell 
1626ff6d951SJohn Birrell 	if (pcb->pcb_pragmas != NULL)
1636ff6d951SJohn Birrell 		dt_idhash_destroy(pcb->pcb_pragmas);
1646ff6d951SJohn Birrell 	if (pcb->pcb_locals != NULL)
1656ff6d951SJohn Birrell 		dt_idhash_destroy(pcb->pcb_locals);
1666ff6d951SJohn Birrell 	if (pcb->pcb_idents != NULL)
1676ff6d951SJohn Birrell 		dt_idhash_destroy(pcb->pcb_idents);
1686ff6d951SJohn Birrell 	if (pcb->pcb_inttab != NULL)
1696ff6d951SJohn Birrell 		dt_inttab_destroy(pcb->pcb_inttab);
1706ff6d951SJohn Birrell 	if (pcb->pcb_strtab != NULL)
1716ff6d951SJohn Birrell 		dt_strtab_destroy(pcb->pcb_strtab);
1726ff6d951SJohn Birrell 	if (pcb->pcb_regs != NULL)
1736ff6d951SJohn Birrell 		dt_regset_destroy(pcb->pcb_regs);
1746ff6d951SJohn Birrell 
1756ff6d951SJohn Birrell 	for (i = 0; i < pcb->pcb_asxreflen; i++)
1766ff6d951SJohn Birrell 		dt_free(dtp, pcb->pcb_asxrefs[i]);
1776ff6d951SJohn Birrell 
1786ff6d951SJohn Birrell 	dt_free(dtp, pcb->pcb_asxrefs);
1796ff6d951SJohn Birrell 	dt_difo_free(dtp, pcb->pcb_difo);
1806ff6d951SJohn Birrell 
1816ff6d951SJohn Birrell 	free(pcb->pcb_filetag);
1826ff6d951SJohn Birrell 	free(pcb->pcb_sflagv);
1836ff6d951SJohn Birrell 
1846ff6d951SJohn Birrell 	dtp->dt_pcb = pcb->pcb_prev;
1856ff6d951SJohn Birrell 	bzero(pcb, sizeof (dt_pcb_t));
1866ff6d951SJohn Birrell 	yyinit(dtp->dt_pcb);
1876ff6d951SJohn Birrell }
188