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