1178479Sjb/*
2178479Sjb * CDDL HEADER START
3178479Sjb *
4178479Sjb * The contents of this file are subject to the terms of the
5178479Sjb * Common Development and Distribution License (the "License").
6178479Sjb * You may not use this file except in compliance with the License.
7178479Sjb *
8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9178479Sjb * or http://www.opensolaris.org/os/licensing.
10178479Sjb * See the License for the specific language governing permissions
11178479Sjb * and limitations under the License.
12178479Sjb *
13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each
14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15178479Sjb * If applicable, add the following below this CDDL HEADER, with the
16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18178479Sjb *
19178479Sjb * CDDL HEADER END
20178479Sjb */
21178479Sjb
22178479Sjb/*
23210767Srpaulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24238558Spfg * Copyright (c) 2011, Joyent Inc. All rights reserved.
25253725Spfg * Copyright (c) 2012 by Delphix. All rights reserved.
26178479Sjb */
27178479Sjb
28178479Sjb/*
29178479Sjb * DTrace D Language Compiler
30178479Sjb *
31178479Sjb * The code in this source file implements the main engine for the D language
32178479Sjb * compiler.  The driver routine for the compiler is dt_compile(), below.  The
33178479Sjb * compiler operates on either stdio FILEs or in-memory strings as its input
34178479Sjb * and can produce either dtrace_prog_t structures from a D program or a single
35178479Sjb * dtrace_difo_t structure from a D expression.  Multiple entry points are
36178479Sjb * provided as wrappers around dt_compile() for the various input/output pairs.
37178479Sjb * The compiler itself is implemented across the following source files:
38178479Sjb *
39178479Sjb * dt_lex.l - lex scanner
40178479Sjb * dt_grammar.y - yacc grammar
41178479Sjb * dt_parser.c - parse tree creation and semantic checking
42178479Sjb * dt_decl.c - declaration stack processing
43178479Sjb * dt_xlator.c - D translator lookup and creation
44178479Sjb * dt_ident.c - identifier and symbol table routines
45178479Sjb * dt_pragma.c - #pragma processing and D pragmas
46178479Sjb * dt_printf.c - D printf() and printa() argument checking and processing
47178479Sjb * dt_cc.c - compiler driver and dtrace_prog_t construction
48178479Sjb * dt_cg.c - DIF code generator
49178479Sjb * dt_as.c - DIF assembler
50178479Sjb * dt_dof.c - dtrace_prog_t -> DOF conversion
51178479Sjb *
52178479Sjb * Several other source files provide collections of utility routines used by
53178479Sjb * these major files.  The compiler itself is implemented in multiple passes:
54178479Sjb *
55178479Sjb * (1) The input program is scanned and parsed by dt_lex.l and dt_grammar.y
56178479Sjb *     and parse tree nodes are constructed using the routines in dt_parser.c.
57178479Sjb *     This node construction pass is described further in dt_parser.c.
58178479Sjb *
59178479Sjb * (2) The parse tree is "cooked" by assigning each clause a context (see the
60178479Sjb *     routine dt_setcontext(), below) based on its probe description and then
61178479Sjb *     recursively descending the tree performing semantic checking.  The cook
62178479Sjb *     routines are also implemented in dt_parser.c and described there.
63178479Sjb *
64178479Sjb * (3) For actions that are DIF expression statements, the DIF code generator
65178479Sjb *     and assembler are invoked to create a finished DIFO for the statement.
66178479Sjb *
67178479Sjb * (4) The dtrace_prog_t data structures for the program clauses and actions
68178479Sjb *     are built, containing pointers to any DIFOs created in step (3).
69178479Sjb *
70178479Sjb * (5) The caller invokes a routine in dt_dof.c to convert the finished program
71178479Sjb *     into DOF format for use in anonymous tracing or enabling in the kernel.
72178479Sjb *
73178479Sjb * In the implementation, steps 2-4 are intertwined in that they are performed
74178479Sjb * in order for each clause as part of a loop that executes over the clauses.
75178479Sjb *
76178479Sjb * The D compiler currently implements nearly no optimization.  The compiler
77178479Sjb * implements integer constant folding as part of pass (1), and a set of very
78178479Sjb * simple peephole optimizations as part of pass (3).  As with any C compiler,
79178479Sjb * a large number of optimizations are possible on both the intermediate data
80178479Sjb * structures and the generated DIF code.  These possibilities should be
81178479Sjb * investigated in the context of whether they will have any substantive effect
82178479Sjb * on the overall DTrace probe effect before they are undertaken.
83178479Sjb */
84178479Sjb
85178479Sjb#include <sys/types.h>
86178479Sjb#include <sys/wait.h>
87237624Spfg#include <sys/sysmacros.h>
88178479Sjb
89178479Sjb#include <assert.h>
90178576Sjb#include <string.h>
91178479Sjb#include <strings.h>
92178479Sjb#include <signal.h>
93178479Sjb#include <unistd.h>
94178479Sjb#include <stdlib.h>
95178479Sjb#include <stdio.h>
96178479Sjb#include <errno.h>
97178479Sjb#include <ucontext.h>
98178479Sjb#include <limits.h>
99178479Sjb#include <ctype.h>
100178479Sjb#include <dirent.h>
101178479Sjb#include <dt_module.h>
102178479Sjb#include <dt_program.h>
103178479Sjb#include <dt_provider.h>
104178479Sjb#include <dt_printf.h>
105178479Sjb#include <dt_pid.h>
106178479Sjb#include <dt_grammar.h>
107178479Sjb#include <dt_ident.h>
108178479Sjb#include <dt_string.h>
109178479Sjb#include <dt_impl.h>
110178479Sjb
111178479Sjbstatic const dtrace_diftype_t dt_void_rtype = {
112178479Sjb	DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, 0
113178479Sjb};
114178479Sjb
115178479Sjbstatic const dtrace_diftype_t dt_int_rtype = {
116178479Sjb	DIF_TYPE_CTF, CTF_K_INTEGER, 0, 0, sizeof (uint64_t)
117178479Sjb};
118178479Sjb
119178479Sjbstatic void *dt_compile(dtrace_hdl_t *, int, dtrace_probespec_t, void *,
120178479Sjb    uint_t, int, char *const[], FILE *, const char *);
121178479Sjb
122178479Sjb
123178479Sjb/*ARGSUSED*/
124178479Sjbstatic int
125178479Sjbdt_idreset(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
126178479Sjb{
127178479Sjb	idp->di_flags &= ~(DT_IDFLG_REF | DT_IDFLG_MOD |
128178479Sjb	    DT_IDFLG_DIFR | DT_IDFLG_DIFW);
129178479Sjb	return (0);
130178479Sjb}
131178479Sjb
132178479Sjb/*ARGSUSED*/
133178479Sjbstatic int
134178479Sjbdt_idpragma(dt_idhash_t *dhp, dt_ident_t *idp, void *ignored)
135178479Sjb{
136178479Sjb	yylineno = idp->di_lineno;
137178479Sjb	xyerror(D_PRAGMA_UNUSED, "unused #pragma %s\n", (char *)idp->di_iarg);
138178479Sjb	return (0);
139178479Sjb}
140178479Sjb
141178479Sjbstatic dtrace_stmtdesc_t *
142178479Sjbdt_stmt_create(dtrace_hdl_t *dtp, dtrace_ecbdesc_t *edp,
143178479Sjb    dtrace_attribute_t descattr, dtrace_attribute_t stmtattr)
144178479Sjb{
145178479Sjb	dtrace_stmtdesc_t *sdp = dtrace_stmt_create(dtp, edp);
146178479Sjb
147178479Sjb	if (sdp == NULL)
148178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
149178479Sjb
150178479Sjb	assert(yypcb->pcb_stmt == NULL);
151178479Sjb	yypcb->pcb_stmt = sdp;
152178479Sjb
153178479Sjb	sdp->dtsd_descattr = descattr;
154178479Sjb	sdp->dtsd_stmtattr = stmtattr;
155178479Sjb
156178479Sjb	return (sdp);
157178479Sjb}
158178479Sjb
159178479Sjbstatic dtrace_actdesc_t *
160178479Sjbdt_stmt_action(dtrace_hdl_t *dtp, dtrace_stmtdesc_t *sdp)
161178479Sjb{
162178479Sjb	dtrace_actdesc_t *new;
163178479Sjb
164178479Sjb	if ((new = dtrace_stmt_action(dtp, sdp)) == NULL)
165178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
166178479Sjb
167178479Sjb	return (new);
168178479Sjb}
169178479Sjb
170178479Sjb/*
171178479Sjb * Utility function to determine if a given action description is destructive.
172178479Sjb * The dtdo_destructive bit is set for us by the DIF assembler (see dt_as.c).
173178479Sjb */
174178479Sjbstatic int
175178479Sjbdt_action_destructive(const dtrace_actdesc_t *ap)
176178479Sjb{
177178479Sjb	return (DTRACEACT_ISDESTRUCTIVE(ap->dtad_kind) || (ap->dtad_kind ==
178178479Sjb	    DTRACEACT_DIFEXPR && ap->dtad_difo->dtdo_destructive));
179178479Sjb}
180178479Sjb
181178479Sjbstatic void
182178479Sjbdt_stmt_append(dtrace_stmtdesc_t *sdp, const dt_node_t *dnp)
183178479Sjb{
184178479Sjb	dtrace_ecbdesc_t *edp = sdp->dtsd_ecbdesc;
185178479Sjb	dtrace_actdesc_t *ap, *tap;
186178479Sjb	int commit = 0;
187178479Sjb	int speculate = 0;
188178479Sjb	int datarec = 0;
189178479Sjb
190178479Sjb	/*
191178479Sjb	 * Make sure that the new statement jibes with the rest of the ECB.
192178479Sjb	 */
193178479Sjb	for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {
194178479Sjb		if (ap->dtad_kind == DTRACEACT_COMMIT) {
195178479Sjb			if (commit) {
196178479Sjb				dnerror(dnp, D_COMM_COMM, "commit( ) may "
197178479Sjb				    "not follow commit( )\n");
198178479Sjb			}
199178479Sjb
200178479Sjb			if (datarec) {
201178479Sjb				dnerror(dnp, D_COMM_DREC, "commit( ) may "
202178479Sjb				    "not follow data-recording action(s)\n");
203178479Sjb			}
204178479Sjb
205178479Sjb			for (tap = ap; tap != NULL; tap = tap->dtad_next) {
206178479Sjb				if (!DTRACEACT_ISAGG(tap->dtad_kind))
207178479Sjb					continue;
208178479Sjb
209178479Sjb				dnerror(dnp, D_AGG_COMM, "aggregating actions "
210178479Sjb				    "may not follow commit( )\n");
211178479Sjb			}
212178479Sjb
213178479Sjb			commit = 1;
214178479Sjb			continue;
215178479Sjb		}
216178479Sjb
217178479Sjb		if (ap->dtad_kind == DTRACEACT_SPECULATE) {
218178479Sjb			if (speculate) {
219178479Sjb				dnerror(dnp, D_SPEC_SPEC, "speculate( ) may "
220178479Sjb				    "not follow speculate( )\n");
221178479Sjb			}
222178479Sjb
223178479Sjb			if (commit) {
224178479Sjb				dnerror(dnp, D_SPEC_COMM, "speculate( ) may "
225178479Sjb				    "not follow commit( )\n");
226178479Sjb			}
227178479Sjb
228178479Sjb			if (datarec) {
229178479Sjb				dnerror(dnp, D_SPEC_DREC, "speculate( ) may "
230178479Sjb				    "not follow data-recording action(s)\n");
231178479Sjb			}
232178479Sjb
233178479Sjb			speculate = 1;
234178479Sjb			continue;
235178479Sjb		}
236178479Sjb
237178479Sjb		if (DTRACEACT_ISAGG(ap->dtad_kind)) {
238178479Sjb			if (speculate) {
239178479Sjb				dnerror(dnp, D_AGG_SPEC, "aggregating actions "
240178479Sjb				    "may not follow speculate( )\n");
241178479Sjb			}
242178479Sjb
243178479Sjb			datarec = 1;
244178479Sjb			continue;
245178479Sjb		}
246178479Sjb
247178479Sjb		if (speculate) {
248178479Sjb			if (dt_action_destructive(ap)) {
249178479Sjb				dnerror(dnp, D_ACT_SPEC, "destructive actions "
250178479Sjb				    "may not follow speculate( )\n");
251178479Sjb			}
252178479Sjb
253178479Sjb			if (ap->dtad_kind == DTRACEACT_EXIT) {
254178479Sjb				dnerror(dnp, D_EXIT_SPEC, "exit( ) may not "
255178479Sjb				    "follow speculate( )\n");
256178479Sjb			}
257178479Sjb		}
258178479Sjb
259178479Sjb		/*
260178479Sjb		 * Exclude all non data-recording actions.
261178479Sjb		 */
262178479Sjb		if (dt_action_destructive(ap) ||
263178479Sjb		    ap->dtad_kind == DTRACEACT_DISCARD)
264178479Sjb			continue;
265178479Sjb
266178479Sjb		if (ap->dtad_kind == DTRACEACT_DIFEXPR &&
267178479Sjb		    ap->dtad_difo->dtdo_rtype.dtdt_kind == DIF_TYPE_CTF &&
268178479Sjb		    ap->dtad_difo->dtdo_rtype.dtdt_size == 0)
269178479Sjb			continue;
270178479Sjb
271178479Sjb		if (commit) {
272178479Sjb			dnerror(dnp, D_DREC_COMM, "data-recording actions "
273178479Sjb			    "may not follow commit( )\n");
274178479Sjb		}
275178479Sjb
276178479Sjb		if (!speculate)
277178479Sjb			datarec = 1;
278178479Sjb	}
279178479Sjb
280178479Sjb	if (dtrace_stmt_add(yypcb->pcb_hdl, yypcb->pcb_prog, sdp) != 0)
281178479Sjb		longjmp(yypcb->pcb_jmpbuf, dtrace_errno(yypcb->pcb_hdl));
282178479Sjb
283178479Sjb	if (yypcb->pcb_stmt == sdp)
284178479Sjb		yypcb->pcb_stmt = NULL;
285178479Sjb}
286178479Sjb
287178479Sjb/*
288178479Sjb * For the first element of an aggregation tuple or for printa(), we create a
289178479Sjb * simple DIF program that simply returns the immediate value that is the ID
290178479Sjb * of the aggregation itself.  This could be optimized in the future by
291178479Sjb * creating a new in-kernel dtad_kind that just returns an integer.
292178479Sjb */
293178479Sjbstatic void
294178479Sjbdt_action_difconst(dtrace_actdesc_t *ap, uint_t id, dtrace_actkind_t kind)
295178479Sjb{
296178479Sjb	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
297178479Sjb	dtrace_difo_t *dp = dt_zalloc(dtp, sizeof (dtrace_difo_t));
298178479Sjb
299178479Sjb	if (dp == NULL)
300178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
301178479Sjb
302178479Sjb	dp->dtdo_buf = dt_alloc(dtp, sizeof (dif_instr_t) * 2);
303178479Sjb	dp->dtdo_inttab = dt_alloc(dtp, sizeof (uint64_t));
304178479Sjb
305178479Sjb	if (dp->dtdo_buf == NULL || dp->dtdo_inttab == NULL) {
306178479Sjb		dt_difo_free(dtp, dp);
307178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
308178479Sjb	}
309178479Sjb
310178479Sjb	dp->dtdo_buf[0] = DIF_INSTR_SETX(0, 1); /* setx	DIF_INTEGER[0], %r1 */
311178479Sjb	dp->dtdo_buf[1] = DIF_INSTR_RET(1);	/* ret	%r1 */
312178479Sjb	dp->dtdo_len = 2;
313178479Sjb	dp->dtdo_inttab[0] = id;
314178479Sjb	dp->dtdo_intlen = 1;
315178479Sjb	dp->dtdo_rtype = dt_int_rtype;
316178479Sjb
317178479Sjb	ap->dtad_difo = dp;
318178479Sjb	ap->dtad_kind = kind;
319178479Sjb}
320178479Sjb
321178479Sjbstatic void
322178479Sjbdt_action_clear(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
323178479Sjb{
324178479Sjb	dt_ident_t *aid;
325178479Sjb	dtrace_actdesc_t *ap;
326178479Sjb	dt_node_t *anp;
327178479Sjb
328178479Sjb	char n[DT_TYPE_NAMELEN];
329178479Sjb	int argc = 0;
330178479Sjb
331178479Sjb	for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
332178479Sjb		argc++; /* count up arguments for error messages below */
333178479Sjb
334178479Sjb	if (argc != 1) {
335178479Sjb		dnerror(dnp, D_CLEAR_PROTO,
336178479Sjb		    "%s( ) prototype mismatch: %d args passed, 1 expected\n",
337178479Sjb		    dnp->dn_ident->di_name, argc);
338178479Sjb	}
339178479Sjb
340178479Sjb	anp = dnp->dn_args;
341178479Sjb	assert(anp != NULL);
342178479Sjb
343178479Sjb	if (anp->dn_kind != DT_NODE_AGG) {
344178479Sjb		dnerror(dnp, D_CLEAR_AGGARG,
345178479Sjb		    "%s( ) argument #1 is incompatible with prototype:\n"
346178479Sjb		    "\tprototype: aggregation\n\t argument: %s\n",
347178479Sjb		    dnp->dn_ident->di_name,
348178479Sjb		    dt_node_type_name(anp, n, sizeof (n)));
349178479Sjb	}
350178479Sjb
351178479Sjb	aid = anp->dn_ident;
352178479Sjb
353178479Sjb	if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
354178479Sjb		dnerror(dnp, D_CLEAR_AGGBAD,
355178479Sjb		    "undefined aggregation: @%s\n", aid->di_name);
356178479Sjb	}
357178479Sjb
358178479Sjb	ap = dt_stmt_action(dtp, sdp);
359178479Sjb	dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
360178479Sjb	ap->dtad_arg = DT_ACT_CLEAR;
361178479Sjb}
362178479Sjb
363178479Sjbstatic void
364178479Sjbdt_action_normalize(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
365178479Sjb{
366178479Sjb	dt_ident_t *aid;
367178479Sjb	dtrace_actdesc_t *ap;
368178479Sjb	dt_node_t *anp, *normal;
369178479Sjb	int denormal = (strcmp(dnp->dn_ident->di_name, "denormalize") == 0);
370178479Sjb
371178479Sjb	char n[DT_TYPE_NAMELEN];
372178479Sjb	int argc = 0;
373178479Sjb
374178479Sjb	for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
375178479Sjb		argc++; /* count up arguments for error messages below */
376178479Sjb
377178479Sjb	if ((denormal && argc != 1) || (!denormal && argc != 2)) {
378178479Sjb		dnerror(dnp, D_NORMALIZE_PROTO,
379178479Sjb		    "%s( ) prototype mismatch: %d args passed, %d expected\n",
380178479Sjb		    dnp->dn_ident->di_name, argc, denormal ? 1 : 2);
381178479Sjb	}
382178479Sjb
383178479Sjb	anp = dnp->dn_args;
384178479Sjb	assert(anp != NULL);
385178479Sjb
386178479Sjb	if (anp->dn_kind != DT_NODE_AGG) {
387178479Sjb		dnerror(dnp, D_NORMALIZE_AGGARG,
388178479Sjb		    "%s( ) argument #1 is incompatible with prototype:\n"
389178479Sjb		    "\tprototype: aggregation\n\t argument: %s\n",
390178479Sjb		    dnp->dn_ident->di_name,
391178479Sjb		    dt_node_type_name(anp, n, sizeof (n)));
392178479Sjb	}
393178479Sjb
394178479Sjb	if ((normal = anp->dn_list) != NULL && !dt_node_is_scalar(normal)) {
395178479Sjb		dnerror(dnp, D_NORMALIZE_SCALAR,
396178479Sjb		    "%s( ) argument #2 must be of scalar type\n",
397178479Sjb		    dnp->dn_ident->di_name);
398178479Sjb	}
399178479Sjb
400178479Sjb	aid = anp->dn_ident;
401178479Sjb
402178479Sjb	if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
403178479Sjb		dnerror(dnp, D_NORMALIZE_AGGBAD,
404178479Sjb		    "undefined aggregation: @%s\n", aid->di_name);
405178479Sjb	}
406178479Sjb
407178479Sjb	ap = dt_stmt_action(dtp, sdp);
408178479Sjb	dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
409178479Sjb
410178479Sjb	if (denormal) {
411178479Sjb		ap->dtad_arg = DT_ACT_DENORMALIZE;
412178479Sjb		return;
413178479Sjb	}
414178479Sjb
415178479Sjb	ap->dtad_arg = DT_ACT_NORMALIZE;
416178479Sjb
417178479Sjb	assert(normal != NULL);
418178479Sjb	ap = dt_stmt_action(dtp, sdp);
419178479Sjb	dt_cg(yypcb, normal);
420178479Sjb
421178479Sjb	ap->dtad_difo = dt_as(yypcb);
422178479Sjb	ap->dtad_kind = DTRACEACT_LIBACT;
423178479Sjb	ap->dtad_arg = DT_ACT_NORMALIZE;
424178479Sjb}
425178479Sjb
426178479Sjbstatic void
427178479Sjbdt_action_trunc(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
428178479Sjb{
429178479Sjb	dt_ident_t *aid;
430178479Sjb	dtrace_actdesc_t *ap;
431178479Sjb	dt_node_t *anp, *trunc;
432178479Sjb
433178479Sjb	char n[DT_TYPE_NAMELEN];
434178479Sjb	int argc = 0;
435178479Sjb
436178479Sjb	for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
437178479Sjb		argc++; /* count up arguments for error messages below */
438178479Sjb
439178479Sjb	if (argc > 2 || argc < 1) {
440178479Sjb		dnerror(dnp, D_TRUNC_PROTO,
441178479Sjb		    "%s( ) prototype mismatch: %d args passed, %s expected\n",
442178479Sjb		    dnp->dn_ident->di_name, argc,
443178479Sjb		    argc < 1 ? "at least 1" : "no more than 2");
444178479Sjb	}
445178479Sjb
446178479Sjb	anp = dnp->dn_args;
447178479Sjb	assert(anp != NULL);
448178479Sjb	trunc = anp->dn_list;
449178479Sjb
450178479Sjb	if (anp->dn_kind != DT_NODE_AGG) {
451178479Sjb		dnerror(dnp, D_TRUNC_AGGARG,
452178479Sjb		    "%s( ) argument #1 is incompatible with prototype:\n"
453178479Sjb		    "\tprototype: aggregation\n\t argument: %s\n",
454178479Sjb		    dnp->dn_ident->di_name,
455178479Sjb		    dt_node_type_name(anp, n, sizeof (n)));
456178479Sjb	}
457178479Sjb
458178479Sjb	if (argc == 2) {
459178479Sjb		assert(trunc != NULL);
460178479Sjb		if (!dt_node_is_scalar(trunc)) {
461178479Sjb			dnerror(dnp, D_TRUNC_SCALAR,
462178479Sjb			    "%s( ) argument #2 must be of scalar type\n",
463178479Sjb			    dnp->dn_ident->di_name);
464178479Sjb		}
465178479Sjb	}
466178479Sjb
467178479Sjb	aid = anp->dn_ident;
468178479Sjb
469178479Sjb	if (aid->di_gen == dtp->dt_gen && !(aid->di_flags & DT_IDFLG_MOD)) {
470178479Sjb		dnerror(dnp, D_TRUNC_AGGBAD,
471178479Sjb		    "undefined aggregation: @%s\n", aid->di_name);
472178479Sjb	}
473178479Sjb
474178479Sjb	ap = dt_stmt_action(dtp, sdp);
475178479Sjb	dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_LIBACT);
476178479Sjb	ap->dtad_arg = DT_ACT_TRUNC;
477178479Sjb
478178479Sjb	ap = dt_stmt_action(dtp, sdp);
479178479Sjb
480178479Sjb	if (argc == 1) {
481178479Sjb		dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
482178479Sjb	} else {
483178479Sjb		assert(trunc != NULL);
484178479Sjb		dt_cg(yypcb, trunc);
485178479Sjb		ap->dtad_difo = dt_as(yypcb);
486178479Sjb		ap->dtad_kind = DTRACEACT_LIBACT;
487178479Sjb	}
488178479Sjb
489178479Sjb	ap->dtad_arg = DT_ACT_TRUNC;
490178479Sjb}
491178479Sjb
492178479Sjbstatic void
493178479Sjbdt_action_printa(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
494178479Sjb{
495178479Sjb	dt_ident_t *aid, *fid;
496178479Sjb	dtrace_actdesc_t *ap;
497178479Sjb	const char *format;
498178479Sjb	dt_node_t *anp, *proto = NULL;
499178479Sjb
500178479Sjb	char n[DT_TYPE_NAMELEN];
501178479Sjb	int argc = 0, argr = 0;
502178479Sjb
503178479Sjb	for (anp = dnp->dn_args; anp != NULL; anp = anp->dn_list)
504178479Sjb		argc++; /* count up arguments for error messages below */
505178479Sjb
506178479Sjb	switch (dnp->dn_args->dn_kind) {
507178479Sjb	case DT_NODE_STRING:
508178479Sjb		format = dnp->dn_args->dn_string;
509178479Sjb		anp = dnp->dn_args->dn_list;
510178479Sjb		argr = 2;
511178479Sjb		break;
512178479Sjb	case DT_NODE_AGG:
513178479Sjb		format = NULL;
514178479Sjb		anp = dnp->dn_args;
515178479Sjb		argr = 1;
516178479Sjb		break;
517178479Sjb	default:
518178479Sjb		format = NULL;
519178479Sjb		anp = dnp->dn_args;
520178479Sjb		argr = 1;
521178479Sjb	}
522178479Sjb
523178479Sjb	if (argc < argr) {
524178479Sjb		dnerror(dnp, D_PRINTA_PROTO,
525178479Sjb		    "%s( ) prototype mismatch: %d args passed, %d expected\n",
526178479Sjb		    dnp->dn_ident->di_name, argc, argr);
527178479Sjb	}
528178479Sjb
529178479Sjb	assert(anp != NULL);
530178479Sjb
531178479Sjb	while (anp != NULL) {
532178479Sjb		if (anp->dn_kind != DT_NODE_AGG) {
533178479Sjb			dnerror(dnp, D_PRINTA_AGGARG,
534178479Sjb			    "%s( ) argument #%d is incompatible with "
535178479Sjb			    "prototype:\n\tprototype: aggregation\n"
536178479Sjb			    "\t argument: %s\n", dnp->dn_ident->di_name, argr,
537178479Sjb			    dt_node_type_name(anp, n, sizeof (n)));
538178479Sjb		}
539178479Sjb
540178479Sjb		aid = anp->dn_ident;
541178479Sjb		fid = aid->di_iarg;
542178479Sjb
543178479Sjb		if (aid->di_gen == dtp->dt_gen &&
544178479Sjb		    !(aid->di_flags & DT_IDFLG_MOD)) {
545178479Sjb			dnerror(dnp, D_PRINTA_AGGBAD,
546178479Sjb			    "undefined aggregation: @%s\n", aid->di_name);
547178479Sjb		}
548178479Sjb
549178479Sjb		/*
550178479Sjb		 * If we have multiple aggregations, we must be sure that
551178479Sjb		 * their key signatures match.
552178479Sjb		 */
553178479Sjb		if (proto != NULL) {
554178479Sjb			dt_printa_validate(proto, anp);
555178479Sjb		} else {
556178479Sjb			proto = anp;
557178479Sjb		}
558178479Sjb
559178479Sjb		if (format != NULL) {
560178479Sjb			yylineno = dnp->dn_line;
561178479Sjb
562178479Sjb			sdp->dtsd_fmtdata =
563178479Sjb			    dt_printf_create(yypcb->pcb_hdl, format);
564178479Sjb			dt_printf_validate(sdp->dtsd_fmtdata,
565178479Sjb			    DT_PRINTF_AGGREGATION, dnp->dn_ident, 1,
566178479Sjb			    fid->di_id, ((dt_idsig_t *)aid->di_data)->dis_args);
567178479Sjb			format = NULL;
568178479Sjb		}
569178479Sjb
570178479Sjb		ap = dt_stmt_action(dtp, sdp);
571178479Sjb		dt_action_difconst(ap, anp->dn_ident->di_id, DTRACEACT_PRINTA);
572178479Sjb
573178479Sjb		anp = anp->dn_list;
574178479Sjb		argr++;
575178479Sjb	}
576178479Sjb}
577178479Sjb
578178479Sjbstatic void
579178479Sjbdt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
580178479Sjb    dtrace_actkind_t kind)
581178479Sjb{
582178479Sjb	dt_node_t *anp, *arg1;
583178479Sjb	dtrace_actdesc_t *ap = NULL;
584178479Sjb	char n[DT_TYPE_NAMELEN], *str;
585178479Sjb
586178479Sjb	assert(DTRACEACT_ISPRINTFLIKE(kind));
587178479Sjb
588178479Sjb	if (dnp->dn_args->dn_kind != DT_NODE_STRING) {
589178479Sjb		dnerror(dnp, D_PRINTF_ARG_FMT,
590178479Sjb		    "%s( ) argument #1 is incompatible with prototype:\n"
591178479Sjb		    "\tprototype: string constant\n\t argument: %s\n",
592178479Sjb		    dnp->dn_ident->di_name,
593178479Sjb		    dt_node_type_name(dnp->dn_args, n, sizeof (n)));
594178479Sjb	}
595178479Sjb
596178479Sjb	arg1 = dnp->dn_args->dn_list;
597178479Sjb	yylineno = dnp->dn_line;
598178479Sjb	str = dnp->dn_args->dn_string;
599178479Sjb
600178479Sjb
601178479Sjb	/*
602178479Sjb	 * If this is an freopen(), we use an empty string to denote that
603178479Sjb	 * stdout should be restored.  For other printf()-like actions, an
604178479Sjb	 * empty format string is illegal:  an empty format string would
605178479Sjb	 * result in malformed DOF, and the compiler thus flags an empty
606178479Sjb	 * format string as a compile-time error.  To avoid propagating the
607178479Sjb	 * freopen() special case throughout the system, we simply transpose
608178479Sjb	 * an empty string into a sentinel string (DT_FREOPEN_RESTORE) that
609178479Sjb	 * denotes that stdout should be restored.
610178479Sjb	 */
611178479Sjb	if (kind == DTRACEACT_FREOPEN) {
612178479Sjb		if (strcmp(str, DT_FREOPEN_RESTORE) == 0) {
613178479Sjb			/*
614178479Sjb			 * Our sentinel is always an invalid argument to
615178479Sjb			 * freopen(), but if it's been manually specified, we
616178479Sjb			 * must fail now instead of when the freopen() is
617178479Sjb			 * actually evaluated.
618178479Sjb			 */
619178479Sjb			dnerror(dnp, D_FREOPEN_INVALID,
620178479Sjb			    "%s( ) argument #1 cannot be \"%s\"\n",
621178479Sjb			    dnp->dn_ident->di_name, DT_FREOPEN_RESTORE);
622178479Sjb		}
623178479Sjb
624178479Sjb		if (str[0] == '\0')
625178479Sjb			str = DT_FREOPEN_RESTORE;
626178479Sjb	}
627178479Sjb
628178479Sjb	sdp->dtsd_fmtdata = dt_printf_create(dtp, str);
629178479Sjb
630178479Sjb	dt_printf_validate(sdp->dtsd_fmtdata, DT_PRINTF_EXACTLEN,
631178479Sjb	    dnp->dn_ident, 1, DTRACEACT_AGGREGATION, arg1);
632178479Sjb
633178479Sjb	if (arg1 == NULL) {
634178479Sjb		dif_instr_t *dbuf;
635178479Sjb		dtrace_difo_t *dp;
636178479Sjb
637178479Sjb		if ((dbuf = dt_alloc(dtp, sizeof (dif_instr_t))) == NULL ||
638178479Sjb		    (dp = dt_zalloc(dtp, sizeof (dtrace_difo_t))) == NULL) {
639178479Sjb			dt_free(dtp, dbuf);
640178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
641178479Sjb		}
642178479Sjb
643178479Sjb		dbuf[0] = DIF_INSTR_RET(DIF_REG_R0); /* ret %r0 */
644178479Sjb
645178479Sjb		dp->dtdo_buf = dbuf;
646178479Sjb		dp->dtdo_len = 1;
647178479Sjb		dp->dtdo_rtype = dt_int_rtype;
648178479Sjb
649178479Sjb		ap = dt_stmt_action(dtp, sdp);
650178479Sjb		ap->dtad_difo = dp;
651178479Sjb		ap->dtad_kind = kind;
652178479Sjb		return;
653178479Sjb	}
654178479Sjb
655178479Sjb	for (anp = arg1; anp != NULL; anp = anp->dn_list) {
656178479Sjb		ap = dt_stmt_action(dtp, sdp);
657178479Sjb		dt_cg(yypcb, anp);
658178479Sjb		ap->dtad_difo = dt_as(yypcb);
659178479Sjb		ap->dtad_kind = kind;
660178479Sjb	}
661178479Sjb}
662178479Sjb
663178479Sjbstatic void
664178479Sjbdt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
665178479Sjb{
666178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
667253725Spfg	boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
668253725Spfg	const char *act = istrace ?  "trace" : "print";
669178479Sjb
670178479Sjb	if (dt_node_is_void(dnp->dn_args)) {
671253725Spfg		dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
672253725Spfg		    "%s( ) may not be applied to a void expression\n", act);
673178479Sjb	}
674178479Sjb
675253725Spfg	if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
676253725Spfg		dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
677253725Spfg		    "%s( ) may not be applied to a translated pointer\n", act);
678178479Sjb	}
679178479Sjb
680253726Spfg	if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
681253726Spfg		dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
682253726Spfg		    "%s( ) may not be applied to an aggregation%s\n", act,
683253726Spfg		    istrace ? "" : " -- did you mean printa()?");
684253726Spfg	}
685253726Spfg
686178479Sjb	dt_cg(yypcb, dnp->dn_args);
687178479Sjb
688253725Spfg	/*
689253725Spfg	 * The print() action behaves identically to trace(), except that it
690253725Spfg	 * stores the CTF type of the argument (if present) within the DOF for
691253725Spfg	 * the DIFEXPR action.  To do this, we set the 'dtsd_strdata' to point
692253725Spfg	 * to the fully-qualified CTF type ID for the result of the DIF
693253725Spfg	 * action.  We use the ID instead of the name to handles complex types
694253725Spfg	 * like arrays and function pointers that can't be resolved by
695253725Spfg	 * ctf_type_lookup().  This is later processed by dtrace_dof_create()
696253725Spfg	 * and turned into a reference into the string table so that we can
697253725Spfg	 * get the type information when we process the data after the fact.
698253725Spfg	 */
699253725Spfg	if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
700253725Spfg		dt_node_t *dret;
701253725Spfg		size_t n;
702253725Spfg		dt_module_t *dmp;
703248708Spfg
704253725Spfg		dret = yypcb->pcb_dret;
705253725Spfg		dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
706248708Spfg
707253725Spfg		n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
708253725Spfg		sdp->dtsd_strdata = dt_alloc(dtp, n);
709253725Spfg		if (sdp->dtsd_strdata == NULL)
710253725Spfg			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
711253725Spfg		(void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
712253725Spfg		    dret->dn_type);
713248708Spfg	}
714248708Spfg
715248708Spfg	ap->dtad_difo = dt_as(yypcb);
716248708Spfg	ap->dtad_kind = DTRACEACT_DIFEXPR;
717248708Spfg}
718248708Spfg
719248708Spfgstatic void
720178479Sjbdt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
721178479Sjb{
722178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
723178479Sjb
724178479Sjb	dt_node_t *addr = dnp->dn_args;
725248690Spfg	dt_node_t *max = dnp->dn_args->dn_list;
726248690Spfg	dt_node_t *size;
727178479Sjb
728178479Sjb	char n[DT_TYPE_NAMELEN];
729178479Sjb
730178479Sjb	if (dt_node_is_integer(addr) == 0 && dt_node_is_pointer(addr) == 0) {
731178479Sjb		dnerror(addr, D_TRACEMEM_ADDR,
732178479Sjb		    "tracemem( ) argument #1 is incompatible with "
733178479Sjb		    "prototype:\n\tprototype: pointer or integer\n"
734178479Sjb		    "\t argument: %s\n",
735178479Sjb		    dt_node_type_name(addr, n, sizeof (n)));
736178479Sjb	}
737178479Sjb
738248690Spfg	if (dt_node_is_posconst(max) == 0) {
739248690Spfg		dnerror(max, D_TRACEMEM_SIZE, "tracemem( ) argument #2 must "
740178479Sjb		    "be a non-zero positive integral constant expression\n");
741178479Sjb	}
742178479Sjb
743248690Spfg	if ((size = max->dn_list) != NULL) {
744248690Spfg		if (size->dn_list != NULL) {
745248690Spfg			dnerror(size, D_TRACEMEM_ARGS, "tracemem ( ) prototype "
746248690Spfg			    "mismatch: expected at most 3 args\n");
747248690Spfg		}
748248690Spfg
749248690Spfg		if (!dt_node_is_scalar(size)) {
750248690Spfg			dnerror(size, D_TRACEMEM_DYNSIZE, "tracemem ( ) "
751248690Spfg			    "dynamic size (argument #3) must be of "
752248690Spfg			    "scalar type\n");
753248690Spfg		}
754248690Spfg
755248690Spfg		dt_cg(yypcb, size);
756248690Spfg		ap->dtad_difo = dt_as(yypcb);
757248690Spfg		ap->dtad_difo->dtdo_rtype = dt_int_rtype;
758248690Spfg		ap->dtad_kind = DTRACEACT_TRACEMEM_DYNSIZE;
759248690Spfg
760248690Spfg		ap = dt_stmt_action(dtp, sdp);
761248690Spfg	}
762248690Spfg
763178479Sjb	dt_cg(yypcb, addr);
764178479Sjb	ap->dtad_difo = dt_as(yypcb);
765248690Spfg	ap->dtad_kind = DTRACEACT_TRACEMEM;
766178479Sjb
767178479Sjb	ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
768248690Spfg	ap->dtad_difo->dtdo_rtype.dtdt_size = max->dn_value;
769178479Sjb}
770178479Sjb
771178479Sjbstatic void
772178479Sjbdt_action_stack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *arg0)
773178479Sjb{
774178479Sjb	ap->dtad_kind = DTRACEACT_STACK;
775178479Sjb
776178479Sjb	if (dtp->dt_options[DTRACEOPT_STACKFRAMES] != DTRACEOPT_UNSET) {
777178479Sjb		ap->dtad_arg = dtp->dt_options[DTRACEOPT_STACKFRAMES];
778178479Sjb	} else {
779178479Sjb		ap->dtad_arg = 0;
780178479Sjb	}
781178479Sjb
782178479Sjb	if (arg0 != NULL) {
783178479Sjb		if (arg0->dn_list != NULL) {
784178479Sjb			dnerror(arg0, D_STACK_PROTO, "stack( ) prototype "
785178479Sjb			    "mismatch: too many arguments\n");
786178479Sjb		}
787178479Sjb
788178479Sjb		if (dt_node_is_posconst(arg0) == 0) {
789178479Sjb			dnerror(arg0, D_STACK_SIZE, "stack( ) size must be a "
790178479Sjb			    "non-zero positive integral constant expression\n");
791178479Sjb		}
792178479Sjb
793178479Sjb		ap->dtad_arg = arg0->dn_value;
794178479Sjb	}
795178479Sjb}
796178479Sjb
797178479Sjbstatic void
798178479Sjbdt_action_stack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
799178479Sjb{
800178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
801178479Sjb	dt_action_stack_args(dtp, ap, dnp->dn_args);
802178479Sjb}
803178479Sjb
804178479Sjbstatic void
805178479Sjbdt_action_ustack_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap, dt_node_t *dnp)
806178479Sjb{
807178479Sjb	uint32_t nframes = 0;
808178479Sjb	uint32_t strsize = 0;	/* default string table size */
809178479Sjb	dt_node_t *arg0 = dnp->dn_args;
810178479Sjb	dt_node_t *arg1 = arg0 != NULL ? arg0->dn_list : NULL;
811178479Sjb
812178479Sjb	assert(dnp->dn_ident->di_id == DT_ACT_JSTACK ||
813178479Sjb	    dnp->dn_ident->di_id == DT_ACT_USTACK);
814178479Sjb
815178479Sjb	if (dnp->dn_ident->di_id == DT_ACT_JSTACK) {
816178479Sjb		if (dtp->dt_options[DTRACEOPT_JSTACKFRAMES] != DTRACEOPT_UNSET)
817178479Sjb			nframes = dtp->dt_options[DTRACEOPT_JSTACKFRAMES];
818178479Sjb
819178479Sjb		if (dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE] != DTRACEOPT_UNSET)
820178479Sjb			strsize = dtp->dt_options[DTRACEOPT_JSTACKSTRSIZE];
821178479Sjb
822178479Sjb		ap->dtad_kind = DTRACEACT_JSTACK;
823178479Sjb	} else {
824178479Sjb		assert(dnp->dn_ident->di_id == DT_ACT_USTACK);
825178479Sjb
826178479Sjb		if (dtp->dt_options[DTRACEOPT_USTACKFRAMES] != DTRACEOPT_UNSET)
827178479Sjb			nframes = dtp->dt_options[DTRACEOPT_USTACKFRAMES];
828178479Sjb
829178479Sjb		ap->dtad_kind = DTRACEACT_USTACK;
830178479Sjb	}
831178479Sjb
832178479Sjb	if (arg0 != NULL) {
833178479Sjb		if (!dt_node_is_posconst(arg0)) {
834178479Sjb			dnerror(arg0, D_USTACK_FRAMES, "ustack( ) argument #1 "
835178479Sjb			    "must be a non-zero positive integer constant\n");
836178479Sjb		}
837178479Sjb		nframes = (uint32_t)arg0->dn_value;
838178479Sjb	}
839178479Sjb
840178479Sjb	if (arg1 != NULL) {
841178479Sjb		if (arg1->dn_kind != DT_NODE_INT ||
842178479Sjb		    ((arg1->dn_flags & DT_NF_SIGNED) &&
843178479Sjb		    (int64_t)arg1->dn_value < 0)) {
844178479Sjb			dnerror(arg1, D_USTACK_STRSIZE, "ustack( ) argument #2 "
845178479Sjb			    "must be a positive integer constant\n");
846178479Sjb		}
847178479Sjb
848178479Sjb		if (arg1->dn_list != NULL) {
849178479Sjb			dnerror(arg1, D_USTACK_PROTO, "ustack( ) prototype "
850178479Sjb			    "mismatch: too many arguments\n");
851178479Sjb		}
852178479Sjb
853178479Sjb		strsize = (uint32_t)arg1->dn_value;
854178479Sjb	}
855178479Sjb
856178479Sjb	ap->dtad_arg = DTRACE_USTACK_ARG(nframes, strsize);
857178479Sjb}
858178479Sjb
859178479Sjbstatic void
860178479Sjbdt_action_ustack(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
861178479Sjb{
862178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
863178479Sjb	dt_action_ustack_args(dtp, ap, dnp);
864178479Sjb}
865178479Sjb
866178479Sjbstatic void
867178479Sjbdt_action_setopt(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
868178479Sjb{
869178479Sjb	dtrace_actdesc_t *ap;
870178479Sjb	dt_node_t *arg0, *arg1;
871178479Sjb
872178479Sjb	/*
873178479Sjb	 * The prototype guarantees that we are called with either one or
874178479Sjb	 * two arguments, and that any arguments that are present are strings.
875178479Sjb	 */
876178479Sjb	arg0 = dnp->dn_args;
877178479Sjb	arg1 = arg0->dn_list;
878178479Sjb
879178479Sjb	ap = dt_stmt_action(dtp, sdp);
880178479Sjb	dt_cg(yypcb, arg0);
881178479Sjb	ap->dtad_difo = dt_as(yypcb);
882178479Sjb	ap->dtad_kind = DTRACEACT_LIBACT;
883178479Sjb	ap->dtad_arg = DT_ACT_SETOPT;
884178479Sjb
885178479Sjb	ap = dt_stmt_action(dtp, sdp);
886178479Sjb
887178479Sjb	if (arg1 == NULL) {
888178479Sjb		dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
889178479Sjb	} else {
890178479Sjb		dt_cg(yypcb, arg1);
891178479Sjb		ap->dtad_difo = dt_as(yypcb);
892178479Sjb		ap->dtad_kind = DTRACEACT_LIBACT;
893178479Sjb	}
894178479Sjb
895178479Sjb	ap->dtad_arg = DT_ACT_SETOPT;
896178479Sjb}
897178479Sjb
898178479Sjb/*ARGSUSED*/
899178479Sjbstatic void
900178479Sjbdt_action_symmod_args(dtrace_hdl_t *dtp, dtrace_actdesc_t *ap,
901178479Sjb    dt_node_t *dnp, dtrace_actkind_t kind)
902178479Sjb{
903178479Sjb	assert(kind == DTRACEACT_SYM || kind == DTRACEACT_MOD ||
904178479Sjb	    kind == DTRACEACT_USYM || kind == DTRACEACT_UMOD ||
905178479Sjb	    kind == DTRACEACT_UADDR);
906178479Sjb
907178479Sjb	dt_cg(yypcb, dnp);
908178479Sjb	ap->dtad_difo = dt_as(yypcb);
909178479Sjb	ap->dtad_kind = kind;
910178479Sjb	ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (uint64_t);
911178479Sjb}
912178479Sjb
913178479Sjbstatic void
914178479Sjbdt_action_symmod(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
915178479Sjb    dtrace_actkind_t kind)
916178479Sjb{
917178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
918178479Sjb	dt_action_symmod_args(dtp, ap, dnp->dn_args, kind);
919178479Sjb}
920178479Sjb
921178479Sjb/*ARGSUSED*/
922178479Sjbstatic void
923178479Sjbdt_action_ftruncate(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
924178479Sjb{
925178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
926178479Sjb
927178479Sjb	/*
928178479Sjb	 * Library actions need a DIFO that serves as an argument.  As
929178479Sjb	 * ftruncate() doesn't take an argument, we generate the constant 0
930178479Sjb	 * in a DIFO; this constant will be ignored when the ftruncate() is
931178479Sjb	 * processed.
932178479Sjb	 */
933178479Sjb	dt_action_difconst(ap, 0, DTRACEACT_LIBACT);
934178479Sjb	ap->dtad_arg = DT_ACT_FTRUNCATE;
935178479Sjb}
936178479Sjb
937178479Sjb/*ARGSUSED*/
938178479Sjbstatic void
939178479Sjbdt_action_stop(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
940178479Sjb{
941178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
942178479Sjb
943178479Sjb	ap->dtad_kind = DTRACEACT_STOP;
944178479Sjb	ap->dtad_arg = 0;
945178479Sjb}
946178479Sjb
947178479Sjb/*ARGSUSED*/
948178479Sjbstatic void
949178479Sjbdt_action_breakpoint(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
950178479Sjb{
951178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
952178479Sjb
953178479Sjb	ap->dtad_kind = DTRACEACT_BREAKPOINT;
954178479Sjb	ap->dtad_arg = 0;
955178479Sjb}
956178479Sjb
957178479Sjb/*ARGSUSED*/
958178479Sjbstatic void
959178479Sjbdt_action_panic(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
960178479Sjb{
961178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
962178479Sjb
963178479Sjb	ap->dtad_kind = DTRACEACT_PANIC;
964178479Sjb	ap->dtad_arg = 0;
965178479Sjb}
966178479Sjb
967178479Sjbstatic void
968178479Sjbdt_action_chill(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
969178479Sjb{
970178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
971178479Sjb
972178479Sjb	dt_cg(yypcb, dnp->dn_args);
973178479Sjb	ap->dtad_difo = dt_as(yypcb);
974178479Sjb	ap->dtad_kind = DTRACEACT_CHILL;
975178479Sjb}
976178479Sjb
977178479Sjbstatic void
978178479Sjbdt_action_raise(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
979178479Sjb{
980178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
981178479Sjb
982178479Sjb	dt_cg(yypcb, dnp->dn_args);
983178479Sjb	ap->dtad_difo = dt_as(yypcb);
984178479Sjb	ap->dtad_kind = DTRACEACT_RAISE;
985178479Sjb}
986178479Sjb
987178479Sjbstatic void
988178479Sjbdt_action_exit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
989178479Sjb{
990178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
991178479Sjb
992178479Sjb	dt_cg(yypcb, dnp->dn_args);
993178479Sjb	ap->dtad_difo = dt_as(yypcb);
994178479Sjb	ap->dtad_kind = DTRACEACT_EXIT;
995178479Sjb	ap->dtad_difo->dtdo_rtype.dtdt_size = sizeof (int);
996178479Sjb}
997178479Sjb
998178479Sjbstatic void
999178479Sjbdt_action_speculate(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1000178479Sjb{
1001178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1002178479Sjb
1003178479Sjb	dt_cg(yypcb, dnp->dn_args);
1004178479Sjb	ap->dtad_difo = dt_as(yypcb);
1005178479Sjb	ap->dtad_kind = DTRACEACT_SPECULATE;
1006178479Sjb}
1007178479Sjb
1008178479Sjbstatic void
1009178576Sjbdt_action_printm(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1010178576Sjb{
1011178576Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1012178576Sjb
1013178576Sjb	dt_node_t *size = dnp->dn_args;
1014178576Sjb	dt_node_t *addr = dnp->dn_args->dn_list;
1015178576Sjb
1016178576Sjb	char n[DT_TYPE_NAMELEN];
1017178576Sjb
1018178576Sjb	if (dt_node_is_posconst(size) == 0) {
1019178576Sjb		dnerror(size, D_PRINTM_SIZE, "printm( ) argument #1 must "
1020178576Sjb		    "be a non-zero positive integral constant expression\n");
1021178576Sjb	}
1022178576Sjb
1023178576Sjb	if (dt_node_is_pointer(addr) == 0) {
1024178576Sjb		dnerror(addr, D_PRINTM_ADDR,
1025178576Sjb		    "printm( ) argument #2 is incompatible with "
1026178576Sjb		    "prototype:\n\tprototype: pointer\n"
1027178576Sjb		    "\t argument: %s\n",
1028178576Sjb		    dt_node_type_name(addr, n, sizeof (n)));
1029178576Sjb	}
1030178576Sjb
1031178576Sjb	dt_cg(yypcb, addr);
1032178576Sjb	ap->dtad_difo = dt_as(yypcb);
1033178576Sjb	ap->dtad_kind = DTRACEACT_PRINTM;
1034178576Sjb
1035178576Sjb	ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
1036178576Sjb	ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value + sizeof(uintptr_t);
1037178576Sjb}
1038178576Sjb
1039178576Sjbstatic void
1040178576Sjbdt_action_printt(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1041178576Sjb{
1042178576Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1043178576Sjb
1044178576Sjb	dt_node_t *size = dnp->dn_args;
1045178576Sjb	dt_node_t *addr = dnp->dn_args->dn_list;
1046178576Sjb
1047178576Sjb	char n[DT_TYPE_NAMELEN];
1048178576Sjb
1049178576Sjb	if (dt_node_is_posconst(size) == 0) {
1050178576Sjb		dnerror(size, D_PRINTT_SIZE, "printt( ) argument #1 must "
1051178576Sjb		    "be a non-zero positive integral constant expression\n");
1052178576Sjb	}
1053178576Sjb
1054178576Sjb	if (addr == NULL || addr->dn_kind != DT_NODE_FUNC ||
1055178576Sjb	    addr->dn_ident != dt_idhash_lookup(dtp->dt_globals, "typeref")) {
1056178576Sjb		dnerror(addr, D_PRINTT_ADDR,
1057178576Sjb		    "printt( ) argument #2 is incompatible with "
1058178576Sjb		    "prototype:\n\tprototype: typeref()\n"
1059178576Sjb		    "\t argument: %s\n",
1060178576Sjb		    dt_node_type_name(addr, n, sizeof (n)));
1061178576Sjb	}
1062178576Sjb
1063178576Sjb	dt_cg(yypcb, addr);
1064178576Sjb	ap->dtad_difo = dt_as(yypcb);
1065178576Sjb	ap->dtad_kind = DTRACEACT_PRINTT;
1066178576Sjb
1067178576Sjb	ap->dtad_difo->dtdo_rtype.dtdt_flags |= DIF_TF_BYREF;
1068178576Sjb
1069178576Sjb	/*
1070178576Sjb	 * Allow additional buffer space for the data size, type size,
1071178576Sjb	 * type string length and a stab in the dark (32 bytes) for the
1072178576Sjb	 * type string. The type string is part of the typeref() that
1073178576Sjb	 * this action references.
1074178576Sjb	 */
1075178576Sjb	ap->dtad_difo->dtdo_rtype.dtdt_size = size->dn_value + 3 * sizeof(uintptr_t) + 32;
1076178576Sjb
1077178576Sjb}
1078178576Sjb
1079178576Sjbstatic void
1080178479Sjbdt_action_commit(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1081178479Sjb{
1082178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1083178479Sjb
1084178479Sjb	dt_cg(yypcb, dnp->dn_args);
1085178479Sjb	ap->dtad_difo = dt_as(yypcb);
1086178479Sjb	ap->dtad_kind = DTRACEACT_COMMIT;
1087178479Sjb}
1088178479Sjb
1089178479Sjbstatic void
1090178479Sjbdt_action_discard(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1091178479Sjb{
1092178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1093178479Sjb
1094178479Sjb	dt_cg(yypcb, dnp->dn_args);
1095178479Sjb	ap->dtad_difo = dt_as(yypcb);
1096178479Sjb	ap->dtad_kind = DTRACEACT_DISCARD;
1097178479Sjb}
1098178479Sjb
1099178479Sjbstatic void
1100178479Sjbdt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1101178479Sjb{
1102178479Sjb	switch (dnp->dn_expr->dn_ident->di_id) {
1103178479Sjb	case DT_ACT_BREAKPOINT:
1104178479Sjb		dt_action_breakpoint(dtp, dnp->dn_expr, sdp);
1105178479Sjb		break;
1106178479Sjb	case DT_ACT_CHILL:
1107178479Sjb		dt_action_chill(dtp, dnp->dn_expr, sdp);
1108178479Sjb		break;
1109178479Sjb	case DT_ACT_CLEAR:
1110178479Sjb		dt_action_clear(dtp, dnp->dn_expr, sdp);
1111178479Sjb		break;
1112178479Sjb	case DT_ACT_COMMIT:
1113178479Sjb		dt_action_commit(dtp, dnp->dn_expr, sdp);
1114178479Sjb		break;
1115178479Sjb	case DT_ACT_DENORMALIZE:
1116178479Sjb		dt_action_normalize(dtp, dnp->dn_expr, sdp);
1117178479Sjb		break;
1118178479Sjb	case DT_ACT_DISCARD:
1119178479Sjb		dt_action_discard(dtp, dnp->dn_expr, sdp);
1120178479Sjb		break;
1121178479Sjb	case DT_ACT_EXIT:
1122178479Sjb		dt_action_exit(dtp, dnp->dn_expr, sdp);
1123178479Sjb		break;
1124178479Sjb	case DT_ACT_FREOPEN:
1125178479Sjb		dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_FREOPEN);
1126178479Sjb		break;
1127178479Sjb	case DT_ACT_FTRUNCATE:
1128178479Sjb		dt_action_ftruncate(dtp, dnp->dn_expr, sdp);
1129178479Sjb		break;
1130178479Sjb	case DT_ACT_MOD:
1131178479Sjb		dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_MOD);
1132178479Sjb		break;
1133178479Sjb	case DT_ACT_NORMALIZE:
1134178479Sjb		dt_action_normalize(dtp, dnp->dn_expr, sdp);
1135178479Sjb		break;
1136178479Sjb	case DT_ACT_PANIC:
1137178479Sjb		dt_action_panic(dtp, dnp->dn_expr, sdp);
1138178479Sjb		break;
1139253725Spfg	case DT_ACT_PRINT:
1140253725Spfg		dt_action_trace(dtp, dnp->dn_expr, sdp);
1141253725Spfg		break;
1142178479Sjb	case DT_ACT_PRINTA:
1143178479Sjb		dt_action_printa(dtp, dnp->dn_expr, sdp);
1144178479Sjb		break;
1145178479Sjb	case DT_ACT_PRINTF:
1146178479Sjb		dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_PRINTF);
1147178479Sjb		break;
1148178576Sjb	case DT_ACT_PRINTM:
1149178576Sjb		dt_action_printm(dtp, dnp->dn_expr, sdp);
1150178576Sjb		break;
1151178576Sjb	case DT_ACT_PRINTT:
1152178576Sjb		dt_action_printt(dtp, dnp->dn_expr, sdp);
1153178576Sjb		break;
1154178479Sjb	case DT_ACT_RAISE:
1155178479Sjb		dt_action_raise(dtp, dnp->dn_expr, sdp);
1156178479Sjb		break;
1157178479Sjb	case DT_ACT_SETOPT:
1158178479Sjb		dt_action_setopt(dtp, dnp->dn_expr, sdp);
1159178479Sjb		break;
1160178479Sjb	case DT_ACT_SPECULATE:
1161178479Sjb		dt_action_speculate(dtp, dnp->dn_expr, sdp);
1162178479Sjb		break;
1163178479Sjb	case DT_ACT_STACK:
1164178479Sjb		dt_action_stack(dtp, dnp->dn_expr, sdp);
1165178479Sjb		break;
1166178479Sjb	case DT_ACT_STOP:
1167178479Sjb		dt_action_stop(dtp, dnp->dn_expr, sdp);
1168178479Sjb		break;
1169178479Sjb	case DT_ACT_SYM:
1170178479Sjb		dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_SYM);
1171178479Sjb		break;
1172178479Sjb	case DT_ACT_SYSTEM:
1173178479Sjb		dt_action_printflike(dtp, dnp->dn_expr, sdp, DTRACEACT_SYSTEM);
1174178479Sjb		break;
1175178479Sjb	case DT_ACT_TRACE:
1176178479Sjb		dt_action_trace(dtp, dnp->dn_expr, sdp);
1177178479Sjb		break;
1178178479Sjb	case DT_ACT_TRACEMEM:
1179178479Sjb		dt_action_tracemem(dtp, dnp->dn_expr, sdp);
1180178479Sjb		break;
1181178479Sjb	case DT_ACT_TRUNC:
1182178479Sjb		dt_action_trunc(dtp, dnp->dn_expr, sdp);
1183178479Sjb		break;
1184178479Sjb	case DT_ACT_UADDR:
1185178479Sjb		dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UADDR);
1186178479Sjb		break;
1187178479Sjb	case DT_ACT_UMOD:
1188178479Sjb		dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_UMOD);
1189178479Sjb		break;
1190178479Sjb	case DT_ACT_USYM:
1191178479Sjb		dt_action_symmod(dtp, dnp->dn_expr, sdp, DTRACEACT_USYM);
1192178479Sjb		break;
1193178479Sjb	case DT_ACT_USTACK:
1194178479Sjb	case DT_ACT_JSTACK:
1195178479Sjb		dt_action_ustack(dtp, dnp->dn_expr, sdp);
1196178479Sjb		break;
1197178479Sjb	default:
1198178479Sjb		dnerror(dnp->dn_expr, D_UNKNOWN, "tracing function %s( ) is "
1199178479Sjb		    "not yet supported\n", dnp->dn_expr->dn_ident->di_name);
1200178479Sjb	}
1201178479Sjb}
1202178479Sjb
1203178479Sjbstatic void
1204178479Sjbdt_compile_exp(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1205178479Sjb{
1206178479Sjb	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
1207178479Sjb
1208178479Sjb	dt_cg(yypcb, dnp->dn_expr);
1209178479Sjb	ap->dtad_difo = dt_as(yypcb);
1210178479Sjb	ap->dtad_difo->dtdo_rtype = dt_void_rtype;
1211178479Sjb	ap->dtad_kind = DTRACEACT_DIFEXPR;
1212178479Sjb}
1213178479Sjb
1214178479Sjbstatic void
1215178479Sjbdt_compile_agg(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
1216178479Sjb{
1217178479Sjb	dt_ident_t *aid, *fid;
1218178479Sjb	dt_node_t *anp, *incr = NULL;
1219178479Sjb	dtrace_actdesc_t *ap;
1220178479Sjb	uint_t n = 1, argmax;
1221178479Sjb	uint64_t arg = 0;
1222178479Sjb
1223178479Sjb	/*
1224178479Sjb	 * If the aggregation has no aggregating function applied to it, then
1225178479Sjb	 * this statement has no effect.  Flag this as a programming error.
1226178479Sjb	 */
1227178479Sjb	if (dnp->dn_aggfun == NULL) {
1228178479Sjb		dnerror(dnp, D_AGG_NULL, "expression has null effect: @%s\n",
1229178479Sjb		    dnp->dn_ident->di_name);
1230178479Sjb	}
1231178479Sjb
1232178479Sjb	aid = dnp->dn_ident;
1233178479Sjb	fid = dnp->dn_aggfun->dn_ident;
1234178479Sjb
1235178479Sjb	if (dnp->dn_aggfun->dn_args != NULL &&
1236178479Sjb	    dt_node_is_scalar(dnp->dn_aggfun->dn_args) == 0) {
1237178479Sjb		dnerror(dnp->dn_aggfun, D_AGG_SCALAR, "%s( ) argument #1 must "
1238178479Sjb		    "be of scalar type\n", fid->di_name);
1239178479Sjb	}
1240178479Sjb
1241178479Sjb	/*
1242178479Sjb	 * The ID of the aggregation itself is implicitly recorded as the first
1243178479Sjb	 * member of each aggregation tuple so we can distinguish them later.
1244178479Sjb	 */
1245178479Sjb	ap = dt_stmt_action(dtp, sdp);
1246178479Sjb	dt_action_difconst(ap, aid->di_id, DTRACEACT_DIFEXPR);
1247178479Sjb
1248178479Sjb	for (anp = dnp->dn_aggtup; anp != NULL; anp = anp->dn_list) {
1249178479Sjb		ap = dt_stmt_action(dtp, sdp);
1250178479Sjb		n++;
1251178479Sjb
1252178479Sjb		if (anp->dn_kind == DT_NODE_FUNC) {
1253178479Sjb			if (anp->dn_ident->di_id == DT_ACT_STACK) {
1254178479Sjb				dt_action_stack_args(dtp, ap, anp->dn_args);
1255178479Sjb				continue;
1256178479Sjb			}
1257178479Sjb
1258178479Sjb			if (anp->dn_ident->di_id == DT_ACT_USTACK ||
1259178479Sjb			    anp->dn_ident->di_id == DT_ACT_JSTACK) {
1260178479Sjb				dt_action_ustack_args(dtp, ap, anp);
1261178479Sjb				continue;
1262178479Sjb			}
1263178479Sjb
1264178479Sjb			switch (anp->dn_ident->di_id) {
1265178479Sjb			case DT_ACT_UADDR:
1266178479Sjb				dt_action_symmod_args(dtp, ap,
1267178479Sjb				    anp->dn_args, DTRACEACT_UADDR);
1268178479Sjb				continue;
1269178479Sjb
1270178479Sjb			case DT_ACT_USYM:
1271178479Sjb				dt_action_symmod_args(dtp, ap,
1272178479Sjb				    anp->dn_args, DTRACEACT_USYM);
1273178479Sjb				continue;
1274178479Sjb
1275178479Sjb			case DT_ACT_UMOD:
1276178479Sjb				dt_action_symmod_args(dtp, ap,
1277178479Sjb				    anp->dn_args, DTRACEACT_UMOD);
1278178479Sjb				continue;
1279178479Sjb
1280178479Sjb			case DT_ACT_SYM:
1281178479Sjb				dt_action_symmod_args(dtp, ap,
1282178479Sjb				    anp->dn_args, DTRACEACT_SYM);
1283178479Sjb				continue;
1284178479Sjb
1285178479Sjb			case DT_ACT_MOD:
1286178479Sjb				dt_action_symmod_args(dtp, ap,
1287178479Sjb				    anp->dn_args, DTRACEACT_MOD);
1288178479Sjb				continue;
1289178479Sjb
1290178479Sjb			default:
1291178479Sjb				break;
1292178479Sjb			}
1293178479Sjb		}
1294178479Sjb
1295178479Sjb		dt_cg(yypcb, anp);
1296178479Sjb		ap->dtad_difo = dt_as(yypcb);
1297178479Sjb		ap->dtad_kind = DTRACEACT_DIFEXPR;
1298178479Sjb	}
1299178479Sjb
1300178479Sjb	if (fid->di_id == DTRACEAGG_LQUANTIZE) {
1301178479Sjb		/*
1302178479Sjb		 * For linear quantization, we have between two and four
1303178479Sjb		 * arguments in addition to the expression:
1304178479Sjb		 *
1305178479Sjb		 *    arg1 => Base value
1306178479Sjb		 *    arg2 => Limit value
1307178479Sjb		 *    arg3 => Quantization level step size (defaults to 1)
1308178479Sjb		 *    arg4 => Quantization increment value (defaults to 1)
1309178479Sjb		 */
1310178479Sjb		dt_node_t *arg1 = dnp->dn_aggfun->dn_args->dn_list;
1311178479Sjb		dt_node_t *arg2 = arg1->dn_list;
1312178479Sjb		dt_node_t *arg3 = arg2->dn_list;
1313178479Sjb		dt_idsig_t *isp;
1314178479Sjb		uint64_t nlevels, step = 1, oarg;
1315178479Sjb		int64_t baseval, limitval;
1316178479Sjb
1317178479Sjb		if (arg1->dn_kind != DT_NODE_INT) {
1318178479Sjb			dnerror(arg1, D_LQUANT_BASETYPE, "lquantize( ) "
1319178479Sjb			    "argument #1 must be an integer constant\n");
1320178479Sjb		}
1321178479Sjb
1322178479Sjb		baseval = (int64_t)arg1->dn_value;
1323178479Sjb
1324178479Sjb		if (baseval < INT32_MIN || baseval > INT32_MAX) {
1325178479Sjb			dnerror(arg1, D_LQUANT_BASEVAL, "lquantize( ) "
1326178479Sjb			    "argument #1 must be a 32-bit quantity\n");
1327178479Sjb		}
1328178479Sjb
1329178479Sjb		if (arg2->dn_kind != DT_NODE_INT) {
1330178479Sjb			dnerror(arg2, D_LQUANT_LIMTYPE, "lquantize( ) "
1331178479Sjb			    "argument #2 must be an integer constant\n");
1332178479Sjb		}
1333178479Sjb
1334178479Sjb		limitval = (int64_t)arg2->dn_value;
1335178479Sjb
1336178479Sjb		if (limitval < INT32_MIN || limitval > INT32_MAX) {
1337178479Sjb			dnerror(arg2, D_LQUANT_LIMVAL, "lquantize( ) "
1338178479Sjb			    "argument #2 must be a 32-bit quantity\n");
1339178479Sjb		}
1340178479Sjb
1341178479Sjb		if (limitval < baseval) {
1342178479Sjb			dnerror(dnp, D_LQUANT_MISMATCH,
1343178479Sjb			    "lquantize( ) base (argument #1) must be less "
1344178479Sjb			    "than limit (argument #2)\n");
1345178479Sjb		}
1346178479Sjb
1347178479Sjb		if (arg3 != NULL) {
1348178479Sjb			if (!dt_node_is_posconst(arg3)) {
1349178479Sjb				dnerror(arg3, D_LQUANT_STEPTYPE, "lquantize( ) "
1350178479Sjb				    "argument #3 must be a non-zero positive "
1351178479Sjb				    "integer constant\n");
1352178479Sjb			}
1353178479Sjb
1354178479Sjb			if ((step = arg3->dn_value) > UINT16_MAX) {
1355178479Sjb				dnerror(arg3, D_LQUANT_STEPVAL, "lquantize( ) "
1356178479Sjb				    "argument #3 must be a 16-bit quantity\n");
1357178479Sjb			}
1358178479Sjb		}
1359178479Sjb
1360178479Sjb		nlevels = (limitval - baseval) / step;
1361178479Sjb
1362178479Sjb		if (nlevels == 0) {
1363178479Sjb			dnerror(dnp, D_LQUANT_STEPLARGE,
1364178479Sjb			    "lquantize( ) step (argument #3) too large: must "
1365178479Sjb			    "have at least one quantization level\n");
1366178479Sjb		}
1367178479Sjb
1368178479Sjb		if (nlevels > UINT16_MAX) {
1369178479Sjb			dnerror(dnp, D_LQUANT_STEPSMALL, "lquantize( ) step "
1370178479Sjb			    "(argument #3) too small: number of quantization "
1371178479Sjb			    "levels must be a 16-bit quantity\n");
1372178479Sjb		}
1373178479Sjb
1374178479Sjb		arg = (step << DTRACE_LQUANTIZE_STEPSHIFT) |
1375178479Sjb		    (nlevels << DTRACE_LQUANTIZE_LEVELSHIFT) |
1376178479Sjb		    ((baseval << DTRACE_LQUANTIZE_BASESHIFT) &
1377178479Sjb		    DTRACE_LQUANTIZE_BASEMASK);
1378178479Sjb
1379178479Sjb		assert(arg != 0);
1380178479Sjb
1381178479Sjb		isp = (dt_idsig_t *)aid->di_data;
1382178479Sjb
1383178479Sjb		if (isp->dis_auxinfo == 0) {
1384178479Sjb			/*
1385178479Sjb			 * This is the first time we've seen an lquantize()
1386178479Sjb			 * for this aggregation; we'll store our argument
1387178479Sjb			 * as the auxiliary signature information.
1388178479Sjb			 */
1389178479Sjb			isp->dis_auxinfo = arg;
1390178479Sjb		} else if ((oarg = isp->dis_auxinfo) != arg) {
1391178479Sjb			/*
1392178479Sjb			 * If we have seen this lquantize() before and the
1393178479Sjb			 * argument doesn't match the original argument, pick
1394178479Sjb			 * the original argument apart to concisely report the
1395178479Sjb			 * mismatch.
1396178479Sjb			 */
1397178479Sjb			int obaseval = DTRACE_LQUANTIZE_BASE(oarg);
1398178479Sjb			int onlevels = DTRACE_LQUANTIZE_LEVELS(oarg);
1399178479Sjb			int ostep = DTRACE_LQUANTIZE_STEP(oarg);
1400178479Sjb
1401178479Sjb			if (obaseval != baseval) {
1402178479Sjb				dnerror(dnp, D_LQUANT_MATCHBASE, "lquantize( ) "
1403178479Sjb				    "base (argument #1) doesn't match previous "
1404178479Sjb				    "declaration: expected %d, found %d\n",
1405178479Sjb				    obaseval, (int)baseval);
1406178479Sjb			}
1407178479Sjb
1408178479Sjb			if (onlevels * ostep != nlevels * step) {
1409178479Sjb				dnerror(dnp, D_LQUANT_MATCHLIM, "lquantize( ) "
1410178479Sjb				    "limit (argument #2) doesn't match previous"
1411178479Sjb				    " declaration: expected %d, found %d\n",
1412178479Sjb				    obaseval + onlevels * ostep,
1413178479Sjb				    (int)baseval + (int)nlevels * (int)step);
1414178479Sjb			}
1415178479Sjb
1416178479Sjb			if (ostep != step) {
1417178479Sjb				dnerror(dnp, D_LQUANT_MATCHSTEP, "lquantize( ) "
1418178479Sjb				    "step (argument #3) doesn't match previous "
1419178479Sjb				    "declaration: expected %d, found %d\n",
1420178479Sjb				    ostep, (int)step);
1421178479Sjb			}
1422178479Sjb
1423178479Sjb			/*
1424178479Sjb			 * We shouldn't be able to get here -- one of the
1425178479Sjb			 * parameters must be mismatched if the arguments
1426178479Sjb			 * didn't match.
1427178479Sjb			 */
1428178479Sjb			assert(0);
1429178479Sjb		}
1430178479Sjb
1431178479Sjb		incr = arg3 != NULL ? arg3->dn_list : NULL;
1432178479Sjb		argmax = 5;
1433178479Sjb	}
1434178479Sjb
1435237624Spfg	if (fid->di_id == DTRACEAGG_LLQUANTIZE) {
1436237624Spfg		/*
1437237624Spfg		 * For log/linear quantizations, we have between one and five
1438237624Spfg		 * arguments in addition to the expression:
1439237624Spfg		 *
1440237624Spfg		 *    arg1 => Factor
1441237624Spfg		 *    arg2 => Low magnitude
1442237624Spfg		 *    arg3 => High magnitude
1443237624Spfg		 *    arg4 => Number of steps per magnitude
1444237624Spfg		 *    arg5 => Quantization increment value (defaults to 1)
1445237624Spfg		 */
1446237624Spfg		dt_node_t *llarg = dnp->dn_aggfun->dn_args->dn_list;
1447237624Spfg		uint64_t oarg, order, v;
1448237624Spfg		dt_idsig_t *isp;
1449237624Spfg		int i;
1450237624Spfg
1451237624Spfg		struct {
1452237624Spfg			char *str;		/* string identifier */
1453237624Spfg			int badtype;		/* error on bad type */
1454237624Spfg			int badval;		/* error on bad value */
1455237624Spfg			int mismatch;		/* error on bad match */
1456237624Spfg			int shift;		/* shift value */
1457237624Spfg			uint16_t value;		/* value itself */
1458237624Spfg		} args[] = {
1459237624Spfg			{ "factor", D_LLQUANT_FACTORTYPE,
1460237624Spfg			    D_LLQUANT_FACTORVAL, D_LLQUANT_FACTORMATCH,
1461237624Spfg			    DTRACE_LLQUANTIZE_FACTORSHIFT },
1462237624Spfg			{ "low magnitude", D_LLQUANT_LOWTYPE,
1463237624Spfg			    D_LLQUANT_LOWVAL, D_LLQUANT_LOWMATCH,
1464237624Spfg			    DTRACE_LLQUANTIZE_LOWSHIFT },
1465237624Spfg			{ "high magnitude", D_LLQUANT_HIGHTYPE,
1466237624Spfg			    D_LLQUANT_HIGHVAL, D_LLQUANT_HIGHMATCH,
1467237624Spfg			    DTRACE_LLQUANTIZE_HIGHSHIFT },
1468237624Spfg			{ "linear steps per magnitude", D_LLQUANT_NSTEPTYPE,
1469237624Spfg			    D_LLQUANT_NSTEPVAL, D_LLQUANT_NSTEPMATCH,
1470237624Spfg			    DTRACE_LLQUANTIZE_NSTEPSHIFT },
1471237624Spfg			{ NULL }
1472237624Spfg		};
1473237624Spfg
1474237624Spfg		assert(arg == 0);
1475237624Spfg
1476237624Spfg		for (i = 0; args[i].str != NULL; i++) {
1477237624Spfg			if (llarg->dn_kind != DT_NODE_INT) {
1478237624Spfg				dnerror(llarg, args[i].badtype, "llquantize( ) "
1479237624Spfg				    "argument #%d (%s) must be an "
1480237624Spfg				    "integer constant\n", i + 1, args[i].str);
1481237624Spfg			}
1482237624Spfg
1483237624Spfg			if ((uint64_t)llarg->dn_value > UINT16_MAX) {
1484237624Spfg				dnerror(llarg, args[i].badval, "llquantize( ) "
1485237624Spfg				    "argument #%d (%s) must be an unsigned "
1486237624Spfg				    "16-bit quantity\n", i + 1, args[i].str);
1487237624Spfg			}
1488237624Spfg
1489237624Spfg			args[i].value = (uint16_t)llarg->dn_value;
1490237624Spfg
1491237624Spfg			assert(!(arg & ((uint64_t)UINT16_MAX <<
1492237624Spfg			    args[i].shift)));
1493237624Spfg			arg |= ((uint64_t)args[i].value << args[i].shift);
1494237624Spfg			llarg = llarg->dn_list;
1495237624Spfg		}
1496237624Spfg
1497237624Spfg		assert(arg != 0);
1498237624Spfg
1499237624Spfg		if (args[0].value < 2) {
1500237624Spfg			dnerror(dnp, D_LLQUANT_FACTORSMALL, "llquantize( ) "
1501237624Spfg			    "factor (argument #1) must be two or more\n");
1502237624Spfg		}
1503237624Spfg
1504237624Spfg		if (args[1].value >= args[2].value) {
1505237624Spfg			dnerror(dnp, D_LLQUANT_MAGRANGE, "llquantize( ) "
1506237624Spfg			    "high magnitude (argument #3) must be greater "
1507237624Spfg			    "than low magnitude (argument #2)\n");
1508237624Spfg		}
1509237624Spfg
1510237624Spfg		if (args[3].value < args[0].value) {
1511237624Spfg			dnerror(dnp, D_LLQUANT_FACTORNSTEPS, "llquantize( ) "
1512237624Spfg			    "factor (argument #1) must be less than or "
1513237624Spfg			    "equal to the number of linear steps per "
1514237624Spfg			    "magnitude (argument #4)\n");
1515237624Spfg		}
1516237624Spfg
1517237624Spfg		for (v = args[0].value; v < args[3].value; v *= args[0].value)
1518237624Spfg			continue;
1519237624Spfg
1520237624Spfg		if ((args[3].value % args[0].value) || (v % args[3].value)) {
1521237624Spfg			dnerror(dnp, D_LLQUANT_FACTOREVEN, "llquantize( ) "
1522237624Spfg			    "factor (argument #1) must evenly divide the "
1523237624Spfg			    "number of steps per magnitude (argument #4), "
1524237624Spfg			    "and the number of steps per magnitude must evenly "
1525237624Spfg			    "divide a power of the factor\n");
1526237624Spfg		}
1527237624Spfg
1528237624Spfg		for (i = 0, order = 1; i < args[2].value; i++) {
1529237624Spfg			if (order * args[0].value > order) {
1530237624Spfg				order *= args[0].value;
1531237624Spfg				continue;
1532237624Spfg			}
1533237624Spfg
1534237624Spfg			dnerror(dnp, D_LLQUANT_MAGTOOBIG, "llquantize( ) "
1535237624Spfg			    "factor (%d) raised to power of high magnitude "
1536237624Spfg			    "(%d) overflows 64-bits\n", args[0].value,
1537237624Spfg			    args[2].value);
1538237624Spfg		}
1539237624Spfg
1540237624Spfg		isp = (dt_idsig_t *)aid->di_data;
1541237624Spfg
1542237624Spfg		if (isp->dis_auxinfo == 0) {
1543237624Spfg			/*
1544237624Spfg			 * This is the first time we've seen an llquantize()
1545237624Spfg			 * for this aggregation; we'll store our argument
1546237624Spfg			 * as the auxiliary signature information.
1547237624Spfg			 */
1548237624Spfg			isp->dis_auxinfo = arg;
1549237624Spfg		} else if ((oarg = isp->dis_auxinfo) != arg) {
1550237624Spfg			/*
1551237624Spfg			 * If we have seen this llquantize() before and the
1552237624Spfg			 * argument doesn't match the original argument, pick
1553237624Spfg			 * the original argument apart to concisely report the
1554237624Spfg			 * mismatch.
1555237624Spfg			 */
1556237624Spfg			int expected = 0, found = 0;
1557237624Spfg
1558237624Spfg			for (i = 0; expected == found; i++) {
1559237624Spfg				assert(args[i].str != NULL);
1560237624Spfg
1561237624Spfg				expected = (oarg >> args[i].shift) & UINT16_MAX;
1562237624Spfg				found = (arg >> args[i].shift) & UINT16_MAX;
1563237624Spfg			}
1564237624Spfg
1565237624Spfg			dnerror(dnp, args[i - 1].mismatch, "llquantize( ) "
1566237624Spfg			    "%s (argument #%d) doesn't match previous "
1567237624Spfg			    "declaration: expected %d, found %d\n",
1568237624Spfg			    args[i - 1].str, i, expected, found);
1569237624Spfg		}
1570237624Spfg
1571237624Spfg		incr = llarg;
1572237624Spfg		argmax = 6;
1573237624Spfg	}
1574237624Spfg
1575178479Sjb	if (fid->di_id == DTRACEAGG_QUANTIZE) {
1576178479Sjb		incr = dnp->dn_aggfun->dn_args->dn_list;
1577178479Sjb		argmax = 2;
1578178479Sjb	}
1579178479Sjb
1580178479Sjb	if (incr != NULL) {
1581178479Sjb		if (!dt_node_is_scalar(incr)) {
1582178479Sjb			dnerror(dnp, D_PROTO_ARG, "%s( ) increment value "
1583178479Sjb			    "(argument #%d) must be of scalar type\n",
1584178479Sjb			    fid->di_name, argmax);
1585178479Sjb		}
1586178479Sjb
1587178479Sjb		if ((anp = incr->dn_list) != NULL) {
1588178479Sjb			int argc = argmax;
1589178479Sjb
1590178479Sjb			for (; anp != NULL; anp = anp->dn_list)
1591178479Sjb				argc++;
1592178479Sjb
1593178479Sjb			dnerror(incr, D_PROTO_LEN, "%s( ) prototype "
1594178479Sjb			    "mismatch: %d args passed, at most %d expected",
1595178479Sjb			    fid->di_name, argc, argmax);
1596178479Sjb		}
1597178479Sjb
1598178479Sjb		ap = dt_stmt_action(dtp, sdp);
1599178479Sjb		n++;
1600178479Sjb
1601178479Sjb		dt_cg(yypcb, incr);
1602178479Sjb		ap->dtad_difo = dt_as(yypcb);
1603178479Sjb		ap->dtad_difo->dtdo_rtype = dt_void_rtype;
1604178479Sjb		ap->dtad_kind = DTRACEACT_DIFEXPR;
1605178479Sjb	}
1606178479Sjb
1607178479Sjb	assert(sdp->dtsd_aggdata == NULL);
1608178479Sjb	sdp->dtsd_aggdata = aid;
1609178479Sjb
1610178479Sjb	ap = dt_stmt_action(dtp, sdp);
1611178479Sjb	assert(fid->di_kind == DT_IDENT_AGGFUNC);
1612178479Sjb	assert(DTRACEACT_ISAGG(fid->di_id));
1613178479Sjb	ap->dtad_kind = fid->di_id;
1614178479Sjb	ap->dtad_ntuple = n;
1615178479Sjb	ap->dtad_arg = arg;
1616178479Sjb
1617178479Sjb	if (dnp->dn_aggfun->dn_args != NULL) {
1618178479Sjb		dt_cg(yypcb, dnp->dn_aggfun->dn_args);
1619178479Sjb		ap->dtad_difo = dt_as(yypcb);
1620178479Sjb	}
1621178479Sjb}
1622178479Sjb
1623178479Sjbstatic void
1624178479Sjbdt_compile_one_clause(dtrace_hdl_t *dtp, dt_node_t *cnp, dt_node_t *pnp)
1625178479Sjb{
1626178479Sjb	dtrace_ecbdesc_t *edp;
1627178479Sjb	dtrace_stmtdesc_t *sdp;
1628178479Sjb	dt_node_t *dnp;
1629178479Sjb
1630178479Sjb	yylineno = pnp->dn_line;
1631178479Sjb	dt_setcontext(dtp, pnp->dn_desc);
1632178479Sjb	(void) dt_node_cook(cnp, DT_IDFLG_REF);
1633178479Sjb
1634178479Sjb	if (DT_TREEDUMP_PASS(dtp, 2))
1635178479Sjb		dt_node_printr(cnp, stderr, 0);
1636178479Sjb
1637178479Sjb	if ((edp = dt_ecbdesc_create(dtp, pnp->dn_desc)) == NULL)
1638178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
1639178479Sjb
1640178479Sjb	assert(yypcb->pcb_ecbdesc == NULL);
1641178479Sjb	yypcb->pcb_ecbdesc = edp;
1642178479Sjb
1643178479Sjb	if (cnp->dn_pred != NULL) {
1644178479Sjb		dt_cg(yypcb, cnp->dn_pred);
1645178479Sjb		edp->dted_pred.dtpdd_difo = dt_as(yypcb);
1646178479Sjb	}
1647178479Sjb
1648178479Sjb	if (cnp->dn_acts == NULL) {
1649178479Sjb		dt_stmt_append(dt_stmt_create(dtp, edp,
1650178479Sjb		    cnp->dn_ctxattr, _dtrace_defattr), cnp);
1651178479Sjb	}
1652178479Sjb
1653178479Sjb	for (dnp = cnp->dn_acts; dnp != NULL; dnp = dnp->dn_list) {
1654178479Sjb		assert(yypcb->pcb_stmt == NULL);
1655178479Sjb		sdp = dt_stmt_create(dtp, edp, cnp->dn_ctxattr, cnp->dn_attr);
1656178479Sjb
1657178479Sjb		switch (dnp->dn_kind) {
1658178479Sjb		case DT_NODE_DEXPR:
1659178479Sjb			if (dnp->dn_expr->dn_kind == DT_NODE_AGG)
1660178479Sjb				dt_compile_agg(dtp, dnp->dn_expr, sdp);
1661178479Sjb			else
1662178479Sjb				dt_compile_exp(dtp, dnp, sdp);
1663178479Sjb			break;
1664178479Sjb		case DT_NODE_DFUNC:
1665178479Sjb			dt_compile_fun(dtp, dnp, sdp);
1666178479Sjb			break;
1667178479Sjb		case DT_NODE_AGG:
1668178479Sjb			dt_compile_agg(dtp, dnp, sdp);
1669178479Sjb			break;
1670178479Sjb		default:
1671178479Sjb			dnerror(dnp, D_UNKNOWN, "internal error -- node kind "
1672178479Sjb			    "%u is not a valid statement\n", dnp->dn_kind);
1673178479Sjb		}
1674178479Sjb
1675178479Sjb		assert(yypcb->pcb_stmt == sdp);
1676178479Sjb		dt_stmt_append(sdp, dnp);
1677178479Sjb	}
1678178479Sjb
1679178479Sjb	assert(yypcb->pcb_ecbdesc == edp);
1680178479Sjb	dt_ecbdesc_release(dtp, edp);
1681178479Sjb	dt_endcontext(dtp);
1682178479Sjb	yypcb->pcb_ecbdesc = NULL;
1683178479Sjb}
1684178479Sjb
1685178479Sjbstatic void
1686178479Sjbdt_compile_clause(dtrace_hdl_t *dtp, dt_node_t *cnp)
1687178479Sjb{
1688178479Sjb	dt_node_t *pnp;
1689178479Sjb
1690178479Sjb	for (pnp = cnp->dn_pdescs; pnp != NULL; pnp = pnp->dn_list)
1691178479Sjb		dt_compile_one_clause(dtp, cnp, pnp);
1692178479Sjb}
1693178479Sjb
1694178479Sjbstatic void
1695178479Sjbdt_compile_xlator(dt_node_t *dnp)
1696178479Sjb{
1697178479Sjb	dt_xlator_t *dxp = dnp->dn_xlator;
1698178479Sjb	dt_node_t *mnp;
1699178479Sjb
1700178479Sjb	for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) {
1701178479Sjb		assert(dxp->dx_membdif[mnp->dn_membid] == NULL);
1702178479Sjb		dt_cg(yypcb, mnp);
1703178479Sjb		dxp->dx_membdif[mnp->dn_membid] = dt_as(yypcb);
1704178479Sjb	}
1705178479Sjb}
1706178479Sjb
1707178479Sjbvoid
1708178479Sjbdt_setcontext(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
1709178479Sjb{
1710178479Sjb	const dtrace_pattr_t *pap;
1711178479Sjb	dt_probe_t *prp;
1712178479Sjb	dt_provider_t *pvp;
1713178479Sjb	dt_ident_t *idp;
1714178479Sjb	char attrstr[8];
1715178479Sjb	int err;
1716178479Sjb
1717178479Sjb	/*
1718178479Sjb	 * Both kernel and pid based providers are allowed to have names
1719178479Sjb	 * ending with what could be interpreted as a number. We assume it's
1720178479Sjb	 * a pid and that we may need to dynamically create probes for
1721178479Sjb	 * that process if:
1722178479Sjb	 *
1723178479Sjb	 * (1) The provider doesn't exist, or,
1724178479Sjb	 * (2) The provider exists and has DTRACE_PRIV_PROC privilege.
1725178479Sjb	 *
1726178479Sjb	 * On an error, dt_pid_create_probes() will set the error message
1727178479Sjb	 * and tag -- we just have to longjmp() out of here.
1728178479Sjb	 */
1729178479Sjb	if (isdigit(pdp->dtpd_provider[strlen(pdp->dtpd_provider) - 1]) &&
1730178479Sjb	    ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) == NULL ||
1731178479Sjb	    pvp->pv_desc.dtvd_priv.dtpp_flags & DTRACE_PRIV_PROC) &&
1732178479Sjb	    dt_pid_create_probes(pdp, dtp, yypcb) != 0) {
1733178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
1734178479Sjb	}
1735178479Sjb
1736178479Sjb	/*
1737178479Sjb	 * Call dt_probe_info() to get the probe arguments and attributes.  If
1738178479Sjb	 * a representative probe is found, set 'pap' to the probe provider's
1739178479Sjb	 * attributes.  Otherwise set 'pap' to default Unstable attributes.
1740178479Sjb	 */
1741178479Sjb	if ((prp = dt_probe_info(dtp, pdp, &yypcb->pcb_pinfo)) == NULL) {
1742178479Sjb		pap = &_dtrace_prvdesc;
1743178479Sjb		err = dtrace_errno(dtp);
1744178479Sjb		bzero(&yypcb->pcb_pinfo, sizeof (dtrace_probeinfo_t));
1745178479Sjb		yypcb->pcb_pinfo.dtp_attr = pap->dtpa_provider;
1746178479Sjb		yypcb->pcb_pinfo.dtp_arga = pap->dtpa_args;
1747178479Sjb	} else {
1748178479Sjb		pap = &prp->pr_pvp->pv_desc.dtvd_attr;
1749178479Sjb		err = 0;
1750178479Sjb	}
1751178479Sjb
1752178479Sjb	if (err == EDT_NOPROBE && !(yypcb->pcb_cflags & DTRACE_C_ZDEFS)) {
1753178479Sjb		xyerror(D_PDESC_ZERO, "probe description %s:%s:%s:%s does not "
1754178479Sjb		    "match any probes\n", pdp->dtpd_provider, pdp->dtpd_mod,
1755178479Sjb		    pdp->dtpd_func, pdp->dtpd_name);
1756178479Sjb	}
1757178479Sjb
1758178479Sjb	if (err != EDT_NOPROBE && err != EDT_UNSTABLE && err != 0)
1759178479Sjb		xyerror(D_PDESC_INVAL, "%s\n", dtrace_errmsg(dtp, err));
1760178479Sjb
1761178479Sjb	dt_dprintf("set context to %s:%s:%s:%s [%u] prp=%p attr=%s argc=%d\n",
1762178479Sjb	    pdp->dtpd_provider, pdp->dtpd_mod, pdp->dtpd_func, pdp->dtpd_name,
1763178479Sjb	    pdp->dtpd_id, (void *)prp, dt_attr_str(yypcb->pcb_pinfo.dtp_attr,
1764178479Sjb	    attrstr, sizeof (attrstr)), yypcb->pcb_pinfo.dtp_argc);
1765178479Sjb
1766178479Sjb	/*
1767178479Sjb	 * Reset the stability attributes of D global variables that vary
1768178479Sjb	 * based on the attributes of the provider and context itself.
1769178479Sjb	 */
1770178479Sjb	if ((idp = dt_idhash_lookup(dtp->dt_globals, "probeprov")) != NULL)
1771178479Sjb		idp->di_attr = pap->dtpa_provider;
1772178479Sjb	if ((idp = dt_idhash_lookup(dtp->dt_globals, "probemod")) != NULL)
1773178479Sjb		idp->di_attr = pap->dtpa_mod;
1774178479Sjb	if ((idp = dt_idhash_lookup(dtp->dt_globals, "probefunc")) != NULL)
1775178479Sjb		idp->di_attr = pap->dtpa_func;
1776178479Sjb	if ((idp = dt_idhash_lookup(dtp->dt_globals, "probename")) != NULL)
1777178479Sjb		idp->di_attr = pap->dtpa_name;
1778178479Sjb	if ((idp = dt_idhash_lookup(dtp->dt_globals, "args")) != NULL)
1779178479Sjb		idp->di_attr = pap->dtpa_args;
1780178479Sjb
1781178479Sjb	yypcb->pcb_pdesc = pdp;
1782178479Sjb	yypcb->pcb_probe = prp;
1783178479Sjb}
1784178479Sjb
1785178479Sjb/*
1786178479Sjb * Reset context-dependent variables and state at the end of cooking a D probe
1787178479Sjb * definition clause.  This ensures that external declarations between clauses
1788178479Sjb * do not reference any stale context-dependent data from the previous clause.
1789178479Sjb */
1790178479Sjbvoid
1791178479Sjbdt_endcontext(dtrace_hdl_t *dtp)
1792178479Sjb{
1793178479Sjb	static const char *const cvars[] = {
1794178479Sjb		"probeprov", "probemod", "probefunc", "probename", "args", NULL
1795178479Sjb	};
1796178479Sjb
1797178479Sjb	dt_ident_t *idp;
1798178479Sjb	int i;
1799178479Sjb
1800178479Sjb	for (i = 0; cvars[i] != NULL; i++) {
1801178479Sjb		if ((idp = dt_idhash_lookup(dtp->dt_globals, cvars[i])) != NULL)
1802178479Sjb			idp->di_attr = _dtrace_defattr;
1803178479Sjb	}
1804178479Sjb
1805178479Sjb	yypcb->pcb_pdesc = NULL;
1806178479Sjb	yypcb->pcb_probe = NULL;
1807178479Sjb}
1808178479Sjb
1809178479Sjbstatic int
1810178479Sjbdt_reduceid(dt_idhash_t *dhp, dt_ident_t *idp, dtrace_hdl_t *dtp)
1811178479Sjb{
1812178479Sjb	if (idp->di_vers != 0 && idp->di_vers > dtp->dt_vmax)
1813178479Sjb		dt_idhash_delete(dhp, idp);
1814178479Sjb
1815178479Sjb	return (0);
1816178479Sjb}
1817178479Sjb
1818178479Sjb/*
1819178479Sjb * When dtrace_setopt() is called for "version", it calls dt_reduce() to remove
1820178479Sjb * any identifiers or translators that have been previously defined as bound to
1821178479Sjb * a version greater than the specified version.  Therefore, in our current
1822178479Sjb * version implementation, establishing a binding is a one-way transformation.
1823178479Sjb * In addition, no versioning is currently provided for types as our .d library
1824178479Sjb * files do not define any types and we reserve prefixes DTRACE_ and dtrace_
1825178479Sjb * for our exclusive use.  If required, type versioning will require more work.
1826178479Sjb */
1827178479Sjbint
1828178479Sjbdt_reduce(dtrace_hdl_t *dtp, dt_version_t v)
1829178479Sjb{
1830178479Sjb	char s[DT_VERSION_STRMAX];
1831178479Sjb	dt_xlator_t *dxp, *nxp;
1832178479Sjb
1833178479Sjb	if (v > dtp->dt_vmax)
1834178479Sjb		return (dt_set_errno(dtp, EDT_VERSREDUCED));
1835178479Sjb	else if (v == dtp->dt_vmax)
1836178479Sjb		return (0); /* no reduction necessary */
1837178479Sjb
1838178479Sjb	dt_dprintf("reducing api version to %s\n",
1839178479Sjb	    dt_version_num2str(v, s, sizeof (s)));
1840178479Sjb
1841178479Sjb	dtp->dt_vmax = v;
1842178479Sjb
1843178479Sjb	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL; dxp = nxp) {
1844178479Sjb		nxp = dt_list_next(dxp);
1845178479Sjb		if ((dxp->dx_souid.di_vers != 0 && dxp->dx_souid.di_vers > v) ||
1846178479Sjb		    (dxp->dx_ptrid.di_vers != 0 && dxp->dx_ptrid.di_vers > v))
1847178479Sjb			dt_list_delete(&dtp->dt_xlators, dxp);
1848178479Sjb	}
1849178479Sjb
1850178479Sjb	(void) dt_idhash_iter(dtp->dt_macros, (dt_idhash_f *)dt_reduceid, dtp);
1851178479Sjb	(void) dt_idhash_iter(dtp->dt_aggs, (dt_idhash_f *)dt_reduceid, dtp);
1852178479Sjb	(void) dt_idhash_iter(dtp->dt_globals, (dt_idhash_f *)dt_reduceid, dtp);
1853178479Sjb	(void) dt_idhash_iter(dtp->dt_tls, (dt_idhash_f *)dt_reduceid, dtp);
1854178479Sjb
1855178479Sjb	return (0);
1856178479Sjb}
1857178479Sjb
1858178479Sjb/*
1859178479Sjb * Fork and exec the cpp(1) preprocessor to run over the specified input file,
1860178479Sjb * and return a FILE handle for the cpp output.  We use the /dev/fd filesystem
1861178479Sjb * here to simplify the code by leveraging file descriptor inheritance.
1862178479Sjb */
1863178479Sjbstatic FILE *
1864178479Sjbdt_preproc(dtrace_hdl_t *dtp, FILE *ifp)
1865178479Sjb{
1866178479Sjb	int argc = dtp->dt_cpp_argc;
1867178479Sjb	char **argv = malloc(sizeof (char *) * (argc + 5));
1868178479Sjb	FILE *ofp = tmpfile();
1869178479Sjb
1870178576Sjb#if defined(sun)
1871178479Sjb	char ipath[20], opath[20]; /* big enough for /dev/fd/ + INT_MAX + \0 */
1872178576Sjb#endif
1873178479Sjb	char verdef[32]; /* big enough for -D__SUNW_D_VERSION=0x%08x + \0 */
1874178479Sjb
1875178479Sjb	struct sigaction act, oact;
1876178479Sjb	sigset_t mask, omask;
1877178479Sjb
1878178479Sjb	int wstat, estat;
1879178479Sjb	pid_t pid;
1880178576Sjb#if defined(sun)
1881178479Sjb	off64_t off;
1882178576Sjb#else
1883178576Sjb	off_t off = 0;
1884178576Sjb#endif
1885178479Sjb	int c;
1886178479Sjb
1887178479Sjb	if (argv == NULL || ofp == NULL) {
1888178479Sjb		(void) dt_set_errno(dtp, errno);
1889178479Sjb		goto err;
1890178479Sjb	}
1891178479Sjb
1892178479Sjb	/*
1893178479Sjb	 * If the input is a seekable file, see if it is an interpreter file.
1894178479Sjb	 * If we see #!, seek past the first line because cpp will choke on it.
1895178479Sjb	 * We start cpp just prior to the \n at the end of this line so that
1896178479Sjb	 * it still sees the newline, ensuring that #line values are correct.
1897178479Sjb	 */
1898178479Sjb	if (isatty(fileno(ifp)) == 0 && (off = ftello64(ifp)) != -1) {
1899178479Sjb		if ((c = fgetc(ifp)) == '#' && (c = fgetc(ifp)) == '!') {
1900178479Sjb			for (off += 2; c != '\n'; off++) {
1901178479Sjb				if ((c = fgetc(ifp)) == EOF)
1902178479Sjb					break;
1903178479Sjb			}
1904178479Sjb			if (c == '\n')
1905178479Sjb				off--; /* start cpp just prior to \n */
1906178479Sjb		}
1907178479Sjb		(void) fflush(ifp);
1908178479Sjb		(void) fseeko64(ifp, off, SEEK_SET);
1909178479Sjb	}
1910178479Sjb
1911178576Sjb#if defined(sun)
1912178479Sjb	(void) snprintf(ipath, sizeof (ipath), "/dev/fd/%d", fileno(ifp));
1913178479Sjb	(void) snprintf(opath, sizeof (opath), "/dev/fd/%d", fileno(ofp));
1914178576Sjb#endif
1915178479Sjb
1916178479Sjb	bcopy(dtp->dt_cpp_argv, argv, sizeof (char *) * argc);
1917178479Sjb
1918178479Sjb	(void) snprintf(verdef, sizeof (verdef),
1919178479Sjb	    "-D__SUNW_D_VERSION=0x%08x", dtp->dt_vmax);
1920178479Sjb	argv[argc++] = verdef;
1921178479Sjb
1922178576Sjb#if defined(sun)
1923178479Sjb	switch (dtp->dt_stdcmode) {
1924178479Sjb	case DT_STDC_XA:
1925178479Sjb	case DT_STDC_XT:
1926178479Sjb		argv[argc++] = "-D__STDC__=0";
1927178479Sjb		break;
1928178479Sjb	case DT_STDC_XC:
1929178479Sjb		argv[argc++] = "-D__STDC__=1";
1930178479Sjb		break;
1931178479Sjb	}
1932178479Sjb
1933178479Sjb	argv[argc++] = ipath;
1934178479Sjb	argv[argc++] = opath;
1935178576Sjb#else
1936178576Sjb	argv[argc++] = "-P";
1937178576Sjb#endif
1938178479Sjb	argv[argc] = NULL;
1939178479Sjb
1940178479Sjb	/*
1941178479Sjb	 * libdtrace must be able to be embedded in other programs that may
1942178479Sjb	 * include application-specific signal handlers.  Therefore, if we
1943178479Sjb	 * need to fork to run cpp(1), we must avoid generating a SIGCHLD
1944178479Sjb	 * that could confuse the containing application.  To do this,
1945178479Sjb	 * we block SIGCHLD and reset its disposition to SIG_DFL.
1946178479Sjb	 * We restore our signal state once we are done.
1947178479Sjb	 */
1948178479Sjb	(void) sigemptyset(&mask);
1949178479Sjb	(void) sigaddset(&mask, SIGCHLD);
1950178479Sjb	(void) sigprocmask(SIG_BLOCK, &mask, &omask);
1951178479Sjb
1952178479Sjb	bzero(&act, sizeof (act));
1953178479Sjb	act.sa_handler = SIG_DFL;
1954178479Sjb	(void) sigaction(SIGCHLD, &act, &oact);
1955178479Sjb
1956178479Sjb	if ((pid = fork1()) == -1) {
1957178479Sjb		(void) sigaction(SIGCHLD, &oact, NULL);
1958178479Sjb		(void) sigprocmask(SIG_SETMASK, &omask, NULL);
1959178479Sjb		(void) dt_set_errno(dtp, EDT_CPPFORK);
1960178479Sjb		goto err;
1961178479Sjb	}
1962178479Sjb
1963178479Sjb	if (pid == 0) {
1964178576Sjb#if !defined(sun)
1965178576Sjb		if (isatty(fileno(ifp)) == 0)
1966178576Sjb			lseek(fileno(ifp), off, SEEK_SET);
1967178576Sjb		dup2(fileno(ifp), 0);
1968178576Sjb		dup2(fileno(ofp), 1);
1969178576Sjb#endif
1970178479Sjb		(void) execvp(dtp->dt_cpp_path, argv);
1971178479Sjb		_exit(errno == ENOENT ? 127 : 126);
1972178479Sjb	}
1973178479Sjb
1974178479Sjb	do {
1975178479Sjb		dt_dprintf("waiting for %s (PID %d)\n", dtp->dt_cpp_path,
1976178479Sjb		    (int)pid);
1977178479Sjb	} while (waitpid(pid, &wstat, 0) == -1 && errno == EINTR);
1978178479Sjb
1979178479Sjb	(void) sigaction(SIGCHLD, &oact, NULL);
1980178479Sjb	(void) sigprocmask(SIG_SETMASK, &omask, NULL);
1981178479Sjb
1982178479Sjb	dt_dprintf("%s returned exit status 0x%x\n", dtp->dt_cpp_path, wstat);
1983178479Sjb	estat = WIFEXITED(wstat) ? WEXITSTATUS(wstat) : -1;
1984178479Sjb
1985178479Sjb	if (estat != 0) {
1986178479Sjb		switch (estat) {
1987178479Sjb		case 126:
1988178479Sjb			(void) dt_set_errno(dtp, EDT_CPPEXEC);
1989178479Sjb			break;
1990178479Sjb		case 127:
1991178479Sjb			(void) dt_set_errno(dtp, EDT_CPPENT);
1992178479Sjb			break;
1993178479Sjb		default:
1994178479Sjb			(void) dt_set_errno(dtp, EDT_CPPERR);
1995178479Sjb		}
1996178479Sjb		goto err;
1997178479Sjb	}
1998178479Sjb
1999178479Sjb	free(argv);
2000178479Sjb	(void) fflush(ofp);
2001178479Sjb	(void) fseek(ofp, 0, SEEK_SET);
2002178479Sjb	return (ofp);
2003178479Sjb
2004178479Sjberr:
2005178479Sjb	free(argv);
2006178479Sjb	(void) fclose(ofp);
2007178479Sjb	return (NULL);
2008178479Sjb}
2009178479Sjb
2010178479Sjbstatic void
2011178479Sjbdt_lib_depend_error(dtrace_hdl_t *dtp, const char *format, ...)
2012178479Sjb{
2013178479Sjb	va_list ap;
2014178479Sjb
2015178479Sjb	va_start(ap, format);
2016178479Sjb	dt_set_errmsg(dtp, NULL, NULL, NULL, 0, format, ap);
2017178479Sjb	va_end(ap);
2018178479Sjb}
2019178479Sjb
2020178479Sjbint
2021178479Sjbdt_lib_depend_add(dtrace_hdl_t *dtp, dt_list_t *dlp, const char *arg)
2022178479Sjb{
2023178479Sjb	dt_lib_depend_t *dld;
2024178479Sjb	const char *end;
2025178479Sjb
2026178479Sjb	assert(arg != NULL);
2027178479Sjb
2028178479Sjb	if ((end = strrchr(arg, '/')) == NULL)
2029178479Sjb		return (dt_set_errno(dtp, EINVAL));
2030178479Sjb
2031178479Sjb	if ((dld = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
2032178479Sjb		return (-1);
2033178479Sjb
2034178479Sjb	if ((dld->dtld_libpath = dt_alloc(dtp, MAXPATHLEN)) == NULL) {
2035178479Sjb		dt_free(dtp, dld);
2036178479Sjb		return (-1);
2037178479Sjb	}
2038178479Sjb
2039178479Sjb	(void) strlcpy(dld->dtld_libpath, arg, end - arg + 2);
2040178479Sjb	if ((dld->dtld_library = strdup(arg)) == NULL) {
2041178479Sjb		dt_free(dtp, dld->dtld_libpath);
2042178479Sjb		dt_free(dtp, dld);
2043178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
2044178479Sjb	}
2045178479Sjb
2046178479Sjb	dt_list_append(dlp, dld);
2047178479Sjb	return (0);
2048178479Sjb}
2049178479Sjb
2050178479Sjbdt_lib_depend_t *
2051178479Sjbdt_lib_depend_lookup(dt_list_t *dld, const char *arg)
2052178479Sjb{
2053178479Sjb	dt_lib_depend_t *dldn;
2054178479Sjb
2055178479Sjb	for (dldn = dt_list_next(dld); dldn != NULL;
2056178479Sjb	    dldn = dt_list_next(dldn)) {
2057178479Sjb		if (strcmp(dldn->dtld_library, arg) == 0)
2058178479Sjb			return (dldn);
2059178479Sjb	}
2060178479Sjb
2061178479Sjb	return (NULL);
2062178479Sjb}
2063178479Sjb
2064178479Sjb/*
2065178479Sjb * Go through all the library files, and, if any library dependencies exist for
2066178479Sjb * that file, add it to that node's list of dependents. The result of this
2067178479Sjb * will be a graph which can then be topologically sorted to produce a
2068178479Sjb * compilation order.
2069178479Sjb */
2070178479Sjbstatic int
2071178479Sjbdt_lib_build_graph(dtrace_hdl_t *dtp)
2072178479Sjb{
2073178479Sjb	dt_lib_depend_t *dld, *dpld;
2074178479Sjb
2075178479Sjb	for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2076178479Sjb	    dld = dt_list_next(dld)) {
2077178479Sjb		char *library = dld->dtld_library;
2078178479Sjb
2079178479Sjb		for (dpld = dt_list_next(&dld->dtld_dependencies); dpld != NULL;
2080178479Sjb		    dpld = dt_list_next(dpld)) {
2081178479Sjb			dt_lib_depend_t *dlda;
2082178479Sjb
2083178479Sjb			if ((dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
2084178479Sjb			    dpld->dtld_library)) == NULL) {
2085178479Sjb				dt_lib_depend_error(dtp,
2086178479Sjb				    "Invalid library dependency in %s: %s\n",
2087178479Sjb				    dld->dtld_library, dpld->dtld_library);
2088178479Sjb
2089178479Sjb				return (dt_set_errno(dtp, EDT_COMPILER));
2090178479Sjb			}
2091178479Sjb
2092178479Sjb			if ((dt_lib_depend_add(dtp, &dlda->dtld_dependents,
2093178479Sjb			    library)) != 0) {
2094178479Sjb				return (-1); /* preserve dt_errno */
2095178479Sjb			}
2096178479Sjb		}
2097178479Sjb	}
2098178479Sjb	return (0);
2099178479Sjb}
2100178479Sjb
2101178479Sjbstatic int
2102178479Sjbdt_topo_sort(dtrace_hdl_t *dtp, dt_lib_depend_t *dld, int *count)
2103178479Sjb{
2104178479Sjb	dt_lib_depend_t *dpld, *dlda, *new;
2105178479Sjb
2106178479Sjb	dld->dtld_start = ++(*count);
2107178479Sjb
2108178479Sjb	for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
2109178479Sjb	    dpld = dt_list_next(dpld)) {
2110178479Sjb		dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep,
2111178479Sjb		    dpld->dtld_library);
2112178479Sjb		assert(dlda != NULL);
2113178479Sjb
2114178479Sjb		if (dlda->dtld_start == 0 &&
2115178479Sjb		    dt_topo_sort(dtp, dlda, count) == -1)
2116178479Sjb			return (-1);
2117178479Sjb	}
2118178479Sjb
2119178479Sjb	if ((new = dt_zalloc(dtp, sizeof (dt_lib_depend_t))) == NULL)
2120178479Sjb		return (-1);
2121178479Sjb
2122178479Sjb	if ((new->dtld_library = strdup(dld->dtld_library)) == NULL) {
2123178479Sjb		dt_free(dtp, new);
2124178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
2125178479Sjb	}
2126178479Sjb
2127178479Sjb	new->dtld_start = dld->dtld_start;
2128178479Sjb	new->dtld_finish = dld->dtld_finish = ++(*count);
2129178479Sjb	dt_list_prepend(&dtp->dt_lib_dep_sorted, new);
2130178479Sjb
2131178479Sjb	dt_dprintf("library %s sorted (%d/%d)\n", new->dtld_library,
2132178479Sjb	    new->dtld_start, new->dtld_finish);
2133178479Sjb
2134178479Sjb	return (0);
2135178479Sjb}
2136178479Sjb
2137178479Sjbstatic int
2138178479Sjbdt_lib_depend_sort(dtrace_hdl_t *dtp)
2139178479Sjb{
2140178479Sjb	dt_lib_depend_t *dld, *dpld, *dlda;
2141178479Sjb	int count = 0;
2142178479Sjb
2143178479Sjb	if (dt_lib_build_graph(dtp) == -1)
2144178479Sjb		return (-1); /* preserve dt_errno */
2145178479Sjb
2146178479Sjb	/*
2147178479Sjb	 * Perform a topological sort of the graph that hangs off
2148178479Sjb	 * dtp->dt_lib_dep. The result of this process will be a
2149178479Sjb	 * dependency ordered list located at dtp->dt_lib_dep_sorted.
2150178479Sjb	 */
2151178479Sjb	for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2152178479Sjb	    dld = dt_list_next(dld)) {
2153178479Sjb		if (dld->dtld_start == 0 &&
2154178479Sjb		    dt_topo_sort(dtp, dld, &count) == -1)
2155178479Sjb			return (-1); /* preserve dt_errno */;
2156178479Sjb	}
2157178479Sjb
2158178479Sjb	/*
2159178479Sjb	 * Check the graph for cycles. If an ancestor's finishing time is
2160178479Sjb	 * less than any of its dependent's finishing times then a back edge
2161178479Sjb	 * exists in the graph and this is a cycle.
2162178479Sjb	 */
2163178479Sjb	for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2164178479Sjb	    dld = dt_list_next(dld)) {
2165178479Sjb		for (dpld = dt_list_next(&dld->dtld_dependents); dpld != NULL;
2166178479Sjb		    dpld = dt_list_next(dpld)) {
2167178479Sjb			dlda = dt_lib_depend_lookup(&dtp->dt_lib_dep_sorted,
2168178479Sjb			    dpld->dtld_library);
2169178479Sjb			assert(dlda != NULL);
2170178479Sjb
2171178479Sjb			if (dlda->dtld_finish > dld->dtld_finish) {
2172178479Sjb				dt_lib_depend_error(dtp,
2173178479Sjb				    "Cyclic dependency detected: %s => %s\n",
2174178479Sjb				    dld->dtld_library, dpld->dtld_library);
2175178479Sjb
2176178479Sjb				return (dt_set_errno(dtp, EDT_COMPILER));
2177178479Sjb			}
2178178479Sjb		}
2179178479Sjb	}
2180178479Sjb
2181178479Sjb	return (0);
2182178479Sjb}
2183178479Sjb
2184178479Sjbstatic void
2185178479Sjbdt_lib_depend_free(dtrace_hdl_t *dtp)
2186178479Sjb{
2187178479Sjb	dt_lib_depend_t *dld, *dlda;
2188178479Sjb
2189178479Sjb	while ((dld = dt_list_next(&dtp->dt_lib_dep)) != NULL) {
2190178479Sjb		while ((dlda = dt_list_next(&dld->dtld_dependencies)) != NULL) {
2191178479Sjb			dt_list_delete(&dld->dtld_dependencies, dlda);
2192178479Sjb			dt_free(dtp, dlda->dtld_library);
2193178479Sjb			dt_free(dtp, dlda->dtld_libpath);
2194178479Sjb			dt_free(dtp, dlda);
2195178479Sjb		}
2196178479Sjb		while ((dlda = dt_list_next(&dld->dtld_dependents)) != NULL) {
2197178479Sjb			dt_list_delete(&dld->dtld_dependents, dlda);
2198178479Sjb			dt_free(dtp, dlda->dtld_library);
2199178479Sjb			dt_free(dtp, dlda->dtld_libpath);
2200178479Sjb			dt_free(dtp, dlda);
2201178479Sjb		}
2202178479Sjb		dt_list_delete(&dtp->dt_lib_dep, dld);
2203178479Sjb		dt_free(dtp, dld->dtld_library);
2204178479Sjb		dt_free(dtp, dld->dtld_libpath);
2205178479Sjb		dt_free(dtp, dld);
2206178479Sjb	}
2207178479Sjb
2208178479Sjb	while ((dld = dt_list_next(&dtp->dt_lib_dep_sorted)) != NULL) {
2209178479Sjb		dt_list_delete(&dtp->dt_lib_dep_sorted, dld);
2210178479Sjb		dt_free(dtp, dld->dtld_library);
2211178479Sjb		dt_free(dtp, dld);
2212178479Sjb	}
2213178479Sjb}
2214178479Sjb
2215178479Sjb/*
2216238558Spfg * Open all the .d library files found in the specified directory and
2217238558Spfg * compile each one of them.  We silently ignore any missing directories and
2218238558Spfg * other files found therein.  We only fail (and thereby fail dt_load_libs()) if
2219238558Spfg * we fail to compile a library and the error is something other than #pragma D
2220238558Spfg * depends_on.  Dependency errors are silently ignored to permit a library
2221238558Spfg * directory to contain libraries which may not be accessible depending on our
2222238558Spfg * privileges.
2223178479Sjb */
2224178479Sjbstatic int
2225178479Sjbdt_load_libs_dir(dtrace_hdl_t *dtp, const char *path)
2226178479Sjb{
2227178479Sjb	struct dirent *dp;
2228238558Spfg	const char *p, *end;
2229178479Sjb	DIR *dirp;
2230178479Sjb
2231178479Sjb	char fname[PATH_MAX];
2232178479Sjb	FILE *fp;
2233178479Sjb	void *rv;
2234178479Sjb	dt_lib_depend_t *dld;
2235178479Sjb
2236178479Sjb	if ((dirp = opendir(path)) == NULL) {
2237178479Sjb		dt_dprintf("skipping lib dir %s: %s\n", path, strerror(errno));
2238178479Sjb		return (0);
2239178479Sjb	}
2240178479Sjb
2241178479Sjb	/* First, parse each file for library dependencies. */
2242178479Sjb	while ((dp = readdir(dirp)) != NULL) {
2243178479Sjb		if ((p = strrchr(dp->d_name, '.')) == NULL || strcmp(p, ".d"))
2244178479Sjb			continue; /* skip any filename not ending in .d */
2245178479Sjb
2246178479Sjb		(void) snprintf(fname, sizeof (fname),
2247178479Sjb		    "%s/%s", path, dp->d_name);
2248178479Sjb
2249178479Sjb		if ((fp = fopen(fname, "r")) == NULL) {
2250178479Sjb			dt_dprintf("skipping library %s: %s\n",
2251178479Sjb			    fname, strerror(errno));
2252178479Sjb			continue;
2253178479Sjb		}
2254178479Sjb
2255238558Spfg		/*
2256238558Spfg		 * Skip files whose name match an already processed library
2257238558Spfg		 */
2258238558Spfg		for (dld = dt_list_next(&dtp->dt_lib_dep); dld != NULL;
2259238558Spfg		    dld = dt_list_next(dld)) {
2260238558Spfg			end = strrchr(dld->dtld_library, '/');
2261238558Spfg			/* dt_lib_depend_add ensures this */
2262238558Spfg			assert(end != NULL);
2263238558Spfg			if (strcmp(end + 1, dp->d_name) == 0)
2264238558Spfg				break;
2265238558Spfg		}
2266238558Spfg
2267238558Spfg		if (dld != NULL) {
2268238558Spfg			dt_dprintf("skipping library %s, already processed "
2269238558Spfg			    "library with the same name: %s", dp->d_name,
2270238558Spfg			    dld->dtld_library);
2271238558Spfg			continue;
2272238558Spfg		}
2273238558Spfg
2274178479Sjb		dtp->dt_filetag = fname;
2275178479Sjb		if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0)
2276238558Spfg			return (-1); /* preserve dt_errno */
2277178479Sjb
2278178479Sjb		rv = dt_compile(dtp, DT_CTX_DPROG,
2279178479Sjb		    DTRACE_PROBESPEC_NAME, NULL,
2280178479Sjb		    DTRACE_C_EMPTY | DTRACE_C_CTL, 0, NULL, fp, NULL);
2281178479Sjb
2282178479Sjb		if (rv != NULL && dtp->dt_errno &&
2283178479Sjb		    (dtp->dt_errno != EDT_COMPILER ||
2284178479Sjb		    dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
2285238558Spfg			return (-1); /* preserve dt_errno */
2286178479Sjb
2287178479Sjb		if (dtp->dt_errno)
2288178479Sjb			dt_dprintf("error parsing library %s: %s\n",
2289178479Sjb			    fname, dtrace_errmsg(dtp, dtrace_errno(dtp)));
2290178479Sjb
2291178479Sjb		(void) fclose(fp);
2292178479Sjb		dtp->dt_filetag = NULL;
2293178479Sjb	}
2294178479Sjb
2295178479Sjb	(void) closedir(dirp);
2296238558Spfg
2297238558Spfg	return (0);
2298238558Spfg}
2299238558Spfg
2300238558Spfg/*
2301238558Spfg * Perform a topological sorting of all the libraries found across the entire
2302238558Spfg * dt_lib_path.  Once sorted, compile each one in topological order to cache its
2303238558Spfg * inlines and translators, etc.  We silently ignore any missing directories and
2304238558Spfg * other files found therein. We only fail (and thereby fail dt_load_libs()) if
2305238558Spfg * we fail to compile a library and the error is something other than #pragma D
2306238558Spfg * depends_on.  Dependency errors are silently ignored to permit a library
2307238558Spfg * directory to contain libraries which may not be accessible depending on our
2308238558Spfg * privileges.
2309238558Spfg */
2310238558Spfgstatic int
2311238558Spfgdt_load_libs_sort(dtrace_hdl_t *dtp)
2312238558Spfg{
2313238558Spfg	dtrace_prog_t *pgp;
2314238558Spfg	FILE *fp;
2315238558Spfg	dt_lib_depend_t *dld;
2316238558Spfg
2317178479Sjb	/*
2318178479Sjb	 * Finish building the graph containing the library dependencies
2319178479Sjb	 * and perform a topological sort to generate an ordered list
2320178479Sjb	 * for compilation.
2321178479Sjb	 */
2322178479Sjb	if (dt_lib_depend_sort(dtp) == -1)
2323178479Sjb		goto err;
2324178479Sjb
2325178479Sjb	for (dld = dt_list_next(&dtp->dt_lib_dep_sorted); dld != NULL;
2326178479Sjb	    dld = dt_list_next(dld)) {
2327178479Sjb
2328178479Sjb		if ((fp = fopen(dld->dtld_library, "r")) == NULL) {
2329178479Sjb			dt_dprintf("skipping library %s: %s\n",
2330178479Sjb			    dld->dtld_library, strerror(errno));
2331178479Sjb			continue;
2332178479Sjb		}
2333178479Sjb
2334178479Sjb		dtp->dt_filetag = dld->dtld_library;
2335178479Sjb		pgp = dtrace_program_fcompile(dtp, fp, DTRACE_C_EMPTY, 0, NULL);
2336178479Sjb		(void) fclose(fp);
2337178479Sjb		dtp->dt_filetag = NULL;
2338178479Sjb
2339178479Sjb		if (pgp == NULL && (dtp->dt_errno != EDT_COMPILER ||
2340178479Sjb		    dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND)))
2341178479Sjb			goto err;
2342178479Sjb
2343178479Sjb		if (pgp == NULL) {
2344178479Sjb			dt_dprintf("skipping library %s: %s\n",
2345178479Sjb			    dld->dtld_library,
2346178479Sjb			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
2347178576Sjb		} else {
2348178576Sjb			dld->dtld_loaded = B_TRUE;
2349178479Sjb			dt_program_destroy(dtp, pgp);
2350178576Sjb		}
2351178479Sjb	}
2352178479Sjb
2353178479Sjb	dt_lib_depend_free(dtp);
2354178479Sjb	return (0);
2355178479Sjb
2356178479Sjberr:
2357178479Sjb	dt_lib_depend_free(dtp);
2358178479Sjb	return (-1); /* preserve dt_errno */
2359178479Sjb}
2360178479Sjb
2361178479Sjb/*
2362178479Sjb * Load the contents of any appropriate DTrace .d library files.  These files
2363178479Sjb * contain inlines and translators that will be cached by the compiler.  We
2364178479Sjb * defer this activity until the first compile to permit libdtrace clients to
2365178479Sjb * add their own library directories and so that we can properly report errors.
2366178479Sjb */
2367178479Sjbstatic int
2368178479Sjbdt_load_libs(dtrace_hdl_t *dtp)
2369178479Sjb{
2370178479Sjb	dt_dirpath_t *dirp;
2371178479Sjb
2372178479Sjb	if (dtp->dt_cflags & DTRACE_C_NOLIBS)
2373178479Sjb		return (0); /* libraries already processed */
2374178479Sjb
2375178479Sjb	dtp->dt_cflags |= DTRACE_C_NOLIBS;
2376178479Sjb
2377238558Spfg	/*
2378238558Spfg	 * /usr/lib/dtrace is always at the head of the list. The rest of the
2379238558Spfg	 * list is specified in the precedence order the user requested. Process
2380238558Spfg	 * everything other than the head first. DTRACE_C_NOLIBS has already
2381238558Spfg	 * been spcified so dt_vopen will ensure that there is always one entry
2382238558Spfg	 * in dt_lib_path.
2383238558Spfg	 */
2384238558Spfg	for (dirp = dt_list_next(dt_list_next(&dtp->dt_lib_path));
2385178479Sjb	    dirp != NULL; dirp = dt_list_next(dirp)) {
2386178479Sjb		if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
2387178479Sjb			dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
2388178479Sjb			return (-1); /* errno is set for us */
2389178479Sjb		}
2390178479Sjb	}
2391178479Sjb
2392238558Spfg	/* Handle /usr/lib/dtrace */
2393238558Spfg	dirp = dt_list_next(&dtp->dt_lib_path);
2394238558Spfg	if (dt_load_libs_dir(dtp, dirp->dir_path) != 0) {
2395238558Spfg		dtp->dt_cflags &= ~DTRACE_C_NOLIBS;
2396238558Spfg		return (-1); /* errno is set for us */
2397238558Spfg	}
2398238558Spfg
2399238558Spfg	if (dt_load_libs_sort(dtp) < 0)
2400238558Spfg		return (-1); /* errno is set for us */
2401238558Spfg
2402178479Sjb	return (0);
2403178479Sjb}
2404178479Sjb
2405178479Sjbstatic void *
2406178479Sjbdt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
2407178479Sjb    uint_t cflags, int argc, char *const argv[], FILE *fp, const char *s)
2408178479Sjb{
2409178479Sjb	dt_node_t *dnp;
2410178479Sjb	dt_decl_t *ddp;
2411178479Sjb	dt_pcb_t pcb;
2412178479Sjb	void *rv;
2413178479Sjb	int err;
2414178479Sjb
2415178479Sjb	if ((fp == NULL && s == NULL) || (cflags & ~DTRACE_C_MASK) != 0) {
2416178479Sjb		(void) dt_set_errno(dtp, EINVAL);
2417178479Sjb		return (NULL);
2418178479Sjb	}
2419178479Sjb
2420178479Sjb	if (dt_list_next(&dtp->dt_lib_path) != NULL && dt_load_libs(dtp) != 0)
2421178479Sjb		return (NULL); /* errno is set for us */
2422178479Sjb
2423210767Srpaulo	if (dtp->dt_globals->dh_nelems != 0)
2424210767Srpaulo		(void) dt_idhash_iter(dtp->dt_globals, dt_idreset, NULL);
2425178479Sjb
2426210767Srpaulo	if (dtp->dt_tls->dh_nelems != 0)
2427210767Srpaulo		(void) dt_idhash_iter(dtp->dt_tls, dt_idreset, NULL);
2428178479Sjb
2429178479Sjb	if (fp && (cflags & DTRACE_C_CPP) && (fp = dt_preproc(dtp, fp)) == NULL)
2430178479Sjb		return (NULL); /* errno is set for us */
2431178479Sjb
2432178479Sjb	dt_pcb_push(dtp, &pcb);
2433178479Sjb
2434178479Sjb	pcb.pcb_fileptr = fp;
2435178479Sjb	pcb.pcb_string = s;
2436178479Sjb	pcb.pcb_strptr = s;
2437178479Sjb	pcb.pcb_strlen = s ? strlen(s) : 0;
2438178479Sjb	pcb.pcb_sargc = argc;
2439178479Sjb	pcb.pcb_sargv = argv;
2440178479Sjb	pcb.pcb_sflagv = argc ? calloc(argc, sizeof (ushort_t)) : NULL;
2441178479Sjb	pcb.pcb_pspec = pspec;
2442178479Sjb	pcb.pcb_cflags = dtp->dt_cflags | cflags;
2443178479Sjb	pcb.pcb_amin = dtp->dt_amin;
2444178479Sjb	pcb.pcb_yystate = -1;
2445178479Sjb	pcb.pcb_context = context;
2446178479Sjb	pcb.pcb_token = context;
2447178479Sjb
2448178479Sjb	if (context != DT_CTX_DPROG)
2449178479Sjb		yybegin(YYS_EXPR);
2450178479Sjb	else if (cflags & DTRACE_C_CTL)
2451178479Sjb		yybegin(YYS_CONTROL);
2452178479Sjb	else
2453178479Sjb		yybegin(YYS_CLAUSE);
2454178479Sjb
2455178479Sjb	if ((err = setjmp(yypcb->pcb_jmpbuf)) != 0)
2456178479Sjb		goto out;
2457178479Sjb
2458178479Sjb	if (yypcb->pcb_sargc != 0 && yypcb->pcb_sflagv == NULL)
2459178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2460178479Sjb
2461178479Sjb	yypcb->pcb_idents = dt_idhash_create("ambiguous", NULL, 0, 0);
2462178479Sjb	yypcb->pcb_locals = dt_idhash_create("clause local", NULL,
2463178479Sjb	    DIF_VAR_OTHER_UBASE, DIF_VAR_OTHER_MAX);
2464178479Sjb
2465178479Sjb	if (yypcb->pcb_idents == NULL || yypcb->pcb_locals == NULL)
2466178479Sjb		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
2467178479Sjb
2468178479Sjb	/*
2469178479Sjb	 * Invoke the parser to evaluate the D source code.  If any errors
2470178479Sjb	 * occur during parsing, an error function will be called and we
2471178479Sjb	 * will longjmp back to pcb_jmpbuf to abort.  If parsing succeeds,
2472178479Sjb	 * we optionally display the parse tree if debugging is enabled.
2473178479Sjb	 */
2474178479Sjb	if (yyparse() != 0 || yypcb->pcb_root == NULL)
2475178479Sjb		xyerror(D_EMPTY, "empty D program translation unit\n");
2476178479Sjb
2477178479Sjb	yybegin(YYS_DONE);
2478178479Sjb
2479178479Sjb	if (cflags & DTRACE_C_CTL)
2480178479Sjb		goto out;
2481178479Sjb
2482178479Sjb	if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 1))
2483178479Sjb		dt_node_printr(yypcb->pcb_root, stderr, 0);
2484178479Sjb
2485178479Sjb	if (yypcb->pcb_pragmas != NULL)
2486178479Sjb		(void) dt_idhash_iter(yypcb->pcb_pragmas, dt_idpragma, NULL);
2487178479Sjb
2488178479Sjb	if (argc > 1 && !(yypcb->pcb_cflags & DTRACE_C_ARGREF) &&
2489178479Sjb	    !(yypcb->pcb_sflagv[argc - 1] & DT_IDFLG_REF)) {
2490178479Sjb		xyerror(D_MACRO_UNUSED, "extraneous argument '%s' ($%d is "
2491178479Sjb		    "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1);
2492178479Sjb	}
2493178479Sjb
2494178479Sjb	/*
2495178479Sjb	 * If we have successfully created a parse tree for a D program, loop
2496178479Sjb	 * over the clauses and actions and instantiate the corresponding
2497178479Sjb	 * libdtrace program.  If we are parsing a D expression, then we
2498178479Sjb	 * simply run the code generator and assembler on the resulting tree.
2499178479Sjb	 */
2500178479Sjb	switch (context) {
2501178479Sjb	case DT_CTX_DPROG:
2502178479Sjb		assert(yypcb->pcb_root->dn_kind == DT_NODE_PROG);
2503178479Sjb
2504178479Sjb		if ((dnp = yypcb->pcb_root->dn_list) == NULL &&
2505178479Sjb		    !(yypcb->pcb_cflags & DTRACE_C_EMPTY))
2506178479Sjb			xyerror(D_EMPTY, "empty D program translation unit\n");
2507178479Sjb
2508178479Sjb		if ((yypcb->pcb_prog = dt_program_create(dtp)) == NULL)
2509178479Sjb			longjmp(yypcb->pcb_jmpbuf, dtrace_errno(dtp));
2510178479Sjb
2511178479Sjb		for (; dnp != NULL; dnp = dnp->dn_list) {
2512178479Sjb			switch (dnp->dn_kind) {
2513178479Sjb			case DT_NODE_CLAUSE:
2514178479Sjb				dt_compile_clause(dtp, dnp);
2515178479Sjb				break;
2516178479Sjb			case DT_NODE_XLATOR:
2517178479Sjb				if (dtp->dt_xlatemode == DT_XL_DYNAMIC)
2518178479Sjb					dt_compile_xlator(dnp);
2519178479Sjb				break;
2520178479Sjb			case DT_NODE_PROVIDER:
2521178479Sjb				(void) dt_node_cook(dnp, DT_IDFLG_REF);
2522178479Sjb				break;
2523178479Sjb			}
2524178479Sjb		}
2525178479Sjb
2526178479Sjb		yypcb->pcb_prog->dp_xrefs = yypcb->pcb_asxrefs;
2527178479Sjb		yypcb->pcb_prog->dp_xrefslen = yypcb->pcb_asxreflen;
2528178479Sjb		yypcb->pcb_asxrefs = NULL;
2529178479Sjb		yypcb->pcb_asxreflen = 0;
2530178479Sjb
2531178479Sjb		rv = yypcb->pcb_prog;
2532178479Sjb		break;
2533178479Sjb
2534178479Sjb	case DT_CTX_DEXPR:
2535178479Sjb		(void) dt_node_cook(yypcb->pcb_root, DT_IDFLG_REF);
2536178479Sjb		dt_cg(yypcb, yypcb->pcb_root);
2537178479Sjb		rv = dt_as(yypcb);
2538178479Sjb		break;
2539178479Sjb
2540178479Sjb	case DT_CTX_DTYPE:
2541178479Sjb		ddp = (dt_decl_t *)yypcb->pcb_root; /* root is really a decl */
2542178479Sjb		err = dt_decl_type(ddp, arg);
2543178479Sjb		dt_decl_free(ddp);
2544178479Sjb
2545178479Sjb		if (err != 0)
2546178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
2547178479Sjb
2548178479Sjb		rv = NULL;
2549178479Sjb		break;
2550178479Sjb	}
2551178479Sjb
2552178479Sjbout:
2553253725Spfg	if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
2554253725Spfg	    DT_TREEDUMP_PASS(dtp, 3))
2555178479Sjb		dt_node_printr(yypcb->pcb_root, stderr, 0);
2556178479Sjb
2557178479Sjb	if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
2558178479Sjb	    lseek64(dtp->dt_cdefs_fd, 0, SEEK_SET) == -1 ||
2559178479Sjb	    ctf_write(dtp->dt_cdefs->dm_ctfp, dtp->dt_cdefs_fd) == CTF_ERR))
2560178479Sjb		dt_dprintf("failed to update CTF cache: %s\n", strerror(errno));
2561178479Sjb
2562178479Sjb	if (dtp->dt_ddefs_fd != -1 && (ftruncate64(dtp->dt_ddefs_fd, 0) == -1 ||
2563178479Sjb	    lseek64(dtp->dt_ddefs_fd, 0, SEEK_SET) == -1 ||
2564178479Sjb	    ctf_write(dtp->dt_ddefs->dm_ctfp, dtp->dt_ddefs_fd) == CTF_ERR))
2565178479Sjb		dt_dprintf("failed to update CTF cache: %s\n", strerror(errno));
2566178479Sjb
2567178479Sjb	if (yypcb->pcb_fileptr && (cflags & DTRACE_C_CPP))
2568178479Sjb		(void) fclose(yypcb->pcb_fileptr); /* close dt_preproc() file */
2569178479Sjb
2570178479Sjb	dt_pcb_pop(dtp, err);
2571178479Sjb	(void) dt_set_errno(dtp, err);
2572178479Sjb	return (err ? NULL : rv);
2573178479Sjb}
2574178479Sjb
2575178479Sjbdtrace_prog_t *
2576178479Sjbdtrace_program_strcompile(dtrace_hdl_t *dtp, const char *s,
2577178479Sjb    dtrace_probespec_t spec, uint_t cflags, int argc, char *const argv[])
2578178479Sjb{
2579178479Sjb	return (dt_compile(dtp, DT_CTX_DPROG,
2580178479Sjb	    spec, NULL, cflags, argc, argv, NULL, s));
2581178479Sjb}
2582178479Sjb
2583178479Sjbdtrace_prog_t *
2584178479Sjbdtrace_program_fcompile(dtrace_hdl_t *dtp, FILE *fp,
2585178479Sjb    uint_t cflags, int argc, char *const argv[])
2586178479Sjb{
2587178479Sjb	return (dt_compile(dtp, DT_CTX_DPROG,
2588178479Sjb	    DTRACE_PROBESPEC_NAME, NULL, cflags, argc, argv, fp, NULL));
2589178479Sjb}
2590178479Sjb
2591178479Sjbint
2592178479Sjbdtrace_type_strcompile(dtrace_hdl_t *dtp, const char *s, dtrace_typeinfo_t *dtt)
2593178479Sjb{
2594178479Sjb	(void) dt_compile(dtp, DT_CTX_DTYPE,
2595178479Sjb	    DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, NULL, s);
2596178479Sjb	return (dtp->dt_errno ? -1 : 0);
2597178479Sjb}
2598178479Sjb
2599178479Sjbint
2600178479Sjbdtrace_type_fcompile(dtrace_hdl_t *dtp, FILE *fp, dtrace_typeinfo_t *dtt)
2601178479Sjb{
2602178479Sjb	(void) dt_compile(dtp, DT_CTX_DTYPE,
2603178479Sjb	    DTRACE_PROBESPEC_NONE, dtt, 0, 0, NULL, fp, NULL);
2604178479Sjb	return (dtp->dt_errno ? -1 : 0);
2605178479Sjb}
2606