17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * DTrace Parsing Control Block 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * A DTrace Parsing Control Block (PCB) contains all of the state that is used 337c478bd9Sstevel@tonic-gate * by a single pass of the D compiler, other than the global variables used by 347c478bd9Sstevel@tonic-gate * lex and yacc. The routines in this file are used to set up and tear down 357c478bd9Sstevel@tonic-gate * PCBs, which are kept on a stack pointed to by the libdtrace global 'yypcb'. 367c478bd9Sstevel@tonic-gate * The main engine of the compiler, dt_compile(), is located in dt_cc.c and is 377c478bd9Sstevel@tonic-gate * responsible for calling these routines to begin and end a compilation pass. 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * Sun's lex/yacc are not MT-safe or re-entrant, but we permit limited nested 407c478bd9Sstevel@tonic-gate * use of dt_compile() once the entire parse tree has been constructed but has 417c478bd9Sstevel@tonic-gate * not yet executed the "cooking" pass (see dt_cc.c for more information). The 427c478bd9Sstevel@tonic-gate * PCB design also makes it easier to debug (since all global state is kept in 437c478bd9Sstevel@tonic-gate * one place) and could permit us to make the D compiler MT-safe or re-entrant 447c478bd9Sstevel@tonic-gate * in the future by adding locks to libdtrace or switching to Flex and Bison. 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #include <strings.h> 487c478bd9Sstevel@tonic-gate #include <stdlib.h> 497c478bd9Sstevel@tonic-gate #include <assert.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <dt_impl.h> 52*1a7c1b72Smws #include <dt_program.h> 537c478bd9Sstevel@tonic-gate #include <dt_provider.h> 547c478bd9Sstevel@tonic-gate #include <dt_pcb.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* 577c478bd9Sstevel@tonic-gate * Initialize the specified PCB by zeroing it and filling in a few default 587c478bd9Sstevel@tonic-gate * members, and then pushing it on to the top of the PCB stack and setting 597c478bd9Sstevel@tonic-gate * yypcb to point to it. Increment the current handle's generation count. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate void 627c478bd9Sstevel@tonic-gate dt_pcb_push(dtrace_hdl_t *dtp, dt_pcb_t *pcb) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * Since lex/yacc are not re-entrant and we don't implement state save, 667c478bd9Sstevel@tonic-gate * assert that if another PCB is active, it is from the same handle and 677c478bd9Sstevel@tonic-gate * has completed execution of yyparse(). If the first assertion fires, 687c478bd9Sstevel@tonic-gate * the caller is calling libdtrace without proper MT locking. If the 697c478bd9Sstevel@tonic-gate * second assertion fires, dt_compile() is being called recursively 707c478bd9Sstevel@tonic-gate * from an illegal location in libdtrace, or a dt_pcb_pop() is missing. 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate if (yypcb != NULL) { 737c478bd9Sstevel@tonic-gate assert(yypcb->pcb_hdl == dtp); 747c478bd9Sstevel@tonic-gate assert(yypcb->pcb_yystate == YYS_DONE); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate bzero(pcb, sizeof (dt_pcb_t)); 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate dt_scope_create(&pcb->pcb_dstack); 807c478bd9Sstevel@tonic-gate dt_idstack_push(&pcb->pcb_globals, dtp->dt_globals); 817c478bd9Sstevel@tonic-gate dt_irlist_create(&pcb->pcb_ir); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate pcb->pcb_hdl = dtp; 847c478bd9Sstevel@tonic-gate pcb->pcb_prev = dtp->dt_pcb; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate dtp->dt_pcb = pcb; 877c478bd9Sstevel@tonic-gate dtp->dt_gen++; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate yyinit(pcb); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate static int 937c478bd9Sstevel@tonic-gate dt_pcb_pop_ident(dt_idhash_t *dhp, dt_ident_t *idp, void *arg) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = arg; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (idp->di_gen == dtp->dt_gen) 987c478bd9Sstevel@tonic-gate dt_idhash_delete(dhp, idp); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate return (0); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Pop the topmost PCB from the PCB stack and destroy any data structures that 1057c478bd9Sstevel@tonic-gate * are associated with it. If 'err' is non-zero, destroy any intermediate 1067c478bd9Sstevel@tonic-gate * state that is left behind as part of a compilation that has failed. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate void 1097c478bd9Sstevel@tonic-gate dt_pcb_pop(dtrace_hdl_t *dtp, int err) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate dt_pcb_t *pcb = yypcb; 112*1a7c1b72Smws uint_t i; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate assert(pcb != NULL); 1157c478bd9Sstevel@tonic-gate assert(pcb == dtp->dt_pcb); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate while (pcb->pcb_dstack.ds_next != NULL) 1187c478bd9Sstevel@tonic-gate (void) dt_scope_pop(); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate dt_scope_destroy(&pcb->pcb_dstack); 1217c478bd9Sstevel@tonic-gate dt_irlist_destroy(&pcb->pcb_ir); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate dt_node_link_free(&pcb->pcb_list); 1247c478bd9Sstevel@tonic-gate dt_node_link_free(&pcb->pcb_hold); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (err != 0) { 1277c478bd9Sstevel@tonic-gate dt_xlator_t *dxp, *nxp; 1287c478bd9Sstevel@tonic-gate dt_provider_t *pvp, *nvp; 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if (pcb->pcb_prog != NULL) 131*1a7c1b72Smws dt_program_destroy(dtp, pcb->pcb_prog); 1327c478bd9Sstevel@tonic-gate if (pcb->pcb_stmt != NULL) 133*1a7c1b72Smws dtrace_stmt_destroy(dtp, pcb->pcb_stmt); 1347c478bd9Sstevel@tonic-gate if (pcb->pcb_ecbdesc != NULL) 135*1a7c1b72Smws dt_ecbdesc_release(dtp, pcb->pcb_ecbdesc); 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate for (dxp = dt_list_next(&dtp->dt_xlators); dxp; dxp = nxp) { 1387c478bd9Sstevel@tonic-gate nxp = dt_list_next(dxp); 1397c478bd9Sstevel@tonic-gate if (dxp->dx_gen == dtp->dt_gen) 1407c478bd9Sstevel@tonic-gate dt_xlator_destroy(dtp, dxp); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate for (pvp = dt_list_next(&dtp->dt_provlist); pvp; pvp = nvp) { 1447c478bd9Sstevel@tonic-gate nvp = dt_list_next(pvp); 1457c478bd9Sstevel@tonic-gate if (pvp->pv_gen == dtp->dt_gen) 1467c478bd9Sstevel@tonic-gate dt_provider_destroy(dtp, pvp); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_aggs, dt_pcb_pop_ident, dtp); 1507c478bd9Sstevel@tonic-gate dt_idhash_update(dtp->dt_aggs); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_globals, dt_pcb_pop_ident, dtp); 1537c478bd9Sstevel@tonic-gate dt_idhash_update(dtp->dt_globals); 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate (void) dt_idhash_iter(dtp->dt_tls, dt_pcb_pop_ident, dtp); 1567c478bd9Sstevel@tonic-gate dt_idhash_update(dtp->dt_tls); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate (void) ctf_discard(dtp->dt_cdefs->dm_ctfp); 1597c478bd9Sstevel@tonic-gate (void) ctf_discard(dtp->dt_ddefs->dm_ctfp); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (pcb->pcb_pragmas != NULL) 1637c478bd9Sstevel@tonic-gate dt_idhash_destroy(pcb->pcb_pragmas); 1647c478bd9Sstevel@tonic-gate if (pcb->pcb_locals != NULL) 1657c478bd9Sstevel@tonic-gate dt_idhash_destroy(pcb->pcb_locals); 1667c478bd9Sstevel@tonic-gate if (pcb->pcb_idents != NULL) 1677c478bd9Sstevel@tonic-gate dt_idhash_destroy(pcb->pcb_idents); 1687c478bd9Sstevel@tonic-gate if (pcb->pcb_inttab != NULL) 1697c478bd9Sstevel@tonic-gate dt_inttab_destroy(pcb->pcb_inttab); 1707c478bd9Sstevel@tonic-gate if (pcb->pcb_strtab != NULL) 1717c478bd9Sstevel@tonic-gate dt_strtab_destroy(pcb->pcb_strtab); 1727c478bd9Sstevel@tonic-gate if (pcb->pcb_regs != NULL) 1737c478bd9Sstevel@tonic-gate dt_regset_destroy(pcb->pcb_regs); 174*1a7c1b72Smws 175*1a7c1b72Smws for (i = 0; i < pcb->pcb_asxreflen; i++) 176*1a7c1b72Smws dt_free(dtp, pcb->pcb_asxrefs[i]); 177*1a7c1b72Smws 178*1a7c1b72Smws dt_free(dtp, pcb->pcb_asxrefs); 179*1a7c1b72Smws dt_difo_free(dtp, pcb->pcb_difo); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate free(pcb->pcb_filetag); 1827c478bd9Sstevel@tonic-gate free(pcb->pcb_sflagv); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate dtp->dt_pcb = pcb->pcb_prev; 1857c478bd9Sstevel@tonic-gate bzero(pcb, sizeof (dt_pcb_t)); 1867c478bd9Sstevel@tonic-gate yyinit(dtp->dt_pcb); 1877c478bd9Sstevel@tonic-gate } 188