17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
523a1cceRoger A. Faulkner * Common Development and Distribution License (the "License").
623a1cceRoger A. Faulkner * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
21e4586ebmws
227c478bdstevel@tonic-gate/*
2323a1cceRoger A. Faulkner * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24bc1f688Robert Mustacchi * Copyright (c) 2015, Joyent Inc. All rights reserved.
25c3bd3abMatthew Ahrens * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
267c478bdstevel@tonic-gate */
277c478bdstevel@tonic-gate
287c478bdstevel@tonic-gate/*
297c478bdstevel@tonic-gate * DTrace D Language Parser
307c478bdstevel@tonic-gate *
317c478bdstevel@tonic-gate * The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the
327c478bdstevel@tonic-gate * parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles
337c478bdstevel@tonic-gate * the construction of the parse tree nodes and their syntactic validation.
347c478bdstevel@tonic-gate * The parse tree is constructed of dt_node_t structures (see <dt_parser.h>)
357c478bdstevel@tonic-gate * that are built in two passes: (1) the "create" pass, where the parse tree
367c478bdstevel@tonic-gate * nodes are allocated by calls from the grammar to dt_node_*() subroutines,
377c478bdstevel@tonic-gate * and (2) the "cook" pass, where nodes are coalesced, assigned D types, and
387c478bdstevel@tonic-gate * validated according to the syntactic rules of the language.
397c478bdstevel@tonic-gate *
407c478bdstevel@tonic-gate * All node allocations are performed using dt_node_alloc().  All node frees
417c478bdstevel@tonic-gate * during the parsing phase are performed by dt_node_free(), which frees node-
427c478bdstevel@tonic-gate * internal state but does not actually free the nodes.  All final node frees
437c478bdstevel@tonic-gate * are done as part of the end of dt_compile() or as part of destroying
447c478bdstevel@tonic-gate * persistent identifiers or translators which have embedded nodes.
457c478bdstevel@tonic-gate *
467c478bdstevel@tonic-gate * The dt_node_* routines that implement pass (1) may allocate new nodes.  The
477c478bdstevel@tonic-gate * dt_cook_* routines that implement pass (2) may *not* allocate new nodes.
487c478bdstevel@tonic-gate * They may free existing nodes using dt_node_free(), but they may not actually
497c478bdstevel@tonic-gate * deallocate any dt_node_t's.  Currently dt_cook_op2() is an exception to this
507c478bdstevel@tonic-gate * rule: see the comments therein for how this issue is resolved.
517c478bdstevel@tonic-gate *
527c478bdstevel@tonic-gate * The dt_cook_* routines are responsible for (at minimum) setting the final
537c478bdstevel@tonic-gate * node type (dn_ctfp/dn_type) and attributes (dn_attr).  If dn_ctfp/dn_type
547c478bdstevel@tonic-gate * are set manually (i.e. not by one of the type assignment functions), then
557c478bdstevel@tonic-gate * the DT_NF_COOKED flag must be set manually on the node.
567c478bdstevel@tonic-gate *
577c478bdstevel@tonic-gate * The cooking pass can be applied to the same parse tree more than once (used
587c478bdstevel@tonic-gate * in the case of a comma-separated list of probe descriptions).  As such, the
597c478bdstevel@tonic-gate * cook routines must not perform any parse tree transformations which would
607c478bdstevel@tonic-gate * be invalid if the tree were subsequently cooked using a different context.
617c478bdstevel@tonic-gate *
627c478bdstevel@tonic-gate * The dn_ctfp and dn_type fields form the type of the node.  This tuple can
637c478bdstevel@tonic-gate * take on the following set of values, which form our type invariants:
647c478bdstevel@tonic-gate *
657c478bdstevel@tonic-gate * 1. dn_ctfp = NULL, dn_type = CTF_ERR
667c478bdstevel@tonic-gate *
677c478bdstevel@tonic-gate *    In this state, the node has unknown type and is not yet cooked.  The
687c478bdstevel@tonic-gate *    DT_NF_COOKED flag is not yet set on the node.
697c478bdstevel@tonic-gate *
707c478bdstevel@tonic-gate * 2. dn_ctfp = DT_DYN_CTFP(dtp), dn_type = DT_DYN_TYPE(dtp)
717c478bdstevel@tonic-gate *
727c478bdstevel@tonic-gate *    In this state, the node is a dynamic D type.  This means that generic
737c478bdstevel@tonic-gate *    operations are not valid on this node and only code that knows how to
747c478bdstevel@tonic-gate *    examine the inner details of the node can operate on it.  A <DYN> node
757c478bdstevel@tonic-gate *    must have dn_ident set to point to an identifier describing the object
767c478bdstevel@tonic-gate *    and its type.  The DT_NF_REF flag is set for all nodes of type <DYN>.
777c478bdstevel@tonic-gate *    At present, the D compiler uses the <DYN> type for:
787c478bdstevel@tonic-gate *
797c478bdstevel@tonic-gate *    - associative arrays that do not yet have a value type defined
807c478bdstevel@tonic-gate *    - translated data (i.e. the result of the xlate operator)
817c478bdstevel@tonic-gate *    - aggregations
827c478bdstevel@tonic-gate *
837c478bdstevel@tonic-gate * 3. dn_ctfp = DT_STR_CTFP(dtp), dn_type = DT_STR_TYPE(dtp)
847c478bdstevel@tonic-gate *
857c478bdstevel@tonic-gate *    In this state, the node is of type D string.  The string type is really
867c478bdstevel@tonic-gate *    a char[0] typedef, but requires special handling throughout the compiler.
877c478bdstevel@tonic-gate *
887c478bdstevel@tonic-gate * 4. dn_ctfp != NULL, dn_type = any other type ID
897c478bdstevel@tonic-gate *
907c478bdstevel@tonic-gate *    In this state, the node is of some known D/CTF type.  The normal libctf
917c478bdstevel@tonic-gate *    APIs can be used to learn more about the type name or structure.  When
927c478bdstevel@tonic-gate *    the type is assigned, the DT_NF_SIGNED, DT_NF_REF, and DT_NF_BITFIELD
937c478bdstevel@tonic-gate *    flags cache the corresponding attributes of the underlying CTF type.
947c478bdstevel@tonic-gate */
957c478bdstevel@tonic-gate
967c478bdstevel@tonic-gate#include <sys/param.h>
97e5803b7Adam H. Leventhal#include <sys/sysmacros.h>
987c478bdstevel@tonic-gate#include <limits.h>
997c478bdstevel@tonic-gate#include <setjmp.h>
1007c478bdstevel@tonic-gate#include <strings.h>
1017c478bdstevel@tonic-gate#include <assert.h>
1027c478bdstevel@tonic-gate#include <alloca.h>
1037c478bdstevel@tonic-gate#include <stdlib.h>
1047c478bdstevel@tonic-gate#include <stdarg.h>
1057c478bdstevel@tonic-gate#include <stdio.h>
1067c478bdstevel@tonic-gate#include <errno.h>
1077c478bdstevel@tonic-gate#include <ctype.h>
1087c478bdstevel@tonic-gate
1097c478bdstevel@tonic-gate#include <dt_impl.h>
1107c478bdstevel@tonic-gate#include <dt_grammar.h>
1117c478bdstevel@tonic-gate#include <dt_module.h>
1127c478bdstevel@tonic-gate#include <dt_provider.h>
1137c478bdstevel@tonic-gate#include <dt_string.h>
1147c478bdstevel@tonic-gate#include <dt_as.h>
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gatedt_pcb_t *yypcb;	/* current control block for parser */
1177c478bdstevel@tonic-gatedt_node_t *yypragma;	/* lex token list for control lines */
1187c478bdstevel@tonic-gatechar yyintprefix;	/* int token macro prefix (+/-) */
1197c478bdstevel@tonic-gatechar yyintsuffix[4];	/* int token suffix string [uU][lL] */
1207c478bdstevel@tonic-gateint yyintdecimal;	/* int token format flag (1=decimal, 0=octal/hex) */
1217c478bdstevel@tonic-gate
1227c478bdstevel@tonic-gatestatic const char *
1237c478bdstevel@tonic-gateopstr(int op)
1247c478bdstevel@tonic-gate{
1257c478bdstevel@tonic-gate	switch (op) {
1267c478bdstevel@tonic-gate	case DT_TOK_COMMA:	return (",");
1277c478bdstevel@tonic-gate	case DT_TOK_ELLIPSIS:	return ("...");
1287c478bdstevel@tonic-gate	case DT_TOK_ASGN:	return ("=");
1297c478bdstevel@tonic-gate	case DT_TOK_ADD_EQ:	return ("+=");
1307c478bdstevel@tonic-gate	case DT_TOK_SUB_EQ:	return ("-=");
1317c478bdstevel@tonic-gate	case DT_TOK_MUL_EQ:	return ("*=");
1327c478bdstevel@tonic-gate	case DT_TOK_DIV_EQ:	return ("/=");
1337c478bdstevel@tonic-gate	case DT_TOK_MOD_EQ:	return ("%=");
1347c478bdstevel@tonic-gate	case DT_TOK_AND_EQ:	return ("&=");
1357c478bdstevel@tonic-gate	case DT_TOK_XOR_EQ:	return ("^=");
1367c478bdstevel@tonic-gate	case DT_TOK_OR_EQ:	return ("|=");
1377c478bdstevel@tonic-gate	case DT_TOK_LSH_EQ:	return ("<<=");
1387c478bdstevel@tonic-gate	case DT_TOK_RSH_EQ:	return (">>=");
1397c478bdstevel@tonic-gate	case DT_TOK_QUESTION:	return ("?");
1407c478bdstevel@tonic-gate	case DT_TOK_COLON:	return (":");
1417c478bdstevel@tonic-gate	case DT_TOK_LOR:	return ("||");
1427c478bdstevel@tonic-gate	case DT_TOK_LXOR:	return ("^^");
1437c478bdstevel@tonic-gate	case DT_TOK_LAND:	return ("&&");
1447c478bdstevel@tonic-gate	case DT_TOK_BOR:	return ("|");
1457c478bdstevel@tonic-gate	case DT_TOK_XOR:	return ("^");
1467c478bdstevel@tonic-gate	case DT_TOK_BAND:	return ("&");
1477c478bdstevel@tonic-gate	case DT_TOK_EQU:	return ("==");
1487c478bdstevel@tonic-gate	case DT_TOK_NEQ:	return ("!=");
1497c478bdstevel@tonic-gate	case DT_TOK_LT:		return ("<");
1507c478bdstevel@tonic-gate	case DT_TOK_LE:		return ("<=");
1517c478bdstevel@tonic-gate	case DT_TOK_GT:		return (">");
1527c478bdstevel@tonic-gate	case DT_TOK_GE:		return (">=");
1537c478bdstevel@tonic-gate	case DT_TOK_LSH:	return ("<<");
1547c478bdstevel@tonic-gate	case DT_TOK_RSH:	return (">>");
1557c478bdstevel@tonic-gate	case DT_TOK_ADD:	return ("+");
1567c478bdstevel@tonic-gate	case DT_TOK_SUB:	return ("-");
1577c478bdstevel@tonic-gate	case DT_TOK_MUL:	return ("*");
1587c478bdstevel@tonic-gate	case DT_TOK_DIV:	return ("/");
1597c478bdstevel@tonic-gate	case DT_TOK_MOD:	return ("%");
1607c478bdstevel@tonic-gate	case DT_TOK_LNEG:	return ("!");
1617c478bdstevel@tonic-gate	case DT_TOK_BNEG:	return ("~");
1627c478bdstevel@tonic-gate	case DT_TOK_ADDADD:	return ("++");
1637c478bdstevel@tonic-gate	case DT_TOK_PREINC:	return ("++");
1647c478bdstevel@tonic-gate	case DT_TOK_POSTINC:	return ("++");
1657c478bdstevel@tonic-gate	case DT_TOK_SUBSUB:	return ("--");
1667c478bdstevel@tonic-gate	case DT_TOK_PREDEC:	return ("--");
1677c478bdstevel@tonic-gate	case DT_TOK_POSTDEC:	return ("--");
1687c478bdstevel@tonic-gate	case DT_TOK_IPOS:	return ("+");
1697c478bdstevel@tonic-gate	case DT_TOK_INEG:	return ("-");
1707c478bdstevel@tonic-gate	case DT_TOK_DEREF:	return ("*");
1717c478bdstevel@tonic-gate	case DT_TOK_ADDROF:	return ("&");
1727c478bdstevel@tonic-gate	case DT_TOK_OFFSETOF:	return ("offsetof");
1737c478bdstevel@tonic-gate	case DT_TOK_SIZEOF:	return ("sizeof");
1747c478bdstevel@tonic-gate	case DT_TOK_STRINGOF:	return ("stringof");
1757c478bdstevel@tonic-gate	case DT_TOK_XLATE:	return ("xlate");
1767c478bdstevel@tonic-gate	case DT_TOK_LPAR:	return ("(");
1777c478bdstevel@tonic-gate	case DT_TOK_RPAR:	return (")");
1787c478bdstevel@tonic-gate	case DT_TOK_LBRAC:	return ("[");
1797c478bdstevel@tonic-gate	case DT_TOK_RBRAC:	return ("]");
1807c478bdstevel@tonic-gate	case DT_TOK_PTR:	return ("->");
1817c478bdstevel@tonic-gate	case DT_TOK_DOT:	return (".");
1827c478bdstevel@tonic-gate	case DT_TOK_STRING:	return ("<string>");
1837c478bdstevel@tonic-gate	case DT_TOK_IDENT:	return ("<ident>");
1847c478bdstevel@tonic-gate	case DT_TOK_TNAME:	return ("<type>");
1857c478bdstevel@tonic-gate	case DT_TOK_INT:	return ("<int>");
1867c478bdstevel@tonic-gate	default:		return ("<?>");
1877c478bdstevel@tonic-gate	}
1887c478bdstevel@tonic-gate}
1897c478bdstevel@tonic-gate
1907c478bdstevel@tonic-gateint
1917c478bdstevel@tonic-gatedt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
1927c478bdstevel@tonic-gate{
1937c478bdstevel@tonic-gate	static const char delimiters[] = " \t\n\r\v\f*`";
1947c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
195a386cc1Robert Mustacchi	const char *p, *q, *r, *end, *obj;
1967c478bdstevel@tonic-gate
1977c478bdstevel@tonic-gate	for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
1987c478bdstevel@tonic-gate		while (isspace(*p))
1997c478bdstevel@tonic-gate			p++;	/* skip leading whitespace prior to token */
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate		if (p == end || (q = strpbrk(p + 1, delimiters)) == NULL)
2027c478bdstevel@tonic-gate			break;	/* empty string or single token remaining */
2037c478bdstevel@tonic-gate
2047c478bdstevel@tonic-gate		if (*q == '`') {
2057c478bdstevel@tonic-gate			char *object = alloca((size_t)(q - p) + 1);
2067c478bdstevel@tonic-gate			char *type = alloca((size_t)(end - s) + 1);
2077c478bdstevel@tonic-gate
2087c478bdstevel@tonic-gate			/*
2097c478bdstevel@tonic-gate			 * Copy from the start of the token (p) to the location
2107c478bdstevel@tonic-gate			 * backquote (q) to extract the nul-terminated object.
2117c478bdstevel@tonic-gate			 */
2127c478bdstevel@tonic-gate			bcopy(p, object, (size_t)(q - p));
2137c478bdstevel@tonic-gate			object[(size_t)(q - p)] = '\0';
2147c478bdstevel@tonic-gate
2157c478bdstevel@tonic-gate			/*
2167c478bdstevel@tonic-gate			 * Copy the original string up to the start of this
2177c478bdstevel@tonic-gate			 * token (p) into type, and then concatenate everything
2187c478bdstevel@tonic-gate			 * after q.  This is the type name without the object.
2197c478bdstevel@tonic-gate			 */
2207c478bdstevel@tonic-gate			bcopy(s, type, (size_t)(p - s));
2217c478bdstevel@tonic-gate			bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
2227c478bdstevel@tonic-gate
223a386cc1Robert Mustacchi			/*
224a386cc1Robert Mustacchi			 * There may be at most three delimeters. The second
225a386cc1Robert Mustacchi			 * delimeter is usually used to distinguish the type
226a386cc1Robert Mustacchi			 * within a given module, however, there could be a link
227a386cc1Robert Mustacchi			 * map id on the scene in which case that delimeter
228a386cc1Robert Mustacchi			 * would be the third. We determine presence of the lmid
229a386cc1Robert Mustacchi			 * if it rouglhly meets the from LM[0-9]
230a386cc1Robert Mustacchi			 */
231a386cc1Robert Mustacchi			if ((r = strchr(q + 1, '`')) != NULL &&
232a386cc1Robert Mustacchi			    ((r = strchr(r + 1, '`')) != NULL)) {
233a386cc1Robert Mustacchi				if (strchr(r + 1, '`') != NULL)
234a386cc1Robert Mustacchi					return (dt_set_errno(dtp,
235a386cc1Robert Mustacchi					    EDT_BADSCOPE));
236a386cc1Robert Mustacchi				if (q[1] != 'L' || q[2] != 'M')
237a386cc1Robert Mustacchi					return (dt_set_errno(dtp,
238a386cc1Robert Mustacchi					    EDT_BADSCOPE));
239a386cc1Robert Mustacchi			}
2407c478bdstevel@tonic-gate
2417c478bdstevel@tonic-gate			return (dtrace_lookup_by_type(dtp, object, type, tip));
2427c478bdstevel@tonic-gate		}
2437c478bdstevel@tonic-gate	}
2447c478bdstevel@tonic-gate
2457c478bdstevel@tonic-gate	if (yypcb->pcb_idepth != 0)
2467c478bdstevel@tonic-gate		obj = DTRACE_OBJ_CDEFS;
2477c478bdstevel@tonic-gate	else
2487c478bdstevel@tonic-gate		obj = DTRACE_OBJ_EVERY;
2497c478bdstevel@tonic-gate
2507c478bdstevel@tonic-gate	return (dtrace_lookup_by_type(dtp, obj, s, tip));
2517c478bdstevel@tonic-gate}
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate/*
2547c478bdstevel@tonic-gate * When we parse type expressions or parse an expression with unary "&", we
2557c478bdstevel@tonic-gate * need to find a type that is a pointer to a previously known type.
2567c478bdstevel@tonic-gate * Unfortunately CTF is limited to a per-container view, so ctf_type_pointer()
2577c478bdstevel@tonic-gate * alone does not suffice for our needs.  We provide a more intelligent wrapper
2587c478bdstevel@tonic-gate * for the compiler that attempts to compute a pointer to either the given type
2597c478bdstevel@tonic-gate * or its base (that is, we try both "foo_t *" and "struct foo *"), and also
2607c478bdstevel@tonic-gate * to potentially construct the required type on-the-fly.
2617c478bdstevel@tonic-gate */
2627c478bdstevel@tonic-gateint
2637c478bdstevel@tonic-gatedt_type_pointer(dtrace_typeinfo_t *tip)
2647c478bdstevel@tonic-gate{
2657c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2667c478bdstevel@tonic-gate	ctf_file_t *ctfp = tip->dtt_ctfp;
2677c478bdstevel@tonic-gate	ctf_id_t type = tip->dtt_type;
2687c478bdstevel@tonic-gate	ctf_id_t base = ctf_type_resolve(ctfp, type);
269a386cc1Robert Mustacchi	uint_t bflags = tip->dtt_flags;
2707c478bdstevel@tonic-gate
2717c478bdstevel@tonic-gate	dt_module_t *dmp;
2727c478bdstevel@tonic-gate	ctf_id_t ptr;
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate	if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR ||
2757c478bdstevel@tonic-gate	    (ptr = ctf_type_pointer(ctfp, base)) != CTF_ERR) {
2767c478bdstevel@tonic-gate		tip->dtt_type = ptr;
2777c478bdstevel@tonic-gate		return (0);
2787c478bdstevel@tonic-gate	}
2797c478bdstevel@tonic-gate
2807c478bdstevel@tonic-gate	if (yypcb->pcb_idepth != 0)
2817c478bdstevel@tonic-gate		dmp = dtp->dt_cdefs;
2827c478bdstevel@tonic-gate	else
2837c478bdstevel@tonic-gate		dmp = dtp->dt_ddefs;
2847c478bdstevel@tonic-gate
2857c478bdstevel@tonic-gate	if (ctfp != dmp->dm_ctfp && ctfp != ctf_parent_file(dmp->dm_ctfp) &&
2867c478bdstevel@tonic-gate	    (type = ctf_add_type(dmp->dm_ctfp, ctfp, type)) == CTF_ERR) {
2877c478bdstevel@tonic-gate		dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
2887c478bdstevel@tonic-gate		return (dt_set_errno(dtp, EDT_CTF));
2897c478bdstevel@tonic-gate	}
2907c478bdstevel@tonic-gate
291bc1f688Robert Mustacchi	ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, type);
2927c478bdstevel@tonic-gate
2937c478bdstevel@tonic-gate	if (ptr == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {
2947c478bdstevel@tonic-gate		dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
2957c478bdstevel@tonic-gate		return (dt_set_errno(dtp, EDT_CTF));
2967c478bdstevel@tonic-gate	}
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gate	tip->dtt_object = dmp->dm_name;
2997c478bdstevel@tonic-gate	tip->dtt_ctfp = dmp->dm_ctfp;
3007c478bdstevel@tonic-gate	tip->dtt_type = ptr;
301a386cc1Robert Mustacchi	tip->dtt_flags = bflags;
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate	return (0);
3047c478bdstevel@tonic-gate}
3057c478bdstevel@tonic-gate
3067c478bdstevel@tonic-gateconst char *
3077c478bdstevel@tonic-gatedt_type_name(ctf_file_t *ctfp, ctf_id_t type, char *buf, size_t len)
3087c478bdstevel@tonic-gate{
3097c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
3107c478bdstevel@tonic-gate
3117c478bdstevel@tonic-gate	if (ctfp == DT_FPTR_CTFP(dtp) && type == DT_FPTR_TYPE(dtp))
3127c478bdstevel@tonic-gate		(void) snprintf(buf, len, "function pointer");
3137c478bdstevel@tonic-gate	else if (ctfp == DT_FUNC_CTFP(dtp) && type == DT_FUNC_TYPE(dtp))
3147c478bdstevel@tonic-gate		(void) snprintf(buf, len, "function");
3157c478bdstevel@tonic-gate	else if (ctfp == DT_DYN_CTFP(dtp) && type == DT_DYN_TYPE(dtp))
3167c478bdstevel@tonic-gate		(void) snprintf(buf, len, "dynamic variable");
3177c478bdstevel@tonic-gate	else if (ctfp == NULL)
3187c478bdstevel@tonic-gate		(void) snprintf(buf, len, "<none>");
3197c478bdstevel@tonic-gate	else if (ctf_type_name(ctfp, type, buf, len) == NULL)
3207c478bdstevel@tonic-gate		(void) snprintf(buf, len, "unknown");
3217c478bdstevel@tonic-gate
3227c478bdstevel@tonic-gate	return (buf);
3237c478bdstevel@tonic-gate}
3247c478bdstevel@tonic-gate
3257c478bdstevel@tonic-gate/*
3267c478bdstevel@tonic-gate * Perform the "usual arithmetic conversions" to determine which of the two
3277c478bdstevel@tonic-gate * input operand types should be promoted and used as a result type.  The
3287c478bdstevel@tonic-gate * rules for this are described in ISOC[6.3.1.8] and K&R[A6.5].
3297c478bdstevel@tonic-gate */
3307c478bdstevel@tonic-gatestatic void
3317c478bdstevel@tonic-gatedt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype)
3327c478bdstevel@tonic-gate{
3337c478bdstevel@tonic-gate	ctf_file_t *lfp = lp->dn_ctfp;
3347c478bdstevel@tonic-gate	ctf_id_t ltype = lp->dn_type;
3357c478bdstevel@tonic-gate
3367c478bdstevel@tonic-gate	ctf_file_t *rfp = rp->dn_ctfp;
3377c478bdstevel@tonic-gate	ctf_id_t rtype = rp->dn_type;
3387c478bdstevel@tonic-gate
3397c478bdstevel@tonic-gate	ctf_id_t lbase = ctf_type_resolve(lfp, ltype);
3407c478bdstevel@tonic-gate	uint_t lkind = ctf_type_kind(lfp, lbase);
3417c478bdstevel@tonic-gate
3427c478bdstevel@tonic-gate	ctf_id_t rbase = ctf_type_resolve(rfp, rtype);
3437c478bdstevel@tonic-gate	uint_t rkind = ctf_type_kind(rfp, rbase);
3447c478bdstevel@tonic-gate
3457c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
3467c478bdstevel@tonic-gate	ctf_encoding_t le, re;
3477c478bdstevel@tonic-gate	uint_t lrank, rrank;
3487c478bdstevel@tonic-gate
3497c478bdstevel@tonic-gate	assert(lkind == CTF_K_INTEGER || lkind == CTF_K_ENUM);
3507c478bdstevel@tonic-gate	assert(rkind == CTF_K_INTEGER || rkind == CTF_K_ENUM);
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gate	if (lkind == CTF_K_ENUM) {
3537c478bdstevel@tonic-gate		lfp = DT_INT_CTFP(dtp);
3547c478bdstevel@tonic-gate		ltype = lbase = DT_INT_TYPE(dtp);
3557c478bdstevel@tonic-gate	}
3567c478bdstevel@tonic-gate
3577c478bdstevel@tonic-gate	if (rkind == CTF_K_ENUM) {
3587c478bdstevel@tonic-gate		rfp = DT_INT_CTFP(dtp);
3597c478bdstevel@tonic-gate		rtype = rbase = DT_INT_TYPE(dtp);
3607c478bdstevel@tonic-gate	}
3617c478bdstevel@tonic-gate
3627c478bdstevel@tonic-gate	if (ctf_type_encoding(lfp, lbase, &le) == CTF_ERR) {
3637c478bdstevel@tonic-gate		yypcb->pcb_hdl->dt_ctferr = ctf_errno(lfp);
3647c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
3657c478bdstevel@tonic-gate	}
3667c478bdstevel@tonic-gate
3677c478bdstevel@tonic-gate	if (ctf_type_encoding(rfp, rbase, &re) == CTF_ERR) {
3687c478bdstevel@tonic-gate		yypcb->pcb_hdl->dt_ctferr = ctf_errno(rfp);
3697c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
3707c478bdstevel@tonic-gate	}
3717c478bdstevel@tonic-gate
3727c478bdstevel@tonic-gate	/*
3737c478bdstevel@tonic-gate	 * Compute an integer rank based on the size and unsigned status.
3747c478bdstevel@tonic-gate	 * If rank is identical, pick the "larger" of the equivalent types
3757c478bdstevel@tonic-gate	 * which we define as having a larger base ctf_id_t.  If rank is
3767c478bdstevel@tonic-gate	 * different, pick the type with the greater rank.
3777c478bdstevel@tonic-gate	 */
3787c478bdstevel@tonic-gate	lrank = le.cte_bits + ((le.cte_format & CTF_INT_SIGNED) == 0);
3797c478bdstevel@tonic-gate	rrank = re.cte_bits + ((re.cte_format & CTF_INT_SIGNED) == 0);
3807c478bdstevel@tonic-gate
3817c478bdstevel@tonic-gate	if (lrank == rrank) {
3827c478bdstevel@tonic-gate		if (lbase - rbase < 0)
3837c478bdstevel@tonic-gate			goto return_rtype;
3847c478bdstevel@tonic-gate		else
3857c478bdstevel@tonic-gate			goto return_ltype;
3867c478bdstevel@tonic-gate	} else if (lrank > rrank) {
3877c478bdstevel@tonic-gate		goto return_ltype;
3887c478bdstevel@tonic-gate	} else
3897c478bdstevel@tonic-gate		goto return_rtype;
3907c478bdstevel@tonic-gate
3917c478bdstevel@tonic-gatereturn_ltype:
3927c478bdstevel@tonic-gate	*ofp = lfp;
3937c478bdstevel@tonic-gate	*otype = ltype;
3947c478bdstevel@tonic-gate	return;
3957c478bdstevel@tonic-gate
3967c478bdstevel@tonic-gatereturn_rtype:
3977c478bdstevel@tonic-gate	*ofp = rfp;
3987c478bdstevel@tonic-gate	*otype = rtype;
3997c478bdstevel@tonic-gate}
4007c478bdstevel@tonic-gate
4017c478bdstevel@tonic-gatevoid
4027c478bdstevel@tonic-gatedt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
4037c478bdstevel@tonic-gate{
4047c478bdstevel@tonic-gate	dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
405a386cc1Robert Mustacchi	dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
4067c478bdstevel@tonic-gate	dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
4077c478bdstevel@tonic-gate}
4087c478bdstevel@tonic-gate
4097c478bdstevel@tonic-gateconst char *
4107c478bdstevel@tonic-gatedt_node_name(const dt_node_t *dnp, char *buf, size_t len)
4117c478bdstevel@tonic-gate{
4127c478bdstevel@tonic-gate	char n1[DT_TYPE_NAMELEN];
4137c478bdstevel@tonic-gate	char n2[DT_TYPE_NAMELEN];
4147c478bdstevel@tonic-gate
4157c478bdstevel@tonic-gate	const char *prefix = "", *suffix = "";
4167c478bdstevel@tonic-gate	const dtrace_syminfo_t *dts;
4177c478bdstevel@tonic-gate	char *s;
4187c478bdstevel@tonic-gate
4197c478bdstevel@tonic-gate	switch (dnp->dn_kind) {
4207c478bdstevel@tonic-gate	case DT_NODE_INT:
4217c478bdstevel@tonic-gate		(void) snprintf(buf, len, "integer constant 0x%llx",
4227c478bdstevel@tonic-gate		    (u_longlong_t)dnp->dn_value);
4237c478bdstevel@tonic-gate		break;
4247c478bdstevel@tonic-gate	case DT_NODE_STRING:
4257c478bdstevel@tonic-gate		s = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));
4267c478bdstevel@tonic-gate		(void) snprintf(buf, len, "string constant \"%s\"",
4277c478bdstevel@tonic-gate		    s != NULL ? s : dnp->dn_string);
4287c478bdstevel@tonic-gate		free(s);
4297c478bdstevel@tonic-gate		break;
4307c478bdstevel@tonic-gate	case DT_NODE_IDENT:
4317c478bdstevel@tonic-gate		(void) snprintf(buf, len, "identifier %s", dnp->dn_string);
4327c478bdstevel@tonic-gate		break;
4337c478bdstevel@tonic-gate	case DT_NODE_VAR:
4347c478bdstevel@tonic-gate	case DT_NODE_FUNC:
4357c478bdstevel@tonic-gate	case DT_NODE_AGG:
4367c478bdstevel@tonic-gate	case DT_NODE_INLINE:
4377c478bdstevel@tonic-gate		switch (dnp->dn_ident->di_kind) {
4387c478bdstevel@tonic-gate		case DT_IDENT_FUNC:
4397c478bdstevel@tonic-gate		case DT_IDENT_AGGFUNC:
4407c478bdstevel@tonic-gate		case DT_IDENT_ACTFUNC:
4417c478bdstevel@tonic-gate			suffix = "( )";
4427c478bdstevel@tonic-gate			break;
4437c478bdstevel@tonic-gate		case DT_IDENT_AGG:
4447c478bdstevel@tonic-gate			prefix = "@";
4457c478bdstevel@tonic-gate			break;
4467c478bdstevel@tonic-gate		}
4477c478bdstevel@tonic-gate		(void) snprintf(buf, len, "%s %s%s%s",
4487c478bdstevel@tonic-gate		    dt_idkind_name(dnp->dn_ident->di_kind),
4497c478bdstevel@tonic-gate		    prefix, dnp->dn_ident->di_name, suffix);
4507c478bdstevel@tonic-gate		break;
4517c478bdstevel@tonic-gate	case DT_NODE_SYM:
4527c478bdstevel@tonic-gate		dts = dnp->dn_ident->di_data;
4537c478bdstevel@tonic-gate		(void) snprintf(buf, len, "symbol %s`%s",
4547c478bdstevel@tonic-gate		    dts->dts_object, dts->dts_name);
4557c478bdstevel@tonic-gate		break;
4567c478bdstevel@tonic-gate	case DT_NODE_TYPE:
4577c478bdstevel@tonic-gate		(void) snprintf(buf, len, "type %s",
4587c478bdstevel@tonic-gate		    dt_node_type_name(dnp, n1, sizeof (n1)));
4597c478bdstevel@tonic-gate		break;
4607c478bdstevel@tonic-gate	case DT_NODE_OP1:
4617c478bdstevel@tonic-gate	case DT_NODE_OP2:
4627c478bdstevel@tonic-gate	case DT_NODE_OP3:
4637c478bdstevel@tonic-gate		(void) snprintf(buf, len, "operator %s", opstr(dnp->dn_op));
4647c478bdstevel@tonic-gate		break;
4657c478bdstevel@tonic-gate	case DT_NODE_DEXPR:
4667c478bdstevel@tonic-gate	case DT_NODE_DFUNC:
4677c478bdstevel@tonic-gate		if (dnp->dn_expr)
4687c478bdstevel@tonic-gate			return (dt_node_name(dnp->dn_expr, buf, len));
4697c478bdstevel@tonic-gate		(void) snprintf(buf, len, "%s", "statement");
4707c478bdstevel@tonic-gate		break;
4717c478bdstevel@tonic-gate	case DT_NODE_PDESC:
4727c478bdstevel@tonic-gate		if (dnp->dn_desc->dtpd_id == 0) {
4737c478bdstevel@tonic-gate			(void) snprintf(buf, len,
4747c478bdstevel@tonic-gate			    "probe description %s:%s:%s:%s",
4757c478bdstevel@tonic-gate			    dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,
4767c478bdstevel@tonic-gate			    dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name);
4777c478bdstevel@tonic-gate		} else {
4787c478bdstevel@tonic-gate			(void) snprintf(buf, len, "probe description %u",
4797c478bdstevel@tonic-gate			    dnp->dn_desc->dtpd_id);
4807c478bdstevel@tonic-gate		}
4817c478bdstevel@tonic-gate		break;
4827c478bdstevel@tonic-gate	case DT_NODE_CLAUSE:
4837c478bdstevel@tonic-gate		(void) snprintf(buf, len, "%s", "clause");
4847c478bdstevel@tonic-gate		break;
4857c478bdstevel@tonic-gate	case DT_NODE_MEMBER:
4867c478bdstevel@tonic-gate		(void) snprintf(buf, len, "member %s", dnp->dn_membname);
4877c478bdstevel@tonic-gate		break;
4887c478bdstevel@tonic-gate	case DT_NODE_XLATOR:
4897c478bdstevel@tonic-gate		(void) snprintf(buf, len, "translator <%s> (%s)",
4907c478bdstevel@tonic-gate		    dt_type_name(dnp->dn_xlator->dx_dst_ctfp,
49123a1cceRoger A. Faulkner		    dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)),
4927c478bdstevel@tonic-gate		    dt_type_name(dnp->dn_xlator->dx_src_ctfp,
49323a1cceRoger A. Faulkner		    dnp->dn_xlator->dx_src_type, n2, sizeof (n2)));
4947c478bdstevel@tonic-gate		break;
4957c478bdstevel@tonic-gate	case DT_NODE_PROG:
4967c478bdstevel@tonic-gate		(void) snprintf(buf, len, "%s", "program");
4977c478bdstevel@tonic-gate		break;
4987c478bdstevel@tonic-gate	default:
4997c478bdstevel@tonic-gate		(void) snprintf(buf, len, "node <%u>", dnp->dn_kind);
5007c478bdstevel@tonic-gate		break;
5017c478bdstevel@tonic-gate	}
5027c478bdstevel@tonic-gate
5037c478bdstevel@tonic-gate	return (buf);
5047c478bdstevel@tonic-gate}
5057c478bdstevel@tonic-gate
5067c478bdstevel@tonic-gate/*
5077c478bdstevel@tonic-gate * dt_node_xalloc() can be used to create new parse nodes from any libdtrace
5087c478bdstevel@tonic-gate * caller.  The caller is responsible for assigning dn_link appropriately.
5097c478bdstevel@tonic-gate */
5107c478bdstevel@tonic-gatedt_node_t *
5117c478bdstevel@tonic-gatedt_node_xalloc(dtrace_hdl_t *dtp, int kind)
5127c478bdstevel@tonic-gate{
5137c478bdstevel@tonic-gate	dt_node_t *dnp = dt_alloc(dtp, sizeof (dt_node_t));
5147c478bdstevel@tonic-gate
5157c478bdstevel@tonic-gate	if (dnp == NULL)
5167c478bdstevel@tonic-gate		return (NULL);
5177c478bdstevel@tonic-gate
5187c478bdstevel@tonic-gate	dnp->dn_ctfp = NULL;
5197c478bdstevel@tonic-gate	dnp->dn_type = CTF_ERR;
5207c478bdstevel@tonic-gate	dnp->dn_kind = (uchar_t)kind;
5217c478bdstevel@tonic-gate	dnp->dn_flags = 0;
5227c478bdstevel@tonic-gate	dnp->dn_op = 0;
5237c478bdstevel@tonic-gate	dnp->dn_line = -1;
5247c478bdstevel@tonic-gate	dnp->dn_reg = -1;
5257c478bdstevel@tonic-gate	dnp->dn_attr = _dtrace_defattr;
5267c478bdstevel@tonic-gate	dnp->dn_list = NULL;
5277c478bdstevel@tonic-gate	dnp->dn_link = NULL;
5287c478bdstevel@tonic-gate	bzero(&dnp->dn_u, sizeof (dnp->dn_u));
5297c478bdstevel@tonic-gate
5307c478bdstevel@tonic-gate	return (dnp);
5317c478bdstevel@tonic-gate}
5327c478bdstevel@tonic-gate
5337c478bdstevel@tonic-gate/*
5347c478bdstevel@tonic-gate * dt_node_alloc() is used to create new parse nodes from the parser.  It
5357c478bdstevel@tonic-gate * assigns the node location based on the current lexer line number and places
5367c478bdstevel@tonic-gate * the new node on the default allocation list.  If allocation fails, we
5377c478bdstevel@tonic-gate * automatically longjmp the caller back to the enclosing compilation call.
5387c478bdstevel@tonic-gate */
5397c478bdstevel@tonic-gatestatic dt_node_t *
5407c478bdstevel@tonic-gatedt_node_alloc(int kind)
5417c478bdstevel@tonic-gate{
5427c478bdstevel@tonic-gate	dt_node_t *dnp = dt_node_xalloc(yypcb->pcb_hdl, kind);
5437c478bdstevel@tonic-gate
5447c478bdstevel@tonic-gate	if (dnp == NULL)
5457c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gate	dnp->dn_line = yylineno;
5487c478bdstevel@tonic-gate	dnp->dn_link = yypcb->pcb_list;
5497c478bdstevel@tonic-gate	yypcb->pcb_list = dnp;
5507c478bdstevel@tonic-gate
5517c478bdstevel@tonic-gate	return (dnp);
5527c478bdstevel@tonic-gate}
5537c478bdstevel@tonic-gate
5547c478bdstevel@tonic-gatevoid
5557c478bdstevel@tonic-gatedt_node_free(dt_node_t *dnp)
5567c478bdstevel@tonic-gate{
5577c478bdstevel@tonic-gate	uchar_t kind = dnp->dn_kind;
5587c478bdstevel@tonic-gate
5597c478bdstevel@tonic-gate	dnp->dn_kind = DT_NODE_FREE;
5607c478bdstevel@tonic-gate
5617c478bdstevel@tonic-gate	switch (kind) {
5627c478bdstevel@tonic-gate	case DT_NODE_STRING:
5637c478bdstevel@tonic-gate	case DT_NODE_IDENT:
5647c478bdstevel@tonic-gate	case DT_NODE_TYPE:
5657c478bdstevel@tonic-gate		free(dnp->dn_string);
5667c478bdstevel@tonic-gate		dnp->dn_string = NULL;
5677c478bdstevel@tonic-gate		break;
5687c478bdstevel@tonic-gate
5697c478bdstevel@tonic-gate	case DT_NODE_VAR:
5707c478bdstevel@tonic-gate	case DT_NODE_FUNC:
5717c478bdstevel@tonic-gate	case DT_NODE_PROBE:
5727c478bdstevel@tonic-gate		if (dnp->dn_ident != NULL) {
5737c478bdstevel@tonic-gate			if (dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN)
5747c478bdstevel@tonic-gate				dt_ident_destroy(dnp->dn_ident);
5757c478bdstevel@tonic-gate			dnp->dn_ident = NULL;
5767c478bdstevel@tonic-gate		}
5777c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_args);
5787c478bdstevel@tonic-gate		break;
5797c478bdstevel@tonic-gate
5807c478bdstevel@tonic-gate	case DT_NODE_OP1:
5817c478bdstevel@tonic-gate		if (dnp->dn_child != NULL) {
5827c478bdstevel@tonic-gate			dt_node_free(dnp->dn_child);
5837c478bdstevel@tonic-gate			dnp->dn_child = NULL;
5847c478bdstevel@tonic-gate		}
5857c478bdstevel@tonic-gate		break;
5867c478bdstevel@tonic-gate
5877c478bdstevel@tonic-gate	case DT_NODE_OP3:
5887c478bdstevel@tonic-gate		if (dnp->dn_expr != NULL) {
5897c478bdstevel@tonic-gate			dt_node_free(dnp->dn_expr);
5907c478bdstevel@tonic-gate			dnp->dn_expr = NULL;
5917c478bdstevel@tonic-gate		}
5927c478bdstevel@tonic-gate		/*FALLTHRU*/
5937c478bdstevel@tonic-gate	case DT_NODE_OP2:
5947c478bdstevel@tonic-gate		if (dnp->dn_left != NULL) {
5957c478bdstevel@tonic-gate			dt_node_free(dnp->dn_left);
5967c478bdstevel@tonic-gate			dnp->dn_left = NULL;
5977c478bdstevel@tonic-gate		}
5987c478bdstevel@tonic-gate		if (dnp->dn_right != NULL) {
5997c478bdstevel@tonic-gate			dt_node_free(dnp->dn_right);
6007c478bdstevel@tonic-gate			dnp->dn_right = NULL;
6017c478bdstevel@tonic-gate		}
6027c478bdstevel@tonic-gate		break;
6037c478bdstevel@tonic-gate
6047c478bdstevel@tonic-gate	case DT_NODE_DEXPR:
6057c478bdstevel@tonic-gate	case DT_NODE_DFUNC:
6067c478bdstevel@tonic-gate		if (dnp->dn_expr != NULL) {
6077c478bdstevel@tonic-gate			dt_node_free(dnp->dn_expr);
6087c478bdstevel@tonic-gate			dnp->dn_expr = NULL;
6097c478bdstevel@tonic-gate		}
6107c478bdstevel@tonic-gate		break;
6117c478bdstevel@tonic-gate
6127c478bdstevel@tonic-gate	case DT_NODE_AGG:
6137c478bdstevel@tonic-gate		if (dnp->dn_aggfun != NULL) {
6147c478bdstevel@tonic-gate			dt_node_free(dnp->dn_aggfun);
6157c478bdstevel@tonic-gate			dnp->dn_aggfun = NULL;
6167c478bdstevel@tonic-gate		}
6177c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_aggtup);
6187c478bdstevel@tonic-gate		break;
6197c478bdstevel@tonic-gate
6207c478bdstevel@tonic-gate	case DT_NODE_PDESC:
6217c478bdstevel@tonic-gate		free(dnp->dn_spec);
6227c478bdstevel@tonic-gate		dnp->dn_spec = NULL;
6237c478bdstevel@tonic-gate		free(dnp->dn_desc);
6247c478bdstevel@tonic-gate		dnp->dn_desc = NULL;
6257c478bdstevel@tonic-gate		break;
6267c478bdstevel@tonic-gate
6277c478bdstevel@tonic-gate	case DT_NODE_CLAUSE:
6287c478bdstevel@tonic-gate		if (dnp->dn_pred != NULL)
6297c478bdstevel@tonic-gate			dt_node_free(dnp->dn_pred);
6307c478bdstevel@tonic-gate		if (dnp->dn_locals != NULL)
6317c478bdstevel@tonic-gate			dt_idhash_destroy(dnp->dn_locals);
6327c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_pdescs);
6337c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_acts);
6347c478bdstevel@tonic-gate		break;
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gate	case DT_NODE_MEMBER:
6377c478bdstevel@tonic-gate		free(dnp->dn_membname);
6387c478bdstevel@tonic-gate		dnp->dn_membname = NULL;
6397c478bdstevel@tonic-gate		if (dnp->dn_membexpr != NULL) {
6407c478bdstevel@tonic-gate			dt_node_free(dnp->dn_membexpr);
6417c478bdstevel@tonic-gate			dnp->dn_membexpr = NULL;
6427c478bdstevel@tonic-gate		}
6437c478bdstevel@tonic-gate		break;
6447c478bdstevel@tonic-gate
6457c478bdstevel@tonic-gate	case DT_NODE_PROVIDER:
6467c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_probes);
6477c478bdstevel@tonic-gate		free(dnp->dn_provname);
6487c478bdstevel@tonic-gate		dnp->dn_provname = NULL;
6497c478bdstevel@tonic-gate		break;
6507c478bdstevel@tonic-gate
6517c478bdstevel@tonic-gate	case DT_NODE_PROG:
6527c478bdstevel@tonic-gate		dt_node_list_free(&dnp->dn_list);
6537c478bdstevel@tonic-gate		break;
6547c478bdstevel@tonic-gate	}
6557c478bdstevel@tonic-gate}
6567c478bdstevel@tonic-gate
6577c478bdstevel@tonic-gatevoid
6587c478bdstevel@tonic-gatedt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
6597c478bdstevel@tonic-gate{
6607c478bdstevel@tonic-gate	if ((yypcb->pcb_cflags & DTRACE_C_EATTR) &&
6617c478bdstevel@tonic-gate	    (dt_attr_cmp(attr, yypcb->pcb_amin) < 0)) {
6627c478bdstevel@tonic-gate		char a[DTRACE_ATTR2STR_MAX];
6637c478bdstevel@tonic-gate		char s[BUFSIZ];
6647c478bdstevel@tonic-gate
6657c478bdstevel@tonic-gate		dnerror(dnp, D_ATTR_MIN, "attributes for %s (%s) are less than "
6667c478bdstevel@tonic-gate		    "predefined minimum\n", dt_node_name(dnp, s, sizeof (s)),
6677c478bdstevel@tonic-gate		    dtrace_attr2str(attr, a, sizeof (a)));
6687c478bdstevel@tonic-gate	}
6697c478bdstevel@tonic-gate
6707c478bdstevel@tonic-gate	dnp->dn_attr = attr;
6717c478bdstevel@tonic-gate}
6727c478bdstevel@tonic-gate
6737c478bdstevel@tonic-gatevoid
674a386cc1Robert Mustacchidt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
675a386cc1Robert Mustacchi    boolean_t user)
6767c478bdstevel@tonic-gate{
6777c478bdstevel@tonic-gate	ctf_id_t base = ctf_type_resolve(fp, type);
6787c478bdstevel@tonic-gate	uint_t kind = ctf_type_kind(fp, base);
6797c478bdstevel@tonic-gate	ctf_encoding_t e;
6807c478bdstevel@tonic-gate
6817c478bdstevel@tonic-gate	dnp->dn_flags &=
6827c478bdstevel@tonic-gate	    ~(DT_NF_SIGNED | DT_NF_REF | DT_NF_BITFIELD | DT_NF_USERLAND);
6837c478bdstevel@tonic-gate
6847c478bdstevel@tonic-gate	if (kind == CTF_K_INTEGER && ctf_type_encoding(fp, base, &e) == 0) {
6857c478bdstevel@tonic-gate		size_t size = e.cte_bits / NBBY;
6867c478bdstevel@tonic-gate
6877c478bdstevel@tonic-gate		if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)))
6887c478bdstevel@tonic-gate			dnp->dn_flags |= DT_NF_BITFIELD;
6897c478bdstevel@tonic-gate
6907c478bdstevel@tonic-gate		if (e.cte_format & CTF_INT_SIGNED)
6917c478bdstevel@tonic-gate			dnp->dn_flags |= DT_NF_SIGNED;
6927c478bdstevel@tonic-gate	}
6937c478bdstevel@tonic-gate
6947c478bdstevel@tonic-gate	if (kind == CTF_K_FLOAT && ctf_type_encoding(fp, base, &e) == 0) {
6957c478bdstevel@tonic-gate		if (e.cte_bits / NBBY > sizeof (uint64_t))
6967c478bdstevel@tonic-gate			dnp->dn_flags |= DT_NF_REF;
6977c478bdstevel@tonic-gate	}
6987c478bdstevel@tonic-gate
6997c478bdstevel@tonic-gate	if (kind == CTF_K_STRUCT || kind == CTF_K_UNION ||
7007c478bdstevel@tonic-gate	    kind == CTF_K_FORWARD ||
7017c478bdstevel@tonic-gate	    kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION)
7027c478bdstevel@tonic-gate		dnp->dn_flags |= DT_NF_REF;
7037c478bdstevel@tonic-gate	else if (yypcb != NULL && fp == DT_DYN_CTFP(yypcb->pcb_hdl) &&
7047c478bdstevel@tonic-gate	    type == DT_DYN_TYPE(yypcb->pcb_hdl))
7057c478bdstevel@tonic-gate		dnp->dn_flags |= DT_NF_REF;
7067c478bdstevel@tonic-gate
707a386cc1Robert Mustacchi	if (user)
708a386cc1Robert Mustacchi		dnp->dn_flags |= DT_NF_USERLAND;
709a386cc1Robert Mustacchi
7107c478bdstevel@tonic-gate	dnp->dn_flags |= DT_NF_COOKED;
7117c478bdstevel@tonic-gate	dnp->dn_ctfp = fp;
7127c478bdstevel@tonic-gate	dnp->dn_type = type;
7137c478bdstevel@tonic-gate}
7147c478bdstevel@tonic-gate
7157c478bdstevel@tonic-gatevoid
7167c478bdstevel@tonic-gatedt_node_type_propagate(const dt_node_t *src, dt_node_t *dst)
7177c478bdstevel@tonic-gate{
7187c478bdstevel@tonic-gate	assert(src->dn_flags & DT_NF_COOKED);
7197c478bdstevel@tonic-gate	dst->dn_flags = src->dn_flags & ~DT_NF_LVALUE;
7207c478bdstevel@tonic-gate	dst->dn_ctfp = src->dn_ctfp;
7217c478bdstevel@tonic-gate	dst->dn_type = src->dn_type;
7227c478bdstevel@tonic-gate}
7237c478bdstevel@tonic-gate
7247c478bdstevel@tonic-gateconst char *
7257c478bdstevel@tonic-gatedt_node_type_name(const dt_node_t *dnp, char *buf, size_t len)
7267c478bdstevel@tonic-gate{
7277c478bdstevel@tonic-gate	if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL) {
7287c478bdstevel@tonic-gate		(void) snprintf(buf, len, "%s",
7297c478bdstevel@tonic-gate		    dt_idkind_name(dt_ident_resolve(dnp->dn_ident)->di_kind));
7307c478bdstevel@tonic-gate		return (buf);
7317c478bdstevel@tonic-gate	}
7327c478bdstevel@tonic-gate
7337c478bdstevel@tonic-gate	if (dnp->dn_flags & DT_NF_USERLAND) {
7347c478bdstevel@tonic-gate		size_t n = snprintf(buf, len, "userland ");
7357c478bdstevel@tonic-gate		len = len > n ? len - n : 0;
7367c478bdstevel@tonic-gate		(void) dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf + n, len);
7377c478bdstevel@tonic-gate		return (buf);
7387c478bdstevel@tonic-gate	}
7397c478bdstevel@tonic-gate
7407c478bdstevel@tonic-gate	return (dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf, len));
7417c478bdstevel@tonic-gate}
7427c478bdstevel@tonic-gate
7437c478bdstevel@tonic-gatesize_t
7447c478bdstevel@tonic-gatedt_node_type_size(const dt_node_t *dnp)
7457c478bdstevel@tonic-gate{
746ec57c73Bryan Cantrill	ctf_id_t base;
747a386cc1Robert Mustacchi	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
748ec57c73Bryan Cantrill
7497c478bdstevel@tonic-gate	if (dnp->dn_kind == DT_NODE_STRING)
7507c478bdstevel@tonic-gate		return (strlen(dnp->dn_string) + 1);
7517c478bdstevel@tonic-gate
7527c478bdstevel@tonic-gate	if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)
7537c478bdstevel@tonic-gate		return (dt_ident_size(dnp->dn_ident));
7547c478bdstevel@tonic-gate
755ec57c73Bryan Cantrill	base = ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type);
756ec57c73Bryan Cantrill
757ec57c73Bryan Cantrill	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
758ec57c73Bryan Cantrill		return (0);
759ec57c73Bryan Cantrill
760a386cc1Robert Mustacchi	/*
761a386cc1Robert Mustacchi	 * Here we have a 32-bit user pointer that is being used with a 64-bit
762a386cc1Robert Mustacchi	 * kernel. When we're using it and its tagged as a userland reference --
763a386cc1Robert Mustacchi	 * then we need to keep it as a 32-bit pointer. However, if we are
764a386cc1Robert Mustacchi	 * referring to it as a kernel address, eg. being used after a copyin()
765a386cc1Robert Mustacchi	 * then we need to make sure that we actually return the kernel's size
766a386cc1Robert Mustacchi	 * of a pointer, 8 bytes.
767a386cc1Robert Mustacchi	 */
768a386cc1Robert Mustacchi	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
769a386cc1Robert Mustacchi	    ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
770a386cc1Robert Mustacchi	    !(dnp->dn_flags & DT_NF_USERLAND) &&
771a386cc1Robert Mustacchi	    dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
772a386cc1Robert Mustacchi			return (8);
773a386cc1Robert Mustacchi
7747c478bdstevel@tonic-gate	return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
7757c478bdstevel@tonic-gate}
7767c478bdstevel@tonic-gate
7777c478bdstevel@tonic-gate/*
7787c478bdstevel@tonic-gate * Determine if the specified parse tree node references an identifier of the
7797c478bdstevel@tonic-gate * specified kind, and if so return a pointer to it; otherwise return NULL.
7807c478bdstevel@tonic-gate * This function resolves the identifier itself, following through any inlines.
7817c478bdstevel@tonic-gate */
7827c478bdstevel@tonic-gatedt_ident_t *
7837c478bdstevel@tonic-gatedt_node_resolve(const dt_node_t *dnp, uint_t idkind)
7847c478bdstevel@tonic-gate{
7857c478bdstevel@tonic-gate	dt_ident_t *idp;
7867c478bdstevel@tonic-gate
7877c478bdstevel@tonic-gate	switch (dnp->dn_kind) {
7887c478bdstevel@tonic-gate	case DT_NODE_VAR:
7897c478bdstevel@tonic-gate	case DT_NODE_SYM:
7907c478bdstevel@tonic-gate	case DT_NODE_FUNC:
7917c478bdstevel@tonic-gate	case DT_NODE_AGG:
7927c478bdstevel@tonic-gate	case DT_NODE_INLINE:
7937c478bdstevel@tonic-gate	case DT_NODE_PROBE:
7947c478bdstevel@tonic-gate		idp = dt_ident_resolve(dnp->dn_ident);
7957c478bdstevel@tonic-gate		return (idp->di_kind == idkind ? idp : NULL);
7967c478bdstevel@tonic-gate	}
7977c478bdstevel@tonic-gate
7987c478bdstevel@tonic-gate	if (dt_node_is_dynamic(dnp)) {
7997c478bdstevel@tonic-gate		idp = dt_ident_resolve(dnp->dn_ident);
8007c478bdstevel@tonic-gate		return (idp->di_kind == idkind ? idp : NULL);
8017c478bdstevel@tonic-gate	}
8027c478bdstevel@tonic-gate
8037c478bdstevel@tonic-gate	return (NULL);
8047c478bdstevel@tonic-gate}
8057c478bdstevel@tonic-gate
8067c478bdstevel@tonic-gatesize_t
8077c478bdstevel@tonic-gatedt_node_sizeof(const dt_node_t *dnp)
8087c478bdstevel@tonic-gate{
8097c478bdstevel@tonic-gate	dtrace_syminfo_t *sip;
8107c478bdstevel@tonic-gate	GElf_Sym sym;
8117c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
8127c478bdstevel@tonic-gate
8137c478bdstevel@tonic-gate	/*
8147c478bdstevel@tonic-gate	 * The size of the node as used for the sizeof() operator depends on
8157c478bdstevel@tonic-gate	 * the kind of the node.  If the node is a SYM, the size is obtained
8167c478bdstevel@tonic-gate	 * from the symbol table; if it is not a SYM, the size is determined
8177c478bdstevel@tonic-gate	 * from the node's type.  This is slightly different from C's sizeof()
8187c478bdstevel@tonic-gate	 * operator in that (for example) when applied to a function, sizeof()
8197c478bdstevel@tonic-gate	 * will evaluate to the length of the function rather than the size of
8207c478bdstevel@tonic-gate	 * the function type.
8217c478bdstevel@tonic-gate	 */
8227c478bdstevel@tonic-gate	if (dnp->dn_kind != DT_NODE_SYM)
8237c478bdstevel@tonic-gate		return (dt_node_type_size(dnp));
8247c478bdstevel@tonic-gate
8257c478bdstevel@tonic-gate	sip = dnp->dn_ident->di_data;
8267c478bdstevel@tonic-gate
8277c478bdstevel@tonic-gate	if (dtrace_lookup_by_name(dtp, sip->dts_object,
8287c478bdstevel@tonic-gate	    sip->dts_name, &sym, NULL) == -1)
8297c478bdstevel@tonic-gate		return (0);
8307c478bdstevel@tonic-gate
8317c478bdstevel@tonic-gate	return (sym.st_size);
8327c478bdstevel@tonic-gate}
8337c478bdstevel@tonic-gate
8347c478bdstevel@tonic-gateint
8357c478bdstevel@tonic-gatedt_node_is_integer(const dt_node_t *dnp)
8367c478bdstevel@tonic-gate{
8377c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
8387c478bdstevel@tonic-gate	ctf_encoding_t e;
8397c478bdstevel@tonic-gate	ctf_id_t type;
8407c478bdstevel@tonic-gate	uint_t kind;
8417c478bdstevel@tonic-gate
8427c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
8437c478bdstevel@tonic-gate
8447c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
8457c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, type);
8467c478bdstevel@tonic-gate
8477c478bdstevel@tonic-gate	if (kind == CTF_K_INTEGER &&
8487c478bdstevel@tonic-gate	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
8497c478bdstevel@tonic-gate		return (0); /* void integer */
8507c478bdstevel@tonic-gate
8517c478bdstevel@tonic-gate	return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM);
8527c478bdstevel@tonic-gate}
8537c478bdstevel@tonic-gate
8547c478bdstevel@tonic-gateint
8557c478bdstevel@tonic-gatedt_node_is_float(const dt_node_t *dnp)
8567c478bdstevel@tonic-gate{
8577c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
8587c478bdstevel@tonic-gate	ctf_encoding_t e;
8597c478bdstevel@tonic-gate	ctf_id_t type;
8607c478bdstevel@tonic-gate	uint_t kind;
8617c478bdstevel@tonic-gate
8627c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
8637c478bdstevel@tonic-gate
8647c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
8657c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, type);
8667c478bdstevel@tonic-gate
8677c478bdstevel@tonic-gate	return (kind == CTF_K_FLOAT &&
8687c478bdstevel@tonic-gate	    ctf_type_encoding(dnp->dn_ctfp, type, &e) == 0 && (
8697c478bdstevel@tonic-gate	    e.cte_format == CTF_FP_SINGLE || e.cte_format == CTF_FP_DOUBLE ||
8707c478bdstevel@tonic-gate	    e.cte_format == CTF_FP_LDOUBLE));
8717c478bdstevel@tonic-gate}
8727c478bdstevel@tonic-gate
8737c478bdstevel@tonic-gateint
8747c478bdstevel@tonic-gatedt_node_is_scalar(const dt_node_t *dnp)
8757c478bdstevel@tonic-gate{
8767c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
8777c478bdstevel@tonic-gate	ctf_encoding_t e;
8787c478bdstevel@tonic-gate	ctf_id_t type;
8797c478bdstevel@tonic-gate	uint_t kind;
8807c478bdstevel@tonic-gate
8817c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
8827c478bdstevel@tonic-gate
8837c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
8847c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, type);
8857c478bdstevel@tonic-gate
8867c478bdstevel@tonic-gate	if (kind == CTF_K_INTEGER &&
8877c478bdstevel@tonic-gate	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
8887c478bdstevel@tonic-gate		return (0); /* void cannot be used as a scalar */
8897c478bdstevel@tonic-gate
8907c478bdstevel@tonic-gate	return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM ||
8917c478bdstevel@tonic-gate	    kind == CTF_K_POINTER);
8927c478bdstevel@tonic-gate}
8937c478bdstevel@tonic-gate
8947c478bdstevel@tonic-gateint
8957c478bdstevel@tonic-gatedt_node_is_arith(const dt_node_t *dnp)
8967c478bdstevel@tonic-gate{
8977c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
8987c478bdstevel@tonic-gate	ctf_encoding_t e;
8997c478bdstevel@tonic-gate	ctf_id_t type;
9007c478bdstevel@tonic-gate	uint_t kind;
9017c478bdstevel@tonic-gate
9027c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
9037c478bdstevel@tonic-gate
9047c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
9057c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, type);
9067c478bdstevel@tonic-gate
9077c478bdstevel@tonic-gate	if (kind == CTF_K_INTEGER)
9087c478bdstevel@tonic-gate		return (ctf_type_encoding(fp, type, &e) == 0 && !IS_VOID(e));
9097c478bdstevel@tonic-gate	else
9107c478bdstevel@tonic-gate		return (kind == CTF_K_ENUM);
9117c478bdstevel@tonic-gate}
9127c478bdstevel@tonic-gate
9137c478bdstevel@tonic-gateint
9147c478bdstevel@tonic-gatedt_node_is_vfptr(const dt_node_t *dnp)
9157c478bdstevel@tonic-gate{
9167c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
9177c478bdstevel@tonic-gate	ctf_encoding_t e;
9187c478bdstevel@tonic-gate	ctf_id_t type;
9197c478bdstevel@tonic-gate	uint_t kind;
9207c478bdstevel@tonic-gate
9217c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
9227c478bdstevel@tonic-gate
9237c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
9247c478bdstevel@tonic-gate	if (ctf_type_kind(fp, type) != CTF_K_POINTER)
9257c478bdstevel@tonic-gate		return (0); /* type is not a pointer */
9267c478bdstevel@tonic-gate
9277c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, ctf_type_reference(fp, type));
9287c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, type);
9297c478bdstevel@tonic-gate
9307c478bdstevel@tonic-gate	return (kind == CTF_K_FUNCTION || (kind == CTF_K_INTEGER &&
9317c478bdstevel@tonic-gate	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)));
9327c478bdstevel@tonic-gate}
9337c478bdstevel@tonic-gate
9347c478bdstevel@tonic-gateint
9357c478bdstevel@tonic-gatedt_node_is_dynamic(const dt_node_t *dnp)
9367c478bdstevel@tonic-gate{
9377c478bdstevel@tonic-gate	if (dnp->dn_kind == DT_NODE_VAR &&
9387c478bdstevel@tonic-gate	    (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {
9397c478bdstevel@tonic-gate		const dt_idnode_t *inp = dnp->dn_ident->di_iarg;
9401a7c1b7mws		return (inp->din_root ? dt_node_is_dynamic(inp->din_root) : 0);
9417c478bdstevel@tonic-gate	}
9427c478bdstevel@tonic-gate
9437c478bdstevel@tonic-gate	return (dnp->dn_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) &&
9447c478bdstevel@tonic-gate	    dnp->dn_type == DT_DYN_TYPE(yypcb->pcb_hdl));
9457c478bdstevel@tonic-gate}
9467c478bdstevel@tonic-gate
9477c478bdstevel@tonic-gateint
9487c478bdstevel@tonic-gatedt_node_is_string(const dt_node_t *dnp)
9497c478bdstevel@tonic-gate{
9507c478bdstevel@tonic-gate	return (dnp->dn_ctfp == DT_STR_CTFP(yypcb->pcb_hdl) &&
9517c478bdstevel@tonic-gate	    dnp->dn_type == DT_STR_TYPE(yypcb->pcb_hdl));
9527c478bdstevel@tonic-gate}
9537c478bdstevel@tonic-gate
9547c478bdstevel@tonic-gateint
9557c478bdstevel@tonic-gatedt_node_is_stack(const dt_node_t *dnp)
9567c478bdstevel@tonic-gate{
9577c478bdstevel@tonic-gate	return (dnp->dn_ctfp == DT_STACK_CTFP(yypcb->pcb_hdl) &&
9587c478bdstevel@tonic-gate	    dnp->dn_type == DT_STACK_TYPE(yypcb->pcb_hdl));
9597c478bdstevel@tonic-gate}
9607c478bdstevel@tonic-gate
9617c478bdstevel@tonic-gateint
962a1b5e53bmcdt_node_is_symaddr(const dt_node_t *dnp)
963a1b5e53bmc{
964a1b5e53bmc	return (dnp->dn_ctfp == DT_SYMADDR_CTFP(yypcb->pcb_hdl) &&
965a1b5e53bmc	    dnp->dn_type == DT_SYMADDR_TYPE(yypcb->pcb_hdl));
966a1b5e53bmc}
967a1b5e53bmc
968a1b5e53bmcint
969a1b5e53bmcdt_node_is_usymaddr(const dt_node_t *dnp)
970a1b5e53bmc{
971a1b5e53bmc	return (dnp->dn_ctfp == DT_USYMADDR_CTFP(yypcb->pcb_hdl) &&
972a1b5e53bmc	    dnp->dn_type == DT_USYMADDR_TYPE(yypcb->pcb_hdl));
973a1b5e53bmc}
974a1b5e53bmc
975a1b5e53bmcint
9767c478bdstevel@tonic-gatedt_node_is_strcompat(const dt_node_t *dnp)
9777c478bdstevel@tonic-gate{
9787c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
9797c478bdstevel@tonic-gate	ctf_encoding_t e;
9807c478bdstevel@tonic-gate	ctf_arinfo_t r;
9817c478bdstevel@tonic-gate	ctf_id_t base;
9827c478bdstevel@tonic-gate	uint_t kind;
9837c478bdstevel@tonic-gate
9847c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
9857c478bdstevel@tonic-gate
9867c478bdstevel@tonic-gate	base = ctf_type_resolve(fp, dnp->dn_type);
9877c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, base);
9887c478bdstevel@tonic-gate
9897c478bdstevel@tonic-gate	if (kind == CTF_K_POINTER &&
9907c478bdstevel@tonic-gate	    (base = ctf_type_reference(fp, base)) != CTF_ERR &&
9917c478bdstevel@tonic-gate	    (base = ctf_type_resolve(fp, base)) != CTF_ERR &&
9927c478bdstevel@tonic-gate	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
9937c478bdstevel@tonic-gate		return (1); /* promote char pointer to string */
9947c478bdstevel@tonic-gate
9957c478bdstevel@tonic-gate	if (kind == CTF_K_ARRAY && ctf_array_info(fp, base, &r) == 0 &&
9967c478bdstevel@tonic-gate	    (base = ctf_type_resolve(fp, r.ctr_contents)) != CTF_ERR &&
9977c478bdstevel@tonic-gate	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
9987c478bdstevel@tonic-gate		return (1); /* promote char array to string */
9997c478bdstevel@tonic-gate
10007c478bdstevel@tonic-gate	return (0);
10017c478bdstevel@tonic-gate}
10027c478bdstevel@tonic-gate
10037c478bdstevel@tonic-gateint
10047c478bdstevel@tonic-gatedt_node_is_pointer(const dt_node_t *dnp)
10057c478bdstevel@tonic-gate{
10067c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
10077c478bdstevel@tonic-gate	uint_t kind;
10087c478bdstevel@tonic-gate
10097c478bdstevel@tonic-gate	assert(dnp->dn_flags & DT_NF_COOKED);
10107c478bdstevel@tonic-gate
10117c478bdstevel@tonic-gate	if (dt_node_is_string(dnp))
10127c478bdstevel@tonic-gate		return (0); /* string are pass-by-ref but act like structs */
10137c478bdstevel@tonic-gate
10147c478bdstevel@tonic-gate	kind = ctf_type_kind(fp, ctf_type_resolve(fp, dnp->dn_type));
10157c478bdstevel@tonic-gate	return (kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
10167c478bdstevel@tonic-gate}
10177c478bdstevel@tonic-gate
10187c478bdstevel@tonic-gateint
10197c478bdstevel@tonic-gatedt_node_is_void(const dt_node_t *dnp)
10207c478bdstevel@tonic-gate{
10217c478bdstevel@tonic-gate	ctf_file_t *fp = dnp->dn_ctfp;
10227c478bdstevel@tonic-gate	ctf_encoding_t e;
10237c478bdstevel@tonic-gate	ctf_id_t type;
10247c478bdstevel@tonic-gate
10257c478bdstevel@tonic-gate	if (dt_node_is_dynamic(dnp))
10267c478bdstevel@tonic-gate		return (0); /* <DYN> is an alias for void but not the same */
10277c478bdstevel@tonic-gate
10287c478bdstevel@tonic-gate	if (dt_node_is_stack(dnp))
10297c478bdstevel@tonic-gate		return (0);
10307c478bdstevel@tonic-gate
1031a1b5e53bmc	if (dt_node_is_symaddr(dnp) || dt_node_is_usymaddr(dnp))
1032a1b5e53bmc		return (0);
1033a1b5e53bmc
10347c478bdstevel@tonic-gate	type = ctf_type_resolve(fp, dnp->dn_type);
10357c478bdstevel@tonic-gate
10367c478bdstevel@tonic-gate	return (ctf_type_kind(fp, type) == CTF_K_INTEGER &&
10377c478bdstevel@tonic-gate	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e));
10387c478bdstevel@tonic-gate}
10397c478bdstevel@tonic-gate
10407c478bdstevel@tonic-gateint
10417c478bdstevel@tonic-gatedt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,
10427c478bdstevel@tonic-gate    ctf_file_t **fpp, ctf_id_t *tp)
10437c478bdstevel@tonic-gate{
10447c478bdstevel@tonic-gate	ctf_file_t *lfp = lp->dn_ctfp;
10457c478bdstevel@tonic-gate	ctf_file_t *rfp = rp->dn_ctfp;
10467c478bdstevel@tonic-gate
10477c478bdstevel@tonic-gate	ctf_id_t lbase = CTF_ERR, rbase = CTF_ERR;
10487c478bdstevel@tonic-gate	ctf_id_t lref = CTF_ERR, rref = CTF_ERR;
10497c478bdstevel@tonic-gate
10507c478bdstevel@tonic-gate	int lp_is_void, rp_is_void, lp_is_int, rp_is_int, compat;
10517c478bdstevel@tonic-gate	uint_t lkind, rkind;
10527c478bdstevel@tonic-gate	ctf_encoding_t e;
10537c478bdstevel@tonic-gate	ctf_arinfo_t r;
10547c478bdstevel@tonic-gate
10557c478bdstevel@tonic-gate	assert(lp->dn_flags & DT_NF_COOKED);
10567c478bdstevel@tonic-gate	assert(rp->dn_flags & DT_NF_COOKED);
10577c478bdstevel@tonic-gate
10587c478bdstevel@tonic-gate	if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp))
10597c478bdstevel@tonic-gate		return (0); /* fail if either node is a dynamic variable */
10607c478bdstevel@tonic-gate
10617c478bdstevel@tonic-gate	lp_is_int = dt_node_is_integer(lp);
10627c478bdstevel@tonic-gate	rp_is_int = dt_node_is_integer(rp);
10637c478bdstevel@tonic-gate
10647c478bdstevel@tonic-gate	if (lp_is_int && rp_is_int)
10657c478bdstevel@tonic-gate		return (0); /* fail if both nodes are integers */
10667c478bdstevel@tonic-gate
10677c478bdstevel@tonic-gate	if (lp_is_int && (lp->dn_kind != DT_NODE_INT || lp->dn_value != 0))
10687c478bdstevel@tonic-gate		return (0); /* fail if lp is an integer that isn't 0 constant */
10697c478bdstevel@tonic-gate
10707c478bdstevel@tonic-gate	if (rp_is_int && (rp->dn_kind != DT_NODE_INT || rp->dn_value != 0))
10717c478bdstevel@tonic-gate		return (0); /* fail if rp is an integer that isn't 0 constant */
10727c478bdstevel@tonic-gate
10737c478bdstevel@tonic-gate	if ((lp_is_int == 0 && rp_is_int == 0) && (
10747c478bdstevel@tonic-gate	    (lp->dn_flags & DT_NF_USERLAND) ^ (rp->dn_flags & DT_NF_USERLAND)))
10757c478bdstevel@tonic-gate		return (0); /* fail if only one pointer is a userland address */
10767c478bdstevel@tonic-gate
10777c478bdstevel@tonic-gate	/*
10787c478bdstevel@tonic-gate	 * Resolve the left-hand and right-hand types to their base type, and
10797c478bdstevel@tonic-gate	 * then resolve the referenced type as well (assuming the base type
10807c478bdstevel@tonic-gate	 * is CTF_K_POINTER or CTF_K_ARRAY).  Otherwise [lr]ref = CTF_ERR.
10817c478bdstevel@tonic-gate	 */
10827c478bdstevel@tonic-gate	if (!lp_is_int) {
10837c478bdstevel@tonic-gate		lbase = ctf_type_resolve(lfp, lp->dn_type);
10847c478bdstevel@tonic-gate		lkind = ctf_type_kind(lfp, lbase);
10857c478bdstevel@tonic-gate
10867c478bdstevel@tonic-gate		if (lkind == CTF_K_POINTER) {
10877c478bdstevel@tonic-gate			lref = ctf_type_resolve(lfp,
10887c478bdstevel@tonic-gate			    ctf_type_reference(lfp, lbase));
10897c478bdstevel@tonic-gate		} else if (lkind == CTF_K_ARRAY &&
10907c478bdstevel@tonic-gate		    ctf_array_info(lfp, lbase, &r) == 0) {
10917c478bdstevel@tonic-gate			lref = ctf_type_resolve(lfp, r.ctr_contents);
10927c478bdstevel@tonic-gate		}
10937c478bdstevel@tonic-gate	}
10947c478bdstevel@tonic-gate
10957c478bdstevel@tonic-gate	if (!rp_is_int) {
10967c478bdstevel@tonic-gate		rbase = ctf_type_resolve(rfp, rp->dn_type);
10977c478bdstevel@tonic-gate		rkind = ctf_type_kind(rfp, rbase);
10987c478bdstevel@tonic-gate
10997c478bdstevel@tonic-gate		if (rkind == CTF_K_POINTER) {
11007c478bdstevel@tonic-gate			rref = ctf_type_resolve(rfp,
11017c478bdstevel@tonic-gate			    ctf_type_reference(rfp, rbase));
11027c478bdstevel@tonic-gate		} else if (rkind == CTF_K_ARRAY &&
11037c478bdstevel@tonic-gate		    ctf_array_info(rfp, rbase, &r) == 0) {
11047c478bdstevel@tonic-gate			rref = ctf_type_resolve(rfp, r.ctr_contents);
11057c478bdstevel@tonic-gate		}
11067c478bdstevel@tonic-gate	}
11077c478bdstevel@tonic-gate
11087c478bdstevel@tonic-gate	/*
11097c478bdstevel@tonic-gate	 * We know that one or the other type may still be a zero-valued
11107c478bdstevel@tonic-gate	 * integer constant.  To simplify the code below, set the integer
11117c478bdstevel@tonic-gate	 * type variables equal to the non-integer types and proceed.
11127c478bdstevel@tonic-gate	 */
11137c478bdstevel@tonic-gate	if (lp_is_int) {
11147c478bdstevel@tonic-gate		lbase = rbase;
11157c478bdstevel@tonic-gate		lkind = rkind;
11167c478bdstevel@tonic-gate		lref = rref;
11177c478bdstevel@tonic-gate		lfp = rfp;
11187c478bdstevel@tonic-gate	} else if (rp_is_int) {
11197c478bdstevel@tonic-gate		rbase = lbase;
11207c478bdstevel@tonic-gate		rkind = lkind;
11217c478bdstevel@tonic-gate		rref = lref;
11227c478bdstevel@tonic-gate		rfp = lfp;
11237c478bdstevel@tonic-gate	}
11247c478bdstevel@tonic-gate
11257c478bdstevel@tonic-gate	lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e);
11267c478bdstevel@tonic-gate	rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e);
11277c478bdstevel@tonic-gate
11287c478bdstevel@tonic-gate	/*
11297c478bdstevel@tonic-gate	 * The types are compatible if both are pointers to the same type, or
11307c478bdstevel@tonic-gate	 * if either pointer is a void pointer.  If they are compatible, set
11317c478bdstevel@tonic-gate	 * tp to point to the more specific pointer type and return it.
11327c478bdstevel@tonic-gate	 */
11337c478bdstevel@tonic-gate	compat = (lkind == CTF_K_POINTER || lkind == CTF_K_ARRAY) &&
11347c478bdstevel@tonic-gate	    (rkind == CTF_K_POINTER || rkind == CTF_K_ARRAY) &&
11357c478bdstevel@tonic-gate	    (lp_is_void || rp_is_void || ctf_type_compat(lfp, lref, rfp, rref));
11367c478bdstevel@tonic-gate
11377c478bdstevel@tonic-gate	if (compat) {
11387c478bdstevel@tonic-gate		if (fpp != NULL)
11397c478bdstevel@tonic-gate			*fpp = rp_is_void ? lfp : rfp;
11407c478bdstevel@tonic-gate		if (tp != NULL)
11417c478bdstevel@tonic-gate			*tp = rp_is_void ? lbase : rbase;
11427c478bdstevel@tonic-gate	}
11437c478bdstevel@tonic-gate
11447c478bdstevel@tonic-gate	return (compat);
11457c478bdstevel@tonic-gate}
11467c478bdstevel@tonic-gate
11477c478bdstevel@tonic-gate/*
11487c478bdstevel@tonic-gate * The rules for checking argument types against parameter types are described
11497c478bdstevel@tonic-gate * in the ANSI-C spec (see K&R[A7.3.2] and K&R[A7.17]).  We use the same rule
11507c478bdstevel@tonic-gate * set to determine whether associative array arguments match the prototype.
11517c478bdstevel@tonic-gate */
11527c478bdstevel@tonic-gateint
11537c478bdstevel@tonic-gatedt_node_is_argcompat(const dt_node_t *lp, const dt_node_t *rp)
11547c478bdstevel@tonic-gate{
11557c478bdstevel@tonic-gate	ctf_file_t *lfp = lp->dn_ctfp;
11567c478bdstevel@tonic-gate	ctf_file_t *rfp = rp->dn_ctfp;
11577c478bdstevel@tonic-gate
11587c478bdstevel@tonic-gate	assert(lp->dn_flags & DT_NF_COOKED);
11597c478bdstevel@tonic-gate	assert(rp->dn_flags & DT_NF_COOKED);
11607c478bdstevel@tonic-gate
11617c478bdstevel@tonic-gate	if (dt_node_is_integer(lp) && dt_node_is_integer(rp))
11627c478bdstevel@tonic-gate		return (1); /* integer types are compatible */
11637c478bdstevel@tonic-gate
11647c478bdstevel@tonic-gate	if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp))
11657c478bdstevel@tonic-gate		return (1); /* string types are compatible */
11667c478bdstevel@tonic-gate
11677c478bdstevel@tonic-gate	if (dt_node_is_stack(lp) && dt_node_is_stack(rp))
11687c478bdstevel@tonic-gate		return (1); /* stack types are compatible */
11697c478bdstevel@tonic-gate
1170a1b5e53bmc	if (dt_node_is_symaddr(lp) && dt_node_is_symaddr(rp))
1171a1b5e53bmc		return (1); /* symaddr types are compatible */
1172a1b5e53bmc
1173a1b5e53bmc	if (dt_node_is_usymaddr(lp) && dt_node_is_usymaddr(rp))
1174a1b5e53bmc		return (1); /* usymaddr types are compatible */
1175a1b5e53bmc
11767c478bdstevel@tonic-gate	switch (ctf_type_kind(lfp, ctf_type_resolve(lfp, lp->dn_type))) {
11777c478bdstevel@tonic-gate	case CTF_K_FUNCTION:
11787c478bdstevel@tonic-gate	case CTF_K_STRUCT:
11797c478bdstevel@tonic-gate	case CTF_K_UNION:
11807c478bdstevel@tonic-gate		return (ctf_type_compat(lfp, lp->dn_type, rfp, rp->dn_type));
11817c478bdstevel@tonic-gate	default:
11827c478bdstevel@tonic-gate		return (dt_node_is_ptrcompat(lp, rp, NULL, NULL));
11837c478bdstevel@tonic-gate	}
11847c478bdstevel@tonic-gate}
11857c478bdstevel@tonic-gate
11867c478bdstevel@tonic-gate/*
11877c478bdstevel@tonic-gate * We provide dt_node_is_posconst() as a convenience routine for callers who
11887c478bdstevel@tonic-gate * wish to verify that an argument is a positive non-zero integer constant.
11897c478bdstevel@tonic-gate */
11907c478bdstevel@tonic-gateint
11917c478bdstevel@tonic-gatedt_node_is_posconst(const dt_node_t *dnp)
11927c478bdstevel@tonic-gate{
11937c478bdstevel@tonic-gate	return (dnp->dn_kind == DT_NODE_INT && dnp->dn_value != 0 && (
11947c478bdstevel@tonic-gate	    (dnp->dn_flags & DT_NF_SIGNED) == 0 || (int64_t)dnp->dn_value > 0));
11957c478bdstevel@tonic-gate}
11967c478bdstevel@tonic-gate
11977c478bdstevel@tonic-gateint
11987c478bdstevel@tonic-gatedt_node_is_actfunc(const dt_node_t *dnp)
11997c478bdstevel@tonic-gate{
12007c478bdstevel@tonic-gate	return (dnp->dn_kind == DT_NODE_FUNC &&
12017c478bdstevel@tonic-gate	    dnp->dn_ident->di_kind == DT_IDENT_ACTFUNC);
12027c478bdstevel@tonic-gate}
12037c478bdstevel@tonic-gate
12047c478bdstevel@tonic-gate/*
12057c478bdstevel@tonic-gate * The original rules for integer constant typing are described in K&R[A2.5.1].
12067c478bdstevel@tonic-gate * However, since we support long long, we instead use the rules from ISO C99
12077c478bdstevel@tonic-gate * clause 6.4.4.1 since that is where long longs are formally described.  The
12087c478bdstevel@tonic-gate * rules require us to know whether the constant was specified in decimal or
12097c478bdstevel@tonic-gate * in octal or hex, which we do by looking at our lexer's 'yyintdecimal' flag.
12107c478bdstevel@tonic-gate * The type of an integer constant is the first of the corresponding list in
12117c478bdstevel@tonic-gate * which its value can be represented:
12127c478bdstevel@tonic-gate *
12137c478bdstevel@tonic-gate * unsuffixed decimal:   int, long, long long
12147c478bdstevel@tonic-gate * unsuffixed oct/hex:   int, unsigned int, long, unsigned long,
12157c478bdstevel@tonic-gate *                       long long, unsigned long long
12167c478bdstevel@tonic-gate * suffix [uU]:          unsigned int, unsigned long, unsigned long long
12177c478bdstevel@tonic-gate * suffix [lL] decimal:  long, long long
12187c478bdstevel@tonic-gate * suffix [lL] oct/hex:  long, unsigned long, long long, unsigned long long
12197c478bdstevel@tonic-gate * suffix [uU][Ll]:      unsigned long, unsigned long long
12207c478bdstevel@tonic-gate * suffix ll/LL decimal: long long
12217c478bdstevel@tonic-gate * suffix ll/LL oct/hex: long long, unsigned long long
12227c478bdstevel@tonic-gate * suffix [uU][ll/LL]:   unsigned long long
12237c478bdstevel@tonic-gate *
12247c478bdstevel@tonic-gate * Given that our lexer has already validated the suffixes by regexp matching,
12257c478bdstevel@tonic-gate * there is an obvious way to concisely encode these rules: construct an array
12267c478bdstevel@tonic-gate * of the types in the order int, unsigned int, long, unsigned long, long long,
12277c478bdstevel@tonic-gate * unsigned long long.  Compute an integer array starting index based on the
12287c478bdstevel@tonic-gate * suffix (e.g. none = 0, u = 1, ull = 5), and compute an increment based on
12297c478bdstevel@tonic-gate * the specifier (dec/oct/hex) and suffix (u).  Then iterate from the starting
12307c478bdstevel@tonic-gate * index to the end, advancing using the increment, and searching until we
12317c478bdstevel@tonic-gate * find a limit that matches or we run out of choices (overflow).  To make it
12327c478bdstevel@tonic-gate * even faster, we precompute the table of type information in dtrace_open().
12337c478bdstevel@tonic-gate */
12347c478bdstevel@tonic-gatedt_node_t *
12357c478bdstevel@tonic-gatedt_node_int(uintmax_t value)
12367c478bdstevel@tonic-gate{
12377c478bdstevel@tonic-gate	dt_node_t *dnp = dt_node_alloc(DT_NODE_INT);
12387c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
12397c478bdstevel@tonic-gate
12407c478bdstevel@tonic-gate	int n = (yyintdecimal | (yyintsuffix[0] == 'u')) + 1;
12417c478bdstevel@tonic-gate	int i = 0;
12427c478bdstevel@tonic-gate
12437c478bdstevel@tonic-gate	const char *p;
12447c478bdstevel@tonic-gate	char c;
12457c478bdstevel@tonic-gate
12467c478bdstevel@tonic-gate	dnp->dn_op = DT_TOK_INT;
12477c478bdstevel@tonic-gate	dnp->dn_value = value;
12487c478bdstevel@tonic-gate
12497c478bdstevel@tonic-gate	for (p = yyintsuffix; (c = *p) != '\0'; p++) {
12507c478bdstevel@tonic-gate		if (c == 'U' || c == 'u')
12517c478bdstevel@tonic-gate			i += 1;
12527c478bdstevel@tonic-gate		else if (c == 'L' || c == 'l')
12537c478bdstevel@tonic-gate			i += 2;
12547c478bdstevel@tonic-gate	}
12557c478bdstevel@tonic-gate
12567c478bdstevel@tonic-gate	for (; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i += n) {
12577c478bdstevel@tonic-gate		if (value <= dtp->dt_ints[i].did_limit) {
12587c478bdstevel@tonic-gate			dt_node_type_assign(dnp,
12597c478bdstevel@tonic-gate			    dtp->dt_ints[i].did_ctfp,
1260a386cc1Robert Mustacchi			    dtp->dt_ints[i].did_type, B_FALSE);
12617c478bdstevel@tonic-gate
12627c478bdstevel@tonic-gate			/*
12637c478bdstevel@tonic-gate			 * If a prefix character is present in macro text, add
12647c478bdstevel@tonic-gate			 * in the corresponding operator node (see dt_lex.l).
12657c478bdstevel@tonic-gate			 */
12667c478bdstevel@tonic-gate			switch (yyintprefix) {
12677c478bdstevel@tonic-gate			case '+':
12687c478bdstevel@tonic-gate				return (dt_node_op1(DT_TOK_IPOS, dnp));
12697c478bdstevel@tonic-gate			case '-':
12707c478bdstevel@tonic-gate				return (dt_node_op1(DT_TOK_INEG, dnp));
12717c478bdstevel@tonic-gate			default:
12727c478bdstevel@tonic-gate				return (dnp);
12737c478bdstevel@tonic-gate			}
12747c478bdstevel@tonic-gate		}
12757c478bdstevel@tonic-gate	}
12767c478bdstevel@tonic-gate
12777c478bdstevel@tonic-gate	xyerror(D_INT_OFLOW, "integer constant 0x%llx cannot be represented "
12787c478bdstevel@tonic-gate	    "in any built-in integral type\n", (u_longlong_t)value);
12797c478bdstevel@tonic-gate	/*NOTREACHED*/
12807c478bdstevel@tonic-gate	return (NULL);		/* keep gcc happy */
12817c478bdstevel@tonic-gate}
12827c478bdstevel@tonic-gate
12837c478bdstevel@tonic-gatedt_node_t *
12847c478bdstevel@tonic-gatedt_node_string(char *string)
12857c478bdstevel@tonic-gate{
12867c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
12877c478bdstevel@tonic-gate	dt_node_t *dnp;
12887c478bdstevel@tonic-gate
12897c478bdstevel@tonic-gate	if (string == NULL)
12907c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
12917c478bdstevel@tonic-gate
12927c478bdstevel@tonic-gate	dnp = dt_node_alloc(DT_NODE_STRING);
12937c478bdstevel@tonic-gate	dnp->dn_op = DT_TOK_STRING;
12947c478bdstevel@tonic-gate	dnp->dn_string = string;
1295a386cc1Robert Mustacchi	dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
12967c478bdstevel@tonic-gate
12977c478bdstevel@tonic-gate	return (dnp);
12987c478bdstevel@tonic-gate}
12997c478bdstevel@tonic-gate
13007c478bdstevel@tonic-gatedt_node_t *
13017c478bdstevel@tonic-gatedt_node_ident(char *name)
13027c478bdstevel@tonic-gate{
13037c478bdstevel@tonic-gate	dt_ident_t *idp;
13047c478bdstevel@tonic-gate	dt_node_t *dnp;
13057c478bdstevel@tonic-gate
13067c478bdstevel@tonic-gate	if (name == NULL)
13077c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
13087c478bdstevel@tonic-gate
13097c478bdstevel@tonic-gate	/*
13107c478bdstevel@tonic-gate	 * If the identifier is an inlined integer constant, then create an INT
13117c478bdstevel@tonic-gate	 * node that is a clone of the inline parse tree node and return that
13127c478bdstevel@tonic-gate	 * immediately, allowing this inline to be used in parsing contexts
13137c478bdstevel@tonic-gate	 * that require constant expressions (e.g. scalar array sizes).
13147c478bdstevel@tonic-gate	 */
13157c478bdstevel@tonic-gate	if ((idp = dt_idstack_lookup(&yypcb->pcb_globals, name)) != NULL &&
13167c478bdstevel@tonic-gate	    (idp->di_flags & DT_IDFLG_INLINE)) {
13177c478bdstevel@tonic-gate		dt_idnode_t *inp = idp->di_iarg;
13187c478bdstevel@tonic-gate
13191a7c1b7mws		if (inp->din_root != NULL &&
13201a7c1b7mws		    inp->din_root->dn_kind == DT_NODE_INT) {
13217c478bdstevel@tonic-gate			free(name);
13227c478bdstevel@tonic-gate
13237c478bdstevel@tonic-gate			dnp = dt_node_alloc(DT_NODE_INT);
13247c478bdstevel@tonic-gate			dnp->dn_op = DT_TOK_INT;
13257c478bdstevel@tonic-gate			dnp->dn_value = inp->din_root->dn_value;
13267c478bdstevel@tonic-gate			dt_node_type_propagate(inp->din_root, dnp);
13277c478bdstevel@tonic-gate
13287c478bdstevel@tonic-gate			return (dnp);
13297c478bdstevel@tonic-gate		}
13307c478bdstevel@tonic-gate	}
13317c478bdstevel@tonic-gate
13327c478bdstevel@tonic-gate	dnp = dt_node_alloc(DT_NODE_IDENT);
13337c478bdstevel@tonic-gate	dnp->dn_op = name[0] == '@' ? DT_TOK_AGG : DT_TOK_IDENT;
13347c478bdstevel@tonic-gate	dnp->dn_string = name;
13357c478bdstevel@tonic-gate
13367c478bdstevel@tonic-gate	return (dnp);
13377c478bdstevel@tonic-gate}
13387c478bdstevel@tonic-gate
13397c478bdstevel@tonic-gate/*
13407c478bdstevel@tonic-gate * Create an empty node of type corresponding to the given declaration.
13417c478bdstevel@tonic-gate * Explicit references to user types (C or D) are assigned the default
13427c478bdstevel@tonic-gate * stability; references to other types are _dtrace_typattr (Private).
13437c478bdstevel@tonic-gate */
13447c478bdstevel@tonic-gatedt_node_t *
13457c478bdstevel@tonic-gatedt_node_type(dt_decl_t *ddp)
13467c478bdstevel@tonic-gate{
13477c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
13487c478bdstevel@tonic-gate	dtrace_typeinfo_t dtt;
13497c478bdstevel@tonic-gate	dt_node_t *dnp;
13507c478bdstevel@tonic-gate	char *name = NULL;
13517c478bdstevel@tonic-gate	int err;
13527c478bdstevel@tonic-gate
13537c478bdstevel@tonic-gate	/*
13547c478bdstevel@tonic-gate	 * If 'ddp' is NULL, we get a decl by popping the decl stack.  This
13557c478bdstevel@tonic-gate	 * form of dt_node_type() is used by parameter rules in dt_grammar.y.
13567c478bdstevel@tonic-gate	 */
13577c478bdstevel@tonic-gate	if (ddp == NULL)
13587c478bdstevel@tonic-gate		ddp = dt_decl_pop_param(&name);
13597c478bdstevel@tonic-gate
13607c478bdstevel@tonic-gate	err = dt_decl_type(ddp, &dtt);
13617c478bdstevel@tonic-gate	dt_decl_free(ddp);
13627c478bdstevel@tonic-gate
13637c478bdstevel@tonic-gate	if (err != 0) {
13647c478bdstevel@tonic-gate		free(name);
13657c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
13667c478bdstevel@tonic-gate	}
13677c478bdstevel@tonic-gate
13687c478bdstevel@tonic-gate	dnp = dt_node_alloc(DT_NODE_TYPE);
13697c478bdstevel@tonic-gate	dnp->dn_op = DT_TOK_IDENT;
13707c478bdstevel@tonic-gate	dnp->dn_string = name;
1371a386cc1Robert Mustacchi
1372a386cc1Robert Mustacchi	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
13737c478bdstevel@tonic-gate
13747c478bdstevel@tonic-gate	if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
13757c478bdstevel@tonic-gate	    dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
13767c478bdstevel@tonic-gate		dt_node_attr_assign(dnp, _dtrace_defattr);
13777c478bdstevel@tonic-gate	else
13787c478bdstevel@tonic-gate		dt_node_attr_assign(dnp, _dtrace_typattr);
13797c478bdstevel@tonic-gate
13807c478bdstevel@tonic-gate	return (dnp);
13817c478bdstevel@tonic-gate}
13827c478bdstevel@tonic-gate
13837c478bdstevel@tonic-gate/*
13847c478bdstevel@tonic-gate * Create a type node corresponding to a varargs (...) parameter by just
13857c478bdstevel@tonic-gate * assigning it type CTF_ERR.  The decl processing code will handle this.
13867c478bdstevel@tonic-gate */
13877c478bdstevel@tonic-gatedt_node_t *
13887c478bdstevel@tonic-gatedt_node_vatype(void)
13897c478bdstevel@tonic-gate{
13907c478bdstevel@tonic-gate	dt_node_t *dnp = dt_node_alloc(DT_NODE_TYPE);
13917c478bdstevel@tonic-gate
13927c478bdstevel@tonic-gate	dnp->dn_op = DT_TOK_IDENT;
13937c478bdstevel@tonic-gate	dnp->dn_ctfp = yypcb->pcb_hdl->dt_cdefs->dm_ctfp;
13947c478bdstevel@tonic-gate	dnp->dn_type = CTF_ERR;
13957c478bdstevel@tonic-gate	dnp->dn_attr = _dtrace_defattr;
13967c478bdstevel@tonic-gate
13977c478bdstevel@tonic-gate	return (dnp);
13987c478bdstevel@tonic-gate}
13997c478bdstevel@tonic-gate
14007c478bdstevel@tonic-gate/*
14017c478bdstevel@tonic-gate * Instantiate a decl using the contents of the current declaration stack.  As
14027c478bdstevel@tonic-gate * we do not currently permit decls to be initialized, this function currently
14037c478bdstevel@tonic-gate * returns NULL and no parse node is created.  When this function is called,
14047c478bdstevel@tonic-gate * the topmost scope's ds_ident pointer will be set to NULL (indicating no
14057c478bdstevel@tonic-gate * init_declarator rule was matched) or will point to the identifier to use.
14067c478bdstevel@tonic-gate */
14077c478bdstevel@tonic-gatedt_node_t *
14087c478bdstevel@tonic-gatedt_node_decl(void)
14097c478bdstevel@tonic-gate{
14107c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
14117c478bdstevel@tonic-gate	dt_scope_t *dsp = &yypcb->pcb_dstack;
14127c478bdstevel@tonic-gate	dt_dclass_t class = dsp->ds_class;
14137c478bdstevel@tonic-gate	dt_decl_t *ddp = dt_decl_top();
14147c478bdstevel@tonic-gate
14157c478bdstevel@tonic-gate	dt_module_t *dmp;
14167c478bdstevel@tonic-gate	dtrace_typeinfo_t dtt;
14177c478bdstevel@tonic-gate	ctf_id_t type;
14187c478bdstevel@tonic-gate
14197c478bdstevel@tonic-gate	char n1[DT_TYPE_NAMELEN];
14207c478bdstevel@tonic-gate	char n2[DT_TYPE_NAMELEN];
14217c478bdstevel@tonic-gate
14227c478bdstevel@tonic-gate	if (dt_decl_type(ddp, &dtt) != 0)
14237c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
14247c478bdstevel@tonic-gate
14257c478bdstevel@tonic-gate	/*
14267c478bdstevel@tonic-gate	 * If we have no declaration identifier, then this is either a spurious
14277c478bdstevel@tonic-gate	 * declaration of an intrinsic type (e.g. "extern int;") or declaration
14287c478bdstevel@tonic-gate	 * or redeclaration of a struct, union, or enum type or tag.
14297c478bdstevel@tonic-gate	 */
14307c478bdstevel@tonic-gate	if (dsp->ds_ident == NULL) {
14317c478bdstevel@tonic-gate		if (ddp->dd_kind != CTF_K_STRUCT &&
14327c478bdstevel@tonic-gate		    ddp->dd_kind != CTF_K_UNION && ddp->dd_kind != CTF_K_ENUM)
14337c478bdstevel@tonic-gate			xyerror(D_DECL_USELESS, "useless declaration\n");
14347c478bdstevel@tonic-gate
14357c478bdstevel@tonic-gate		dt_dprintf("type %s added as id %ld\n", dt_type_name(
14367c478bdstevel@tonic-gate		    ddp->dd_ctfp, ddp->dd_type, n1, sizeof (n1)), ddp->dd_type);
14377c478bdstevel@tonic-gate
14387c478bdstevel@tonic-gate		return (NULL);
14397c478bdstevel@tonic-gate	}
14407c478bdstevel@tonic-gate
14417c478bdstevel@tonic-gate	if (strchr(dsp->ds_ident, '`') != NULL) {
14427c478bdstevel@tonic-gate		xyerror(D_DECL_SCOPE, "D scoping operator may not be used in "
14437c478bdstevel@tonic-gate		    "a declaration name (%s)\n", dsp->ds_ident);
14447c478bdstevel@tonic-gate	}
14457c478bdstevel@tonic-gate
14467c478bdstevel@tonic-gate	/*
14477c478bdstevel@tonic-gate	 * If we are nested inside of a C include file, add the declaration to
14487c478bdstevel@tonic-gate	 * the C definition module; otherwise use the D definition module.
14497c478bdstevel@tonic-gate	 */
14507c478bdstevel@tonic-gate	if (yypcb->pcb_idepth != 0)
14517c478bdstevel@tonic-gate		dmp = dtp->dt_cdefs;
14527c478bdstevel@tonic-gate	else
14537c478bdstevel@tonic-gate		dmp = dtp->dt_ddefs;
14547c478bdstevel@tonic-gate
14557c478bdstevel@tonic-gate	/*
14567c478bdstevel@tonic-gate	 * If we see a global or static declaration of a function prototype,
14577c478bdstevel@tonic-gate	 * treat this as equivalent to a D extern declaration.
14587c478bdstevel@tonic-gate	 */
14597c478bdstevel@tonic-gate	if (ctf_type_kind(dtt.dtt_ctfp, dtt.dtt_type) == CTF_K_FUNCTION &&
14607c478bdstevel@tonic-gate	    (class == DT_DC_DEFAULT || class == DT_DC_STATIC))
14617c478bdstevel@tonic-gate		class = DT_DC_EXTERN;
14627c478bdstevel@tonic-gate
14637c478bdstevel@tonic-gate	switch (class) {
14647c478bdstevel@tonic-gate	case DT_DC_AUTO:
14657c478bdstevel@tonic-gate	case DT_DC_REGISTER:
14667c478bdstevel@tonic-gate	case DT_DC_STATIC:
14677c478bdstevel@tonic-gate		xyerror(D_DECL_BADCLASS, "specified storage class not "
14687c478bdstevel@tonic-gate		    "appropriate in D\n");
14697c478bdstevel@tonic-gate		/*NOTREACHED*/
14707c478bdstevel@tonic-gate
14717c478bdstevel@tonic-gate	case DT_DC_EXTERN: {
14727c478bdstevel@tonic-gate		dtrace_typeinfo_t ott;
14737c478bdstevel@tonic-gate		dtrace_syminfo_t dts;
14747c478bdstevel@tonic-gate		GElf_Sym sym;
14757c478bdstevel@tonic-gate
14767c478bdstevel@tonic-gate		int exists = dtrace_lookup_by_name(dtp,
14777c478bdstevel@tonic-gate		    dmp->dm_name, dsp->ds_ident, &sym, &dts) == 0;
14787c478bdstevel@tonic-gate
14797c478bdstevel@tonic-gate		if (exists && (dtrace_symbol_type(dtp, &sym, &dts, &ott) != 0 ||
14807c478bdstevel@tonic-gate		    ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type,
14817c478bdstevel@tonic-gate		    ott.dtt_ctfp, ott.dtt_type) != 0)) {
14827c478bdstevel@tonic-gate			xyerror(D_DECL_IDRED, "identifier redeclared: %s`%s\n"
14837c478bdstevel@tonic-gate			    "\t current: %s\n\tprevious: %s\n",
14847c478bdstevel@tonic-gate			    dmp->dm_name, dsp->ds_ident,
14857c478bdstevel@tonic-gate			    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
148623a1cceRoger A. Faulkner			    n1, sizeof (n1)),
14877c478bdstevel@tonic-gate			    dt_type_name(ott.dtt_ctfp, ott.dtt_type,
148823a1cceRoger A. Faulkner			    n2, sizeof (n2)));
14897c478bdstevel@tonic-gate		} else if (!exists && dt_module_extern(dtp, dmp,
14907c478bdstevel@tonic-gate		    dsp->ds_ident, &dtt) == NULL) {
14917c478bdstevel@tonic-gate			xyerror(D_UNKNOWN,
14927c478bdstevel@tonic-gate			    "failed to extern %s: %s\n", dsp->ds_ident,
14937c478bdstevel@tonic-gate			    dtrace_errmsg(dtp, dtrace_errno(dtp)));
14947c478bdstevel@tonic-gate		} else {
14957c478bdstevel@tonic-gate			dt_dprintf("extern %s`%s type=<%s>\n",
14967c478bdstevel@tonic-gate			    dmp->dm_name, dsp->ds_ident,
14977c478bdstevel@tonic-gate			    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
149823a1cceRoger A. Faulkner			    n1, sizeof (n1)));
14997c478bdstevel@tonic-gate		}
15007c478bdstevel@tonic-gate		break;
15017c478bdstevel@tonic-gate	}
15027c478bdstevel@tonic-gate
15037c478bdstevel@tonic-gate	case DT_DC_TYPEDEF:
1504e4586ebmws		if (dt_idstack_lookup(&yypcb->pcb_globals, dsp->ds_ident)) {
1505e4586ebmws			xyerror(D_DECL_IDRED, "global variable identifier "
1506e4586ebmws			    "redeclared: %s\n", dsp->ds_ident);
1507e4586ebmws		}
1508e4586ebmws
1509e4586ebmws		if (ctf_lookup_by_name(dmp->dm_ctfp,
1510e4586ebmws		    dsp->ds_ident) != CTF_ERR) {
1511e4586ebmws			xyerror(D_DECL_IDRED,
1512e4586ebmws			    "typedef redeclared: %s\n", dsp->ds_ident);
1513e4586ebmws		}
1514e4586ebmws
15157c478bdstevel@tonic-gate		/*
15167c478bdstevel@tonic-gate		 * If the source type for the typedef is not defined in the
15177c478bdstevel@tonic-gate		 * target container or its parent, copy the type to the target
15187c478bdstevel@tonic-gate		 * container and reset dtt_ctfp and dtt_type to the copy.
15197c478bdstevel@tonic-gate		 */
15207c478bdstevel@tonic-gate		if (dtt.dtt_ctfp != dmp->dm_ctfp &&
15217c478bdstevel@tonic-gate		    dtt.dtt_ctfp != ctf_parent_file(dmp->dm_ctfp)) {
15227c478bdstevel@tonic-gate
15237c478bdstevel@tonic-gate			dtt.dtt_type = ctf_add_type(dmp->dm_ctfp,
15247c478bdstevel@tonic-gate			    dtt.dtt_ctfp, dtt.dtt_type);
15257c478bdstevel@tonic-gate			dtt.dtt_ctfp = dmp->dm_ctfp;
15267c478bdstevel@tonic-gate
15277c478bdstevel@tonic-gate			if (dtt.dtt_type == CTF_ERR ||
15287c478bdstevel@tonic-gate			    ctf_update(dtt.dtt_ctfp) == CTF_ERR) {
15297c478bdstevel@tonic-gate				xyerror(D_UNKNOWN, "failed to copy typedef %s "
15307c478bdstevel@tonic-gate				    "source type: %s\n", dsp->ds_ident,
15317c478bdstevel@tonic-gate				    ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));
15327c478bdstevel@tonic-gate			}
15337c478bdstevel@tonic-gate		}
15347c478bdstevel@tonic-gate
15357c478bdstevel@tonic-gate		type = ctf_add_typedef(dmp->dm_ctfp,
15367c478bdstevel@tonic-gate		    CTF_ADD_ROOT, dsp->ds_ident, dtt.dtt_type);
15377c478bdstevel@tonic-gate
15387c478bdstevel@tonic-gate		if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {
15397c478bdstevel@tonic-gate			xyerror(D_UNKNOWN, "failed to typedef %s: %s\n",
15407c478bdstevel@tonic-gate			    dsp->ds_ident, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
15417c478bdstevel@tonic-gate		}
15427c478bdstevel@tonic-gate
15437c478bdstevel@tonic-gate		dt_dprintf("typedef %s added as id %ld\n", dsp->ds_ident, type);
15447c478bdstevel@tonic-gate		break;
15457c478bdstevel@tonic-gate
15467c478bdstevel@tonic-gate	default: {
15477c478bdstevel@tonic-gate		ctf_encoding_t cte;
15487c478bdstevel@tonic-gate		dt_idhash_t *dhp;
15497c478bdstevel@tonic-gate		dt_ident_t *idp;
15507c478bdstevel@tonic-gate		dt_node_t idn;
15517c478bdstevel@tonic-gate		int assc, idkind;
15527c478bdstevel@tonic-gate		uint_t id, kind;
15537c478bdstevel@tonic-gate		ushort_t idflags;
15547c478bdstevel@tonic-gate
15557c478bdstevel@tonic-gate		switch (class) {
15567c478bdstevel@tonic-gate		case DT_DC_THIS:
15577c478bdstevel@tonic-gate			dhp = yypcb->pcb_locals;
15587c478bdstevel@tonic-gate			idflags = DT_IDFLG_LOCAL;
15597c478bdstevel@tonic-gate			idp = dt_idhash_lookup(dhp, dsp->ds_ident);
15607c478bdstevel@tonic-gate			break;
15617c478bdstevel@tonic-gate		case DT_DC_SELF:
15627c478bdstevel@tonic-gate			dhp = dtp->dt_tls;
15637c478bdstevel@tonic-gate			idflags = DT_IDFLG_TLS;
15647c478bdstevel@tonic-gate			idp = dt_idhash_lookup(dhp, dsp->ds_ident);
15657c478bdstevel@tonic-gate			break;
15667c478bdstevel@tonic-gate		default:
15677c478bdstevel@tonic-gate			dhp = dtp->dt_globals;
15687c478bdstevel@tonic-gate			idflags = 0;
15697c478bdstevel@tonic-gate			idp = dt_idstack_lookup(
15707c478bdstevel@tonic-gate			    &yypcb->pcb_globals, dsp->ds_ident);
15717c478bdstevel@tonic-gate			break;
15727c478bdstevel@tonic-gate		}
15737c478bdstevel@tonic-gate
15747c478bdstevel@tonic-gate		if (ddp->dd_kind == CTF_K_ARRAY && ddp->dd_node == NULL) {
15757c478bdstevel@tonic-gate			xyerror(D_DECL_ARRNULL,
15767c478bdstevel@tonic-gate			    "array declaration requires array dimension or "
15777c478bdstevel@tonic-gate			    "tuple signature: %s\n", dsp->ds_ident);
15787c478bdstevel@tonic-gate		}
15797c478bdstevel@tonic-gate
15807c478bdstevel@tonic-gate		if (idp != NULL && idp->di_gen == 0) {
15817c478bdstevel@tonic-gate			xyerror(D_DECL_IDRED, "built-in identifier "
15827c478bdstevel@tonic-gate			    "redeclared: %s\n", idp->di_name);
15837c478bdstevel@tonic-gate		}
15847c478bdstevel@tonic-gate
1585e4586ebmws		if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_CDEFS,
1586e4586ebmws		    dsp->ds_ident, NULL) == 0 ||
1587e4586ebmws		    dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS,
1588e4586ebmws		    dsp->ds_ident, NULL) == 0) {
1589e4586ebmws			xyerror(D_DECL_IDRED, "typedef identifier "
1590e4586ebmws			    "redeclared: %s\n", dsp->ds_ident);
1591e4586ebmws		}
1592e4586ebmws
15937c478bdstevel@tonic-gate		/*
15947c478bdstevel@tonic-gate		 * Cache some attributes of the decl to make the rest of this
15957c478bdstevel@tonic-gate		 * code simpler: if the decl is an array which is subscripted
15967c478bdstevel@tonic-gate		 * by a type rather than an integer, then it's an associative
15977c478bdstevel@tonic-gate		 * array (assc).  We then expect to match either DT_IDENT_ARRAY
15987c478bdstevel@tonic-gate		 * for associative arrays or DT_IDENT_SCALAR for anything else.
15997c478bdstevel@tonic-gate		 */
16007c478bdstevel@tonic-gate		assc = ddp->dd_kind == CTF_K_ARRAY &&
16017c478bdstevel@tonic-gate		    ddp->dd_node->dn_kind == DT_NODE_TYPE;
16027c478bdstevel@tonic-gate
16037c478bdstevel@tonic-gate		idkind = assc ? DT_IDENT_ARRAY : DT_IDENT_SCALAR;
16047c478bdstevel@tonic-gate
16057c478bdstevel@tonic-gate		/*
16067c478bdstevel@tonic-gate		 * Create a fake dt_node_t on the stack so we can determine the
16077c478bdstevel@tonic-gate		 * type of any matching identifier by assigning to this node.
16087c478bdstevel@tonic-gate		 * If the pre-existing ident has its di_type set, propagate
16097c478bdstevel@tonic-gate		 * the type by hand so as not to trigger a prototype check for
16107c478bdstevel@tonic-gate		 * arrays (yet); otherwise we use dt_ident_cook() on the ident
16117c478bdstevel@tonic-gate		 * to ensure it is fully initialized before looking at it.
16127c478bdstevel@tonic-gate		 */
16137c478bdstevel@tonic-gate		bzero(&idn, sizeof (dt_node_t));
16147c478bdstevel@tonic-gate
16157c478bdstevel@tonic-gate		if (idp != NULL && idp->di_type != CTF_ERR)
1616a386cc1Robert Mustacchi			dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
1617a386cc1Robert Mustacchi			    B_FALSE);
16187c478bdstevel@tonic-gate		else if (idp != NULL)
16197c478bdstevel@tonic-gate			(void) dt_ident_cook(&idn, idp, NULL);
16207c478bdstevel@tonic-gate
16217c478bdstevel@tonic-gate		if (assc) {
16227c478bdstevel@tonic-gate			if (class == DT_DC_THIS) {
16237c478bdstevel@tonic-gate				xyerror(D_DECL_LOCASSC, "associative arrays "
16247c478bdstevel@tonic-gate				    "may not be declared as local variables:"
16257c478bdstevel@tonic-gate				    " %s\n", dsp->ds_ident);
16267c478bdstevel@tonic-gate			}
16277c478bdstevel@tonic-gate
16287c478bdstevel@tonic-gate			if (dt_decl_type(ddp->dd_next, &dtt) != 0)
16297c478bdstevel@tonic-gate				longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
16307c478bdstevel@tonic-gate		}
16317c478bdstevel@tonic-gate
16327c478bdstevel@tonic-gate		if (idp != NULL && (idp->di_kind != idkind ||
16337c478bdstevel@tonic-gate		    ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type,
16347c478bdstevel@tonic-gate		    idn.dn_ctfp, idn.dn_type) != 0)) {
16357c478bdstevel@tonic-gate			xyerror(D_DECL_IDRED, "identifier redeclared: %s\n"
16367c478bdstevel@tonic-gate			    "\t current: %s %s\n\tprevious: %s %s\n",
16377c478bdstevel@tonic-gate			    dsp->ds_ident, dt_idkind_name(idkind),
16387c478bdstevel@tonic-gate			    dt_type_name(dtt.dtt_ctfp,
16397c478bdstevel@tonic-gate			    dtt.dtt_type, n1, sizeof (n1)),
16407c478bdstevel@tonic-gate			    dt_idkind_name(idp->di_kind),
16417c478bdstevel@tonic-gate			    dt_node_type_name(&idn, n2, sizeof (n2)));
16427c478bdstevel@tonic-gate
16437c478bdstevel@tonic-gate		} else if (idp != NULL && assc) {
16447c478bdstevel@tonic-gate			const dt_idsig_t *isp = idp->di_data;
16457c478bdstevel@tonic-gate			dt_node_t *dnp = ddp->dd_node;
16467c478bdstevel@tonic-gate			int argc = 0;
16477c478bdstevel@tonic-gate
16487c478bdstevel@tonic-gate			for (; dnp != NULL; dnp = dnp->dn_list, argc++) {
16497c478bdstevel@tonic-gate				const dt_node_t *pnp = &isp->dis_args[argc];
16507c478bdstevel@tonic-gate
16517c478bdstevel@tonic-gate				if (argc >= isp->dis_argc)
16527c478bdstevel@tonic-gate					continue; /* tuple length mismatch */
16537c478bdstevel@tonic-gate
16547c478bdstevel@tonic-gate				if (ctf_type_cmp(dnp->dn_ctfp, dnp->dn_type,
16557c478bdstevel@tonic-gate				    pnp->dn_ctfp, pnp->dn_type) == 0)
16567c478bdstevel@tonic-gate					continue;
16577c478bdstevel@tonic-gate
16587c478bdstevel@tonic-gate				xyerror(D_DECL_IDRED,
16597c478bdstevel@tonic-gate				    "identifier redeclared: %s\n"
16607c478bdstevel@tonic-gate				    "\t current: %s, key #%d of type %s\n"
16617c478bdstevel@tonic-gate				    "\tprevious: %s, key #%d of type %s\n",
16627c478bdstevel@tonic-gate				    dsp->ds_ident,
16637c478bdstevel@tonic-gate				    dt_idkind_name(idkind), argc + 1,
16647c478bdstevel@tonic-gate				    dt_node_type_name(dnp, n1, sizeof (n1)),
16657c478bdstevel@tonic-gate				    dt_idkind_name(idp->di_kind), argc + 1,
16667c478bdstevel@tonic-gate				    dt_node_type_name(pnp, n2, sizeof (n2)));
16677c478bdstevel@tonic-gate			}
16687c478bdstevel@tonic-gate
16697c478bdstevel@tonic-gate			if (isp->dis_argc != argc) {
16707c478bdstevel@tonic-gate				xyerror(D_DECL_IDRED,
16717c478bdstevel@tonic-gate				    "identifier redeclared: %s\n"
16727c478bdstevel@tonic-gate				    "\t current: %s of %s, tuple length %d\n"
16737c478bdstevel@tonic-gate				    "\tprevious: %s of %s, tuple length %d\n",
16747c478bdstevel@tonic-gate				    dsp->ds_ident, dt_idkind_name(idkind),
16757c478bdstevel@tonic-gate				    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
16767c478bdstevel@tonic-gate				    n1, sizeof (n1)), argc,
16777c478bdstevel@tonic-gate				    dt_idkind_name(idp->di_kind),
16787c478bdstevel@tonic-gate				    dt_node_type_name(&idn, n2, sizeof (n2)),
16797c478bdstevel@tonic-gate				    isp->dis_argc);
16807c478bdstevel@tonic-gate			}
16817c478bdstevel@tonic-gate
16827c478bdstevel@tonic-gate		} else if (idp == NULL) {
16837c478bdstevel@tonic-gate			type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
16847c478bdstevel@tonic-gate			kind = ctf_type_kind(dtt.dtt_ctfp, type);
16857c478bdstevel@tonic-gate
16867c478bdstevel@tonic-gate			switch (kind) {
16877c478bdstevel@tonic-gate			case CTF_K_INTEGER:
16887c478bdstevel@tonic-gate				if (ctf_type_encoding(dtt.dtt_ctfp, type,
16897c478bdstevel@tonic-gate				    &cte) == 0 && IS_VOID(cte)) {
16907c478bdstevel@tonic-gate					xyerror(D_DECL_VOIDOBJ, "cannot have "
16917c478bdstevel@tonic-gate					    "void object: %s\n", dsp->ds_ident);
16927c478bdstevel@tonic-gate				}
16937c478bdstevel@tonic-gate				break;
16947c478bdstevel@tonic-gate			case CTF_K_STRUCT:
16957c478bdstevel@tonic-gate			case CTF_K_UNION:
16967c478bdstevel@tonic-gate				if (ctf_type_size(dtt.dtt_ctfp, type) != 0)
16977c478bdstevel@tonic-gate					break; /* proceed to declaring */
16987c478bdstevel@tonic-gate				/*FALLTHRU*/
16997c478bdstevel@tonic-gate			case CTF_K_FORWARD:
17007c478bdstevel@tonic-gate				xyerror(D_DECL_INCOMPLETE,
17017c478bdstevel@tonic-gate				    "incomplete struct/union/enum %s: %s\n",
17027c478bdstevel@tonic-gate				    dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,
17037c478bdstevel@tonic-gate				    n1, sizeof (n1)), dsp->ds_ident);
17047c478bdstevel@tonic-gate				/*NOTREACHED*/
17057c478bdstevel@tonic-gate			}
17067c478bdstevel@tonic-gate
17077c478bdstevel@tonic-gate			if (dt_idhash_nextid(dhp, &id) == -1) {
17087c478bdstevel@tonic-gate				xyerror(D_ID_OFLOW, "cannot create %s: limit "
17097c478bdstevel@tonic-gate				    "on number of %s variables exceeded\n",
17107c478bdstevel@tonic-gate				    dsp->ds_ident, dt_idhash_name(dhp));
17117c478bdstevel@tonic-gate			}
17127c478bdstevel@tonic-gate
17137c478bdstevel@tonic-gate			dt_dprintf("declare %s %s variable %s, id=%u\n",
17147c478bdstevel@tonic-gate			    dt_idhash_name(dhp), dt_idkind_name(idkind),
17157c478bdstevel@tonic-gate			    dsp->ds_ident, id);
17167c478bdstevel@tonic-gate
17177c478bdstevel@tonic-gate			idp = dt_idhash_insert(dhp, dsp->ds_ident, idkind,
17187c478bdstevel@tonic-gate			    idflags | DT_IDFLG_WRITE | DT_IDFLG_DECL, id,
17197c478bdstevel@tonic-gate			    _dtrace_defattr, 0, assc ? &dt_idops_assc :
17207c478bdstevel@tonic-gate			    &dt_idops_thaw, NULL, dtp->dt_gen);
17217c478bdstevel@tonic-gate
17227c478bdstevel@tonic-gate			if (idp == NULL)
17237c478bdstevel@tonic-gate				longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
17247c478bdstevel@tonic-gate
17257c478bdstevel@tonic-gate			dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type);
17267c478bdstevel@tonic-gate
17277c478bdstevel@tonic-gate			/*
17287c478bdstevel@tonic-gate			 * If we are declaring an associative array, use our
17297c478bdstevel@tonic-gate			 * fake parse node to cook the new assoc identifier.
17307c478bdstevel@tonic-gate			 * This will force the ident code to instantiate the
17317c478bdstevel@tonic-gate			 * array type signature corresponding to the list of
17327c478bdstevel@tonic-gate			 * types pointed to by ddp->dd_node.  We also reset
17337c478bdstevel@tonic-gate			 * the identifier's attributes based upon the result.
17347c478bdstevel@tonic-gate			 */
17357c478bdstevel@tonic-gate			if (assc) {
17367c478bdstevel@tonic-gate				idp->di_attr =
17377c478bdstevel@tonic-gate				    dt_ident_cook(&idn, idp, &ddp->dd_node);
17387c478bdstevel@tonic-gate			}
17397c478bdstevel@tonic-gate		}
17407c478bdstevel@tonic-gate	}
17417c478bdstevel@tonic-gate
17427c478bdstevel@tonic-gate	} /* end of switch */
17437c478bdstevel@tonic-gate
17447c478bdstevel@tonic-gate	free(dsp->ds_ident);
17457c478bdstevel@tonic-gate	dsp->ds_ident = NULL;
17467c478bdstevel@tonic-gate
17477c478bdstevel@tonic-gate	return (NULL);
17487c478bdstevel@tonic-gate}
17497c478bdstevel@tonic-gate
17507c478bdstevel@tonic-gatedt_node_t *
17517c478bdstevel@tonic-gatedt_node_func(dt_node_t *dnp, dt_node_t *args)
17527c478bdstevel@tonic-gate{
17537c478bdstevel@tonic-gate	dt_ident_t *idp;
17547c478bdstevel@tonic-gate
17557c478bdstevel@tonic-gate	if (dnp->dn_kind != DT_NODE_IDENT) {
17567c478bdstevel@tonic-gate		xyerror(D_FUNC_IDENT,
17577c478bdstevel@tonic-gate		    "function designator is not of function type\n");
17587c478bdstevel@tonic-gate	}
17597c478bdstevel@tonic-gate
17607c478bdstevel@tonic-gate	idp = dt_idstack_lookup(&yypcb->pcb_globals, dnp->dn_string);
17617c478bdstevel@tonic-gate
17627c478bdstevel@tonic-gate	if (idp == NULL) {
17637c478bdstevel@tonic-gate		xyerror(D_FUNC_UNDEF,
17647c478bdstevel@tonic-gate		    "undefined function name: %s\n", dnp->dn_string);
17657c478bdstevel@tonic-gate	}
17667c478bdstevel@tonic-gate
17677c478bdstevel@tonic-gate	if (idp->di_kind != DT_IDENT_FUNC &&
17687c478bdstevel@tonic-gate	    idp->di_kind != DT_IDENT_AGGFUNC &&
17697c478bdstevel@tonic-gate	    idp->di_kind != DT_IDENT_ACTFUNC) {
17707c478bdstevel@tonic-gate		xyerror(D_FUNC_IDKIND, "%s '%s' may not be referenced as a "
17717c478bdstevel@tonic-gate		    "function\n", dt_idkind_name(idp->di_kind), idp->di_name);
17727c478bdstevel@tonic-gate	}
17737c478bdstevel@tonic-gate
17747c478bdstevel@tonic-gate	free(dnp->dn_string);
17757c478bdstevel@tonic-gate	dnp->dn_string = NULL;
17767c478bdstevel@tonic-gate
17777c478bdstevel@tonic-gate	dnp->dn_kind = DT_NODE_FUNC;
17787c478bdstevel@tonic-gate	dnp->dn_flags &= ~DT_NF_COOKED;
17797c478bdstevel@tonic-gate	dnp->dn_ident = idp;
17807c478bdstevel@tonic-gate	dnp->dn_args = args;
17817c478bdstevel@tonic-gate	dnp->dn_list = NULL;
17827c478bdstevel@tonic-gate
17837c478bdstevel@tonic-gate	return (dnp);
17847c478bdstevel@tonic-gate}
17857c478bdstevel@tonic-gate
17867c478bdstevel@tonic-gate/*
17877c478bdstevel@tonic-gate * The offsetof() function is special because it takes a type name as an
17887c478bdstevel@tonic-gate * argument.  It does not actually construct its own node; after looking up the
17897c478bdstevel@tonic-gate * structure or union offset, we just return an integer node with the offset.
17907c478bdstevel@tonic-gate */
17917c478bdstevel@tonic-gatedt_node_t *
17927c478bdstevel@tonic-gatedt_node_offsetof(dt_decl_t *ddp, char *s)
17937c478bdstevel@tonic-gate{
17947c478bdstevel@tonic-gate	dtrace_typeinfo_t dtt;
17957c478bdstevel@tonic-gate	dt_node_t dn;
17967c478bdstevel@tonic-gate	char *name;
17977c478bdstevel@tonic-gate	int err;
17987c478bdstevel@tonic-gate
17997c478bdstevel@tonic-gate	ctf_membinfo_t ctm;
18007c478bdstevel@tonic-gate	ctf_id_t type;
18017c478bdstevel@tonic-gate	uint_t kind;
18027c478bdstevel@tonic-gate
180323a1cceRoger A. Faulkner	name = strdupa(s);
18047c478bdstevel@tonic-gate	free(s);
18057c478bdstevel@tonic-gate
18067c478bdstevel@tonic-gate	err = dt_decl_type(ddp, &dtt);
18077c478bdstevel@tonic-gate	dt_decl_free(ddp);
18087c478bdstevel@tonic-gate
18097c478bdstevel@tonic-gate	if (err != 0)
18107c478bdstevel@tonic-gate		longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);
18117c478bdstevel@tonic-gate
18127c478bdstevel@tonic-gate	type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);
18137c478bdstevel@tonic-gate	kind = ctf_type_kind(dtt.dtt_ctfp, type);
18147c478bdstevel@tonic-gate
18157c478bdstevel@tonic-gate	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {
18167c478bdstevel@tonic-gate		xyerror(D_OFFSETOF_TYPE,
18177c478bdstevel@tonic-gate		    "offsetof operand must be a struct or union type\n");
18187c478bdstevel@tonic-gate	}
18197c478bdstevel@tonic-gate
18207c478bdstevel@tonic-gate	if (ctf_member_info(dtt.dtt_ctfp, type, name, &ctm) == CTF_ERR) {
18217c478bdstevel@tonic-gate		xyerror(D_UNKNOWN, "failed to determine offset of %s: %s\n",
18227c478bdstevel@tonic-gate		    name, ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));
18237c478bdstevel@tonic-gate	}
18247c478bdstevel@tonic-gate
18257c478bdstevel@tonic-gate	bzero(&dn, sizeof (dn));
1826a386cc1Robert Mustacchi	dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
18277c478bdstevel@tonic-gate
18287c478bdstevel@tonic-gate	if (dn.dn_flags & DT_NF_BITFIELD) {
18297c478bdstevel@tonic-gate		xyerror(D_OFFSETOF_BITFIELD,
18307c478bdstevel@tonic-gate		    "cannot take offset of a bit-field: %s\n", name);
18317c478bdstevel@tonic-gate	}
18327c478bdstevel@tonic-gate
18337c478bdstevel@tonic-gate	return (dt_node_int(ctm.ctm_offset / NBBY));
18347c478bdstevel@tonic-gate}
18357c478bdstevel@tonic-gate
18367c478bdstevel@tonic-gatedt_node_t *
18377c478bdstevel@tonic-gatedt_node_op1(int op, dt_node_t *cp)
18387c478bdstevel@tonic-gate{
18397c478bdstevel@tonic-gate	dt_node_t *dnp;
18407c478bdstevel@tonic-gate
18417c478bdstevel@tonic-gate	if (cp->dn_kind == DT_NODE_INT) {
18427c478bdstevel@tonic-gate		switch (op) {
18437c478bdstevel@tonic-gate		case DT_TOK_INEG:
18447c478bdstevel@tonic-gate			/*
18457c478bdstevel@tonic-gate			 * If we're negating an unsigned integer, zero out any
18467c478bdstevel@tonic-gate			 * extra top bits to truncate the value to the size of
18477c478bdstevel@tonic-gate			 * the effective type determined by dt_node_int().
18487c478bdstevel@tonic-gate			 */
18497c478bdstevel@tonic-gate			cp->dn_value = -cp->dn_value;
18507c478bdstevel@tonic-gate			if (!(cp->dn_flags & DT_NF_SIGNED)) {
18517c478bdstevel@tonic-gate				cp->dn_value &= ~0ULL >>
18527c478bdstevel@tonic-gate				    (64 - dt_node_type_size(cp) * NBBY);
18537c478bdstevel@tonic-gate			}
18547c478bdstevel@tonic-gate			/*FALLTHRU*/
18557c478bdstevel@tonic-gate		case DT_TOK_IPOS:
18567c478bdstevel@tonic-gate			return (cp);
18577c478bdstevel@tonic-gate		case DT_TOK_BNEG:
18587c478bdstevel@tonic-gate			cp->dn_value = ~cp->dn_value;
18597c478bdstevel@tonic-gate			return (cp);
18607c478bdstevel@tonic-gate		case DT_TOK_LNEG:
18617c478bdstevel@tonic-gate			cp->dn_value = !cp->dn_value;
18627c478bdstevel@tonic-gate			return (cp);
18637c478bdstevel@tonic-gate		}
18647c478bdstevel@tonic-gate	}
18657c478bdstevel@tonic-gate
18667c478bdstevel@tonic-gate	/*
18677c478bdstevel@tonic-gate	 * If sizeof is applied to a type_name or string constant, we can
18687c478bdstevel@tonic-gate	 * transform 'cp' into an integer constant in the node construction
18697c478bdstevel@tonic-gate	 * pass so that it can then be used for arithmetic in this pass.
18707c478bdstevel@tonic-gate	 */
18717c478bdstevel@tonic-gate	if (op == DT_TOK_SIZEOF &&
18727c478bdstevel@tonic-gate	    (cp->dn_kind == DT_NODE_STRING || cp->dn_kind == DT_NODE_TYPE)) {
18737c478bdstevel@tonic-gate		dtrace_hdl_t *dtp = yypcb->pcb_hdl;
18747c478bdstevel@tonic-gate		size_t size = dt_node_type_size(cp);
18757c478bdstevel@tonic-gate
18767c478bdstevel@tonic-gate		if (size == 0) {
18777c478bdstevel@tonic-gate			xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an "
18787c478bdstevel@tonic-gate			    "operand of unknown size\n");
18797c478bdstevel@tonic-gate		}
18807c478bdstevel@tonic-gate
18817c478bdstevel@tonic-gate		dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
1882a386cc1Robert Mustacchi		    ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
1883a386cc1Robert Mustacchi		    B_FALSE);
18847c478bdstevel@tonic-gate
18857c478bdstevel@tonic-gate		cp->dn_kind = DT_NODE_INT;
18867c478bdstevel@tonic-gate		cp->dn_op = DT_TOK_INT;
18877c478bdstevel@tonic-gate		cp->dn_value = size;
18887c478bdstevel@tonic-gate
18897c478bdstevel@tonic-gate		return (cp);
18907c478bdstevel@tonic-gate	}
18917c478bdstevel@tonic-gate
18927c478bdstevel@tonic-gate	dnp = dt_node_alloc(DT_NODE_OP1);
18937c478bdstevel@tonic-gate	assert(op <= USHRT_MAX);
18947c478bdstevel@tonic-gate	dnp->dn_op = (ushort_t)op;
18957c478bdstevel@tonic-gate	dnp->dn_child = cp;
18967c478bdstevel@tonic-gate
18977c478bdstevel@tonic-gate	return (dnp);
18987c478bdstevel@tonic-gate}
18997c478bdstevel@tonic-gate
1900e5803b7Adam H. Leventhal/*
1901e5803b7Adam H. Leventhal * If an integer constant is being cast to another integer type, we can
1902e5803b7Adam H. Leventhal * perform the cast as part of integer constant folding in this pass. We must
1903e5803b7Adam H. Leventhal * take action when the integer is being cast to a smaller type or if it is
1904e5803b7Adam H. Leventhal * changing signed-ness. If so, we first shift rp's bits bits high (losing
1905e5803b7Adam H. Leventhal * excess bits if narrowing) and then shift them down with either a logical
1906e5803b7Adam H. Leventhal * shift (unsigned) or arithmetic shift (signed).
1907e5803b7Adam H. Leventhal */
1908e5803b7Adam H. Leventhalstatic void
1909e5803b7Adam H. Leventhaldt_cast(dt_node_t *lp, dt_node_t *rp)
1910e5803b7Adam H. Leventhal{
1911e5803b7Adam H. Leventhal	size_t srcsize = dt_node_type_size(rp);
1912e5803b7Adam H. Leventhal	size_t dstsize = dt_node_type_size(lp);
1913e5803b7Adam H. Leventhal
1914e5803b7Adam H. Leventhal	if (dstsize < srcsize) {
1915e5803b7Adam H. Leventhal		int n = (sizeof (uint64_t) - dstsize) * NBBY;
1916e5803b7Adam H. Leventhal		rp->dn_value <<= n;
1917e5803b7Adam H. Leventhal		rp->dn_value >>= n;
1918e5803b7Adam H. Leventhal	} else if (dstsize > srcsize) {
1919e5803b7Adam H. Leventhal		int n = (sizeof (uint64_t) - srcsize) * NBBY;
1920e5803b7Adam H. Leventhal		int s = (dstsize - srcsize) * NBBY;
1921e5803b7Adam H. Leventhal
1922e5803b7Adam H. Leventhal		rp->dn_value <<= n;
1923e5803b7Adam H. Leventhal		if (rp->dn_flags & DT_NF_SIGNED) {
1924e5803b7Adam H. Leventhal			rp->dn_value = (intmax_t)rp->dn_value >> s;
1925e5803b7Adam H. Leventhal			rp->dn_value >>= n - s;
1926e5803b7Adam H. Leventhal		} else {
1927e5803b7Adam H. Leventhal			rp->dn_value >>= n;
1928e5803b7Adam H. Leventhal		}
1929e5803b7Adam H. Leventhal	}
1930e5803b7Adam H. Leventhal}
1931e5803b7Adam H. Leventhal
19327c478bdstevel@tonic-gatedt_node_t *
19337c478bdstevel@tonic-gatedt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
19347c478bdstevel@tonic-gate{
19357c478bdstevel@tonic-gate	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
19367c478bdstevel@tonic-gate	dt_node_t *dnp;
19377c478bdstevel@tonic-gate
19387c478bdstevel@tonic-gate	/*
19397c478bdstevel@tonic-gate	 * First we check for operations that are illegal -- namely those that
19407c478bdstevel@tonic-gate	 * might result in integer division by zero, and abort if one is found.
19417c478bdstevel@tonic-gate	 */
19427c478bdstevel@tonic-gate	if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0 &&
19437c478bdstevel@tonic-gate	    (op == DT_TOK_MOD || op == DT_TOK_DIV ||
19447c478bdstevel@tonic-gate	    op == DT_TOK_MOD_EQ || op == DT_TOK_DIV_EQ))
19457c478bdstevel@tonic-gate		xyerror(D_DIV_ZERO, "expression contains division by zero\n");
19467c478bdstevel@tonic-gate
19477c478bdstevel@tonic-gate	/*
19487c478bdstevel@tonic-gate	 * If both children are immediate values, we can just perform inline
19497c478bdstevel@tonic-gate	 * calculation and return a new immediate node with the result.
19507c478bdstevel@tonic-gate	 */
19517c478bdstevel@tonic-gate	if (lp->dn_kind == DT_NODE_INT && rp->dn_kind == DT_NODE_INT) {
19527c478bdstevel@tonic-gate		uintmax_t l = lp->dn_value;
19537c478bdstevel@tonic-gate		uintmax_t r = rp->dn_value;
19547c478bdstevel@tonic-gate
19557c478bdstevel@tonic-gate		dnp = dt_node_int(0); /* allocate new integer node for result */
19567c478bdstevel@tonic-gate
19577c478bd