Print this page
7085 add support for "if" and "else" statements in dtrace


   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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.

  24  * Copyright (c) 2013, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2012 by Delphix. All rights reserved.
  26  * Copyright 2015 Gary Mills
  27  */
  28 
  29 /*
  30  * DTrace D Language Compiler
  31  *
  32  * The code in this source file implements the main engine for the D language
  33  * compiler.  The driver routine for the compiler is dt_compile(), below.  The
  34  * compiler operates on either stdio FILEs or in-memory strings as its input
  35  * and can produce either dtrace_prog_t structures from a D program or a single
  36  * dtrace_difo_t structure from a D expression.  Multiple entry points are
  37  * provided as wrappers around dt_compile() for the various input/output pairs.
  38  * The compiler itself is implemented across the following source files:
  39  *
  40  * dt_lex.l - lex scanner
  41  * dt_grammar.y - yacc grammar
  42  * dt_parser.c - parse tree creation and semantic checking
  43  * dt_decl.c - declaration stack processing
  44  * dt_xlator.c - D translator lookup and creation
  45  * dt_ident.c - identifier and symbol table routines


 102 #include <dt_program.h>
 103 #include <dt_provider.h>
 104 #include <dt_printf.h>
 105 #include <dt_pid.h>
 106 #include <dt_grammar.h>
 107 #include <dt_ident.h>
 108 #include <dt_string.h>
 109 #include <dt_impl.h>
 110 
 111 static const dtrace_diftype_t dt_void_rtype = {
 112         DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, 0
 113 };
 114 
 115 static const dtrace_diftype_t dt_int_rtype = {
 116         DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, sizeof (uint64_t)
 117 };
 118 
 119 static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *,
 120     uint_t, int, char *const[], FILE *, const char *);
 121 
 122 
 123 /*ARGSUSED*/
 124 static int
 125 dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
 126 {
 127         idp->di_flags &= ~(DT_IDFLG_REF | DT_IDFLG_MOD |
 128             DT_IDFLG_DIFR | DT_IDFLG_DIFW);
 129         return (0);
 130 }
 131 
 132 /*ARGSUSED*/
 133 static int
 134 dt_idpragma(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
 135 {
 136         yylineno = idp->di_lineno;
 137         xyerror(D_PRAGMA_UNUSED, "unused #pragma %s\n", (char *)idp->di_iarg);
 138         return (0);
 139 }
 140 
 141 static dtrace_stmtdesc_t *
 142 dt_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp,


2402                 xyerror(D_EMPTY, "empty D program translation unit\n");
2403 
2404         yybegin(YYS_DONE);
2405 
2406         if (cflags & DTRACE_C_CTL)
2407                 goto out;
2408 
2409         if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1))
2410                 dt_node_printr(yypcb->pcb_root, stderr, 0);
2411 
2412         if (yypcb->pcb_pragmas != NULL)
2413                 (void) dt_idhash_iter(yypcb->pcb_pragmas, dt_idpragma, NULL);
2414 
2415         if (argc > 1 && !(yypcb->pcb_cflags & DTRACE_C_ARGREF) &&
2416             !(yypcb->pcb_sflagv[argc - 1] & DT_IDFLG_REF)) {
2417                 xyerror(D_MACRO_UNUSED, "extraneous argument '%s' ($%d is "
2418                     "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1);
2419         }
2420 
2421         /*






















2422          * If we have successfully created a parse tree for a D program, loop
2423          * over the clauses and actions and instantiate the corresponding
2424          * libdtrace program.  If we are parsing a D expression, then we
2425          * simply run the code generator and assembler on the resulting tree.
2426          */
2427         switch (context) {
2428         case DT_CTX_DPROG:
2429                 assert(yypcb->pcb_root->dn_kind == DT_NODE_PROG);
2430 
2431                 if ((dnp = yypcb->pcb_root->dn_list) == NULL &&
2432                     !(yypcb->pcb_cflags & DTRACE_C_EMPTY))
2433                         xyerror(D_EMPTY, "empty D program translation unit\n");
2434 
2435                 if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL)
2436                         longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp));
2437 
2438                 for (; dnp != NULL; dnp = dnp->dn_list) {
2439                         switch (dnp->dn_kind) {
2440                         case DT_NODE_CLAUSE:


2441                                 dt_compile_clause(dtp, dnp);
2442                                 break;
2443                         case DT_NODE_XLATOR:
2444                                 if (dtp->dt_xlatemode == DT_XL_DYNAMIC)
2445                                         dt_compile_xlator(dnp);
2446                                 break;
2447                         case DT_NODE_PROVIDER:
2448                                 (void) dt_node_cook(dnp, DT_IDFLG_REF);
2449                                 break;
2450                         }
2451                 }
2452 
2453                 yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs;
2454                 yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen;
2455                 yypcb->pcb_asxrefs = NULL;
2456                 yypcb->pcb_asxreflen = 0;
2457 
2458                 rv = yypcb->pcb_prog;
2459                 break;
2460 




   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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
  25  * Copyright (c) 2013, Joyent Inc. All rights reserved.

  26  * Copyright 2015 Gary Mills
  27  */
  28 
  29 /*
  30  * DTrace D Language Compiler
  31  *
  32  * The code in this source file implements the main engine for the D language
  33  * compiler.  The driver routine for the compiler is dt_compile(), below.  The
  34  * compiler operates on either stdio FILEs or in-memory strings as its input
  35  * and can produce either dtrace_prog_t structures from a D program or a single
  36  * dtrace_difo_t structure from a D expression.  Multiple entry points are
  37  * provided as wrappers around dt_compile() for the various input/output pairs.
  38  * The compiler itself is implemented across the following source files:
  39  *
  40  * dt_lex.l - lex scanner
  41  * dt_grammar.y - yacc grammar
  42  * dt_parser.c - parse tree creation and semantic checking
  43  * dt_decl.c - declaration stack processing
  44  * dt_xlator.c - D translator lookup and creation
  45  * dt_ident.c - identifier and symbol table routines


 102 #include <dt_program.h>
 103 #include <dt_provider.h>
 104 #include <dt_printf.h>
 105 #include <dt_pid.h>
 106 #include <dt_grammar.h>
 107 #include <dt_ident.h>
 108 #include <dt_string.h>
 109 #include <dt_impl.h>
 110 
 111 static const dtrace_diftype_t dt_void_rtype = {
 112         DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, 0
 113 };
 114 
 115 static const dtrace_diftype_t dt_int_rtype = {
 116         DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, sizeof (uint64_t)
 117 };
 118 
 119 static void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *,
 120     uint_t, int, char *const[], FILE *, const char *);
 121 

 122 /*ARGSUSED*/
 123 static int
 124 dt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
 125 {
 126         idp->di_flags &= ~(DT_IDFLG_REF | DT_IDFLG_MOD |
 127             DT_IDFLG_DIFR | DT_IDFLG_DIFW);
 128         return (0);
 129 }
 130 
 131 /*ARGSUSED*/
 132 static int
 133 dt_idpragma(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
 134 {
 135         yylineno = idp->di_lineno;
 136         xyerror(D_PRAGMA_UNUSED, "unused #pragma %s\n", (char *)idp->di_iarg);
 137         return (0);
 138 }
 139 
 140 static dtrace_stmtdesc_t *
 141 dt_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp,


2401                 xyerror(D_EMPTY, "empty D program translation unit\n");
2402 
2403         yybegin(YYS_DONE);
2404 
2405         if (cflags & DTRACE_C_CTL)
2406                 goto out;
2407 
2408         if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1))
2409                 dt_node_printr(yypcb->pcb_root, stderr, 0);
2410 
2411         if (yypcb->pcb_pragmas != NULL)
2412                 (void) dt_idhash_iter(yypcb->pcb_pragmas, dt_idpragma, NULL);
2413 
2414         if (argc > 1 && !(yypcb->pcb_cflags & DTRACE_C_ARGREF) &&
2415             !(yypcb->pcb_sflagv[argc - 1] & DT_IDFLG_REF)) {
2416                 xyerror(D_MACRO_UNUSED, "extraneous argument '%s' ($%d is "
2417                     "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1);
2418         }
2419 
2420         /*
2421          * Perform sugar transformations (for "if" / "else") and replace the
2422          * existing clause chain with the new one.
2423          */
2424         if (context == DT_CTX_DPROG) {
2425                 dt_node_t *dnp, *next_dnp;
2426                 dt_node_t *new_list = NULL;
2427 
2428                 for (dnp = yypcb->pcb_root->dn_list;
2429                     dnp != NULL; dnp = next_dnp) {
2430                         /* remove this node from the list */
2431                         next_dnp = dnp->dn_list;
2432                         dnp->dn_list = NULL;
2433 
2434                         if (dnp->dn_kind == DT_NODE_CLAUSE)
2435                                 dnp = dt_compile_sugar(dtp, dnp);
2436                         /* append node to the new list */
2437                         new_list = dt_node_link(new_list, dnp);
2438                 }
2439                 yypcb->pcb_root->dn_list = new_list;
2440         }
2441 
2442         /*
2443          * If we have successfully created a parse tree for a D program, loop
2444          * over the clauses and actions and instantiate the corresponding
2445          * libdtrace program.  If we are parsing a D expression, then we
2446          * simply run the code generator and assembler on the resulting tree.
2447          */
2448         switch (context) {
2449         case DT_CTX_DPROG:
2450                 assert(yypcb->pcb_root->dn_kind == DT_NODE_PROG);
2451 
2452                 if ((dnp = yypcb->pcb_root->dn_list) == NULL &&
2453                     !(yypcb->pcb_cflags & DTRACE_C_EMPTY))
2454                         xyerror(D_EMPTY, "empty D program translation unit\n");
2455 
2456                 if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL)
2457                         longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp));
2458 
2459                 for (; dnp != NULL; dnp = dnp->dn_list) {
2460                         switch (dnp->dn_kind) {
2461                         case DT_NODE_CLAUSE:
2462                                 if (DT_TREEDUMP_PASS(dtp, 4))
2463                                         dt_printd(dnp, stderr, 0);
2464                                 dt_compile_clause(dtp, dnp);
2465                                 break;
2466                         case DT_NODE_XLATOR:
2467                                 if (dtp->dt_xlatemode == DT_XL_DYNAMIC)
2468                                         dt_compile_xlator(dnp);
2469                                 break;
2470                         case DT_NODE_PROVIDER:
2471                                 (void) dt_node_cook(dnp, DT_IDFLG_REF);
2472                                 break;
2473                         }
2474                 }
2475 
2476                 yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs;
2477                 yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen;
2478                 yypcb->pcb_asxrefs = NULL;
2479                 yypcb->pcb_asxreflen = 0;
2480 
2481                 rv = yypcb->pcb_prog;
2482                 break;
2483