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
|