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/*
23178479Sjb * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24178479Sjb * Use is subject to license terms.
25268578Srpaulo * Copyright (c) 2013 by Delphix. All rights reserved.
26268578Srpaulo * Copyright (c) 2013 Joyent, Inc. All rights reserved.
27178479Sjb */
28178479Sjb
29178479Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
30178479Sjb
31178574Sjb#if defined(sun)
32178479Sjb#include <sys/sysmacros.h>
33178574Sjb#endif
34178479Sjb#include <strings.h>
35178479Sjb#include <stdlib.h>
36178574Sjb#if defined(sun)
37178479Sjb#include <alloca.h>
38178574Sjb#endif
39178479Sjb#include <assert.h>
40178479Sjb#include <errno.h>
41178479Sjb#include <ctype.h>
42178574Sjb#if defined(sun)
43178479Sjb#include <sys/procfs_isa.h>
44178574Sjb#endif
45178479Sjb#include <limits.h>
46178479Sjb
47178479Sjb#include <dt_ident.h>
48178479Sjb#include <dt_parser.h>
49178479Sjb#include <dt_provider.h>
50178479Sjb#include <dt_strtab.h>
51178479Sjb#include <dt_impl.h>
52178479Sjb
53178479Sjb/*
54178479Sjb * Common code for cooking an identifier that uses a typed signature list (we
55178479Sjb * use this for associative arrays and functions).  If the argument list is
56178479Sjb * of the same length and types, then return the return type.  Otherwise
57178479Sjb * print an appropriate compiler error message and abort the compile.
58178479Sjb */
59178479Sjbstatic void
60178479Sjbdt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,
61178479Sjb    int argc, dt_node_t *args, const char *prefix, const char *suffix)
62178479Sjb{
63178479Sjb	dt_idsig_t *isp = idp->di_data;
64178479Sjb	int i, compat, mismatch, arglimit, iskey;
65178479Sjb
66178479Sjb	char n1[DT_TYPE_NAMELEN];
67178479Sjb	char n2[DT_TYPE_NAMELEN];
68178479Sjb
69178479Sjb	iskey = idp->di_kind == DT_IDENT_ARRAY || idp->di_kind == DT_IDENT_AGG;
70178479Sjb
71178479Sjb	if (isp->dis_varargs >= 0) {
72178479Sjb		mismatch = argc < isp->dis_varargs;
73178479Sjb		arglimit = isp->dis_varargs;
74178479Sjb	} else if (isp->dis_optargs >= 0) {
75178479Sjb		mismatch = (argc < isp->dis_optargs || argc > isp->dis_argc);
76178479Sjb		arglimit = argc;
77178479Sjb	} else {
78178479Sjb		mismatch = argc != isp->dis_argc;
79178479Sjb		arglimit = isp->dis_argc;
80178479Sjb	}
81178479Sjb
82178479Sjb	if (mismatch) {
83178479Sjb		xyerror(D_PROTO_LEN, "%s%s%s prototype mismatch: %d %s%s"
84178479Sjb		    "passed, %s%d expected\n", prefix, idp->di_name, suffix,
85178479Sjb		    argc, iskey ? "key" : "arg", argc == 1 ? " " : "s ",
86178479Sjb		    isp->dis_optargs >= 0 ? "at least " : "",
87178479Sjb		    isp->dis_optargs >= 0 ? isp->dis_optargs : arglimit);
88178479Sjb	}
89178479Sjb
90178479Sjb	for (i = 0; i < arglimit; i++, args = args->dn_list) {
91178479Sjb		if (isp->dis_args[i].dn_ctfp != NULL)
92178479Sjb			compat = dt_node_is_argcompat(&isp->dis_args[i], args);
93178479Sjb		else
94178479Sjb			compat = 1; /* "@" matches any type */
95178479Sjb
96178479Sjb		if (!compat) {
97178479Sjb			xyerror(D_PROTO_ARG,
98178479Sjb			    "%s%s%s %s #%d is incompatible with "
99178479Sjb			    "prototype:\n\tprototype: %s\n\t%9s: %s\n",
100178479Sjb			    prefix, idp->di_name, suffix,
101178479Sjb			    iskey ? "key" : "argument", i + 1,
102178479Sjb			    dt_node_type_name(&isp->dis_args[i], n1,
103178479Sjb			    sizeof (n1)),
104178479Sjb			    iskey ? "key" : "argument",
105178479Sjb			    dt_node_type_name(args, n2, sizeof (n2)));
106178479Sjb		}
107178479Sjb	}
108178479Sjb
109268578Srpaulo	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
110178479Sjb}
111178479Sjb
112178479Sjb/*
113178479Sjb * Cook an associative array identifier.  If this is the first time we are
114178479Sjb * cooking this array, create its signature based on the argument list.
115178479Sjb * Otherwise validate the argument list against the existing signature.
116178479Sjb */
117178479Sjbstatic void
118178479Sjbdt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
119178479Sjb{
120178479Sjb	if (idp->di_data == NULL) {
121178479Sjb		dt_idsig_t *isp = idp->di_data = malloc(sizeof (dt_idsig_t));
122178479Sjb		char n[DT_TYPE_NAMELEN];
123178479Sjb		int i;
124178479Sjb
125178479Sjb		if (isp == NULL)
126178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
127178479Sjb
128178479Sjb		isp->dis_varargs = -1;
129178479Sjb		isp->dis_optargs = -1;
130178479Sjb		isp->dis_argc = argc;
131178479Sjb		isp->dis_args = NULL;
132178479Sjb		isp->dis_auxinfo = 0;
133178479Sjb
134178479Sjb		if (argc != 0 && (isp->dis_args = calloc(argc,
135178479Sjb		    sizeof (dt_node_t))) == NULL) {
136178479Sjb			idp->di_data = NULL;
137178479Sjb			free(isp);
138178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
139178479Sjb		}
140178479Sjb
141178479Sjb		/*
142178479Sjb		 * If this identifier has not been explicitly declared earlier,
143178479Sjb		 * set the identifier's base type to be our special type <DYN>.
144178479Sjb		 * If this ident is an aggregation, it will remain as is.  If
145178479Sjb		 * this ident is an associative array, it will be reassigned
146178479Sjb		 * based on the result type of the first assignment statement.
147178479Sjb		 */
148178479Sjb		if (!(idp->di_flags & DT_IDFLG_DECL)) {
149178479Sjb			idp->di_ctfp = DT_DYN_CTFP(yypcb->pcb_hdl);
150178479Sjb			idp->di_type = DT_DYN_TYPE(yypcb->pcb_hdl);
151178479Sjb		}
152178479Sjb
153178479Sjb		for (i = 0; i < argc; i++, args = args->dn_list) {
154178479Sjb			if (dt_node_is_dynamic(args) || dt_node_is_void(args)) {
155178479Sjb				xyerror(D_KEY_TYPE, "%s expression may not be "
156178479Sjb				    "used as %s index: key #%d\n",
157178479Sjb				    dt_node_type_name(args, n, sizeof (n)),
158178479Sjb				    dt_idkind_name(idp->di_kind), i + 1);
159178479Sjb			}
160178479Sjb
161178479Sjb			dt_node_type_propagate(args, &isp->dis_args[i]);
162178479Sjb			isp->dis_args[i].dn_list = &isp->dis_args[i + 1];
163178479Sjb		}
164178479Sjb
165178479Sjb		if (argc != 0)
166178479Sjb			isp->dis_args[argc - 1].dn_list = NULL;
167178479Sjb
168268578Srpaulo		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
169178479Sjb
170178479Sjb	} else {
171178479Sjb		dt_idcook_sign(dnp, idp, argc, args,
172178479Sjb		    idp->di_kind == DT_IDENT_AGG ? "@" : "", "[ ]");
173178479Sjb	}
174178479Sjb}
175178479Sjb
176178479Sjb/*
177178479Sjb * Cook a function call.  If this is the first time we are cooking this
178178479Sjb * identifier, create its type signature based on predefined prototype stored
179178479Sjb * in di_iarg.  We then validate the argument list against this signature.
180178479Sjb */
181178479Sjbstatic void
182178479Sjbdt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
183178479Sjb{
184178479Sjb	if (idp->di_data == NULL) {
185178479Sjb		dtrace_hdl_t *dtp = yypcb->pcb_hdl;
186178479Sjb		dtrace_typeinfo_t dtt;
187178479Sjb		dt_idsig_t *isp;
188178479Sjb		char *s, *p1, *p2;
189178479Sjb		int i = 0;
190178479Sjb
191178479Sjb		assert(idp->di_iarg != NULL);
192178479Sjb		s = alloca(strlen(idp->di_iarg) + 1);
193178479Sjb		(void) strcpy(s, idp->di_iarg);
194178479Sjb
195178479Sjb		if ((p2 = strrchr(s, ')')) != NULL)
196178479Sjb			*p2 = '\0'; /* mark end of parameter list string */
197178479Sjb
198178479Sjb		if ((p1 = strchr(s, '(')) != NULL)
199178479Sjb			*p1++ = '\0'; /* mark end of return type string */
200178479Sjb
201178479Sjb		if (p1 == NULL || p2 == NULL) {
202178479Sjb			xyerror(D_UNKNOWN, "internal error: malformed entry "
203178479Sjb			    "for built-in function %s\n", idp->di_name);
204178479Sjb		}
205178479Sjb
206178479Sjb		for (p2 = p1; *p2 != '\0'; p2++) {
207178479Sjb			if (!isspace(*p2)) {
208178479Sjb				i++;
209178479Sjb				break;
210178479Sjb			}
211178479Sjb		}
212178479Sjb
213178479Sjb		for (p2 = strchr(p2, ','); p2++ != NULL; i++)
214178479Sjb			p2 = strchr(p2, ',');
215178479Sjb
216178479Sjb		/*
217178479Sjb		 * We first allocate a new ident signature structure with the
218178479Sjb		 * appropriate number of argument entries, and then look up
219178479Sjb		 * the return type and store its CTF data in di_ctfp/type.
220178479Sjb		 */
221178479Sjb		if ((isp = idp->di_data = malloc(sizeof (dt_idsig_t))) == NULL)
222178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
223178479Sjb
224178479Sjb		isp->dis_varargs = -1;
225178479Sjb		isp->dis_optargs = -1;
226178479Sjb		isp->dis_argc = i;
227178479Sjb		isp->dis_args = NULL;
228178479Sjb		isp->dis_auxinfo = 0;
229178479Sjb
230178479Sjb		if (i != 0 && (isp->dis_args = calloc(i,
231178479Sjb		    sizeof (dt_node_t))) == NULL) {
232178479Sjb			idp->di_data = NULL;
233178479Sjb			free(isp);
234178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
235178479Sjb		}
236178479Sjb
237178479Sjb		if (dt_type_lookup(s, &dtt) == -1) {
238178479Sjb			xyerror(D_UNKNOWN, "failed to resolve type of %s (%s):"
239178479Sjb			    " %s\n", idp->di_name, s,
240178479Sjb			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
241178479Sjb		}
242178479Sjb
243178479Sjb		if (idp->di_kind == DT_IDENT_AGGFUNC) {
244178479Sjb			idp->di_ctfp = DT_DYN_CTFP(dtp);
245178479Sjb			idp->di_type = DT_DYN_TYPE(dtp);
246178479Sjb		} else {
247178479Sjb			idp->di_ctfp = dtt.dtt_ctfp;
248178479Sjb			idp->di_type = dtt.dtt_type;
249178479Sjb		}
250178479Sjb
251178479Sjb		/*
252178479Sjb		 * For each comma-delimited parameter in the prototype string,
253178479Sjb		 * we look up the corresponding type and store its CTF data in
254178479Sjb		 * the corresponding location in dis_args[].  We also recognize
255178479Sjb		 * the special type string "@" to indicate that the specified
256178479Sjb		 * parameter may be a D expression of *any* type (represented
257178479Sjb		 * as a dis_args[] element with ctfp = NULL, type == CTF_ERR).
258178479Sjb		 * If a varargs "..." is present, we record the argument index
259178479Sjb		 * in dis_varargs for the benefit of dt_idcook_sign(), above.
260178479Sjb		 * If the type of an argument is enclosed in square brackets
261178479Sjb		 * (e.g. "[int]"), the argument is considered optional:  the
262178479Sjb		 * argument may be absent, but if it is present, it must be of
263178479Sjb		 * the specified type.  Note that varargs may not optional,
264178479Sjb		 * optional arguments may not follow varargs, and non-optional
265178479Sjb		 * arguments may not follow optional arguments.
266178479Sjb		 */
267178479Sjb		for (i = 0; i < isp->dis_argc; i++, p1 = p2) {
268178479Sjb			while (isspace(*p1))
269178479Sjb				p1++; /* skip leading whitespace */
270178479Sjb
271178479Sjb			if ((p2 = strchr(p1, ',')) == NULL)
272178479Sjb				p2 = p1 + strlen(p1);
273178479Sjb			else
274178479Sjb				*p2++ = '\0';
275178479Sjb
276178479Sjb			if (strcmp(p1, "@") == 0 || strcmp(p1, "...") == 0) {
277178479Sjb				isp->dis_args[i].dn_ctfp = NULL;
278178479Sjb				isp->dis_args[i].dn_type = CTF_ERR;
279178479Sjb				if (*p1 == '.')
280178479Sjb					isp->dis_varargs = i;
281178479Sjb				continue;
282178479Sjb			}
283178479Sjb
284178479Sjb			if (*p1 == '[' && p1[strlen(p1) - 1] == ']') {
285178479Sjb				if (isp->dis_varargs != -1) {
286178479Sjb					xyerror(D_UNKNOWN, "optional arg#%d "
287178479Sjb					    "may not follow variable arg#%d\n",
288178479Sjb					    i + 1, isp->dis_varargs + 1);
289178479Sjb				}
290178479Sjb
291178479Sjb				if (isp->dis_optargs == -1)
292178479Sjb					isp->dis_optargs = i;
293178479Sjb
294178479Sjb				p1[strlen(p1) - 1] = '\0';
295178479Sjb				p1++;
296178479Sjb			} else if (isp->dis_optargs != -1) {
297178479Sjb				xyerror(D_UNKNOWN, "required arg#%d may not "
298178479Sjb				    "follow optional arg#%d\n", i + 1,
299178479Sjb				    isp->dis_optargs + 1);
300178479Sjb			}
301178479Sjb
302178479Sjb			if (dt_type_lookup(p1, &dtt) == -1) {
303178479Sjb				xyerror(D_UNKNOWN, "failed to resolve type of "
304178479Sjb				    "%s arg#%d (%s): %s\n", idp->di_name, i + 1,
305178479Sjb				    p1, dtrace_errmsg(dtp, dtrace_errno(dtp)));
306178479Sjb			}
307178479Sjb
308178479Sjb			dt_node_type_assign(&isp->dis_args[i],
309268578Srpaulo			    dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
310178479Sjb		}
311178479Sjb	}
312178479Sjb
313178479Sjb	dt_idcook_sign(dnp, idp, argc, args, "", "( )");
314178479Sjb}
315178479Sjb
316178479Sjb/*
317178479Sjb * Cook a reference to the dynamically typed args[] array.  We verify that the
318178479Sjb * reference is using a single integer constant, and then construct a new ident
319178479Sjb * representing the appropriate type or translation specifically for this node.
320178479Sjb */
321178479Sjbstatic void
322178479Sjbdt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
323178479Sjb{
324178479Sjb	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
325178479Sjb	dt_probe_t *prp = yypcb->pcb_probe;
326178479Sjb
327178479Sjb	dt_node_t tag, *nnp, *xnp;
328178479Sjb	dt_xlator_t *dxp;
329178479Sjb	dt_ident_t *xidp;
330178479Sjb
331178479Sjb	char n1[DT_TYPE_NAMELEN];
332178479Sjb	char n2[DT_TYPE_NAMELEN];
333178479Sjb
334178479Sjb	if (argc != 1) {
335178479Sjb		xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s"
336178479Sjb		    "passed, 1 expected\n", idp->di_name, argc,
337178479Sjb		    argc == 1 ? " " : "s ");
338178479Sjb	}
339178479Sjb
340178479Sjb	if (ap->dn_kind != DT_NODE_INT) {
341178479Sjb		xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with "
342178479Sjb		    "prototype:\n\tprototype: %s\n\t argument: %s\n",
343178479Sjb		    idp->di_name, "integer constant",
344178479Sjb		    dt_type_name(ap->dn_ctfp, ap->dn_type, n1, sizeof (n1)));
345178479Sjb	}
346178479Sjb
347178479Sjb	if (yypcb->pcb_pdesc == NULL) {
348178479Sjb		xyerror(D_ARGS_NONE, "%s[ ] may not be referenced outside "
349178479Sjb		    "of a probe clause\n", idp->di_name);
350178479Sjb	}
351178479Sjb
352178479Sjb	if (prp == NULL) {
353178479Sjb		xyerror(D_ARGS_MULTI,
354178479Sjb		    "%s[ ] may not be referenced because probe description %s "
355178479Sjb		    "matches an unstable set of probes\n", idp->di_name,
356178479Sjb		    dtrace_desc2str(yypcb->pcb_pdesc, n1, sizeof (n1)));
357178479Sjb	}
358178479Sjb
359178479Sjb	if (ap->dn_value >= prp->pr_argc) {
360178479Sjb		xyerror(D_ARGS_IDX, "index %lld is out of range for %s %s[ ]\n",
361178479Sjb		    (longlong_t)ap->dn_value, dtrace_desc2str(yypcb->pcb_pdesc,
362178479Sjb		    n1, sizeof (n1)), idp->di_name);
363178479Sjb	}
364178479Sjb
365178479Sjb	/*
366178479Sjb	 * Look up the native and translated argument types for the probe.
367178479Sjb	 * If no translation is needed, these will be the same underlying node.
368178479Sjb	 * If translation is needed, look up the appropriate translator.  Once
369178479Sjb	 * we have the appropriate node, create a new dt_ident_t for this node,
370178479Sjb	 * assign it the appropriate attributes, and set the type of 'dnp'.
371178479Sjb	 */
372178479Sjb	xnp = prp->pr_xargv[ap->dn_value];
373178479Sjb	nnp = prp->pr_nargv[prp->pr_mapping[ap->dn_value]];
374178479Sjb
375178479Sjb	if (xnp->dn_type == CTF_ERR) {
376178479Sjb		xyerror(D_ARGS_TYPE, "failed to resolve translated type for "
377178479Sjb		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
378178479Sjb	}
379178479Sjb
380178479Sjb	if (nnp->dn_type == CTF_ERR) {
381178479Sjb		xyerror(D_ARGS_TYPE, "failed to resolve native type for "
382178479Sjb		    "%s[%lld]\n", idp->di_name, (longlong_t)ap->dn_value);
383178479Sjb	}
384178479Sjb
385178479Sjb	if (dtp->dt_xlatemode == DT_XL_STATIC && (
386178479Sjb	    nnp == xnp || dt_node_is_argcompat(nnp, xnp))) {
387178479Sjb		dnp->dn_ident = dt_ident_create(idp->di_name, idp->di_kind,
388178479Sjb		    idp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
389178479Sjb		    idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);
390178479Sjb
391178479Sjb		if (dnp->dn_ident == NULL)
392178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
393178479Sjb
394178479Sjb		dt_node_type_assign(dnp,
395178479Sjb		    prp->pr_argv[ap->dn_value].dtt_ctfp,
396268578Srpaulo		    prp->pr_argv[ap->dn_value].dtt_type,
397268578Srpaulo		    prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
398268578Srpaulo		    B_TRUE : B_FALSE);
399178479Sjb
400178479Sjb	} else if ((dxp = dt_xlator_lookup(dtp,
401178479Sjb	    nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
402178479Sjb	    dxp = dt_xlator_lookup(dtp, dt_probe_tag(prp, ap->dn_value, &tag),
403178479Sjb	    xnp, DT_XLATE_EXACT | DT_XLATE_EXTERN)) != NULL) {
404178479Sjb
405178479Sjb		xidp = dt_xlator_ident(dxp, xnp->dn_ctfp, xnp->dn_type);
406178479Sjb
407178479Sjb		dnp->dn_ident = dt_ident_create(idp->di_name, xidp->di_kind,
408178479Sjb		    xidp->di_flags | DT_IDFLG_ORPHAN, idp->di_id, idp->di_attr,
409178479Sjb		    idp->di_vers, idp->di_ops, idp->di_iarg, idp->di_gen);
410178479Sjb
411178479Sjb		if (dnp->dn_ident == NULL)
412178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
413178479Sjb
414178479Sjb		if (dt_xlator_dynamic(dxp))
415178479Sjb			dxp->dx_arg = (int)ap->dn_value;
416178479Sjb
417178479Sjb		/*
418178479Sjb		 * Propagate relevant members from the translator's internal
419178479Sjb		 * dt_ident_t.  This code must be kept in sync with the state
420178479Sjb		 * that is initialized for idents in dt_xlator_create().
421178479Sjb		 */
422178479Sjb		dnp->dn_ident->di_data = xidp->di_data;
423178479Sjb		dnp->dn_ident->di_ctfp = xidp->di_ctfp;
424178479Sjb		dnp->dn_ident->di_type = xidp->di_type;
425178479Sjb
426268578Srpaulo		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
427268578Srpaulo		    B_FALSE);
428178479Sjb
429178479Sjb	} else {
430178479Sjb		xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
431178479Sjb		    "is not defined\n", idp->di_name, (longlong_t)ap->dn_value,
432178479Sjb		    dt_node_type_name(nnp, n1, sizeof (n1)),
433178479Sjb		    dt_node_type_name(xnp, n2, sizeof (n2)));
434178479Sjb	}
435178479Sjb
436178479Sjb	assert(dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN);
437178479Sjb	assert(dnp->dn_ident->di_id == idp->di_id);
438178479Sjb}
439178479Sjb
440178479Sjbstatic void
441178479Sjbdt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
442178479Sjb{
443178479Sjb	dtrace_typeinfo_t dtt;
444178479Sjb	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
445178479Sjb	char n[DT_TYPE_NAMELEN];
446178479Sjb
447178479Sjb	if (argc != 1) {
448178479Sjb		xyerror(D_PROTO_LEN, "%s[ ] prototype mismatch: %d arg%s"
449178479Sjb		    "passed, 1 expected\n", idp->di_name,
450178479Sjb		    argc, argc == 1 ? " " : "s ");
451178479Sjb	}
452178479Sjb
453178479Sjb	if (ap->dn_kind != DT_NODE_INT) {
454178479Sjb		xyerror(D_PROTO_ARG, "%s[ ] argument #1 is incompatible with "
455178479Sjb		    "prototype:\n\tprototype: %s\n\t argument: %s\n",
456178479Sjb		    idp->di_name, "integer constant",
457178479Sjb		    dt_type_name(ap->dn_ctfp, ap->dn_type, n, sizeof (n)));
458178479Sjb	}
459178479Sjb
460178479Sjb	if ((ap->dn_flags & DT_NF_SIGNED) && (int64_t)ap->dn_value < 0) {
461178479Sjb		xyerror(D_REGS_IDX, "index %lld is out of range for array %s\n",
462178479Sjb		    (longlong_t)ap->dn_value, idp->di_name);
463178479Sjb	}
464178479Sjb
465178479Sjb	if (dt_type_lookup("uint64_t", &dtt) == -1) {
466178479Sjb		xyerror(D_UNKNOWN, "failed to resolve type of %s: %s\n",
467178479Sjb		    idp->di_name, dtrace_errmsg(dtp, dtrace_errno(dtp)));
468178479Sjb	}
469178479Sjb
470178479Sjb	idp->di_ctfp = dtt.dtt_ctfp;
471178479Sjb	idp->di_type = dtt.dtt_type;
472178479Sjb
473268578Srpaulo	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
474178479Sjb}
475178479Sjb
476178479Sjb/*ARGSUSED*/
477178479Sjbstatic void
478178479Sjbdt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
479178479Sjb{
480178479Sjb	if (idp->di_type == CTF_ERR) {
481178479Sjb		dtrace_hdl_t *dtp = yypcb->pcb_hdl;
482178479Sjb		dtrace_typeinfo_t dtt;
483178479Sjb
484178479Sjb		if (dt_type_lookup(idp->di_iarg, &dtt) == -1) {
485178479Sjb			xyerror(D_UNKNOWN,
486178479Sjb			    "failed to resolve type %s for identifier %s: %s\n",
487178479Sjb			    (const char *)idp->di_iarg, idp->di_name,
488178479Sjb			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
489178479Sjb		}
490178479Sjb
491178479Sjb		idp->di_ctfp = dtt.dtt_ctfp;
492178479Sjb		idp->di_type = dtt.dtt_type;
493178479Sjb	}
494178479Sjb
495268578Srpaulo	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
496178479Sjb}
497178479Sjb
498178479Sjb/*ARGSUSED*/
499178479Sjbstatic void
500178479Sjbdt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
501178479Sjb{
502178479Sjb	if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
503268578Srpaulo		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
504178479Sjb}
505178479Sjb
506178479Sjbstatic void
507178479Sjbdt_idcook_inline(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
508178479Sjb{
509178479Sjb	if (idp->di_kind == DT_IDENT_ARRAY)
510178479Sjb		dt_idcook_assc(dnp, idp, argc, args);
511178479Sjb	else
512178479Sjb		dt_idcook_thaw(dnp, idp, argc, args);
513178479Sjb}
514178479Sjb
515178479Sjbstatic void
516178479Sjbdt_iddtor_sign(dt_ident_t *idp)
517178479Sjb{
518178479Sjb	if (idp->di_data != NULL)
519178479Sjb		free(((dt_idsig_t *)idp->di_data)->dis_args);
520178479Sjb	free(idp->di_data);
521178479Sjb}
522178479Sjb
523178479Sjbstatic void
524178479Sjbdt_iddtor_free(dt_ident_t *idp)
525178479Sjb{
526178479Sjb	free(idp->di_data);
527178479Sjb}
528178479Sjb
529178479Sjbstatic void
530178479Sjbdt_iddtor_inline(dt_ident_t *idp)
531178479Sjb{
532178479Sjb	dt_idnode_t *inp = idp->di_iarg;
533178479Sjb
534178479Sjb	if (inp != NULL) {
535178479Sjb		dt_node_link_free(&inp->din_list);
536178479Sjb
537178479Sjb		if (inp->din_hash != NULL)
538178479Sjb			dt_idhash_destroy(inp->din_hash);
539178479Sjb
540178479Sjb		free(inp->din_argv);
541178479Sjb		free(inp);
542178479Sjb	}
543178479Sjb
544178479Sjb	if (idp->di_kind == DT_IDENT_ARRAY)
545178479Sjb		dt_iddtor_sign(idp);
546178479Sjb	else
547178479Sjb		dt_iddtor_free(idp);
548178479Sjb}
549178479Sjb
550178479Sjb/*ARGSUSED*/
551178479Sjbstatic void
552178479Sjbdt_iddtor_none(dt_ident_t *idp)
553178479Sjb{
554178479Sjb	/* do nothing */
555178479Sjb}
556178479Sjb
557178479Sjbstatic void
558178479Sjbdt_iddtor_probe(dt_ident_t *idp)
559178479Sjb{
560178479Sjb	if (idp->di_data != NULL)
561178479Sjb		dt_probe_destroy(idp->di_data);
562178479Sjb}
563178479Sjb
564178479Sjbstatic size_t
565178479Sjbdt_idsize_type(dt_ident_t *idp)
566178479Sjb{
567178479Sjb	return (ctf_type_size(idp->di_ctfp, idp->di_type));
568178479Sjb}
569178479Sjb
570178479Sjb/*ARGSUSED*/
571178479Sjbstatic size_t
572178479Sjbdt_idsize_none(dt_ident_t *idp)
573178479Sjb{
574178479Sjb	return (0);
575178479Sjb}
576178479Sjb
577178479Sjbconst dt_idops_t dt_idops_assc = {
578178479Sjb	dt_idcook_assc,
579178479Sjb	dt_iddtor_sign,
580178479Sjb	dt_idsize_none,
581178479Sjb};
582178479Sjb
583178479Sjbconst dt_idops_t dt_idops_func = {
584178479Sjb	dt_idcook_func,
585178479Sjb	dt_iddtor_sign,
586178479Sjb	dt_idsize_none,
587178479Sjb};
588178479Sjb
589178479Sjbconst dt_idops_t dt_idops_args = {
590178479Sjb	dt_idcook_args,
591178479Sjb	dt_iddtor_none,
592178479Sjb	dt_idsize_none,
593178479Sjb};
594178479Sjb
595178479Sjbconst dt_idops_t dt_idops_regs = {
596178479Sjb	dt_idcook_regs,
597178479Sjb	dt_iddtor_free,
598178479Sjb	dt_idsize_none,
599178479Sjb};
600178479Sjb
601178479Sjbconst dt_idops_t dt_idops_type = {
602178479Sjb	dt_idcook_type,
603178479Sjb	dt_iddtor_free,
604178479Sjb	dt_idsize_type,
605178479Sjb};
606178479Sjb
607178479Sjbconst dt_idops_t dt_idops_thaw = {
608178479Sjb	dt_idcook_thaw,
609178479Sjb	dt_iddtor_free,
610178479Sjb	dt_idsize_type,
611178479Sjb};
612178479Sjb
613178479Sjbconst dt_idops_t dt_idops_inline = {
614178479Sjb	dt_idcook_inline,
615178479Sjb	dt_iddtor_inline,
616178479Sjb	dt_idsize_type,
617178479Sjb};
618178479Sjb
619178479Sjbconst dt_idops_t dt_idops_probe = {
620178479Sjb	dt_idcook_thaw,
621178479Sjb	dt_iddtor_probe,
622178479Sjb	dt_idsize_none,
623178479Sjb};
624178479Sjb
625178479Sjbstatic void
626178479Sjbdt_idhash_populate(dt_idhash_t *dhp)
627178479Sjb{
628178479Sjb	const dt_ident_t *idp = dhp->dh_tmpl;
629178479Sjb
630178479Sjb	dhp->dh_tmpl = NULL; /* clear dh_tmpl first to avoid recursion */
631178479Sjb	dt_dprintf("populating %s idhash from %p\n", dhp->dh_name, (void *)idp);
632178479Sjb
633178479Sjb	for (; idp->di_name != NULL; idp++) {
634178479Sjb		if (dt_idhash_insert(dhp, idp->di_name,
635178479Sjb		    idp->di_kind, idp->di_flags, idp->di_id, idp->di_attr,
636178479Sjb		    idp->di_vers, idp->di_ops ? idp->di_ops : &dt_idops_thaw,
637178479Sjb		    idp->di_iarg, 0) == NULL)
638178479Sjb			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
639178479Sjb	}
640178479Sjb}
641178479Sjb
642178479Sjbdt_idhash_t *
643178479Sjbdt_idhash_create(const char *name, const dt_ident_t *tmpl,
644178479Sjb    uint_t min, uint_t max)
645178479Sjb{
646178479Sjb	dt_idhash_t *dhp;
647178479Sjb	size_t size;
648178479Sjb
649178479Sjb	assert(min <= max);
650178479Sjb
651178479Sjb	size = sizeof (dt_idhash_t) +
652178479Sjb	    sizeof (dt_ident_t *) * (_dtrace_strbuckets - 1);
653178479Sjb
654178479Sjb	if ((dhp = malloc(size)) == NULL)
655178479Sjb		return (NULL);
656178479Sjb
657178479Sjb	bzero(dhp, size);
658178479Sjb	dhp->dh_name = name;
659178479Sjb	dhp->dh_tmpl = tmpl;
660178479Sjb	dhp->dh_nextid = min;
661178479Sjb	dhp->dh_minid = min;
662178479Sjb	dhp->dh_maxid = max;
663178479Sjb	dhp->dh_hashsz = _dtrace_strbuckets;
664178479Sjb
665178479Sjb	return (dhp);
666178479Sjb}
667178479Sjb
668178479Sjb/*
669178479Sjb * Destroy an entire identifier hash.  This must be done using two passes with
670178479Sjb * an inlined version of dt_ident_destroy() to avoid referencing freed memory.
671178479Sjb * In the first pass di_dtor() is called for all identifiers; then the second
672178479Sjb * pass frees the actual dt_ident_t's.  These must be done separately because
673178479Sjb * a di_dtor() may operate on data structures which contain references to other
674178479Sjb * identifiers inside of this hash itself (e.g. a global inline definition
675178479Sjb * which contains a parse tree that refers to another global variable).
676178479Sjb */
677178479Sjbvoid
678178479Sjbdt_idhash_destroy(dt_idhash_t *dhp)
679178479Sjb{
680178479Sjb	dt_ident_t *idp, *next;
681178479Sjb	ulong_t i;
682178479Sjb
683178479Sjb	for (i = 0; i < dhp->dh_hashsz; i++) {
684178479Sjb		for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) {
685178479Sjb			next = idp->di_next;
686178479Sjb			idp->di_ops->di_dtor(idp);
687178479Sjb		}
688178479Sjb	}
689178479Sjb
690178479Sjb	for (i = 0; i < dhp->dh_hashsz; i++) {
691178479Sjb		for (idp = dhp->dh_hash[i]; idp != NULL; idp = next) {
692178479Sjb			next = idp->di_next;
693178479Sjb			free(idp->di_name);
694178479Sjb			free(idp);
695178479Sjb		}
696178479Sjb	}
697178479Sjb
698178479Sjb	free(dhp);
699178479Sjb}
700178479Sjb
701178479Sjbvoid
702178479Sjbdt_idhash_update(dt_idhash_t *dhp)
703178479Sjb{
704178479Sjb	uint_t nextid = dhp->dh_minid;
705178479Sjb	dt_ident_t *idp;
706178479Sjb	ulong_t i;
707178479Sjb
708178479Sjb	for (i = 0; i < dhp->dh_hashsz; i++) {
709178479Sjb		for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next) {
710178479Sjb			/*
711178479Sjb			 * Right now we're hard coding which types need to be
712178479Sjb			 * reset, but ideally this would be done dynamically.
713178479Sjb			 */
714178479Sjb			if (idp->di_kind == DT_IDENT_ARRAY ||
715178479Sjb			    idp->di_kind == DT_IDENT_SCALAR ||
716178479Sjb			    idp->di_kind == DT_IDENT_AGG)
717178479Sjb				nextid = MAX(nextid, idp->di_id + 1);
718178479Sjb		}
719178479Sjb	}
720178479Sjb
721178479Sjb	dhp->dh_nextid = nextid;
722178479Sjb}
723178479Sjb
724178479Sjbdt_ident_t *
725178479Sjbdt_idhash_lookup(dt_idhash_t *dhp, const char *name)
726178479Sjb{
727178479Sjb	size_t len;
728178479Sjb	ulong_t h = dt_strtab_hash(name, &len) % dhp->dh_hashsz;
729178479Sjb	dt_ident_t *idp;
730178479Sjb
731178479Sjb	if (dhp->dh_tmpl != NULL)
732178479Sjb		dt_idhash_populate(dhp); /* fill hash w/ initial population */
733178479Sjb
734178479Sjb	for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) {
735178479Sjb		if (strcmp(idp->di_name, name) == 0)
736178479Sjb			return (idp);
737178479Sjb	}
738178479Sjb
739178479Sjb	return (NULL);
740178479Sjb}
741178479Sjb
742178479Sjbint
743178479Sjbdt_idhash_nextid(dt_idhash_t *dhp, uint_t *p)
744178479Sjb{
745178479Sjb	if (dhp->dh_nextid >= dhp->dh_maxid)
746178479Sjb		return (-1); /* no more id's are free to allocate */
747178479Sjb
748178479Sjb	*p = dhp->dh_nextid++;
749178479Sjb	return (0);
750178479Sjb}
751178479Sjb
752178479Sjbulong_t
753178479Sjbdt_idhash_size(const dt_idhash_t *dhp)
754178479Sjb{
755178479Sjb	return (dhp->dh_nelems);
756178479Sjb}
757178479Sjb
758178479Sjbconst char *
759178479Sjbdt_idhash_name(const dt_idhash_t *dhp)
760178479Sjb{
761178479Sjb	return (dhp->dh_name);
762178479Sjb}
763178479Sjb
764178479Sjbdt_ident_t *
765178479Sjbdt_idhash_insert(dt_idhash_t *dhp, const char *name, ushort_t kind,
766178479Sjb    ushort_t flags, uint_t id, dtrace_attribute_t attr, uint_t vers,
767178479Sjb    const dt_idops_t *ops, void *iarg, ulong_t gen)
768178479Sjb{
769178479Sjb	dt_ident_t *idp;
770178479Sjb	ulong_t h;
771178479Sjb
772178479Sjb	if (dhp->dh_tmpl != NULL)
773178479Sjb		dt_idhash_populate(dhp); /* fill hash w/ initial population */
774178479Sjb
775178479Sjb	idp = dt_ident_create(name, kind, flags, id,
776178479Sjb	    attr, vers, ops, iarg, gen);
777178479Sjb
778178479Sjb	if (idp == NULL)
779178479Sjb		return (NULL);
780178479Sjb
781178479Sjb	h = dt_strtab_hash(name, NULL) % dhp->dh_hashsz;
782178479Sjb	idp->di_next = dhp->dh_hash[h];
783178479Sjb
784178479Sjb	dhp->dh_hash[h] = idp;
785178479Sjb	dhp->dh_nelems++;
786178479Sjb
787178479Sjb	if (dhp->dh_defer != NULL)
788178479Sjb		dhp->dh_defer(dhp, idp);
789178479Sjb
790178479Sjb	return (idp);
791178479Sjb}
792178479Sjb
793178479Sjbvoid
794178479Sjbdt_idhash_xinsert(dt_idhash_t *dhp, dt_ident_t *idp)
795178479Sjb{
796178479Sjb	ulong_t h;
797178479Sjb
798178479Sjb	if (dhp->dh_tmpl != NULL)
799178479Sjb		dt_idhash_populate(dhp); /* fill hash w/ initial population */
800178479Sjb
801178479Sjb	h = dt_strtab_hash(idp->di_name, NULL) % dhp->dh_hashsz;
802178479Sjb	idp->di_next = dhp->dh_hash[h];
803178479Sjb	idp->di_flags &= ~DT_IDFLG_ORPHAN;
804178479Sjb
805178479Sjb	dhp->dh_hash[h] = idp;
806178479Sjb	dhp->dh_nelems++;
807178479Sjb
808178479Sjb	if (dhp->dh_defer != NULL)
809178479Sjb		dhp->dh_defer(dhp, idp);
810178479Sjb}
811178479Sjb
812178479Sjbvoid
813178479Sjbdt_idhash_delete(dt_idhash_t *dhp, dt_ident_t *key)
814178479Sjb{
815178479Sjb	size_t len;
816178479Sjb	ulong_t h = dt_strtab_hash(key->di_name, &len) % dhp->dh_hashsz;
817178479Sjb	dt_ident_t **pp = &dhp->dh_hash[h];
818178479Sjb	dt_ident_t *idp;
819178479Sjb
820178479Sjb	for (idp = dhp->dh_hash[h]; idp != NULL; idp = idp->di_next) {
821178479Sjb		if (idp == key)
822178479Sjb			break;
823178479Sjb		else
824178479Sjb			pp = &idp->di_next;
825178479Sjb	}
826178479Sjb
827178479Sjb	assert(idp == key);
828178479Sjb	*pp = idp->di_next;
829178479Sjb
830178479Sjb	assert(dhp->dh_nelems != 0);
831178479Sjb	dhp->dh_nelems--;
832178479Sjb
833178479Sjb	if (!(idp->di_flags & DT_IDFLG_ORPHAN))
834178479Sjb		dt_ident_destroy(idp);
835178479Sjb}
836178479Sjb
837178479Sjbstatic int
838178479Sjbdt_idhash_comp(const void *lp, const void *rp)
839178479Sjb{
840178479Sjb	const dt_ident_t *lhs = *((const dt_ident_t **)lp);
841178479Sjb	const dt_ident_t *rhs = *((const dt_ident_t **)rp);
842178479Sjb
843178479Sjb	if (lhs->di_id != rhs->di_id)
844178479Sjb		return ((int)(lhs->di_id - rhs->di_id));
845178479Sjb	else
846178479Sjb		return (strcmp(lhs->di_name, rhs->di_name));
847178479Sjb}
848178479Sjb
849178479Sjbint
850178479Sjbdt_idhash_iter(dt_idhash_t *dhp, dt_idhash_f *func, void *data)
851178479Sjb{
852178479Sjb	dt_ident_t **ids;
853178479Sjb	dt_ident_t *idp;
854178479Sjb	ulong_t i, j, n;
855178479Sjb	int rv;
856178479Sjb
857178479Sjb	if (dhp->dh_tmpl != NULL)
858178479Sjb		dt_idhash_populate(dhp); /* fill hash w/ initial population */
859178479Sjb
860178479Sjb	n = dhp->dh_nelems;
861178479Sjb	ids = alloca(sizeof (dt_ident_t *) * n);
862178479Sjb
863178479Sjb	for (i = 0, j = 0; i < dhp->dh_hashsz; i++) {
864178479Sjb		for (idp = dhp->dh_hash[i]; idp != NULL; idp = idp->di_next)
865178479Sjb			ids[j++] = idp;
866178479Sjb	}
867178479Sjb
868178479Sjb	qsort(ids, dhp->dh_nelems, sizeof (dt_ident_t *), dt_idhash_comp);
869178479Sjb
870178479Sjb	for (i = 0; i < n; i++) {
871178479Sjb		if ((rv = func(dhp, ids[i], data)) != 0)
872178479Sjb			return (rv);
873178479Sjb	}
874178479Sjb
875178479Sjb	return (0);
876178479Sjb}
877178479Sjb
878178479Sjbdt_ident_t *
879178479Sjbdt_idstack_lookup(dt_idstack_t *sp, const char *name)
880178479Sjb{
881178479Sjb	dt_idhash_t *dhp;
882178479Sjb	dt_ident_t *idp;
883178479Sjb
884178479Sjb	for (dhp = dt_list_prev(&sp->dids_list);
885178479Sjb	    dhp != NULL; dhp = dt_list_prev(dhp)) {
886178479Sjb		if ((idp = dt_idhash_lookup(dhp, name)) != NULL)
887178479Sjb			return (idp);
888178479Sjb	}
889178479Sjb
890178479Sjb	return (NULL);
891178479Sjb}
892178479Sjb
893178479Sjbvoid
894178479Sjbdt_idstack_push(dt_idstack_t *sp, dt_idhash_t *dhp)
895178479Sjb{
896178479Sjb	dt_list_append(&sp->dids_list, dhp);
897178479Sjb}
898178479Sjb
899178479Sjbvoid
900178479Sjbdt_idstack_pop(dt_idstack_t *sp, dt_idhash_t *dhp)
901178479Sjb{
902178479Sjb	assert(dt_list_prev(&sp->dids_list) == dhp);
903178479Sjb	dt_list_delete(&sp->dids_list, dhp);
904178479Sjb}
905178479Sjb
906178479Sjbdt_ident_t *
907178479Sjbdt_ident_create(const char *name, ushort_t kind, ushort_t flags, uint_t id,
908178479Sjb    dtrace_attribute_t attr, uint_t vers,
909178479Sjb    const dt_idops_t *ops, void *iarg, ulong_t gen)
910178479Sjb{
911178479Sjb	dt_ident_t *idp;
912178479Sjb	char *s = NULL;
913178479Sjb
914178479Sjb	if ((name != NULL && (s = strdup(name)) == NULL) ||
915178479Sjb	    (idp = malloc(sizeof (dt_ident_t))) == NULL) {
916178479Sjb		free(s);
917178479Sjb		return (NULL);
918178479Sjb	}
919178479Sjb
920178479Sjb	idp->di_name = s;
921178479Sjb	idp->di_kind = kind;
922178479Sjb	idp->di_flags = flags;
923178479Sjb	idp->di_id = id;
924178479Sjb	idp->di_attr = attr;
925178479Sjb	idp->di_vers = vers;
926178479Sjb	idp->di_ops = ops;
927178479Sjb	idp->di_iarg = iarg;
928178479Sjb	idp->di_data = NULL;
929178479Sjb	idp->di_ctfp = NULL;
930178479Sjb	idp->di_type = CTF_ERR;
931178479Sjb	idp->di_next = NULL;
932178479Sjb	idp->di_gen = gen;
933178479Sjb	idp->di_lineno = yylineno;
934178479Sjb
935178479Sjb	return (idp);
936178479Sjb}
937178479Sjb
938178479Sjb/*
939178479Sjb * Destroy an individual identifier.  This code must be kept in sync with the
940178479Sjb * dt_idhash_destroy() function below, which separates out the call to di_dtor.
941178479Sjb */
942178479Sjbvoid
943178479Sjbdt_ident_destroy(dt_ident_t *idp)
944178479Sjb{
945178479Sjb	idp->di_ops->di_dtor(idp);
946178479Sjb	free(idp->di_name);
947178479Sjb	free(idp);
948178479Sjb}
949178479Sjb
950178479Sjbvoid
951178479Sjbdt_ident_morph(dt_ident_t *idp, ushort_t kind,
952178479Sjb    const dt_idops_t *ops, void *iarg)
953178479Sjb{
954178479Sjb	idp->di_ops->di_dtor(idp);
955178479Sjb	idp->di_kind = kind;
956178479Sjb	idp->di_ops = ops;
957178479Sjb	idp->di_iarg = iarg;
958178479Sjb	idp->di_data = NULL;
959178479Sjb}
960178479Sjb
961178479Sjbdtrace_attribute_t
962178479Sjbdt_ident_cook(dt_node_t *dnp, dt_ident_t *idp, dt_node_t **pargp)
963178479Sjb{
964178479Sjb	dtrace_attribute_t attr;
965178479Sjb	dt_node_t *args, *argp;
966178479Sjb	int argc = 0;
967178479Sjb
968178479Sjb	attr = dt_node_list_cook(pargp, DT_IDFLG_REF);
969178479Sjb	args = pargp ? *pargp : NULL;
970178479Sjb
971178479Sjb	for (argp = args; argp != NULL; argp = argp->dn_list)
972178479Sjb		argc++;
973178479Sjb
974178479Sjb	idp->di_ops->di_cook(dnp, idp, argc, args);
975178479Sjb
976178479Sjb	if (idp->di_flags & DT_IDFLG_USER)
977178479Sjb		dnp->dn_flags |= DT_NF_USERLAND;
978178479Sjb
979178479Sjb	return (dt_attr_min(attr, idp->di_attr));
980178479Sjb}
981178479Sjb
982178479Sjbvoid
983178479Sjbdt_ident_type_assign(dt_ident_t *idp, ctf_file_t *fp, ctf_id_t type)
984178479Sjb{
985178479Sjb	idp->di_ctfp = fp;
986178479Sjb	idp->di_type = type;
987178479Sjb}
988178479Sjb
989178479Sjbdt_ident_t *
990178479Sjbdt_ident_resolve(dt_ident_t *idp)
991178479Sjb{
992178479Sjb	while (idp->di_flags & DT_IDFLG_INLINE) {
993178479Sjb		const dt_node_t *dnp = ((dt_idnode_t *)idp->di_iarg)->din_root;
994178479Sjb
995178479Sjb		if (dnp == NULL)
996178479Sjb			break; /* can't resolve any further yet */
997178479Sjb
998178479Sjb		switch (dnp->dn_kind) {
999178479Sjb		case DT_NODE_VAR:
1000178479Sjb		case DT_NODE_SYM:
1001178479Sjb		case DT_NODE_FUNC:
1002178479Sjb		case DT_NODE_AGG:
1003178479Sjb		case DT_NODE_INLINE:
1004178479Sjb		case DT_NODE_PROBE:
1005178479Sjb			idp = dnp->dn_ident;
1006178479Sjb			continue;
1007178479Sjb		}
1008178479Sjb
1009178479Sjb		if (dt_node_is_dynamic(dnp))
1010178479Sjb			idp = dnp->dn_ident;
1011178479Sjb		else
1012178479Sjb			break;
1013178479Sjb	}
1014178479Sjb
1015178479Sjb	return (idp);
1016178479Sjb}
1017178479Sjb
1018178479Sjbsize_t
1019178479Sjbdt_ident_size(dt_ident_t *idp)
1020178479Sjb{
1021178479Sjb	idp = dt_ident_resolve(idp);
1022178479Sjb	return (idp->di_ops->di_size(idp));
1023178479Sjb}
1024178479Sjb
1025178479Sjbint
1026178479Sjbdt_ident_unref(const dt_ident_t *idp)
1027178479Sjb{
1028178479Sjb	return (idp->di_gen == yypcb->pcb_hdl->dt_gen &&
1029178479Sjb	    (idp->di_flags & (DT_IDFLG_REF|DT_IDFLG_MOD|DT_IDFLG_DECL)) == 0);
1030178479Sjb}
1031178479Sjb
1032178479Sjbconst char *
1033178479Sjbdt_idkind_name(uint_t kind)
1034178479Sjb{
1035178479Sjb	switch (kind) {
1036178479Sjb	case DT_IDENT_ARRAY:	return ("associative array");
1037178479Sjb	case DT_IDENT_SCALAR:	return ("scalar");
1038178479Sjb	case DT_IDENT_PTR:	return ("pointer");
1039178479Sjb	case DT_IDENT_FUNC:	return ("function");
1040178479Sjb	case DT_IDENT_AGG:	return ("aggregation");
1041178479Sjb	case DT_IDENT_AGGFUNC:	return ("aggregating function");
1042178479Sjb	case DT_IDENT_ACTFUNC:	return ("tracing function");
1043178479Sjb	case DT_IDENT_XLSOU:	return ("translated data");
1044178479Sjb	case DT_IDENT_XLPTR:	return ("pointer to translated data");
1045178479Sjb	case DT_IDENT_SYMBOL:	return ("external symbol reference");
1046178479Sjb	case DT_IDENT_ENUM:	return ("enumerator");
1047178479Sjb	case DT_IDENT_PRAGAT:	return ("#pragma attributes");
1048178479Sjb	case DT_IDENT_PRAGBN:	return ("#pragma binding");
1049178479Sjb	case DT_IDENT_PROBE:	return ("probe definition");
1050178479Sjb	default:		return ("<?>");
1051178479Sjb	}
1052178479Sjb}
1053