17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
523a1cceaSRoger A. Faulkner  * Common Development and Distribution License (the "License").
623a1cceaSRoger A. Faulkner  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21e4586ebfSmws 
227c478bd9Sstevel@tonic-gate /*
2323a1cceaSRoger A. Faulkner  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*bc1f688bSRobert Mustacchi  * Copyright (c) 2015, Joyent Inc. All rights reserved.
25c3bd3abdSMatthew Ahrens  * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * DTrace D Language Parser
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the
327c478bd9Sstevel@tonic-gate  * parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles
337c478bd9Sstevel@tonic-gate  * the construction of the parse tree nodes and their syntactic validation.
347c478bd9Sstevel@tonic-gate  * The parse tree is constructed of dt_node_t structures (see <dt_parser.h>)
357c478bd9Sstevel@tonic-gate  * that are built in two passes: (1) the "create" pass, where the parse tree
367c478bd9Sstevel@tonic-gate  * nodes are allocated by calls from the grammar to dt_node_*() subroutines,
377c478bd9Sstevel@tonic-gate  * and (2) the "cook" pass, where nodes are coalesced, assigned D types, and
387c478bd9Sstevel@tonic-gate  * validated according to the syntactic rules of the language.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * All node allocations are performed using dt_node_alloc().  All node frees
417c478bd9Sstevel@tonic-gate  * during the parsing phase are performed by dt_node_free(), which frees node-
427c478bd9Sstevel@tonic-gate  * internal state but does not actually free the nodes.  All final node frees
437c478bd9Sstevel@tonic-gate  * are done as part of the end of dt_compile() or as part of destroying
447c478bd9Sstevel@tonic-gate  * persistent identifiers or translators which have embedded nodes.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * The dt_node_* routines that implement pass (1) may allocate new nodes.  The
477c478bd9Sstevel@tonic-gate  * dt_cook_* routines that implement pass (2) may *not* allocate new nodes.
487c478bd9Sstevel@tonic-gate  * They may free existing nodes using dt_node_free(), but they may not actually
497c478bd9Sstevel@tonic-gate  * deallocate any dt_node_t's.  Currently dt_cook_op2() is an exception to this
507c478bd9Sstevel@tonic-gate  * rule: see the comments therein for how this issue is resolved.
517c478bd9Sstevel@tonic-gate  *
527c478bd9Sstevel@tonic-gate  * The dt_cook_* routines are responsible for (at minimum) setting the final
537c478bd9Sstevel@tonic-gate  * node type (dn_ctfp/dn_type) and attributes (dn_attr).  If dn_ctfp/dn_type
547c478bd9Sstevel@tonic-gate  * are set manually (i.e. not by one of the type assignment functions), then
557c478bd9Sstevel@tonic-gate  * the DT_NF_COOKED flag must be set manually on the node.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * The cooking pass can be applied to the same parse tree more than once (used
587c478bd9Sstevel@tonic-gate  * in the case of a comma-separated list of probe descriptions).  As such, the
597c478bd9Sstevel@tonic-gate  * cook routines must not perform any parse tree transformations which would
607c478bd9Sstevel@tonic-gate  * be invalid if the tree were subsequently cooked using a different context.
617c478bd9Sstevel@tonic-gate  *
627c478bd9Sstevel@tonic-gate  * The dn_ctfp and dn_type fields form the type of the node.  This tuple can
637c478bd9Sstevel@tonic-gate  * take on the following set of values, which form our type invariants:
647c478bd9Sstevel@tonic-gate  *
657c478bd9Sstevel@tonic-gate  * 1. dn_ctfp = NULL, dn_type = CTF_ERR
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  *    In this state, the node has unknown type and is not yet cooked.  The
687c478bd9Sstevel@tonic-gate  *    DT_NF_COOKED flag is not yet set on the node.
697c478bd9Sstevel@tonic-gate  *
707c478bd9Sstevel@tonic-gate  * 2. dn_ctfp = DT_DYN_CTFP(dtp), dn_type = DT_DYN_TYPE(dtp)
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  *    In this state, the node is a dynamic D type.  This means that generic
737c478bd9Sstevel@tonic-gate  *    operations are not valid on this node and only code that knows how to
747c478bd9Sstevel@tonic-gate  *    examine the inner details of the node can operate on it.  A <DYN> node
757c478bd9Sstevel@tonic-gate  *    must have dn_ident set to point to an identifier describing the object
767c478bd9Sstevel@tonic-gate  *    and its type.  The DT_NF_REF flag is set for all nodes of type <DYN>.
777c478bd9Sstevel@tonic-gate  *    At present, the D compiler uses the <DYN> type for:
787c478bd9Sstevel@tonic-gate  *
797c478bd9Sstevel@tonic-gate  *    - associative arrays that do not yet have a value type defined
807c478bd9Sstevel@tonic-gate  *    - translated data (i.e. the result of the xlate operator)
817c478bd9Sstevel@tonic-gate  *    - aggregations
827c478bd9Sstevel@tonic-gate  *
837c478bd9Sstevel@tonic-gate  * 3. dn_ctfp = DT_STR_CTFP(dtp), dn_type = DT_STR_TYPE(dtp)
847c478bd9Sstevel@tonic-gate  *
857c478bd9Sstevel@tonic-gate  *    In this state, the node is of type D string.  The string type is really
867c478bd9Sstevel@tonic-gate  *    a char[0] typedef, but requires special handling throughout the compiler.
877c478bd9Sstevel@tonic-gate  *
887c478bd9Sstevel@tonic-gate  * 4. dn_ctfp != NULL, dn_type = any other type ID
897c478bd9Sstevel@tonic-gate  *
907c478bd9Sstevel@tonic-gate  *    In this state, the node is of some known D/CTF type.  The normal libctf
917c478bd9Sstevel@tonic-gate  *    APIs can be used to learn more about the type name or structure.  When
927c478bd9Sstevel@tonic-gate  *    the type is assigned, the DT_NF_SIGNED, DT_NF_REF, and DT_NF_BITFIELD
937c478bd9Sstevel@tonic-gate  *    flags cache the corresponding attributes of the underlying CTF type.
947c478bd9Sstevel@tonic-gate  */
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #include <sys/param.h>
97e5803b76SAdam H. Leventhal #include <sys/sysmacros.h>
987c478bd9Sstevel@tonic-gate #include <limits.h>
997c478bd9Sstevel@tonic-gate #include <setjmp.h>
1007c478bd9Sstevel@tonic-gate #include <strings.h>
1017c478bd9Sstevel@tonic-gate #include <assert.h>
1027c478bd9Sstevel@tonic-gate #include <alloca.h>
1037c478bd9Sstevel@tonic-gate #include <stdlib.h>
1047c478bd9Sstevel@tonic-gate #include <stdarg.h>
1057c478bd9Sstevel@tonic-gate #include <stdio.h>
1067c478bd9Sstevel@tonic-gate #include <errno.h>
1077c478bd9Sstevel@tonic-gate #include <ctype.h>
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #include <dt_impl.h>
1107c478bd9Sstevel@tonic-gate #include <dt_grammar.h>
1117c478bd9Sstevel@tonic-gate #include <dt_module.h>
1127c478bd9Sstevel@tonic-gate #include <dt_provider.h>
1137c478bd9Sstevel@tonic-gate #include <dt_string.h>
1147c478bd9Sstevel@tonic-gate #include <dt_as.h>
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate dt_pcb_t *yypcb;	/* current control block for parser */
1177c478bd9Sstevel@tonic-gate dt_node_t *yypragma;	/* lex token list for control lines */
1187c478bd9Sstevel@tonic-gate char yyintprefix;	/* int token macro prefix (+/-) */
1197c478bd9Sstevel@tonic-gate char yyintsuffix[4];	/* int token suffix string [uU][lL] */
1207c478bd9Sstevel@tonic-gate int yyintdecimal;	/* int token format flag (1=decimal, 0=octal/hex) */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static const char *
opstr(int op)1237c478bd9Sstevel@tonic-gate opstr(int op)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	switch (op) {
1267c478bd9Sstevel@tonic-gate 	case DT_TOK_COMMA:	return (",");
1277c478bd9Sstevel@tonic-gate 	case DT_TOK_ELLIPSIS:	return ("...");
1287c478bd9Sstevel@tonic-gate 	case DT_TOK_ASGN:	return ("=");
1297c478bd9Sstevel@tonic-gate 	case DT_TOK_ADD_EQ:	return ("+=");
1307c478bd9Sstevel@tonic-gate 	case DT_TOK_SUB_EQ:	return ("-=");
1317c478bd9Sstevel@tonic-gate 	case DT_TOK_MUL_EQ:	return ("*=");
1327c478bd9Sstevel@tonic-gate 	case DT_TOK_DIV_EQ:	return ("/=");
1337c478bd9Sstevel@tonic-gate 	case DT_TOK_MOD_EQ:	return ("%=");
1347c478bd9Sstevel@tonic-gate 	case DT_TOK_AND_EQ:	return ("&=");
1357c478bd9Sstevel@tonic-gate 	case DT_TOK_XOR_EQ:	return ("^=");
1367c478bd9Sstevel@tonic-gate 	case DT_TOK_OR_EQ:	return ("|=");
1377c478bd9Sstevel@tonic-gate 	case DT_TOK_LSH_EQ:	return ("<<=");
1387c478bd9Sstevel@tonic-gate 	case DT_TOK_RSH_EQ:	return (">>=");
1397c478bd9Sstevel@tonic-gate 	case DT_TOK_QUESTION:	return ("?");
1407c478bd9Sstevel@tonic-gate 	case DT_TOK_COLON:	return (":");
1417c478bd9Sstevel@tonic-gate 	case DT_TOK_LOR:	return ("||");
1427c478bd9Sstevel@tonic-gate 	case DT_TOK_LXOR:	return ("^^");
1437c478bd9Sstevel@tonic-gate 	case DT_TOK_LAND:	return ("&&");
1447c478bd9Sstevel@tonic-gate 	case DT_TOK_BOR:	return ("|");
1457c478bd9Sstevel@tonic-gate 	case DT_TOK_XOR:	return ("^");
1467c478bd9Sstevel@tonic-gate 	case DT_TOK_BAND:	return ("&");
1477c478bd9Sstevel@tonic-gate 	case DT_TOK_EQU:	return ("==");
1487c478bd9Sstevel@tonic-gate 	case DT_TOK_NEQ:	return ("!=");
1497c478bd9Sstevel@tonic-gate 	case DT_TOK_LT:		return ("<");
1507c478bd9Sstevel@tonic-gate 	case DT_TOK_LE:		return ("<=");
1517c478bd9Sstevel@tonic-gate 	case DT_TOK_GT:		return (">");
1527c478bd9Sstevel@tonic-gate 	case DT_TOK_GE:		return (">=");
1537c478bd9Sstevel@tonic-gate 	case DT_TOK_LSH:	return ("<<");
1547c478bd9Sstevel@tonic-gate 	case DT_TOK_RSH:	return (">>");
1557c478bd9Sstevel@tonic-gate 	case DT_TOK_ADD:	return ("+");
1567c478bd9Sstevel@tonic-gate 	case DT_TOK_SUB:	return ("-");
1577c478bd9Sstevel@tonic-gate 	case DT_TOK_MUL:	return ("*");
1587c478bd9Sstevel@tonic-gate 	case DT_TOK_DIV:	return ("/");
1597c478bd9Sstevel@tonic-gate 	case DT_TOK_MOD:	return ("%");
1607c478bd9Sstevel@tonic-gate 	case DT_TOK_LNEG:	return ("!");
1617c478bd9Sstevel@tonic-gate 	case DT_TOK_BNEG:	return ("~");
1627c478bd9Sstevel@tonic-gate 	case DT_TOK_ADDADD:	return ("++");
1637c478bd9Sstevel@tonic-gate 	case DT_TOK_PREINC:	return ("++");
1647c478bd9Sstevel@tonic-gate 	case DT_TOK_POSTINC:	return ("++");
1657c478bd9Sstevel@tonic-gate 	case DT_TOK_SUBSUB:	return ("--");
1667c478bd9Sstevel@tonic-gate 	case DT_TOK_PREDEC:	return ("--");
1677c478bd9Sstevel@tonic-gate 	case DT_TOK_POSTDEC:	return ("--");
1687c478bd9Sstevel@tonic-gate 	case DT_TOK_IPOS:	return ("+");
1697c478bd9Sstevel@tonic-gate 	case DT_TOK_INEG:	return ("-");
1707c478bd9Sstevel@tonic-gate 	case DT_TOK_DEREF:	return ("*");
1717c478bd9Sstevel@tonic-gate 	case DT_TOK_ADDROF:	return ("&");
1727c478bd9Sstevel@tonic-gate 	case DT_TOK_OFFSETOF:	return ("offsetof");
1737c478bd9Sstevel@tonic-gate 	case DT_TOK_SIZEOF:	return ("sizeof");
1747c478bd9Sstevel@tonic-gate 	case DT_TOK_STRINGOF:	return ("stringof");
1757c478bd9Sstevel@tonic-gate 	case DT_TOK_XLATE:	return ("xlate");
1767c478bd9Sstevel@tonic-gate 	case DT_TOK_LPAR:	return ("(");
1777c478bd9Sstevel@tonic-gate 	case DT_TOK_RPAR:	return (")");
1787c478bd9Sstevel@tonic-gate 	case DT_TOK_LBRAC:	return ("[");
1797c478bd9Sstevel@tonic-gate 	case DT_TOK_RBRAC:	return ("]");
1807c478bd9Sstevel@tonic-gate 	case DT_TOK_PTR:	return ("->");
1817c478bd9Sstevel@tonic-gate 	case DT_TOK_DOT:	return (".");
1827c478bd9Sstevel@tonic-gate 	case DT_TOK_STRING:	return ("<string>");
1837c478bd9Sstevel@tonic-gate 	case DT_TOK_IDENT:	return ("<ident>");
1847c478bd9Sstevel@tonic-gate 	case DT_TOK_TNAME:	return ("<type>");
1857c478bd9Sstevel@tonic-gate 	case DT_TOK_INT:	return ("<int>");
1867c478bd9Sstevel@tonic-gate 	default:		return ("<?>");
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate int
dt_type_lookup(const char * s,dtrace_typeinfo_t * tip)1917c478bd9Sstevel@tonic-gate dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	static const char delimiters[] = " \t\n\r\v\f*`";
1947c478bd9Sstevel@tonic-gate 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
195a386cc11SRobert Mustacchi 	const char *p, *q, *r, *end, *obj;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
1987c478bd9Sstevel@tonic-gate 		while (isspace(*p))
1997c478bd9Sstevel@tonic-gate 			p++;	/* skip leading whitespace prior to token */
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		if (p == end || (q = strpbrk(p + 1, delimiters)) == NULL)
2027c478bd9Sstevel@tonic-gate 			break;	/* empty string or single token remaining */
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 		if (*q == '`') {
2057c478bd9Sstevel@tonic-gate 			char *object = alloca((size_t)(q - p) + 1);
2067c478bd9Sstevel@tonic-gate 			char *type = alloca((size_t)(end - s) + 1);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 			/*
2097c478bd9Sstevel@tonic-gate 			 * Copy from the start of the token (p) to the location
2107c478bd9Sstevel@tonic-gate 			 * backquote (q) to extract the nul-terminated object.
2117c478bd9Sstevel@tonic-gate 			 */
2127c478bd9Sstevel@tonic-gate 			bcopy(p, object, (size_t)(q - p));
2137c478bd9Sstevel@tonic-gate 			object[(size_t)(q - p)] = '\0';
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 			/*
2167c478bd9Sstevel@tonic-gate 			 * Copy the original string up to the start of this
2177c478bd9Sstevel@tonic-gate 			 * token (p) into type, and then concatenate everything
2187c478bd9Sstevel@tonic-gate 			 * after q.  This is the type name without the object.
2197c478bd9Sstevel@tonic-gate 			 */
2207c478bd9Sstevel@tonic-gate 			bcopy(s, type, (size_t)(p - s));
2217c478bd9Sstevel@tonic-gate 			bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
2227c478bd9Sstevel@tonic-gate 
223a386cc11SRobert Mustacchi 			/*
224a386cc11SRobert Mustacchi 			 * There may be at most three delimeters. The second
225a386cc11SRobert Mustacchi 			 * delimeter is usually used to distinguish the type
226a386cc11SRobert Mustacchi 			 * within a given module, however, there could be a link
227a386cc11SRobert Mustacchi 			 * map id on the scene in which case that delimeter
228a386cc11SRobert Mustacchi 			 * would be the third. We determine presence of the lmid
229a386cc11SRobert Mustacchi 			 * if it rouglhly meets the from LM[0-9]
230a386cc11SRobert Mustacchi 			 */
231a386cc11SRobert Mustacchi 			if ((r = strchr(q + 1, '`')) != NULL &&
232a386cc11SRobert Mustacchi 			    ((r = strchr(r + 1, '`')) != NULL)) {
233a386cc11SRobert Mustacchi 				if (strchr(r + 1, '`') != NULL)
234a386cc11SRobert Mustacchi 					return (dt_set_errno(dtp,
235a386cc11SRobert Mustacchi 					    EDT_BADSCOPE));
236a386cc11SRobert Mustacchi 				if (q[1] != 'L' || q[2] != 'M')
237a386cc11SRobert Mustacchi 					return (dt_set_errno(dtp,
238a386cc11SRobert Mustacchi 					    EDT_BADSCOPE));
239a386cc11SRobert Mustacchi 			}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 			return (dtrace_lookup_by_type(dtp, object, type, tip));
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (yypcb->pcb_idepth != 0)
2467c478bd9Sstevel@tonic-gate 		obj = DTRACE_OBJ_CDEFS;
2477c478bd9Sstevel@tonic-gate 	else
2487c478bd9Sstevel@tonic-gate 		obj = DTRACE_OBJ_EVERY;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	return (dtrace_lookup_by_type(dtp, obj, s, tip));
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate  * When we parse type expressions or parse an expression with unary "&", we
2557c478bd9Sstevel@tonic-gate  * need to find a type that is a pointer to a previously known type.
2567c478bd9Sstevel@tonic-gate  * Unfortunately CTF is limited to a per-container view, so ctf_type_pointer()
2577c478bd9Sstevel@tonic-gate  * alone does not suffice for our needs.  We provide a more intelligent wrapper
2587c478bd9Sstevel@tonic-gate  * for the compiler that attempts to compute a pointer to either the given type
2597c478bd9Sstevel@tonic-gate  * or its base (that is, we try both "foo_t *" and "struct foo *"), and also
2607c478bd9Sstevel@tonic-gate  * to potentially construct the required type on-the-fly.
2617c478bd9Sstevel@tonic-gate  */
2627c478bd9Sstevel@tonic-gate int
dt_type_pointer(dtrace_typeinfo_t * tip)2637c478bd9Sstevel@tonic-gate dt_type_pointer(dtrace_typeinfo_t *tip)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
2667c478bd9Sstevel@tonic-gate 	ctf_file_t *ctfp = tip->dtt_ctfp;
2677c478bd9Sstevel@tonic-gate 	ctf_id_t type = tip->dtt_type;
2687c478bd9Sstevel@tonic-gate 	ctf_id_t base = ctf_type_resolve(ctfp, type);
269a386cc11SRobert Mustacchi 	uint_t bflags = tip->dtt_flags;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	dt_module_t *dmp;
2727c478bd9Sstevel@tonic-gate 	ctf_id_t ptr;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR ||
2757c478bd9Sstevel@tonic-gate 	    (ptr = ctf_type_pointer(ctfp, base)) != CTF_ERR) {
2767c478bd9Sstevel@tonic-gate 		tip->dtt_type = ptr;
2777c478bd9Sstevel@tonic-gate 		return (0);
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	if (yypcb->pcb_idepth != 0)
2817c478bd9Sstevel@tonic-gate 		dmp = dtp->dt_cdefs;
2827c478bd9Sstevel@tonic-gate 	else
2837c478bd9Sstevel@tonic-gate 		dmp = dtp->dt_ddefs;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (ctfp != dmp->dm_ctfp && ctfp != ctf_parent_file(dmp->dm_ctfp) &&
2867c478bd9Sstevel@tonic-gate 	    (type = ctf_add_type(dmp->dm_ctfp, ctfp, type)) == CTF_ERR) {
2877c478bd9Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
2887c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
291*bc1f688bSRobert Mustacchi 	ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, NULL, type);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	if (ptr == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {
2947c478bd9Sstevel@tonic-gate 		dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
2957c478bd9Sstevel@tonic-gate 		return (dt_set_errno(dtp, EDT_CTF));
2967c478bd9Sstevel@tonic-gate 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	tip->dtt_object = dmp->dm_name;
2997c478bd9Sstevel@tonic-gate 	tip->dtt_ctfp = dmp->dm_ctfp;
3007c478bd9Sstevel@tonic-gate 	tip->dtt_type = ptr;
301a386cc11SRobert Mustacchi 	tip->dtt_flags = bflags;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	return (0);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate const char *
dt_type_name(ctf_file_t * ctfp,ctf_id_t type,char * buf,size_t len)3077c478bd9Sstevel@tonic-gate dt_type_name(ctf_file_t *ctfp, ctf_id_t type, char *buf, size_t len)
3087c478bd9Sstevel@tonic-gate {
3097c478bd9Sstevel@tonic-gate 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if (ctfp == DT_FPTR_CTFP(dtp) && type == DT_FPTR_TYPE(dtp))
3127c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "function pointer");
3137c478bd9Sstevel@tonic-gate 	else if (ctfp == DT_FUNC_CTFP(dtp) && type == DT_FUNC_TYPE(dtp))
3147c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "function");
3157c478bd9Sstevel@tonic-gate 	else if (ctfp == DT_DYN_CTFP(dtp) && type == DT_DYN_TYPE(dtp))
3167c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "dynamic variable");
3177c478bd9Sstevel@tonic-gate 	else if (ctfp == NULL)
3187c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "<none>");
3197c478bd9Sstevel@tonic-gate 	else if (ctf_type_name(ctfp, type, buf, len) == NULL)
3207c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "unknown");
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	return (buf);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * Perform the "usual arithmetic conversions" to determine which of the two
3277c478bd9Sstevel@tonic-gate  * input operand types should be promoted and used as a result type.  The
3287c478bd9Sstevel@tonic-gate  * rules for this are described in ISOC[6.3.1.8] and K&R[A6.5].
3297c478bd9Sstevel@tonic-gate  */
3307c478bd9Sstevel@tonic-gate static void
dt_type_promote(dt_node_t * lp,dt_node_t * rp,ctf_file_t ** ofp,ctf_id_t * otype)3317c478bd9Sstevel@tonic-gate dt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate 	ctf_file_t *lfp = lp->dn_ctfp;
3347c478bd9Sstevel@tonic-gate 	ctf_id_t ltype = lp->dn_type;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	ctf_file_t *rfp = rp->dn_ctfp;
3377c478bd9Sstevel@tonic-gate 	ctf_id_t rtype = rp->dn_type;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	ctf_id_t lbase = ctf_type_resolve(lfp, ltype);
3407c478bd9Sstevel@tonic-gate 	uint_t lkind = ctf_type_kind(lfp, lbase);
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	ctf_id_t rbase = ctf_type_resolve(rfp, rtype);
3437c478bd9Sstevel@tonic-gate 	uint_t rkind = ctf_type_kind(rfp, rbase);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
3467c478bd9Sstevel@tonic-gate 	ctf_encoding_t le, re;
3477c478bd9Sstevel@tonic-gate 	uint_t lrank, rrank;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	assert(lkind == CTF_K_INTEGER || lkind == CTF_K_ENUM);
3507c478bd9Sstevel@tonic-gate 	assert(rkind == CTF_K_INTEGER || rkind == CTF_K_ENUM);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (lkind == CTF_K_ENUM) {
3537c478bd9Sstevel@tonic-gate 		lfp = DT_INT_CTFP(dtp);
3547c478bd9Sstevel@tonic-gate 		ltype = lbase = DT_INT_TYPE(dtp);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	if (rkind == CTF_K_ENUM) {
3587c478bd9Sstevel@tonic-gate 		rfp = DT_INT_CTFP(dtp);
3597c478bd9Sstevel@tonic-gate 		rtype = rbase = DT_INT_TYPE(dtp);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (ctf_type_encoding(lfp, lbase, &le) == CTF_ERR) {
3637c478bd9Sstevel@tonic-gate 		yypcb->pcb_hdl->dt_ctferr = ctf_errno(lfp);
3647c478bd9Sstevel@tonic-gate 		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	if (ctf_type_encoding(rfp, rbase, &re) == CTF_ERR) {
3687c478bd9Sstevel@tonic-gate 		yypcb->pcb_hdl->dt_ctferr = ctf_errno(rfp);
3697c478bd9Sstevel@tonic-gate 		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	/*
3737c478bd9Sstevel@tonic-gate 	 * Compute an integer rank based on the size and unsigned status.
3747c478bd9Sstevel@tonic-gate 	 * If rank is identical, pick the "larger" of the equivalent types
3757c478bd9Sstevel@tonic-gate 	 * which we define as having a larger base ctf_id_t.  If rank is
3767c478bd9Sstevel@tonic-gate 	 * different, pick the type with the greater rank.
3777c478bd9Sstevel@tonic-gate 	 */
3787c478bd9Sstevel@tonic-gate 	lrank = le.cte_bits + ((le.cte_format & CTF_INT_SIGNED) == 0);
3797c478bd9Sstevel@tonic-gate 	rrank = re.cte_bits + ((re.cte_format & CTF_INT_SIGNED) == 0);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (lrank == rrank) {
3827c478bd9Sstevel@tonic-gate 		if (lbase - rbase < 0)
3837c478bd9Sstevel@tonic-gate 			goto return_rtype;
3847c478bd9Sstevel@tonic-gate 		else
3857c478bd9Sstevel@tonic-gate 			goto return_ltype;
3867c478bd9Sstevel@tonic-gate 	} else if (lrank > rrank) {
3877c478bd9Sstevel@tonic-gate 		goto return_ltype;
3887c478bd9Sstevel@tonic-gate 	} else
3897c478bd9Sstevel@tonic-gate 		goto return_rtype;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate return_ltype:
3927c478bd9Sstevel@tonic-gate 	*ofp = lfp;
3937c478bd9Sstevel@tonic-gate 	*otype = ltype;
3947c478bd9Sstevel@tonic-gate 	return;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate return_rtype:
3977c478bd9Sstevel@tonic-gate 	*ofp = rfp;
3987c478bd9Sstevel@tonic-gate 	*otype = rtype;
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate void
dt_node_promote(dt_node_t * lp,dt_node_t * rp,dt_node_t * dnp)4027c478bd9Sstevel@tonic-gate dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
4037c478bd9Sstevel@tonic-gate {
4047c478bd9Sstevel@tonic-gate 	dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
405a386cc11SRobert Mustacchi 	dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
4067c478bd9Sstevel@tonic-gate 	dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate const char *
dt_node_name(const dt_node_t * dnp,char * buf,size_t len)4107c478bd9Sstevel@tonic-gate dt_node_name(const dt_node_t *dnp, char *buf, size_t len)
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	char n1[DT_TYPE_NAMELEN];
4137c478bd9Sstevel@tonic-gate 	char n2[DT_TYPE_NAMELEN];
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	const char *prefix = "", *suffix = "";
4167c478bd9Sstevel@tonic-gate 	const dtrace_syminfo_t *dts;
4177c478bd9Sstevel@tonic-gate 	char *s;
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	switch (dnp->dn_kind) {
4207c478bd9Sstevel@tonic-gate 	case DT_NODE_INT:
4217c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "integer constant 0x%llx",
4227c478bd9Sstevel@tonic-gate 		    (u_longlong_t)dnp->dn_value);
4237c478bd9Sstevel@tonic-gate 		break;
4247c478bd9Sstevel@tonic-gate 	case DT_NODE_STRING:
4257c478bd9Sstevel@tonic-gate 		s = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));
4267c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "string constant \"%s\"",
4277c478bd9Sstevel@tonic-gate 		    s != NULL ? s : dnp->dn_string);
4287c478bd9Sstevel@tonic-gate 		free(s);
4297c478bd9Sstevel@tonic-gate 		break;
4307c478bd9Sstevel@tonic-gate 	case DT_NODE_IDENT:
4317c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "identifier %s", dnp->dn_string);
4327c478bd9Sstevel@tonic-gate 		break;
4337c478bd9Sstevel@tonic-gate 	case DT_NODE_VAR:
4347c478bd9Sstevel@tonic-gate 	case DT_NODE_FUNC:
4357c478bd9Sstevel@tonic-gate 	case DT_NODE_AGG:
4367c478bd9Sstevel@tonic-gate 	case DT_NODE_INLINE:
4377c478bd9Sstevel@tonic-gate 		switch (dnp->dn_ident->di_kind) {
4387c478bd9Sstevel@tonic-gate 		case DT_IDENT_FUNC:
4397c478bd9Sstevel@tonic-gate 		case DT_IDENT_AGGFUNC:
4407c478bd9Sstevel@tonic-gate 		case DT_IDENT_ACTFUNC:
4417c478bd9Sstevel@tonic-gate 			suffix = "( )";
4427c478bd9Sstevel@tonic-gate 			break;
4437c478bd9Sstevel@tonic-gate 		case DT_IDENT_AGG:
4447c478bd9Sstevel@tonic-gate 			prefix = "@";
4457c478bd9Sstevel@tonic-gate 			break;
4467c478bd9Sstevel@tonic-gate 		}
4477c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "%s %s%s%s",
4487c478bd9Sstevel@tonic-gate 		    dt_idkind_name(dnp->dn_ident->di_kind),
4497c478bd9Sstevel@tonic-gate 		    prefix, dnp->dn_ident->di_name, suffix);
4507c478bd9Sstevel@tonic-gate 		break;
4517c478bd9Sstevel@tonic-gate 	case DT_NODE_SYM:
4527c478bd9Sstevel@tonic-gate 		dts = dnp->dn_ident->di_data;
4537c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "symbol %s`%s",
4547c478bd9Sstevel@tonic-gate 		    dts->dts_object, dts->dts_name);
4557c478bd9Sstevel@tonic-gate 		break;
4567c478bd9Sstevel@tonic-gate 	case DT_NODE_TYPE:
4577c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "type %s",
4587c478bd9Sstevel@tonic-gate 		    dt_node_type_name(dnp, n1, sizeof (n1)));
4597c478bd9Sstevel@tonic-gate 		break;
4607c478bd9Sstevel@tonic-gate 	case DT_NODE_OP1:
4617c478bd9Sstevel@tonic-gate 	case DT_NODE_OP2:
4627c478bd9Sstevel@tonic-gate 	case DT_NODE_OP3:
4637c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "operator %s", opstr(dnp->dn_op));
4647c478bd9Sstevel@tonic-gate 		break;
4657c478bd9Sstevel@tonic-gate 	case DT_NODE_DEXPR:
4667c478bd9Sstevel@tonic-gate 	case DT_NODE_DFUNC:
4677c478bd9Sstevel@tonic-gate 		if (dnp->dn_expr)
4687c478bd9Sstevel@tonic-gate 			return (dt_node_name(dnp->dn_expr, buf, len));
4697c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "%s", "statement");
4707c478bd9Sstevel@tonic-gate 		break;
4717c478bd9Sstevel@tonic-gate 	case DT_NODE_PDESC:
4727c478bd9Sstevel@tonic-gate 		if (dnp->dn_desc->dtpd_id == 0) {
4737c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, len,
4747c478bd9Sstevel@tonic-gate 			    "probe description %s:%s:%s:%s",
4757c478bd9Sstevel@tonic-gate 			    dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,
4767c478bd9Sstevel@tonic-gate 			    dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name);
4777c478bd9Sstevel@tonic-gate 		} else {
4787c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, len, "probe description %u",
4797c478bd9Sstevel@tonic-gate 			    dnp->dn_desc->dtpd_id);
4807c478bd9Sstevel@tonic-gate 		}
4817c478bd9Sstevel@tonic-gate 		break;
4827c478bd9Sstevel@tonic-gate 	case DT_NODE_CLAUSE:
4837c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "%s", "clause");
4847c478bd9Sstevel@tonic-gate 		break;
4857c478bd9Sstevel@tonic-gate 	case DT_NODE_MEMBER:
4867c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "member %s", dnp->dn_membname);
4877c478bd9Sstevel@tonic-gate 		break;
4887c478bd9Sstevel@tonic-gate 	case DT_NODE_XLATOR:
4897c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "translator <%s> (%s)",
4907c478bd9Sstevel@tonic-gate 		    dt_type_name(dnp->dn_xlator->dx_dst_ctfp,
49123a1cceaSRoger A. Faulkner 		    dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)),
4927c478bd9Sstevel@tonic-gate 		    dt_type_name(dnp->dn_xlator->dx_src_ctfp,
49323a1cceaSRoger A. Faulkner 		    dnp->dn_xlator->dx_src_type, n2, sizeof (n2)));
4947c478bd9Sstevel@tonic-gate 		break;
4957c478bd9Sstevel@tonic-gate 	case DT_NODE_PROG:
4967c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "%s", "program");
4977c478bd9Sstevel@tonic-gate 		break;
4987c478bd9Sstevel@tonic-gate 	default:
4997c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "node <%u>", dnp->dn_kind);
5007c478bd9Sstevel@tonic-gate 		break;
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	return (buf);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate /*
5077c478bd9Sstevel@tonic-gate  * dt_node_xalloc() can be used to create new parse nodes from any libdtrace
5087c478bd9Sstevel@tonic-gate  * caller.  The caller is responsible for assigning dn_link appropriately.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate dt_node_t *
dt_node_xalloc(dtrace_hdl_t * dtp,int kind)5117c478bd9Sstevel@tonic-gate dt_node_xalloc(dtrace_hdl_t *dtp, int kind)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	dt_node_t *dnp = dt_alloc(dtp, sizeof (dt_node_t));
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (dnp == NULL)
5167c478bd9Sstevel@tonic-gate 		return (NULL);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	dnp->dn_ctfp = NULL;
5197c478bd9Sstevel@tonic-gate 	dnp->dn_type = CTF_ERR;
5207c478bd9Sstevel@tonic-gate 	dnp->dn_kind = (uchar_t)kind;
5217c478bd9Sstevel@tonic-gate 	dnp->dn_flags = 0;
5227c478bd9Sstevel@tonic-gate 	dnp->dn_op = 0;
5237c478bd9Sstevel@tonic-gate 	dnp->dn_line = -1;
5247c478bd9Sstevel@tonic-gate 	dnp->dn_reg = -1;
5257c478bd9Sstevel@tonic-gate 	dnp->dn_attr = _dtrace_defattr;
5267c478bd9Sstevel@tonic-gate 	dnp->dn_list = NULL;
5277c478bd9Sstevel@tonic-gate 	dnp->dn_link = NULL;
5287c478bd9Sstevel@tonic-gate 	bzero(&dnp->dn_u, sizeof (dnp->dn_u));
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	return (dnp);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  * dt_node_alloc() is used to create new parse nodes from the parser.  It
5357c478bd9Sstevel@tonic-gate  * assigns the node location based on the current lexer line number and places
5367c478bd9Sstevel@tonic-gate  * the new node on the default allocation list.  If allocation fails, we
5377c478bd9Sstevel@tonic-gate  * automatically longjmp the caller back to the enclosing compilation call.
5387c478bd9Sstevel@tonic-gate  */
5397c478bd9Sstevel@tonic-gate static dt_node_t *
dt_node_alloc(int kind)5407c478bd9Sstevel@tonic-gate dt_node_alloc(int kind)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	dt_node_t *dnp = dt_node_xalloc(yypcb->pcb_hdl, kind);
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	if (dnp == NULL)
5457c478bd9Sstevel@tonic-gate 		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	dnp->dn_line = yylineno;
5487c478bd9Sstevel@tonic-gate 	dnp->dn_link = yypcb->pcb_list;
5497c478bd9Sstevel@tonic-gate 	yypcb->pcb_list = dnp;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	return (dnp);
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate void
dt_node_free(dt_node_t * dnp)5557c478bd9Sstevel@tonic-gate dt_node_free(dt_node_t *dnp)
5567c478bd9Sstevel@tonic-gate {
5577c478bd9Sstevel@tonic-gate 	uchar_t kind = dnp->dn_kind;
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	dnp->dn_kind = DT_NODE_FREE;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	switch (kind) {
5627c478bd9Sstevel@tonic-gate 	case DT_NODE_STRING:
5637c478bd9Sstevel@tonic-gate 	case DT_NODE_IDENT:
5647c478bd9Sstevel@tonic-gate 	case DT_NODE_TYPE:
5657c478bd9Sstevel@tonic-gate 		free(dnp->dn_string);
5667c478bd9Sstevel@tonic-gate 		dnp->dn_string = NULL;
5677c478bd9Sstevel@tonic-gate 		break;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	case DT_NODE_VAR:
5707c478bd9Sstevel@tonic-gate 	case DT_NODE_FUNC:
5717c478bd9Sstevel@tonic-gate 	case DT_NODE_PROBE:
5727c478bd9Sstevel@tonic-gate 		if (dnp->dn_ident != NULL) {
5737c478bd9Sstevel@tonic-gate 			if (dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN)
5747c478bd9Sstevel@tonic-gate 				dt_ident_destroy(dnp->dn_ident);
5757c478bd9Sstevel@tonic-gate 			dnp->dn_ident = NULL;
5767c478bd9Sstevel@tonic-gate 		}
5777c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_args);
5787c478bd9Sstevel@tonic-gate 		break;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	case DT_NODE_OP1:
5817c478bd9Sstevel@tonic-gate 		if (dnp->dn_child != NULL) {
5827c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_child);
5837c478bd9Sstevel@tonic-gate 			dnp->dn_child = NULL;
5847c478bd9Sstevel@tonic-gate 		}
5857c478bd9Sstevel@tonic-gate 		break;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	case DT_NODE_OP3:
5887c478bd9Sstevel@tonic-gate 		if (dnp->dn_expr != NULL) {
5897c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_expr);
5907c478bd9Sstevel@tonic-gate 			dnp->dn_expr = NULL;
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
5937c478bd9Sstevel@tonic-gate 	case DT_NODE_OP2:
5947c478bd9Sstevel@tonic-gate 		if (dnp->dn_left != NULL) {
5957c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_left);
5967c478bd9Sstevel@tonic-gate 			dnp->dn_left = NULL;
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		if (dnp->dn_right != NULL) {
5997c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_right);
6007c478bd9Sstevel@tonic-gate 			dnp->dn_right = NULL;
6017c478bd9Sstevel@tonic-gate 		}
6027c478bd9Sstevel@tonic-gate 		break;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	case DT_NODE_DEXPR:
6057c478bd9Sstevel@tonic-gate 	case DT_NODE_DFUNC:
6067c478bd9Sstevel@tonic-gate 		if (dnp->dn_expr != NULL) {
6077c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_expr);
6087c478bd9Sstevel@tonic-gate 			dnp->dn_expr = NULL;
6097c478bd9Sstevel@tonic-gate 		}
6107c478bd9Sstevel@tonic-gate 		break;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	case DT_NODE_AGG:
6137c478bd9Sstevel@tonic-gate 		if (dnp->dn_aggfun != NULL) {
6147c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_aggfun);
6157c478bd9Sstevel@tonic-gate 			dnp->dn_aggfun = NULL;
6167c478bd9Sstevel@tonic-gate 		}
6177c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_aggtup);
6187c478bd9Sstevel@tonic-gate 		break;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	case DT_NODE_PDESC:
6217c478bd9Sstevel@tonic-gate 		free(dnp->dn_spec);
6227c478bd9Sstevel@tonic-gate 		dnp->dn_spec = NULL;
6237c478bd9Sstevel@tonic-gate 		free(dnp->dn_desc);
6247c478bd9Sstevel@tonic-gate 		dnp->dn_desc = NULL;
6257c478bd9Sstevel@tonic-gate 		break;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	case DT_NODE_CLAUSE:
6287c478bd9Sstevel@tonic-gate 		if (dnp->dn_pred != NULL)
6297c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_pred);
6307c478bd9Sstevel@tonic-gate 		if (dnp->dn_locals != NULL)
6317c478bd9Sstevel@tonic-gate 			dt_idhash_destroy(dnp->dn_locals);
6327c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_pdescs);
6337c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_acts);
6347c478bd9Sstevel@tonic-gate 		break;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	case DT_NODE_MEMBER:
6377c478bd9Sstevel@tonic-gate 		free(dnp->dn_membname);
6387c478bd9Sstevel@tonic-gate 		dnp->dn_membname = NULL;
6397c478bd9Sstevel@tonic-gate 		if (dnp->dn_membexpr != NULL) {
6407c478bd9Sstevel@tonic-gate 			dt_node_free(dnp->dn_membexpr);
6417c478bd9Sstevel@tonic-gate 			dnp->dn_membexpr = NULL;
6427c478bd9Sstevel@tonic-gate 		}
6437c478bd9Sstevel@tonic-gate 		break;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	case DT_NODE_PROVIDER:
6467c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_probes);
6477c478bd9Sstevel@tonic-gate 		free(dnp->dn_provname);
6487c478bd9Sstevel@tonic-gate 		dnp->dn_provname = NULL;
6497c478bd9Sstevel@tonic-gate 		break;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	case DT_NODE_PROG:
6527c478bd9Sstevel@tonic-gate 		dt_node_list_free(&dnp->dn_list);
6537c478bd9Sstevel@tonic-gate 		break;
6547c478bd9Sstevel@tonic-gate 	}
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate void
dt_node_attr_assign(dt_node_t * dnp,dtrace_attribute_t attr)6587c478bd9Sstevel@tonic-gate dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
6597c478bd9Sstevel@tonic-gate {
6607c478bd9Sstevel@tonic-gate 	if ((yypcb->pcb_cflags & DTRACE_C_EATTR) &&
6617c478bd9Sstevel@tonic-gate 	    (dt_attr_cmp(attr, yypcb->pcb_amin) < 0)) {
6627c478bd9Sstevel@tonic-gate 		char a[DTRACE_ATTR2STR_MAX];
6637c478bd9Sstevel@tonic-gate 		char s[BUFSIZ];
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 		dnerror(dnp, D_ATTR_MIN, "attributes for %s (%s) are less than "
6667c478bd9Sstevel@tonic-gate 		    "predefined minimum\n", dt_node_name(dnp, s, sizeof (s)),
6677c478bd9Sstevel@tonic-gate 		    dtrace_attr2str(attr, a, sizeof (a)));
6687c478bd9Sstevel@tonic-gate 	}
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	dnp->dn_attr = attr;
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate void
dt_node_type_assign(dt_node_t * dnp,ctf_file_t * fp,ctf_id_t type,boolean_t user)674a386cc11SRobert Mustacchi dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
675a386cc11SRobert Mustacchi     boolean_t user)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	ctf_id_t base = ctf_type_resolve(fp, type);
6787c478bd9Sstevel@tonic-gate 	uint_t kind = ctf_type_kind(fp, base);
6797c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	dnp->dn_flags &=
6827c478bd9Sstevel@tonic-gate 	    ~(DT_NF_SIGNED | DT_NF_REF | DT_NF_BITFIELD | DT_NF_USERLAND);
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_INTEGER && ctf_type_encoding(fp, base, &e) == 0) {
6857c478bd9Sstevel@tonic-gate 		size_t size = e.cte_bits / NBBY;
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 		if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)))
6887c478bd9Sstevel@tonic-gate 			dnp->dn_flags |= DT_NF_BITFIELD;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 		if (e.cte_format & CTF_INT_SIGNED)
6917c478bd9Sstevel@tonic-gate 			dnp->dn_flags |= DT_NF_SIGNED;
6927c478bd9Sstevel@tonic-gate 	}
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_FLOAT && ctf_type_encoding(fp, base, &e) == 0) {
6957c478bd9Sstevel@tonic-gate 		if (e.cte_bits / NBBY > sizeof (uint64_t))
6967c478bd9Sstevel@tonic-gate 			dnp->dn_flags |= DT_NF_REF;
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_STRUCT || kind == CTF_K_UNION ||
7007c478bd9Sstevel@tonic-gate 	    kind == CTF_K_FORWARD ||
7017c478bd9Sstevel@tonic-gate 	    kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION)
7027c478bd9Sstevel@tonic-gate 		dnp->dn_flags |= DT_NF_REF;
7037c478bd9Sstevel@tonic-gate 	else if (yypcb != NULL && fp == DT_DYN_CTFP(yypcb->pcb_hdl) &&
7047c478bd9Sstevel@tonic-gate 	    type == DT_DYN_TYPE(yypcb->pcb_hdl))
7057c478bd9Sstevel@tonic-gate 		dnp->dn_flags |= DT_NF_REF;
7067c478bd9Sstevel@tonic-gate 
707a386cc11SRobert Mustacchi 	if (user)
708a386cc11SRobert Mustacchi 		dnp->dn_flags |= DT_NF_USERLAND;
709a386cc11SRobert Mustacchi 
7107c478bd9Sstevel@tonic-gate 	dnp->dn_flags |= DT_NF_COOKED;
7117c478bd9Sstevel@tonic-gate 	dnp->dn_ctfp = fp;
7127c478bd9Sstevel@tonic-gate 	dnp->dn_type = type;
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate void
dt_node_type_propagate(const dt_node_t * src,dt_node_t * dst)7167c478bd9Sstevel@tonic-gate dt_node_type_propagate(const dt_node_t *src, dt_node_t *dst)
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate 	assert(src->dn_flags & DT_NF_COOKED);
7197c478bd9Sstevel@tonic-gate 	dst->dn_flags = src->dn_flags & ~DT_NF_LVALUE;
7207c478bd9Sstevel@tonic-gate 	dst->dn_ctfp = src->dn_ctfp;
7217c478bd9Sstevel@tonic-gate 	dst->dn_type = src->dn_type;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate const char *
dt_node_type_name(const dt_node_t * dnp,char * buf,size_t len)7257c478bd9Sstevel@tonic-gate dt_node_type_name(const dt_node_t *dnp, char *buf, size_t len)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate 	if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL) {
7287c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, len, "%s",
7297c478bd9Sstevel@tonic-gate 		    dt_idkind_name(dt_ident_resolve(dnp->dn_ident)->di_kind));
7307c478bd9Sstevel@tonic-gate 		return (buf);
7317c478bd9Sstevel@tonic-gate 	}
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 	if (dnp->dn_flags & DT_NF_USERLAND) {
7347c478bd9Sstevel@tonic-gate 		size_t n = snprintf(buf, len, "userland ");
7357c478bd9Sstevel@tonic-gate 		len = len > n ? len - n : 0;
7367c478bd9Sstevel@tonic-gate 		(void) dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf + n, len);
7377c478bd9Sstevel@tonic-gate 		return (buf);
7387c478bd9Sstevel@tonic-gate 	}
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	return (dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf, len));
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate size_t
dt_node_type_size(const dt_node_t * dnp)7447c478bd9Sstevel@tonic-gate dt_node_type_size(const dt_node_t *dnp)
7457c478bd9Sstevel@tonic-gate {
746ec57c73dSBryan Cantrill 	ctf_id_t base;
747a386cc11SRobert Mustacchi 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
748ec57c73dSBryan Cantrill 
7497c478bd9Sstevel@tonic-gate 	if (dnp->dn_kind == DT_NODE_STRING)
7507c478bd9Sstevel@tonic-gate 		return (strlen(dnp->dn_string) + 1);
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 	if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)
7537c478bd9Sstevel@tonic-gate 		return (dt_ident_size(dnp->dn_ident));
7547c478bd9Sstevel@tonic-gate 
755ec57c73dSBryan Cantrill 	base = ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type);
756ec57c73dSBryan Cantrill 
757ec57c73dSBryan Cantrill 	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
758ec57c73dSBryan Cantrill 		return (0);
759ec57c73dSBryan Cantrill 
760a386cc11SRobert Mustacchi 	/*
761a386cc11SRobert Mustacchi 	 * Here we have a 32-bit user pointer that is being used with a 64-bit
762a386cc11SRobert Mustacchi 	 * kernel. When we're using it and its tagged as a userland reference --
763a386cc11SRobert Mustacchi 	 * then we need to keep it as a 32-bit pointer. However, if we are
764a386cc11SRobert Mustacchi 	 * referring to it as a kernel address, eg. being used after a copyin()
765a386cc11SRobert Mustacchi 	 * then we need to make sure that we actually return the kernel's size
766a386cc11SRobert Mustacchi 	 * of a pointer, 8 bytes.
767a386cc11SRobert Mustacchi 	 */
768a386cc11SRobert Mustacchi 	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
769a386cc11SRobert Mustacchi 	    ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
770a386cc11SRobert Mustacchi 	    !(dnp->dn_flags & DT_NF_USERLAND) &&
771a386cc11SRobert Mustacchi 	    dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
772a386cc11SRobert Mustacchi 			return (8);
773a386cc11SRobert Mustacchi 
7747c478bd9Sstevel@tonic-gate 	return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate  * Determine if the specified parse tree node references an identifier of the
7797c478bd9Sstevel@tonic-gate  * specified kind, and if so return a pointer to it; otherwise return NULL.
7807c478bd9Sstevel@tonic-gate  * This function resolves the identifier itself, following through any inlines.
7817c478bd9Sstevel@tonic-gate  */
7827c478bd9Sstevel@tonic-gate dt_ident_t *
dt_node_resolve(const dt_node_t * dnp,uint_t idkind)7837c478bd9Sstevel@tonic-gate dt_node_resolve(const dt_node_t *dnp, uint_t idkind)
7847c478bd9Sstevel@tonic-gate {
7857c478bd9Sstevel@tonic-gate 	dt_ident_t *idp;
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate 	switch (dnp->dn_kind) {
7887c478bd9Sstevel@tonic-gate 	case DT_NODE_VAR:
7897c478bd9Sstevel@tonic-gate 	case DT_NODE_SYM:
7907c478bd9Sstevel@tonic-gate 	case DT_NODE_FUNC:
7917c478bd9Sstevel@tonic-gate 	case DT_NODE_AGG:
7927c478bd9Sstevel@tonic-gate 	case DT_NODE_INLINE:
7937c478bd9Sstevel@tonic-gate 	case DT_NODE_PROBE:
7947c478bd9Sstevel@tonic-gate 		idp = dt_ident_resolve(dnp->dn_ident);
7957c478bd9Sstevel@tonic-gate 		return (idp->di_kind == idkind ? idp : NULL);
7967c478bd9Sstevel@tonic-gate 	}
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 	if (dt_node_is_dynamic(dnp)) {
7997c478bd9Sstevel@tonic-gate 		idp = dt_ident_resolve(dnp->dn_ident);
8007c478bd9Sstevel@tonic-gate 		return (idp->di_kind == idkind ? idp : NULL);
8017c478bd9Sstevel@tonic-gate 	}
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	return (NULL);
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate size_t
dt_node_sizeof(const dt_node_t * dnp)8077c478bd9Sstevel@tonic-gate dt_node_sizeof(const dt_node_t *dnp)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	dtrace_syminfo_t *sip;
8107c478bd9Sstevel@tonic-gate 	GElf_Sym sym;
8117c478bd9Sstevel@tonic-gate 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	/*
8147c478bd9Sstevel@tonic-gate 	 * The size of the node as used for the sizeof() operator depends on
8157c478bd9Sstevel@tonic-gate 	 * the kind of the node.  If the node is a SYM, the size is obtained
8167c478bd9Sstevel@tonic-gate 	 * from the symbol table; if it is not a SYM, the size is determined
8177c478bd9Sstevel@tonic-gate 	 * from the node's type.  This is slightly different from C's sizeof()
8187c478bd9Sstevel@tonic-gate 	 * operator in that (for example) when applied to a function, sizeof()
8197c478bd9Sstevel@tonic-gate 	 * will evaluate to the length of the function rather than the size of
8207c478bd9Sstevel@tonic-gate 	 * the function type.
8217c478bd9Sstevel@tonic-gate 	 */
8227c478bd9Sstevel@tonic-gate 	if (dnp->dn_kind != DT_NODE_SYM)
8237c478bd9Sstevel@tonic-gate 		return (dt_node_type_size(dnp));
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	sip = dnp->dn_ident->di_data;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (dtrace_lookup_by_name(dtp, sip->dts_object,
8287c478bd9Sstevel@tonic-gate 	    sip->dts_name, &sym, NULL) == -1)
8297c478bd9Sstevel@tonic-gate 		return (0);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	return (sym.st_size);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate int
dt_node_is_integer(const dt_node_t * dnp)8357c478bd9Sstevel@tonic-gate dt_node_is_integer(const dt_node_t *dnp)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
8387c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
8397c478bd9Sstevel@tonic-gate 	ctf_id_t type;
8407c478bd9Sstevel@tonic-gate 	uint_t kind;
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, dnp->dn_type);
8457c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, type);
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_INTEGER &&
8487c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
8497c478bd9Sstevel@tonic-gate 		return (0); /* void integer */
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM);
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate int
dt_node_is_float(const dt_node_t * dnp)8557c478bd9Sstevel@tonic-gate dt_node_is_float(const dt_node_t *dnp)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
8587c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
8597c478bd9Sstevel@tonic-gate 	ctf_id_t type;
8607c478bd9Sstevel@tonic-gate 	uint_t kind;
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, dnp->dn_type);
8657c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, type);
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	return (kind == CTF_K_FLOAT &&
8687c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(dnp->dn_ctfp, type, &e) == 0 && (
8697c478bd9Sstevel@tonic-gate 	    e.cte_format == CTF_FP_SINGLE || e.cte_format == CTF_FP_DOUBLE ||
8707c478bd9Sstevel@tonic-gate 	    e.cte_format == CTF_FP_LDOUBLE));
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate int
dt_node_is_scalar(const dt_node_t * dnp)8747c478bd9Sstevel@tonic-gate dt_node_is_scalar(const dt_node_t *dnp)
8757c478bd9Sstevel@tonic-gate {
8767c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
8777c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
8787c478bd9Sstevel@tonic-gate 	ctf_id_t type;
8797c478bd9Sstevel@tonic-gate 	uint_t kind;
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, dnp->dn_type);
8847c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, type);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_INTEGER &&
8877c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))
8887c478bd9Sstevel@tonic-gate 		return (0); /* void cannot be used as a scalar */
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM ||
8917c478bd9Sstevel@tonic-gate 	    kind == CTF_K_POINTER);
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate int
dt_node_is_arith(const dt_node_t * dnp)8957c478bd9Sstevel@tonic-gate dt_node_is_arith(const dt_node_t *dnp)
8967c478bd9Sstevel@tonic-gate {
8977c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
8987c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
8997c478bd9Sstevel@tonic-gate 	ctf_id_t type;
9007c478bd9Sstevel@tonic-gate 	uint_t kind;
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, dnp->dn_type);
9057c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, type);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_INTEGER)
9087c478bd9Sstevel@tonic-gate 		return (ctf_type_encoding(fp, type, &e) == 0 && !IS_VOID(e));
9097c478bd9Sstevel@tonic-gate 	else
9107c478bd9Sstevel@tonic-gate 		return (kind == CTF_K_ENUM);
9117c478bd9Sstevel@tonic-gate }
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate int
dt_node_is_vfptr(const dt_node_t * dnp)9147c478bd9Sstevel@tonic-gate dt_node_is_vfptr(const dt_node_t *dnp)
9157c478bd9Sstevel@tonic-gate {
9167c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
9177c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
9187c478bd9Sstevel@tonic-gate 	ctf_id_t type;
9197c478bd9Sstevel@tonic-gate 	uint_t kind;
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, dnp->dn_type);
9247c478bd9Sstevel@tonic-gate 	if (ctf_type_kind(fp, type) != CTF_K_POINTER)
9257c478bd9Sstevel@tonic-gate 		return (0); /* type is not a pointer */
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	type = ctf_type_resolve(fp, ctf_type_reference(fp, type));
9287c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, type);
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	return (kind == CTF_K_FUNCTION || (kind == CTF_K_INTEGER &&
9317c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)));
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate int
dt_node_is_dynamic(const dt_node_t * dnp)9357c478bd9Sstevel@tonic-gate dt_node_is_dynamic(const dt_node_t *dnp)
9367c478bd9Sstevel@tonic-gate {
9377c478bd9Sstevel@tonic-gate 	if (dnp->dn_kind == DT_NODE_VAR &&
9387c478bd9Sstevel@tonic-gate 	    (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {
9397c478bd9Sstevel@tonic-gate 		const dt_idnode_t *inp = dnp->dn_ident->di_iarg;
9401a7c1b72Smws 		return (inp->din_root ? dt_node_is_dynamic(inp->din_root) : 0);
9417c478bd9Sstevel@tonic-gate 	}
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	return (dnp->dn_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) &&
9447c478bd9Sstevel@tonic-gate 	    dnp->dn_type == DT_DYN_TYPE(yypcb->pcb_hdl));
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate int
dt_node_is_string(const dt_node_t * dnp)9487c478bd9Sstevel@tonic-gate dt_node_is_string(const dt_node_t *dnp)
9497c478bd9Sstevel@tonic-gate {
9507c478bd9Sstevel@tonic-gate 	return (dnp->dn_ctfp == DT_STR_CTFP(yypcb->pcb_hdl) &&
9517c478bd9Sstevel@tonic-gate 	    dnp->dn_type == DT_STR_TYPE(yypcb->pcb_hdl));
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate int
dt_node_is_stack(const dt_node_t * dnp)9557c478bd9Sstevel@tonic-gate dt_node_is_stack(const dt_node_t *dnp)
9567c478bd9Sstevel@tonic-gate {
9577c478bd9Sstevel@tonic-gate 	return (dnp->dn_ctfp == DT_STACK_CTFP(yypcb->pcb_hdl) &&
9587c478bd9Sstevel@tonic-gate 	    dnp->dn_type == DT_STACK_TYPE(yypcb->pcb_hdl));
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate 
961a1b5e537Sbmc int
dt_node_is_symaddr(const dt_node_t * dnp)962a1b5e537Sbmc dt_node_is_symaddr(const dt_node_t *dnp)
963a1b5e537Sbmc {
964a1b5e537Sbmc 	return (dnp->dn_ctfp == DT_SYMADDR_CTFP(yypcb->pcb_hdl) &&
965a1b5e537Sbmc 	    dnp->dn_type == DT_SYMADDR_TYPE(yypcb->pcb_hdl));
966a1b5e537Sbmc }
967a1b5e537Sbmc 
968a1b5e537Sbmc int
dt_node_is_usymaddr(const dt_node_t * dnp)969a1b5e537Sbmc dt_node_is_usymaddr(const dt_node_t *dnp)
970a1b5e537Sbmc {
971a1b5e537Sbmc 	return (dnp->dn_ctfp == DT_USYMADDR_CTFP(yypcb->pcb_hdl) &&
972a1b5e537Sbmc 	    dnp->dn_type == DT_USYMADDR_TYPE(yypcb->pcb_hdl));
973a1b5e537Sbmc }
974a1b5e537Sbmc 
9757c478bd9Sstevel@tonic-gate int
dt_node_is_strcompat(const dt_node_t * dnp)9767c478bd9Sstevel@tonic-gate dt_node_is_strcompat(const dt_node_t *dnp)
9777c478bd9Sstevel@tonic-gate {
9787c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
9797c478bd9Sstevel@tonic-gate 	ctf_encoding_t e;
9807c478bd9Sstevel@tonic-gate 	ctf_arinfo_t r;
9817c478bd9Sstevel@tonic-gate 	ctf_id_t base;
9827c478bd9Sstevel@tonic-gate 	uint_t kind;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	base = ctf_type_resolve(fp, dnp->dn_type);
9877c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, base);
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_POINTER &&
9907c478bd9Sstevel@tonic-gate 	    (base = ctf_type_reference(fp, base)) != CTF_ERR &&
9917c478bd9Sstevel@tonic-gate 	    (base = ctf_type_resolve(fp, base)) != CTF_ERR &&
9927c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
9937c478bd9Sstevel@tonic-gate 		return (1); /* promote char pointer to string */
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	if (kind == CTF_K_ARRAY && ctf_array_info(fp, base, &r) == 0 &&
9967c478bd9Sstevel@tonic-gate 	    (base = ctf_type_resolve(fp, r.ctr_contents)) != CTF_ERR &&
9977c478bd9Sstevel@tonic-gate 	    ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))
9987c478bd9Sstevel@tonic-gate 		return (1); /* promote char array to string */
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	return (0);
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate int
dt_node_is_pointer(const dt_node_t * dnp)10047c478bd9Sstevel@tonic-gate dt_node_is_pointer(const dt_node_t *dnp)
10057c478bd9Sstevel@tonic-gate {
10067c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
10077c478bd9Sstevel@tonic-gate 	uint_t kind;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	assert(dnp->dn_flags & DT_NF_COOKED);
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	if (dt_node_is_string(dnp))
10127c478bd9Sstevel@tonic-gate 		return (0); /* string are pass-by-ref but act like structs */
10137c478bd9Sstevel@tonic-gate 
10147c478bd9Sstevel@tonic-gate 	kind = ctf_type_kind(fp, ctf_type_resolve(fp, dnp->dn_type));
10157c478bd9Sstevel@tonic-gate 	return (kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate 
10187c478bd9Sstevel@tonic-gate int
dt_node_is_void(const dt_node_t * dnp)10197c478bd9Sstevel@tonic-gate dt_node_is_void(const dt_node_t *dnp)
10207c478bd9Sstevel@tonic-gate {
10217c478bd9Sstevel@tonic-gate 	ctf_file_t *fp = dnp->dn_ctfp;
10227c478bd9Sstevel@tonic-gate 	ctf_encoding_t