1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * DTrace D Language Parser 31*7c478bd9Sstevel@tonic-gate * 32*7c478bd9Sstevel@tonic-gate * The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the 33*7c478bd9Sstevel@tonic-gate * parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles 34*7c478bd9Sstevel@tonic-gate * the construction of the parse tree nodes and their syntactic validation. 35*7c478bd9Sstevel@tonic-gate * The parse tree is constructed of dt_node_t structures (see <dt_parser.h>) 36*7c478bd9Sstevel@tonic-gate * that are built in two passes: (1) the "create" pass, where the parse tree 37*7c478bd9Sstevel@tonic-gate * nodes are allocated by calls from the grammar to dt_node_*() subroutines, 38*7c478bd9Sstevel@tonic-gate * and (2) the "cook" pass, where nodes are coalesced, assigned D types, and 39*7c478bd9Sstevel@tonic-gate * validated according to the syntactic rules of the language. 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * All node allocations are performed using dt_node_alloc(). All node frees 42*7c478bd9Sstevel@tonic-gate * during the parsing phase are performed by dt_node_free(), which frees node- 43*7c478bd9Sstevel@tonic-gate * internal state but does not actually free the nodes. All final node frees 44*7c478bd9Sstevel@tonic-gate * are done as part of the end of dt_compile() or as part of destroying 45*7c478bd9Sstevel@tonic-gate * persistent identifiers or translators which have embedded nodes. 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * The dt_node_* routines that implement pass (1) may allocate new nodes. The 48*7c478bd9Sstevel@tonic-gate * dt_cook_* routines that implement pass (2) may *not* allocate new nodes. 49*7c478bd9Sstevel@tonic-gate * They may free existing nodes using dt_node_free(), but they may not actually 50*7c478bd9Sstevel@tonic-gate * deallocate any dt_node_t's. Currently dt_cook_op2() is an exception to this 51*7c478bd9Sstevel@tonic-gate * rule: see the comments therein for how this issue is resolved. 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * The dt_cook_* routines are responsible for (at minimum) setting the final 54*7c478bd9Sstevel@tonic-gate * node type (dn_ctfp/dn_type) and attributes (dn_attr). If dn_ctfp/dn_type 55*7c478bd9Sstevel@tonic-gate * are set manually (i.e. not by one of the type assignment functions), then 56*7c478bd9Sstevel@tonic-gate * the DT_NF_COOKED flag must be set manually on the node. 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate * The cooking pass can be applied to the same parse tree more than once (used 59*7c478bd9Sstevel@tonic-gate * in the case of a comma-separated list of probe descriptions). As such, the 60*7c478bd9Sstevel@tonic-gate * cook routines must not perform any parse tree transformations which would 61*7c478bd9Sstevel@tonic-gate * be invalid if the tree were subsequently cooked using a different context. 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * The dn_ctfp and dn_type fields form the type of the node. This tuple can 64*7c478bd9Sstevel@tonic-gate * take on the following set of values, which form our type invariants: 65*7c478bd9Sstevel@tonic-gate * 66*7c478bd9Sstevel@tonic-gate * 1. dn_ctfp = NULL, dn_type = CTF_ERR 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * In this state, the node has unknown type and is not yet cooked. The 69*7c478bd9Sstevel@tonic-gate * DT_NF_COOKED flag is not yet set on the node. 70*7c478bd9Sstevel@tonic-gate * 71*7c478bd9Sstevel@tonic-gate * 2. dn_ctfp = DT_DYN_CTFP(dtp), dn_type = DT_DYN_TYPE(dtp) 72*7c478bd9Sstevel@tonic-gate * 73*7c478bd9Sstevel@tonic-gate * In this state, the node is a dynamic D type. This means that generic 74*7c478bd9Sstevel@tonic-gate * operations are not valid on this node and only code that knows how to 75*7c478bd9Sstevel@tonic-gate * examine the inner details of the node can operate on it. A <DYN> node 76*7c478bd9Sstevel@tonic-gate * must have dn_ident set to point to an identifier describing the object 77*7c478bd9Sstevel@tonic-gate * and its type. The DT_NF_REF flag is set for all nodes of type <DYN>. 78*7c478bd9Sstevel@tonic-gate * At present, the D compiler uses the <DYN> type for: 79*7c478bd9Sstevel@tonic-gate * 80*7c478bd9Sstevel@tonic-gate * - associative arrays that do not yet have a value type defined 81*7c478bd9Sstevel@tonic-gate * - translated data (i.e. the result of the xlate operator) 82*7c478bd9Sstevel@tonic-gate * - aggregations 83*7c478bd9Sstevel@tonic-gate * 84*7c478bd9Sstevel@tonic-gate * 3. dn_ctfp = DT_STR_CTFP(dtp), dn_type = DT_STR_TYPE(dtp) 85*7c478bd9Sstevel@tonic-gate * 86*7c478bd9Sstevel@tonic-gate * In this state, the node is of type D string. The string type is really 87*7c478bd9Sstevel@tonic-gate * a char[0] typedef, but requires special handling throughout the compiler. 88*7c478bd9Sstevel@tonic-gate * 89*7c478bd9Sstevel@tonic-gate * 4. dn_ctfp != NULL, dn_type = any other type ID 90*7c478bd9Sstevel@tonic-gate * 91*7c478bd9Sstevel@tonic-gate * In this state, the node is of some known D/CTF type. The normal libctf 92*7c478bd9Sstevel@tonic-gate * APIs can be used to learn more about the type name or structure. When 93*7c478bd9Sstevel@tonic-gate * the type is assigned, the DT_NF_SIGNED, DT_NF_REF, and DT_NF_BITFIELD 94*7c478bd9Sstevel@tonic-gate * flags cache the corresponding attributes of the underlying CTF type. 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 98*7c478bd9Sstevel@tonic-gate #include <limits.h> 99*7c478bd9Sstevel@tonic-gate #include <setjmp.h> 100*7c478bd9Sstevel@tonic-gate #include <strings.h> 101*7c478bd9Sstevel@tonic-gate #include <assert.h> 102*7c478bd9Sstevel@tonic-gate #include <alloca.h> 103*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 104*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 105*7c478bd9Sstevel@tonic-gate #include <stdio.h> 106*7c478bd9Sstevel@tonic-gate #include <errno.h> 107*7c478bd9Sstevel@tonic-gate #include <ctype.h> 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate #include <dt_impl.h> 110*7c478bd9Sstevel@tonic-gate #include <dt_grammar.h> 111*7c478bd9Sstevel@tonic-gate #include <dt_module.h> 112*7c478bd9Sstevel@tonic-gate #include <dt_provider.h> 113*7c478bd9Sstevel@tonic-gate #include <dt_string.h> 114*7c478bd9Sstevel@tonic-gate #include <dt_as.h> 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate dt_pcb_t *yypcb; /* current control block for parser */ 117*7c478bd9Sstevel@tonic-gate dt_node_t *yypragma; /* lex token list for control lines */ 118*7c478bd9Sstevel@tonic-gate char yyintprefix; /* int token macro prefix (+/-) */ 119*7c478bd9Sstevel@tonic-gate char yyintsuffix[4]; /* int token suffix string [uU][lL] */ 120*7c478bd9Sstevel@tonic-gate int yyintdecimal; /* int token format flag (1=decimal, 0=octal/hex) */ 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static const char * 123*7c478bd9Sstevel@tonic-gate opstr(int op) 124*7c478bd9Sstevel@tonic-gate { 125*7c478bd9Sstevel@tonic-gate switch (op) { 126*7c478bd9Sstevel@tonic-gate case DT_TOK_COMMA: return (","); 127*7c478bd9Sstevel@tonic-gate case DT_TOK_ELLIPSIS: return ("..."); 128*7c478bd9Sstevel@tonic-gate case DT_TOK_ASGN: return ("="); 129*7c478bd9Sstevel@tonic-gate case DT_TOK_ADD_EQ: return ("+="); 130*7c478bd9Sstevel@tonic-gate case DT_TOK_SUB_EQ: return ("-="); 131*7c478bd9Sstevel@tonic-gate case DT_TOK_MUL_EQ: return ("*="); 132*7c478bd9Sstevel@tonic-gate case DT_TOK_DIV_EQ: return ("/="); 133*7c478bd9Sstevel@tonic-gate case DT_TOK_MOD_EQ: return ("%="); 134*7c478bd9Sstevel@tonic-gate case DT_TOK_AND_EQ: return ("&="); 135*7c478bd9Sstevel@tonic-gate case DT_TOK_XOR_EQ: return ("^="); 136*7c478bd9Sstevel@tonic-gate case DT_TOK_OR_EQ: return ("|="); 137*7c478bd9Sstevel@tonic-gate case DT_TOK_LSH_EQ: return ("<<="); 138*7c478bd9Sstevel@tonic-gate case DT_TOK_RSH_EQ: return (">>="); 139*7c478bd9Sstevel@tonic-gate case DT_TOK_QUESTION: return ("?"); 140*7c478bd9Sstevel@tonic-gate case DT_TOK_COLON: return (":"); 141*7c478bd9Sstevel@tonic-gate case DT_TOK_LOR: return ("||"); 142*7c478bd9Sstevel@tonic-gate case DT_TOK_LXOR: return ("^^"); 143*7c478bd9Sstevel@tonic-gate case DT_TOK_LAND: return ("&&"); 144*7c478bd9Sstevel@tonic-gate case DT_TOK_BOR: return ("|"); 145*7c478bd9Sstevel@tonic-gate case DT_TOK_XOR: return ("^"); 146*7c478bd9Sstevel@tonic-gate case DT_TOK_BAND: return ("&"); 147*7c478bd9Sstevel@tonic-gate case DT_TOK_EQU: return ("=="); 148*7c478bd9Sstevel@tonic-gate case DT_TOK_NEQ: return ("!="); 149*7c478bd9Sstevel@tonic-gate case DT_TOK_LT: return ("<"); 150*7c478bd9Sstevel@tonic-gate case DT_TOK_LE: return ("<="); 151*7c478bd9Sstevel@tonic-gate case DT_TOK_GT: return (">"); 152*7c478bd9Sstevel@tonic-gate case DT_TOK_GE: return (">="); 153*7c478bd9Sstevel@tonic-gate case DT_TOK_LSH: return ("<<"); 154*7c478bd9Sstevel@tonic-gate case DT_TOK_RSH: return (">>"); 155*7c478bd9Sstevel@tonic-gate case DT_TOK_ADD: return ("+"); 156*7c478bd9Sstevel@tonic-gate case DT_TOK_SUB: return ("-"); 157*7c478bd9Sstevel@tonic-gate case DT_TOK_MUL: return ("*"); 158*7c478bd9Sstevel@tonic-gate case DT_TOK_DIV: return ("/"); 159*7c478bd9Sstevel@tonic-gate case DT_TOK_MOD: return ("%"); 160*7c478bd9Sstevel@tonic-gate case DT_TOK_LNEG: return ("!"); 161*7c478bd9Sstevel@tonic-gate case DT_TOK_BNEG: return ("~"); 162*7c478bd9Sstevel@tonic-gate case DT_TOK_ADDADD: return ("++"); 163*7c478bd9Sstevel@tonic-gate case DT_TOK_PREINC: return ("++"); 164*7c478bd9Sstevel@tonic-gate case DT_TOK_POSTINC: return ("++"); 165*7c478bd9Sstevel@tonic-gate case DT_TOK_SUBSUB: return ("--"); 166*7c478bd9Sstevel@tonic-gate case DT_TOK_PREDEC: return ("--"); 167*7c478bd9Sstevel@tonic-gate case DT_TOK_POSTDEC: return ("--"); 168*7c478bd9Sstevel@tonic-gate case DT_TOK_IPOS: return ("+"); 169*7c478bd9Sstevel@tonic-gate case DT_TOK_INEG: return ("-"); 170*7c478bd9Sstevel@tonic-gate case DT_TOK_DEREF: return ("*"); 171*7c478bd9Sstevel@tonic-gate case DT_TOK_ADDROF: return ("&"); 172*7c478bd9Sstevel@tonic-gate case DT_TOK_OFFSETOF: return ("offsetof"); 173*7c478bd9Sstevel@tonic-gate case DT_TOK_SIZEOF: return ("sizeof"); 174*7c478bd9Sstevel@tonic-gate case DT_TOK_STRINGOF: return ("stringof"); 175*7c478bd9Sstevel@tonic-gate case DT_TOK_XLATE: return ("xlate"); 176*7c478bd9Sstevel@tonic-gate case DT_TOK_LPAR: return ("("); 177*7c478bd9Sstevel@tonic-gate case DT_TOK_RPAR: return (")"); 178*7c478bd9Sstevel@tonic-gate case DT_TOK_LBRAC: return ("["); 179*7c478bd9Sstevel@tonic-gate case DT_TOK_RBRAC: return ("]"); 180*7c478bd9Sstevel@tonic-gate case DT_TOK_PTR: return ("->"); 181*7c478bd9Sstevel@tonic-gate case DT_TOK_DOT: return ("."); 182*7c478bd9Sstevel@tonic-gate case DT_TOK_STRING: return ("<string>"); 183*7c478bd9Sstevel@tonic-gate case DT_TOK_IDENT: return ("<ident>"); 184*7c478bd9Sstevel@tonic-gate case DT_TOK_TNAME: return ("<type>"); 185*7c478bd9Sstevel@tonic-gate case DT_TOK_INT: return ("<int>"); 186*7c478bd9Sstevel@tonic-gate default: return ("<?>"); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate int 191*7c478bd9Sstevel@tonic-gate dt_type_lookup(const char *s, dtrace_typeinfo_t *tip) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate static const char delimiters[] = " \t\n\r\v\f*`"; 194*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 195*7c478bd9Sstevel@tonic-gate const char *p, *q, *end, *obj; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate for (p = s, end = s + strlen(s); *p != '\0'; p = q) { 198*7c478bd9Sstevel@tonic-gate while (isspace(*p)) 199*7c478bd9Sstevel@tonic-gate p++; /* skip leading whitespace prior to token */ 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (p == end || (q = strpbrk(p + 1, delimiters)) == NULL) 202*7c478bd9Sstevel@tonic-gate break; /* empty string or single token remaining */ 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (*q == '`') { 205*7c478bd9Sstevel@tonic-gate char *object = alloca((size_t)(q - p) + 1); 206*7c478bd9Sstevel@tonic-gate char *type = alloca((size_t)(end - s) + 1); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * Copy from the start of the token (p) to the location 210*7c478bd9Sstevel@tonic-gate * backquote (q) to extract the nul-terminated object. 211*7c478bd9Sstevel@tonic-gate */ 212*7c478bd9Sstevel@tonic-gate bcopy(p, object, (size_t)(q - p)); 213*7c478bd9Sstevel@tonic-gate object[(size_t)(q - p)] = '\0'; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* 216*7c478bd9Sstevel@tonic-gate * Copy the original string up to the start of this 217*7c478bd9Sstevel@tonic-gate * token (p) into type, and then concatenate everything 218*7c478bd9Sstevel@tonic-gate * after q. This is the type name without the object. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate bcopy(s, type, (size_t)(p - s)); 221*7c478bd9Sstevel@tonic-gate bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate if (strchr(q + 1, '`') != NULL) 224*7c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, EDT_BADSCOPE)); 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate return (dtrace_lookup_by_type(dtp, object, type, tip)); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate if (yypcb->pcb_idepth != 0) 231*7c478bd9Sstevel@tonic-gate obj = DTRACE_OBJ_CDEFS; 232*7c478bd9Sstevel@tonic-gate else 233*7c478bd9Sstevel@tonic-gate obj = DTRACE_OBJ_EVERY; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate return (dtrace_lookup_by_type(dtp, obj, s, tip)); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * When we parse type expressions or parse an expression with unary "&", we 240*7c478bd9Sstevel@tonic-gate * need to find a type that is a pointer to a previously known type. 241*7c478bd9Sstevel@tonic-gate * Unfortunately CTF is limited to a per-container view, so ctf_type_pointer() 242*7c478bd9Sstevel@tonic-gate * alone does not suffice for our needs. We provide a more intelligent wrapper 243*7c478bd9Sstevel@tonic-gate * for the compiler that attempts to compute a pointer to either the given type 244*7c478bd9Sstevel@tonic-gate * or its base (that is, we try both "foo_t *" and "struct foo *"), and also 245*7c478bd9Sstevel@tonic-gate * to potentially construct the required type on-the-fly. 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate int 248*7c478bd9Sstevel@tonic-gate dt_type_pointer(dtrace_typeinfo_t *tip) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 251*7c478bd9Sstevel@tonic-gate ctf_file_t *ctfp = tip->dtt_ctfp; 252*7c478bd9Sstevel@tonic-gate ctf_id_t type = tip->dtt_type; 253*7c478bd9Sstevel@tonic-gate ctf_id_t base = ctf_type_resolve(ctfp, type); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate dt_module_t *dmp; 256*7c478bd9Sstevel@tonic-gate ctf_id_t ptr; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR || 259*7c478bd9Sstevel@tonic-gate (ptr = ctf_type_pointer(ctfp, base)) != CTF_ERR) { 260*7c478bd9Sstevel@tonic-gate tip->dtt_type = ptr; 261*7c478bd9Sstevel@tonic-gate return (0); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (yypcb->pcb_idepth != 0) 265*7c478bd9Sstevel@tonic-gate dmp = dtp->dt_cdefs; 266*7c478bd9Sstevel@tonic-gate else 267*7c478bd9Sstevel@tonic-gate dmp = dtp->dt_ddefs; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (ctfp != dmp->dm_ctfp && ctfp != ctf_parent_file(dmp->dm_ctfp) && 270*7c478bd9Sstevel@tonic-gate (type = ctf_add_type(dmp->dm_ctfp, ctfp, type)) == CTF_ERR) { 271*7c478bd9Sstevel@tonic-gate dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp); 272*7c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, EDT_CTF)); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, type); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate if (ptr == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) { 278*7c478bd9Sstevel@tonic-gate dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp); 279*7c478bd9Sstevel@tonic-gate return (dt_set_errno(dtp, EDT_CTF)); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate tip->dtt_object = dmp->dm_name; 283*7c478bd9Sstevel@tonic-gate tip->dtt_ctfp = dmp->dm_ctfp; 284*7c478bd9Sstevel@tonic-gate tip->dtt_type = ptr; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate return (0); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate const char * 290*7c478bd9Sstevel@tonic-gate dt_type_name(ctf_file_t *ctfp, ctf_id_t type, char *buf, size_t len) 291*7c478bd9Sstevel@tonic-gate { 292*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate if (ctfp == DT_FPTR_CTFP(dtp) && type == DT_FPTR_TYPE(dtp)) 295*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "function pointer"); 296*7c478bd9Sstevel@tonic-gate else if (ctfp == DT_FUNC_CTFP(dtp) && type == DT_FUNC_TYPE(dtp)) 297*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "function"); 298*7c478bd9Sstevel@tonic-gate else if (ctfp == DT_DYN_CTFP(dtp) && type == DT_DYN_TYPE(dtp)) 299*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "dynamic variable"); 300*7c478bd9Sstevel@tonic-gate else if (ctfp == NULL) 301*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "<none>"); 302*7c478bd9Sstevel@tonic-gate else if (ctf_type_name(ctfp, type, buf, len) == NULL) 303*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "unknown"); 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate return (buf); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* 309*7c478bd9Sstevel@tonic-gate * Perform the "usual arithmetic conversions" to determine which of the two 310*7c478bd9Sstevel@tonic-gate * input operand types should be promoted and used as a result type. The 311*7c478bd9Sstevel@tonic-gate * rules for this are described in ISOC[6.3.1.8] and K&R[A6.5]. 312*7c478bd9Sstevel@tonic-gate */ 313*7c478bd9Sstevel@tonic-gate static void 314*7c478bd9Sstevel@tonic-gate dt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype) 315*7c478bd9Sstevel@tonic-gate { 316*7c478bd9Sstevel@tonic-gate ctf_file_t *lfp = lp->dn_ctfp; 317*7c478bd9Sstevel@tonic-gate ctf_id_t ltype = lp->dn_type; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate ctf_file_t *rfp = rp->dn_ctfp; 320*7c478bd9Sstevel@tonic-gate ctf_id_t rtype = rp->dn_type; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate ctf_id_t lbase = ctf_type_resolve(lfp, ltype); 323*7c478bd9Sstevel@tonic-gate uint_t lkind = ctf_type_kind(lfp, lbase); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate ctf_id_t rbase = ctf_type_resolve(rfp, rtype); 326*7c478bd9Sstevel@tonic-gate uint_t rkind = ctf_type_kind(rfp, rbase); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 329*7c478bd9Sstevel@tonic-gate ctf_encoding_t le, re; 330*7c478bd9Sstevel@tonic-gate uint_t lrank, rrank; 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate assert(lkind == CTF_K_INTEGER || lkind == CTF_K_ENUM); 333*7c478bd9Sstevel@tonic-gate assert(rkind == CTF_K_INTEGER || rkind == CTF_K_ENUM); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate if (lkind == CTF_K_ENUM) { 336*7c478bd9Sstevel@tonic-gate lfp = DT_INT_CTFP(dtp); 337*7c478bd9Sstevel@tonic-gate ltype = lbase = DT_INT_TYPE(dtp); 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate if (rkind == CTF_K_ENUM) { 341*7c478bd9Sstevel@tonic-gate rfp = DT_INT_CTFP(dtp); 342*7c478bd9Sstevel@tonic-gate rtype = rbase = DT_INT_TYPE(dtp); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (ctf_type_encoding(lfp, lbase, &le) == CTF_ERR) { 346*7c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr = ctf_errno(lfp); 347*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (ctf_type_encoding(rfp, rbase, &re) == CTF_ERR) { 351*7c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr = ctf_errno(rfp); 352*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate /* 356*7c478bd9Sstevel@tonic-gate * Compute an integer rank based on the size and unsigned status. 357*7c478bd9Sstevel@tonic-gate * If rank is identical, pick the "larger" of the equivalent types 358*7c478bd9Sstevel@tonic-gate * which we define as having a larger base ctf_id_t. If rank is 359*7c478bd9Sstevel@tonic-gate * different, pick the type with the greater rank. 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate lrank = le.cte_bits + ((le.cte_format & CTF_INT_SIGNED) == 0); 362*7c478bd9Sstevel@tonic-gate rrank = re.cte_bits + ((re.cte_format & CTF_INT_SIGNED) == 0); 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate if (lrank == rrank) { 365*7c478bd9Sstevel@tonic-gate if (lbase - rbase < 0) 366*7c478bd9Sstevel@tonic-gate goto return_rtype; 367*7c478bd9Sstevel@tonic-gate else 368*7c478bd9Sstevel@tonic-gate goto return_ltype; 369*7c478bd9Sstevel@tonic-gate } else if (lrank > rrank) { 370*7c478bd9Sstevel@tonic-gate goto return_ltype; 371*7c478bd9Sstevel@tonic-gate } else 372*7c478bd9Sstevel@tonic-gate goto return_rtype; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate return_ltype: 375*7c478bd9Sstevel@tonic-gate *ofp = lfp; 376*7c478bd9Sstevel@tonic-gate *otype = ltype; 377*7c478bd9Sstevel@tonic-gate return; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate return_rtype: 380*7c478bd9Sstevel@tonic-gate *ofp = rfp; 381*7c478bd9Sstevel@tonic-gate *otype = rtype; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate void 385*7c478bd9Sstevel@tonic-gate dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp) 386*7c478bd9Sstevel@tonic-gate { 387*7c478bd9Sstevel@tonic-gate dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type); 388*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type); 389*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate const char * 393*7c478bd9Sstevel@tonic-gate dt_node_name(const dt_node_t *dnp, char *buf, size_t len) 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 396*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate const char *prefix = "", *suffix = ""; 399*7c478bd9Sstevel@tonic-gate const dtrace_syminfo_t *dts; 400*7c478bd9Sstevel@tonic-gate char *s; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate switch (dnp->dn_kind) { 403*7c478bd9Sstevel@tonic-gate case DT_NODE_INT: 404*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "integer constant 0x%llx", 405*7c478bd9Sstevel@tonic-gate (u_longlong_t)dnp->dn_value); 406*7c478bd9Sstevel@tonic-gate break; 407*7c478bd9Sstevel@tonic-gate case DT_NODE_STRING: 408*7c478bd9Sstevel@tonic-gate s = strchr2esc(dnp->dn_string, strlen(dnp->dn_string)); 409*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "string constant \"%s\"", 410*7c478bd9Sstevel@tonic-gate s != NULL ? s : dnp->dn_string); 411*7c478bd9Sstevel@tonic-gate free(s); 412*7c478bd9Sstevel@tonic-gate break; 413*7c478bd9Sstevel@tonic-gate case DT_NODE_IDENT: 414*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "identifier %s", dnp->dn_string); 415*7c478bd9Sstevel@tonic-gate break; 416*7c478bd9Sstevel@tonic-gate case DT_NODE_VAR: 417*7c478bd9Sstevel@tonic-gate case DT_NODE_FUNC: 418*7c478bd9Sstevel@tonic-gate case DT_NODE_AGG: 419*7c478bd9Sstevel@tonic-gate case DT_NODE_INLINE: 420*7c478bd9Sstevel@tonic-gate switch (dnp->dn_ident->di_kind) { 421*7c478bd9Sstevel@tonic-gate case DT_IDENT_FUNC: 422*7c478bd9Sstevel@tonic-gate case DT_IDENT_AGGFUNC: 423*7c478bd9Sstevel@tonic-gate case DT_IDENT_ACTFUNC: 424*7c478bd9Sstevel@tonic-gate suffix = "( )"; 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate case DT_IDENT_AGG: 427*7c478bd9Sstevel@tonic-gate prefix = "@"; 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "%s %s%s%s", 431*7c478bd9Sstevel@tonic-gate dt_idkind_name(dnp->dn_ident->di_kind), 432*7c478bd9Sstevel@tonic-gate prefix, dnp->dn_ident->di_name, suffix); 433*7c478bd9Sstevel@tonic-gate break; 434*7c478bd9Sstevel@tonic-gate case DT_NODE_SYM: 435*7c478bd9Sstevel@tonic-gate dts = dnp->dn_ident->di_data; 436*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "symbol %s`%s", 437*7c478bd9Sstevel@tonic-gate dts->dts_object, dts->dts_name); 438*7c478bd9Sstevel@tonic-gate break; 439*7c478bd9Sstevel@tonic-gate case DT_NODE_TYPE: 440*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "type %s", 441*7c478bd9Sstevel@tonic-gate dt_node_type_name(dnp, n1, sizeof (n1))); 442*7c478bd9Sstevel@tonic-gate break; 443*7c478bd9Sstevel@tonic-gate case DT_NODE_OP1: 444*7c478bd9Sstevel@tonic-gate case DT_NODE_OP2: 445*7c478bd9Sstevel@tonic-gate case DT_NODE_OP3: 446*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "operator %s", opstr(dnp->dn_op)); 447*7c478bd9Sstevel@tonic-gate break; 448*7c478bd9Sstevel@tonic-gate case DT_NODE_DEXPR: 449*7c478bd9Sstevel@tonic-gate case DT_NODE_DFUNC: 450*7c478bd9Sstevel@tonic-gate if (dnp->dn_expr) 451*7c478bd9Sstevel@tonic-gate return (dt_node_name(dnp->dn_expr, buf, len)); 452*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "%s", "statement"); 453*7c478bd9Sstevel@tonic-gate break; 454*7c478bd9Sstevel@tonic-gate case DT_NODE_PDESC: 455*7c478bd9Sstevel@tonic-gate if (dnp->dn_desc->dtpd_id == 0) { 456*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, 457*7c478bd9Sstevel@tonic-gate "probe description %s:%s:%s:%s", 458*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod, 459*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name); 460*7c478bd9Sstevel@tonic-gate } else { 461*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "probe description %u", 462*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_id); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate break; 465*7c478bd9Sstevel@tonic-gate case DT_NODE_CLAUSE: 466*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "%s", "clause"); 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate case DT_NODE_MEMBER: 469*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "member %s", dnp->dn_membname); 470*7c478bd9Sstevel@tonic-gate break; 471*7c478bd9Sstevel@tonic-gate case DT_NODE_XLATOR: 472*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "translator <%s> (%s)", 473*7c478bd9Sstevel@tonic-gate dt_type_name(dnp->dn_xlator->dx_dst_ctfp, 474*7c478bd9Sstevel@tonic-gate dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)), 475*7c478bd9Sstevel@tonic-gate dt_type_name(dnp->dn_xlator->dx_src_ctfp, 476*7c478bd9Sstevel@tonic-gate dnp->dn_xlator->dx_src_type, n2, sizeof (n2))); 477*7c478bd9Sstevel@tonic-gate break; 478*7c478bd9Sstevel@tonic-gate case DT_NODE_PROG: 479*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "%s", "program"); 480*7c478bd9Sstevel@tonic-gate break; 481*7c478bd9Sstevel@tonic-gate default: 482*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "node <%u>", dnp->dn_kind); 483*7c478bd9Sstevel@tonic-gate break; 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate return (buf); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * dt_node_xalloc() can be used to create new parse nodes from any libdtrace 491*7c478bd9Sstevel@tonic-gate * caller. The caller is responsible for assigning dn_link appropriately. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate dt_node_t * 494*7c478bd9Sstevel@tonic-gate dt_node_xalloc(dtrace_hdl_t *dtp, int kind) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_alloc(dtp, sizeof (dt_node_t)); 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate if (dnp == NULL) 499*7c478bd9Sstevel@tonic-gate return (NULL); 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate dnp->dn_ctfp = NULL; 502*7c478bd9Sstevel@tonic-gate dnp->dn_type = CTF_ERR; 503*7c478bd9Sstevel@tonic-gate dnp->dn_kind = (uchar_t)kind; 504*7c478bd9Sstevel@tonic-gate dnp->dn_flags = 0; 505*7c478bd9Sstevel@tonic-gate dnp->dn_op = 0; 506*7c478bd9Sstevel@tonic-gate dnp->dn_line = -1; 507*7c478bd9Sstevel@tonic-gate dnp->dn_reg = -1; 508*7c478bd9Sstevel@tonic-gate dnp->dn_attr = _dtrace_defattr; 509*7c478bd9Sstevel@tonic-gate dnp->dn_list = NULL; 510*7c478bd9Sstevel@tonic-gate dnp->dn_link = NULL; 511*7c478bd9Sstevel@tonic-gate bzero(&dnp->dn_u, sizeof (dnp->dn_u)); 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate return (dnp); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * dt_node_alloc() is used to create new parse nodes from the parser. It 518*7c478bd9Sstevel@tonic-gate * assigns the node location based on the current lexer line number and places 519*7c478bd9Sstevel@tonic-gate * the new node on the default allocation list. If allocation fails, we 520*7c478bd9Sstevel@tonic-gate * automatically longjmp the caller back to the enclosing compilation call. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate static dt_node_t * 523*7c478bd9Sstevel@tonic-gate dt_node_alloc(int kind) 524*7c478bd9Sstevel@tonic-gate { 525*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_xalloc(yypcb->pcb_hdl, kind); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate if (dnp == NULL) 528*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate dnp->dn_line = yylineno; 531*7c478bd9Sstevel@tonic-gate dnp->dn_link = yypcb->pcb_list; 532*7c478bd9Sstevel@tonic-gate yypcb->pcb_list = dnp; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate return (dnp); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate void 538*7c478bd9Sstevel@tonic-gate dt_node_free(dt_node_t *dnp) 539*7c478bd9Sstevel@tonic-gate { 540*7c478bd9Sstevel@tonic-gate uchar_t kind = dnp->dn_kind; 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate dnp->dn_kind = DT_NODE_FREE; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate switch (kind) { 545*7c478bd9Sstevel@tonic-gate case DT_NODE_STRING: 546*7c478bd9Sstevel@tonic-gate case DT_NODE_IDENT: 547*7c478bd9Sstevel@tonic-gate case DT_NODE_TYPE: 548*7c478bd9Sstevel@tonic-gate free(dnp->dn_string); 549*7c478bd9Sstevel@tonic-gate dnp->dn_string = NULL; 550*7c478bd9Sstevel@tonic-gate break; 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate case DT_NODE_VAR: 553*7c478bd9Sstevel@tonic-gate case DT_NODE_FUNC: 554*7c478bd9Sstevel@tonic-gate case DT_NODE_PROBE: 555*7c478bd9Sstevel@tonic-gate if (dnp->dn_ident != NULL) { 556*7c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN) 557*7c478bd9Sstevel@tonic-gate dt_ident_destroy(dnp->dn_ident); 558*7c478bd9Sstevel@tonic-gate dnp->dn_ident = NULL; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_args); 561*7c478bd9Sstevel@tonic-gate break; 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate case DT_NODE_OP1: 564*7c478bd9Sstevel@tonic-gate if (dnp->dn_child != NULL) { 565*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_child); 566*7c478bd9Sstevel@tonic-gate dnp->dn_child = NULL; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate break; 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate case DT_NODE_OP3: 571*7c478bd9Sstevel@tonic-gate if (dnp->dn_expr != NULL) { 572*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_expr); 573*7c478bd9Sstevel@tonic-gate dnp->dn_expr = NULL; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 576*7c478bd9Sstevel@tonic-gate case DT_NODE_OP2: 577*7c478bd9Sstevel@tonic-gate if (dnp->dn_left != NULL) { 578*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_left); 579*7c478bd9Sstevel@tonic-gate dnp->dn_left = NULL; 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate if (dnp->dn_right != NULL) { 582*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_right); 583*7c478bd9Sstevel@tonic-gate dnp->dn_right = NULL; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate break; 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate case DT_NODE_DEXPR: 588*7c478bd9Sstevel@tonic-gate case DT_NODE_DFUNC: 589*7c478bd9Sstevel@tonic-gate if (dnp->dn_expr != NULL) { 590*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_expr); 591*7c478bd9Sstevel@tonic-gate dnp->dn_expr = NULL; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate break; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate case DT_NODE_AGG: 596*7c478bd9Sstevel@tonic-gate if (dnp->dn_aggfun != NULL) { 597*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_aggfun); 598*7c478bd9Sstevel@tonic-gate dnp->dn_aggfun = NULL; 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_aggtup); 601*7c478bd9Sstevel@tonic-gate break; 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate case DT_NODE_PDESC: 604*7c478bd9Sstevel@tonic-gate free(dnp->dn_spec); 605*7c478bd9Sstevel@tonic-gate dnp->dn_spec = NULL; 606*7c478bd9Sstevel@tonic-gate free(dnp->dn_desc); 607*7c478bd9Sstevel@tonic-gate dnp->dn_desc = NULL; 608*7c478bd9Sstevel@tonic-gate break; 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate case DT_NODE_CLAUSE: 611*7c478bd9Sstevel@tonic-gate if (dnp->dn_pred != NULL) 612*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_pred); 613*7c478bd9Sstevel@tonic-gate if (dnp->dn_locals != NULL) 614*7c478bd9Sstevel@tonic-gate dt_idhash_destroy(dnp->dn_locals); 615*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_pdescs); 616*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_acts); 617*7c478bd9Sstevel@tonic-gate break; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate case DT_NODE_MEMBER: 620*7c478bd9Sstevel@tonic-gate free(dnp->dn_membname); 621*7c478bd9Sstevel@tonic-gate dnp->dn_membname = NULL; 622*7c478bd9Sstevel@tonic-gate if (dnp->dn_membexpr != NULL) { 623*7c478bd9Sstevel@tonic-gate dt_node_free(dnp->dn_membexpr); 624*7c478bd9Sstevel@tonic-gate dnp->dn_membexpr = NULL; 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate break; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate case DT_NODE_PROVIDER: 629*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_probes); 630*7c478bd9Sstevel@tonic-gate free(dnp->dn_provname); 631*7c478bd9Sstevel@tonic-gate dnp->dn_provname = NULL; 632*7c478bd9Sstevel@tonic-gate break; 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate case DT_NODE_PROG: 635*7c478bd9Sstevel@tonic-gate dt_node_list_free(&dnp->dn_list); 636*7c478bd9Sstevel@tonic-gate break; 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate void 641*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate if ((yypcb->pcb_cflags & DTRACE_C_EATTR) && 644*7c478bd9Sstevel@tonic-gate (dt_attr_cmp(attr, yypcb->pcb_amin) < 0)) { 645*7c478bd9Sstevel@tonic-gate char a[DTRACE_ATTR2STR_MAX]; 646*7c478bd9Sstevel@tonic-gate char s[BUFSIZ]; 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_ATTR_MIN, "attributes for %s (%s) are less than " 649*7c478bd9Sstevel@tonic-gate "predefined minimum\n", dt_node_name(dnp, s, sizeof (s)), 650*7c478bd9Sstevel@tonic-gate dtrace_attr2str(attr, a, sizeof (a))); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate dnp->dn_attr = attr; 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate void 657*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type) 658*7c478bd9Sstevel@tonic-gate { 659*7c478bd9Sstevel@tonic-gate ctf_id_t base = ctf_type_resolve(fp, type); 660*7c478bd9Sstevel@tonic-gate uint_t kind = ctf_type_kind(fp, base); 661*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate dnp->dn_flags &= 664*7c478bd9Sstevel@tonic-gate ~(DT_NF_SIGNED | DT_NF_REF | DT_NF_BITFIELD | DT_NF_USERLAND); 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_INTEGER && ctf_type_encoding(fp, base, &e) == 0) { 667*7c478bd9Sstevel@tonic-gate size_t size = e.cte_bits / NBBY; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1))) 670*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_BITFIELD; 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate if (e.cte_format & CTF_INT_SIGNED) 673*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_SIGNED; 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_FLOAT && ctf_type_encoding(fp, base, &e) == 0) { 677*7c478bd9Sstevel@tonic-gate if (e.cte_bits / NBBY > sizeof (uint64_t)) 678*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_REF; 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_STRUCT || kind == CTF_K_UNION || 682*7c478bd9Sstevel@tonic-gate kind == CTF_K_FORWARD || 683*7c478bd9Sstevel@tonic-gate kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION) 684*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_REF; 685*7c478bd9Sstevel@tonic-gate else if (yypcb != NULL && fp == DT_DYN_CTFP(yypcb->pcb_hdl) && 686*7c478bd9Sstevel@tonic-gate type == DT_DYN_TYPE(yypcb->pcb_hdl)) 687*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_REF; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_COOKED; 690*7c478bd9Sstevel@tonic-gate dnp->dn_ctfp = fp; 691*7c478bd9Sstevel@tonic-gate dnp->dn_type = type; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate void 695*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(const dt_node_t *src, dt_node_t *dst) 696*7c478bd9Sstevel@tonic-gate { 697*7c478bd9Sstevel@tonic-gate assert(src->dn_flags & DT_NF_COOKED); 698*7c478bd9Sstevel@tonic-gate dst->dn_flags = src->dn_flags & ~DT_NF_LVALUE; 699*7c478bd9Sstevel@tonic-gate dst->dn_ctfp = src->dn_ctfp; 700*7c478bd9Sstevel@tonic-gate dst->dn_type = src->dn_type; 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate const char * 704*7c478bd9Sstevel@tonic-gate dt_node_type_name(const dt_node_t *dnp, char *buf, size_t len) 705*7c478bd9Sstevel@tonic-gate { 706*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL) { 707*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, len, "%s", 708*7c478bd9Sstevel@tonic-gate dt_idkind_name(dt_ident_resolve(dnp->dn_ident)->di_kind)); 709*7c478bd9Sstevel@tonic-gate return (buf); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_USERLAND) { 713*7c478bd9Sstevel@tonic-gate size_t n = snprintf(buf, len, "userland "); 714*7c478bd9Sstevel@tonic-gate len = len > n ? len - n : 0; 715*7c478bd9Sstevel@tonic-gate (void) dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf + n, len); 716*7c478bd9Sstevel@tonic-gate return (buf); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate return (dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf, len)); 720*7c478bd9Sstevel@tonic-gate } 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate size_t 723*7c478bd9Sstevel@tonic-gate dt_node_type_size(const dt_node_t *dnp) 724*7c478bd9Sstevel@tonic-gate { 725*7c478bd9Sstevel@tonic-gate if (dnp->dn_kind == DT_NODE_STRING) 726*7c478bd9Sstevel@tonic-gate return (strlen(dnp->dn_string) + 1); 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL) 729*7c478bd9Sstevel@tonic-gate return (dt_ident_size(dnp->dn_ident)); 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type)); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * Determine if the specified parse tree node references an identifier of the 736*7c478bd9Sstevel@tonic-gate * specified kind, and if so return a pointer to it; otherwise return NULL. 737*7c478bd9Sstevel@tonic-gate * This function resolves the identifier itself, following through any inlines. 738*7c478bd9Sstevel@tonic-gate */ 739*7c478bd9Sstevel@tonic-gate dt_ident_t * 740*7c478bd9Sstevel@tonic-gate dt_node_resolve(const dt_node_t *dnp, uint_t idkind) 741*7c478bd9Sstevel@tonic-gate { 742*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate switch (dnp->dn_kind) { 745*7c478bd9Sstevel@tonic-gate case DT_NODE_VAR: 746*7c478bd9Sstevel@tonic-gate case DT_NODE_SYM: 747*7c478bd9Sstevel@tonic-gate case DT_NODE_FUNC: 748*7c478bd9Sstevel@tonic-gate case DT_NODE_AGG: 749*7c478bd9Sstevel@tonic-gate case DT_NODE_INLINE: 750*7c478bd9Sstevel@tonic-gate case DT_NODE_PROBE: 751*7c478bd9Sstevel@tonic-gate idp = dt_ident_resolve(dnp->dn_ident); 752*7c478bd9Sstevel@tonic-gate return (idp->di_kind == idkind ? idp : NULL); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(dnp)) { 756*7c478bd9Sstevel@tonic-gate idp = dt_ident_resolve(dnp->dn_ident); 757*7c478bd9Sstevel@tonic-gate return (idp->di_kind == idkind ? idp : NULL); 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate return (NULL); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate size_t 764*7c478bd9Sstevel@tonic-gate dt_node_sizeof(const dt_node_t *dnp) 765*7c478bd9Sstevel@tonic-gate { 766*7c478bd9Sstevel@tonic-gate dtrace_syminfo_t *sip; 767*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 768*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate /* 771*7c478bd9Sstevel@tonic-gate * The size of the node as used for the sizeof() operator depends on 772*7c478bd9Sstevel@tonic-gate * the kind of the node. If the node is a SYM, the size is obtained 773*7c478bd9Sstevel@tonic-gate * from the symbol table; if it is not a SYM, the size is determined 774*7c478bd9Sstevel@tonic-gate * from the node's type. This is slightly different from C's sizeof() 775*7c478bd9Sstevel@tonic-gate * operator in that (for example) when applied to a function, sizeof() 776*7c478bd9Sstevel@tonic-gate * will evaluate to the length of the function rather than the size of 777*7c478bd9Sstevel@tonic-gate * the function type. 778*7c478bd9Sstevel@tonic-gate */ 779*7c478bd9Sstevel@tonic-gate if (dnp->dn_kind != DT_NODE_SYM) 780*7c478bd9Sstevel@tonic-gate return (dt_node_type_size(dnp)); 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate sip = dnp->dn_ident->di_data; 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate if (dtrace_lookup_by_name(dtp, sip->dts_object, 785*7c478bd9Sstevel@tonic-gate sip->dts_name, &sym, NULL) == -1) 786*7c478bd9Sstevel@tonic-gate return (0); 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate return (sym.st_size); 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate int 792*7c478bd9Sstevel@tonic-gate dt_node_is_integer(const dt_node_t *dnp) 793*7c478bd9Sstevel@tonic-gate { 794*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 795*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 796*7c478bd9Sstevel@tonic-gate ctf_id_t type; 797*7c478bd9Sstevel@tonic-gate uint_t kind; 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 802*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, type); 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_INTEGER && 805*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)) 806*7c478bd9Sstevel@tonic-gate return (0); /* void integer */ 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate int 812*7c478bd9Sstevel@tonic-gate dt_node_is_float(const dt_node_t *dnp) 813*7c478bd9Sstevel@tonic-gate { 814*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 815*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 816*7c478bd9Sstevel@tonic-gate ctf_id_t type; 817*7c478bd9Sstevel@tonic-gate uint_t kind; 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 822*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, type); 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_FLOAT && 825*7c478bd9Sstevel@tonic-gate ctf_type_encoding(dnp->dn_ctfp, type, &e) == 0 && ( 826*7c478bd9Sstevel@tonic-gate e.cte_format == CTF_FP_SINGLE || e.cte_format == CTF_FP_DOUBLE || 827*7c478bd9Sstevel@tonic-gate e.cte_format == CTF_FP_LDOUBLE)); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate int 831*7c478bd9Sstevel@tonic-gate dt_node_is_scalar(const dt_node_t *dnp) 832*7c478bd9Sstevel@tonic-gate { 833*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 834*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 835*7c478bd9Sstevel@tonic-gate ctf_id_t type; 836*7c478bd9Sstevel@tonic-gate uint_t kind; 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 841*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, type); 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_INTEGER && 844*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)) 845*7c478bd9Sstevel@tonic-gate return (0); /* void cannot be used as a scalar */ 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM || 848*7c478bd9Sstevel@tonic-gate kind == CTF_K_POINTER); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate int 852*7c478bd9Sstevel@tonic-gate dt_node_is_arith(const dt_node_t *dnp) 853*7c478bd9Sstevel@tonic-gate { 854*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 855*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 856*7c478bd9Sstevel@tonic-gate ctf_id_t type; 857*7c478bd9Sstevel@tonic-gate uint_t kind; 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 860*7c478bd9Sstevel@tonic-gate 861*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 862*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, type); 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_INTEGER) 865*7c478bd9Sstevel@tonic-gate return (ctf_type_encoding(fp, type, &e) == 0 && !IS_VOID(e)); 866*7c478bd9Sstevel@tonic-gate else 867*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_ENUM); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate int 871*7c478bd9Sstevel@tonic-gate dt_node_is_vfptr(const dt_node_t *dnp) 872*7c478bd9Sstevel@tonic-gate { 873*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 874*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 875*7c478bd9Sstevel@tonic-gate ctf_id_t type; 876*7c478bd9Sstevel@tonic-gate uint_t kind; 877*7c478bd9Sstevel@tonic-gate 878*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 881*7c478bd9Sstevel@tonic-gate if (ctf_type_kind(fp, type) != CTF_K_POINTER) 882*7c478bd9Sstevel@tonic-gate return (0); /* type is not a pointer */ 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, ctf_type_reference(fp, type)); 885*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, type); 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_FUNCTION || (kind == CTF_K_INTEGER && 888*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate int 892*7c478bd9Sstevel@tonic-gate dt_node_is_dynamic(const dt_node_t *dnp) 893*7c478bd9Sstevel@tonic-gate { 894*7c478bd9Sstevel@tonic-gate if (dnp->dn_kind == DT_NODE_VAR && 895*7c478bd9Sstevel@tonic-gate (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) { 896*7c478bd9Sstevel@tonic-gate const dt_idnode_t *inp = dnp->dn_ident->di_iarg; 897*7c478bd9Sstevel@tonic-gate return (dt_node_is_dynamic(inp->din_root)); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate return (dnp->dn_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) && 901*7c478bd9Sstevel@tonic-gate dnp->dn_type == DT_DYN_TYPE(yypcb->pcb_hdl)); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate int 905*7c478bd9Sstevel@tonic-gate dt_node_is_string(const dt_node_t *dnp) 906*7c478bd9Sstevel@tonic-gate { 907*7c478bd9Sstevel@tonic-gate return (dnp->dn_ctfp == DT_STR_CTFP(yypcb->pcb_hdl) && 908*7c478bd9Sstevel@tonic-gate dnp->dn_type == DT_STR_TYPE(yypcb->pcb_hdl)); 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate int 912*7c478bd9Sstevel@tonic-gate dt_node_is_stack(const dt_node_t *dnp) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate return (dnp->dn_ctfp == DT_STACK_CTFP(yypcb->pcb_hdl) && 915*7c478bd9Sstevel@tonic-gate dnp->dn_type == DT_STACK_TYPE(yypcb->pcb_hdl)); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate int 919*7c478bd9Sstevel@tonic-gate dt_node_is_strcompat(const dt_node_t *dnp) 920*7c478bd9Sstevel@tonic-gate { 921*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 922*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 923*7c478bd9Sstevel@tonic-gate ctf_arinfo_t r; 924*7c478bd9Sstevel@tonic-gate ctf_id_t base; 925*7c478bd9Sstevel@tonic-gate uint_t kind; 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate base = ctf_type_resolve(fp, dnp->dn_type); 930*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, base); 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_POINTER && 933*7c478bd9Sstevel@tonic-gate (base = ctf_type_reference(fp, base)) != CTF_ERR && 934*7c478bd9Sstevel@tonic-gate (base = ctf_type_resolve(fp, base)) != CTF_ERR && 935*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e)) 936*7c478bd9Sstevel@tonic-gate return (1); /* promote char pointer to string */ 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_ARRAY && ctf_array_info(fp, base, &r) == 0 && 939*7c478bd9Sstevel@tonic-gate (base = ctf_type_resolve(fp, r.ctr_contents)) != CTF_ERR && 940*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e)) 941*7c478bd9Sstevel@tonic-gate return (1); /* promote char array to string */ 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate return (0); 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate int 947*7c478bd9Sstevel@tonic-gate dt_node_is_pointer(const dt_node_t *dnp) 948*7c478bd9Sstevel@tonic-gate { 949*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 950*7c478bd9Sstevel@tonic-gate uint_t kind; 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate assert(dnp->dn_flags & DT_NF_COOKED); 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate if (dt_node_is_string(dnp)) 955*7c478bd9Sstevel@tonic-gate return (0); /* string are pass-by-ref but act like structs */ 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(fp, ctf_type_resolve(fp, dnp->dn_type)); 958*7c478bd9Sstevel@tonic-gate return (kind == CTF_K_POINTER || kind == CTF_K_ARRAY); 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate 961*7c478bd9Sstevel@tonic-gate int 962*7c478bd9Sstevel@tonic-gate dt_node_is_void(const dt_node_t *dnp) 963*7c478bd9Sstevel@tonic-gate { 964*7c478bd9Sstevel@tonic-gate ctf_file_t *fp = dnp->dn_ctfp; 965*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 966*7c478bd9Sstevel@tonic-gate ctf_id_t type; 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(dnp)) 969*7c478bd9Sstevel@tonic-gate return (0); /* <DYN> is an alias for void but not the same */ 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate if (dt_node_is_stack(dnp)) 972*7c478bd9Sstevel@tonic-gate return (0); 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dnp->dn_type); 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate return (ctf_type_kind(fp, type) == CTF_K_INTEGER && 977*7c478bd9Sstevel@tonic-gate ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)); 978*7c478bd9Sstevel@tonic-gate } 979*7c478bd9Sstevel@tonic-gate 980*7c478bd9Sstevel@tonic-gate int 981*7c478bd9Sstevel@tonic-gate dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp, 982*7c478bd9Sstevel@tonic-gate ctf_file_t **fpp, ctf_id_t *tp) 983*7c478bd9Sstevel@tonic-gate { 984*7c478bd9Sstevel@tonic-gate ctf_file_t *lfp = lp->dn_ctfp; 985*7c478bd9Sstevel@tonic-gate ctf_file_t *rfp = rp->dn_ctfp; 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate ctf_id_t lbase = CTF_ERR, rbase = CTF_ERR; 988*7c478bd9Sstevel@tonic-gate ctf_id_t lref = CTF_ERR, rref = CTF_ERR; 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate int lp_is_void, rp_is_void, lp_is_int, rp_is_int, compat; 991*7c478bd9Sstevel@tonic-gate uint_t lkind, rkind; 992*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 993*7c478bd9Sstevel@tonic-gate ctf_arinfo_t r; 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate assert(lp->dn_flags & DT_NF_COOKED); 996*7c478bd9Sstevel@tonic-gate assert(rp->dn_flags & DT_NF_COOKED); 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp)) 999*7c478bd9Sstevel@tonic-gate return (0); /* fail if either node is a dynamic variable */ 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate lp_is_int = dt_node_is_integer(lp); 1002*7c478bd9Sstevel@tonic-gate rp_is_int = dt_node_is_integer(rp); 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate if (lp_is_int && rp_is_int) 1005*7c478bd9Sstevel@tonic-gate return (0); /* fail if both nodes are integers */ 1006*7c478bd9Sstevel@tonic-gate 1007*7c478bd9Sstevel@tonic-gate if (lp_is_int && (lp->dn_kind != DT_NODE_INT || lp->dn_value != 0)) 1008*7c478bd9Sstevel@tonic-gate return (0); /* fail if lp is an integer that isn't 0 constant */ 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate if (rp_is_int && (rp->dn_kind != DT_NODE_INT || rp->dn_value != 0)) 1011*7c478bd9Sstevel@tonic-gate return (0); /* fail if rp is an integer that isn't 0 constant */ 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate if ((lp_is_int == 0 && rp_is_int == 0) && ( 1014*7c478bd9Sstevel@tonic-gate (lp->dn_flags & DT_NF_USERLAND) ^ (rp->dn_flags & DT_NF_USERLAND))) 1015*7c478bd9Sstevel@tonic-gate return (0); /* fail if only one pointer is a userland address */ 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate /* 1018*7c478bd9Sstevel@tonic-gate * Resolve the left-hand and right-hand types to their base type, and 1019*7c478bd9Sstevel@tonic-gate * then resolve the referenced type as well (assuming the base type 1020*7c478bd9Sstevel@tonic-gate * is CTF_K_POINTER or CTF_K_ARRAY). Otherwise [lr]ref = CTF_ERR. 1021*7c478bd9Sstevel@tonic-gate */ 1022*7c478bd9Sstevel@tonic-gate if (!lp_is_int) { 1023*7c478bd9Sstevel@tonic-gate lbase = ctf_type_resolve(lfp, lp->dn_type); 1024*7c478bd9Sstevel@tonic-gate lkind = ctf_type_kind(lfp, lbase); 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate if (lkind == CTF_K_POINTER) { 1027*7c478bd9Sstevel@tonic-gate lref = ctf_type_resolve(lfp, 1028*7c478bd9Sstevel@tonic-gate ctf_type_reference(lfp, lbase)); 1029*7c478bd9Sstevel@tonic-gate } else if (lkind == CTF_K_ARRAY && 1030*7c478bd9Sstevel@tonic-gate ctf_array_info(lfp, lbase, &r) == 0) { 1031*7c478bd9Sstevel@tonic-gate lref = ctf_type_resolve(lfp, r.ctr_contents); 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate } 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate if (!rp_is_int) { 1036*7c478bd9Sstevel@tonic-gate rbase = ctf_type_resolve(rfp, rp->dn_type); 1037*7c478bd9Sstevel@tonic-gate rkind = ctf_type_kind(rfp, rbase); 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if (rkind == CTF_K_POINTER) { 1040*7c478bd9Sstevel@tonic-gate rref = ctf_type_resolve(rfp, 1041*7c478bd9Sstevel@tonic-gate ctf_type_reference(rfp, rbase)); 1042*7c478bd9Sstevel@tonic-gate } else if (rkind == CTF_K_ARRAY && 1043*7c478bd9Sstevel@tonic-gate ctf_array_info(rfp, rbase, &r) == 0) { 1044*7c478bd9Sstevel@tonic-gate rref = ctf_type_resolve(rfp, r.ctr_contents); 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate 1048*7c478bd9Sstevel@tonic-gate /* 1049*7c478bd9Sstevel@tonic-gate * We know that one or the other type may still be a zero-valued 1050*7c478bd9Sstevel@tonic-gate * integer constant. To simplify the code below, set the integer 1051*7c478bd9Sstevel@tonic-gate * type variables equal to the non-integer types and proceed. 1052*7c478bd9Sstevel@tonic-gate */ 1053*7c478bd9Sstevel@tonic-gate if (lp_is_int) { 1054*7c478bd9Sstevel@tonic-gate lbase = rbase; 1055*7c478bd9Sstevel@tonic-gate lkind = rkind; 1056*7c478bd9Sstevel@tonic-gate lref = rref; 1057*7c478bd9Sstevel@tonic-gate lfp = rfp; 1058*7c478bd9Sstevel@tonic-gate } else if (rp_is_int) { 1059*7c478bd9Sstevel@tonic-gate rbase = lbase; 1060*7c478bd9Sstevel@tonic-gate rkind = lkind; 1061*7c478bd9Sstevel@tonic-gate rref = lref; 1062*7c478bd9Sstevel@tonic-gate rfp = lfp; 1063*7c478bd9Sstevel@tonic-gate } 1064*7c478bd9Sstevel@tonic-gate 1065*7c478bd9Sstevel@tonic-gate lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e); 1066*7c478bd9Sstevel@tonic-gate rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e); 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate /* 1069*7c478bd9Sstevel@tonic-gate * The types are compatible if both are pointers to the same type, or 1070*7c478bd9Sstevel@tonic-gate * if either pointer is a void pointer. If they are compatible, set 1071*7c478bd9Sstevel@tonic-gate * tp to point to the more specific pointer type and return it. 1072*7c478bd9Sstevel@tonic-gate */ 1073*7c478bd9Sstevel@tonic-gate compat = (lkind == CTF_K_POINTER || lkind == CTF_K_ARRAY) && 1074*7c478bd9Sstevel@tonic-gate (rkind == CTF_K_POINTER || rkind == CTF_K_ARRAY) && 1075*7c478bd9Sstevel@tonic-gate (lp_is_void || rp_is_void || ctf_type_compat(lfp, lref, rfp, rref)); 1076*7c478bd9Sstevel@tonic-gate 1077*7c478bd9Sstevel@tonic-gate if (compat) { 1078*7c478bd9Sstevel@tonic-gate if (fpp != NULL) 1079*7c478bd9Sstevel@tonic-gate *fpp = rp_is_void ? lfp : rfp; 1080*7c478bd9Sstevel@tonic-gate if (tp != NULL) 1081*7c478bd9Sstevel@tonic-gate *tp = rp_is_void ? lbase : rbase; 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate 1084*7c478bd9Sstevel@tonic-gate return (compat); 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate /* 1088*7c478bd9Sstevel@tonic-gate * The rules for checking argument types against parameter types are described 1089*7c478bd9Sstevel@tonic-gate * in the ANSI-C spec (see K&R[A7.3.2] and K&R[A7.17]). We use the same rule 1090*7c478bd9Sstevel@tonic-gate * set to determine whether associative array arguments match the prototype. 1091*7c478bd9Sstevel@tonic-gate */ 1092*7c478bd9Sstevel@tonic-gate int 1093*7c478bd9Sstevel@tonic-gate dt_node_is_argcompat(const dt_node_t *lp, const dt_node_t *rp) 1094*7c478bd9Sstevel@tonic-gate { 1095*7c478bd9Sstevel@tonic-gate ctf_file_t *lfp = lp->dn_ctfp; 1096*7c478bd9Sstevel@tonic-gate ctf_file_t *rfp = rp->dn_ctfp; 1097*7c478bd9Sstevel@tonic-gate 1098*7c478bd9Sstevel@tonic-gate assert(lp->dn_flags & DT_NF_COOKED); 1099*7c478bd9Sstevel@tonic-gate assert(rp->dn_flags & DT_NF_COOKED); 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate if (dt_node_is_integer(lp) && dt_node_is_integer(rp)) 1102*7c478bd9Sstevel@tonic-gate return (1); /* integer types are compatible */ 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp)) 1105*7c478bd9Sstevel@tonic-gate return (1); /* string types are compatible */ 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate if (dt_node_is_stack(lp) && dt_node_is_stack(rp)) 1108*7c478bd9Sstevel@tonic-gate return (1); /* stack types are compatible */ 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate switch (ctf_type_kind(lfp, ctf_type_resolve(lfp, lp->dn_type))) { 1111*7c478bd9Sstevel@tonic-gate case CTF_K_FUNCTION: 1112*7c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 1113*7c478bd9Sstevel@tonic-gate case CTF_K_UNION: 1114*7c478bd9Sstevel@tonic-gate return (ctf_type_compat(lfp, lp->dn_type, rfp, rp->dn_type)); 1115*7c478bd9Sstevel@tonic-gate default: 1116*7c478bd9Sstevel@tonic-gate return (dt_node_is_ptrcompat(lp, rp, NULL, NULL)); 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate } 1119*7c478bd9Sstevel@tonic-gate 1120*7c478bd9Sstevel@tonic-gate /* 1121*7c478bd9Sstevel@tonic-gate * We provide dt_node_is_posconst() as a convenience routine for callers who 1122*7c478bd9Sstevel@tonic-gate * wish to verify that an argument is a positive non-zero integer constant. 1123*7c478bd9Sstevel@tonic-gate */ 1124*7c478bd9Sstevel@tonic-gate int 1125*7c478bd9Sstevel@tonic-gate dt_node_is_posconst(const dt_node_t *dnp) 1126*7c478bd9Sstevel@tonic-gate { 1127*7c478bd9Sstevel@tonic-gate return (dnp->dn_kind == DT_NODE_INT && dnp->dn_value != 0 && ( 1128*7c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) == 0 || (int64_t)dnp->dn_value > 0)); 1129*7c478bd9Sstevel@tonic-gate } 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate int 1132*7c478bd9Sstevel@tonic-gate dt_node_is_actfunc(const dt_node_t *dnp) 1133*7c478bd9Sstevel@tonic-gate { 1134*7c478bd9Sstevel@tonic-gate return (dnp->dn_kind == DT_NODE_FUNC && 1135*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_kind == DT_IDENT_ACTFUNC); 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate /* 1139*7c478bd9Sstevel@tonic-gate * The original rules for integer constant typing are described in K&R[A2.5.1]. 1140*7c478bd9Sstevel@tonic-gate * However, since we support long long, we instead use the rules from ISO C99 1141*7c478bd9Sstevel@tonic-gate * clause 6.4.4.1 since that is where long longs are formally described. The 1142*7c478bd9Sstevel@tonic-gate * rules require us to know whether the constant was specified in decimal or 1143*7c478bd9Sstevel@tonic-gate * in octal or hex, which we do by looking at our lexer's 'yyintdecimal' flag. 1144*7c478bd9Sstevel@tonic-gate * The type of an integer constant is the first of the corresponding list in 1145*7c478bd9Sstevel@tonic-gate * which its value can be represented: 1146*7c478bd9Sstevel@tonic-gate * 1147*7c478bd9Sstevel@tonic-gate * unsuffixed decimal: int, long, long long 1148*7c478bd9Sstevel@tonic-gate * unsuffixed oct/hex: int, unsigned int, long, unsigned long, 1149*7c478bd9Sstevel@tonic-gate * long long, unsigned long long 1150*7c478bd9Sstevel@tonic-gate * suffix [uU]: unsigned int, unsigned long, unsigned long long 1151*7c478bd9Sstevel@tonic-gate * suffix [lL] decimal: long, long long 1152*7c478bd9Sstevel@tonic-gate * suffix [lL] oct/hex: long, unsigned long, long long, unsigned long long 1153*7c478bd9Sstevel@tonic-gate * suffix [uU][Ll]: unsigned long, unsigned long long 1154*7c478bd9Sstevel@tonic-gate * suffix ll/LL decimal: long long 1155*7c478bd9Sstevel@tonic-gate * suffix ll/LL oct/hex: long long, unsigned long long 1156*7c478bd9Sstevel@tonic-gate * suffix [uU][ll/LL]: unsigned long long 1157*7c478bd9Sstevel@tonic-gate * 1158*7c478bd9Sstevel@tonic-gate * Given that our lexer has already validated the suffixes by regexp matching, 1159*7c478bd9Sstevel@tonic-gate * there is an obvious way to concisely encode these rules: construct an array 1160*7c478bd9Sstevel@tonic-gate * of the types in the order int, unsigned int, long, unsigned long, long long, 1161*7c478bd9Sstevel@tonic-gate * unsigned long long. Compute an integer array starting index based on the 1162*7c478bd9Sstevel@tonic-gate * suffix (e.g. none = 0, u = 1, ull = 5), and compute an increment based on 1163*7c478bd9Sstevel@tonic-gate * the specifier (dec/oct/hex) and suffix (u). Then iterate from the starting 1164*7c478bd9Sstevel@tonic-gate * index to the end, advancing using the increment, and searching until we 1165*7c478bd9Sstevel@tonic-gate * find a limit that matches or we run out of choices (overflow). To make it 1166*7c478bd9Sstevel@tonic-gate * even faster, we precompute the table of type information in dtrace_open(). 1167*7c478bd9Sstevel@tonic-gate */ 1168*7c478bd9Sstevel@tonic-gate dt_node_t * 1169*7c478bd9Sstevel@tonic-gate dt_node_int(uintmax_t value) 1170*7c478bd9Sstevel@tonic-gate { 1171*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_INT); 1172*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate int n = (yyintdecimal | (yyintsuffix[0] == 'u')) + 1; 1175*7c478bd9Sstevel@tonic-gate int i = 0; 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate const char *p; 1178*7c478bd9Sstevel@tonic-gate char c; 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_INT; 1181*7c478bd9Sstevel@tonic-gate dnp->dn_value = value; 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate for (p = yyintsuffix; (c = *p) != '\0'; p++) { 1184*7c478bd9Sstevel@tonic-gate if (c == 'U' || c == 'u') 1185*7c478bd9Sstevel@tonic-gate i += 1; 1186*7c478bd9Sstevel@tonic-gate else if (c == 'L' || c == 'l') 1187*7c478bd9Sstevel@tonic-gate i += 2; 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate 1190*7c478bd9Sstevel@tonic-gate for (; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i += n) { 1191*7c478bd9Sstevel@tonic-gate if (value <= dtp->dt_ints[i].did_limit) { 1192*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1193*7c478bd9Sstevel@tonic-gate dtp->dt_ints[i].did_ctfp, 1194*7c478bd9Sstevel@tonic-gate dtp->dt_ints[i].did_type); 1195*7c478bd9Sstevel@tonic-gate 1196*7c478bd9Sstevel@tonic-gate /* 1197*7c478bd9Sstevel@tonic-gate * If a prefix character is present in macro text, add 1198*7c478bd9Sstevel@tonic-gate * in the corresponding operator node (see dt_lex.l). 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate switch (yyintprefix) { 1201*7c478bd9Sstevel@tonic-gate case '+': 1202*7c478bd9Sstevel@tonic-gate return (dt_node_op1(DT_TOK_IPOS, dnp)); 1203*7c478bd9Sstevel@tonic-gate case '-': 1204*7c478bd9Sstevel@tonic-gate return (dt_node_op1(DT_TOK_INEG, dnp)); 1205*7c478bd9Sstevel@tonic-gate default: 1206*7c478bd9Sstevel@tonic-gate return (dnp); 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate } 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate xyerror(D_INT_OFLOW, "integer constant 0x%llx cannot be represented " 1212*7c478bd9Sstevel@tonic-gate "in any built-in integral type\n", (u_longlong_t)value); 1213*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1214*7c478bd9Sstevel@tonic-gate return (NULL); /* keep gcc happy */ 1215*7c478bd9Sstevel@tonic-gate } 1216*7c478bd9Sstevel@tonic-gate 1217*7c478bd9Sstevel@tonic-gate dt_node_t * 1218*7c478bd9Sstevel@tonic-gate dt_node_string(char *string) 1219*7c478bd9Sstevel@tonic-gate { 1220*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1221*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate if (string == NULL) 1224*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_STRING); 1227*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_STRING; 1228*7c478bd9Sstevel@tonic-gate dnp->dn_string = string; 1229*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp)); 1230*7c478bd9Sstevel@tonic-gate 1231*7c478bd9Sstevel@tonic-gate return (dnp); 1232*7c478bd9Sstevel@tonic-gate } 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate dt_node_t * 1235*7c478bd9Sstevel@tonic-gate dt_node_ident(char *name) 1236*7c478bd9Sstevel@tonic-gate { 1237*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 1238*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate if (name == NULL) 1241*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate /* 1244*7c478bd9Sstevel@tonic-gate * If the identifier is an inlined integer constant, then create an INT 1245*7c478bd9Sstevel@tonic-gate * node that is a clone of the inline parse tree node and return that 1246*7c478bd9Sstevel@tonic-gate * immediately, allowing this inline to be used in parsing contexts 1247*7c478bd9Sstevel@tonic-gate * that require constant expressions (e.g. scalar array sizes). 1248*7c478bd9Sstevel@tonic-gate */ 1249*7c478bd9Sstevel@tonic-gate if ((idp = dt_idstack_lookup(&yypcb->pcb_globals, name)) != NULL && 1250*7c478bd9Sstevel@tonic-gate (idp->di_flags & DT_IDFLG_INLINE)) { 1251*7c478bd9Sstevel@tonic-gate dt_idnode_t *inp = idp->di_iarg; 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate if (inp->din_root->dn_kind == DT_NODE_INT) { 1254*7c478bd9Sstevel@tonic-gate free(name); 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_INT); 1257*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_INT; 1258*7c478bd9Sstevel@tonic-gate dnp->dn_value = inp->din_root->dn_value; 1259*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(inp->din_root, dnp); 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate return (dnp); 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate } 1264*7c478bd9Sstevel@tonic-gate 1265*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_IDENT); 1266*7c478bd9Sstevel@tonic-gate dnp->dn_op = name[0] == '@' ? DT_TOK_AGG : DT_TOK_IDENT; 1267*7c478bd9Sstevel@tonic-gate dnp->dn_string = name; 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate return (dnp); 1270*7c478bd9Sstevel@tonic-gate } 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate /* 1273*7c478bd9Sstevel@tonic-gate * Create an empty node of type corresponding to the given declaration. 1274*7c478bd9Sstevel@tonic-gate * Explicit references to user types (C or D) are assigned the default 1275*7c478bd9Sstevel@tonic-gate * stability; references to other types are _dtrace_typattr (Private). 1276*7c478bd9Sstevel@tonic-gate */ 1277*7c478bd9Sstevel@tonic-gate dt_node_t * 1278*7c478bd9Sstevel@tonic-gate dt_node_type(dt_decl_t *ddp) 1279*7c478bd9Sstevel@tonic-gate { 1280*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1281*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 1282*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 1283*7c478bd9Sstevel@tonic-gate char *name = NULL; 1284*7c478bd9Sstevel@tonic-gate int err; 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate /* 1287*7c478bd9Sstevel@tonic-gate * If 'ddp' is NULL, we get a decl by popping the decl stack. This 1288*7c478bd9Sstevel@tonic-gate * form of dt_node_type() is used by parameter rules in dt_grammar.y. 1289*7c478bd9Sstevel@tonic-gate */ 1290*7c478bd9Sstevel@tonic-gate if (ddp == NULL) 1291*7c478bd9Sstevel@tonic-gate ddp = dt_decl_pop_param(&name); 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate err = dt_decl_type(ddp, &dtt); 1294*7c478bd9Sstevel@tonic-gate dt_decl_free(ddp); 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate if (err != 0) { 1297*7c478bd9Sstevel@tonic-gate free(name); 1298*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 1299*7c478bd9Sstevel@tonic-gate } 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_TYPE); 1302*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_IDENT; 1303*7c478bd9Sstevel@tonic-gate dnp->dn_string = name; 1304*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); 1305*7c478bd9Sstevel@tonic-gate 1306*7c478bd9Sstevel@tonic-gate if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp || 1307*7c478bd9Sstevel@tonic-gate dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp) 1308*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, _dtrace_defattr); 1309*7c478bd9Sstevel@tonic-gate else 1310*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, _dtrace_typattr); 1311*7c478bd9Sstevel@tonic-gate 1312*7c478bd9Sstevel@tonic-gate return (dnp); 1313*7c478bd9Sstevel@tonic-gate } 1314*7c478bd9Sstevel@tonic-gate 1315*7c478bd9Sstevel@tonic-gate /* 1316*7c478bd9Sstevel@tonic-gate * Create a type node corresponding to a varargs (...) parameter by just 1317*7c478bd9Sstevel@tonic-gate * assigning it type CTF_ERR. The decl processing code will handle this. 1318*7c478bd9Sstevel@tonic-gate */ 1319*7c478bd9Sstevel@tonic-gate dt_node_t * 1320*7c478bd9Sstevel@tonic-gate dt_node_vatype(void) 1321*7c478bd9Sstevel@tonic-gate { 1322*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_TYPE); 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_IDENT; 1325*7c478bd9Sstevel@tonic-gate dnp->dn_ctfp = yypcb->pcb_hdl->dt_cdefs->dm_ctfp; 1326*7c478bd9Sstevel@tonic-gate dnp->dn_type = CTF_ERR; 1327*7c478bd9Sstevel@tonic-gate dnp->dn_attr = _dtrace_defattr; 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate return (dnp); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate /* 1333*7c478bd9Sstevel@tonic-gate * Instantiate a decl using the contents of the current declaration stack. As 1334*7c478bd9Sstevel@tonic-gate * we do not currently permit decls to be initialized, this function currently 1335*7c478bd9Sstevel@tonic-gate * returns NULL and no parse node is created. When this function is called, 1336*7c478bd9Sstevel@tonic-gate * the topmost scope's ds_ident pointer will be set to NULL (indicating no 1337*7c478bd9Sstevel@tonic-gate * init_declarator rule was matched) or will point to the identifier to use. 1338*7c478bd9Sstevel@tonic-gate */ 1339*7c478bd9Sstevel@tonic-gate dt_node_t * 1340*7c478bd9Sstevel@tonic-gate dt_node_decl(void) 1341*7c478bd9Sstevel@tonic-gate { 1342*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1343*7c478bd9Sstevel@tonic-gate dt_scope_t *dsp = &yypcb->pcb_dstack; 1344*7c478bd9Sstevel@tonic-gate dt_dclass_t class = dsp->ds_class; 1345*7c478bd9Sstevel@tonic-gate dt_decl_t *ddp = dt_decl_top(); 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate dt_module_t *dmp; 1348*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 1349*7c478bd9Sstevel@tonic-gate ctf_id_t type; 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 1352*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate if (dt_decl_type(ddp, &dtt) != 0) 1355*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate /* 1358*7c478bd9Sstevel@tonic-gate * If we have no declaration identifier, then this is either a spurious 1359*7c478bd9Sstevel@tonic-gate * declaration of an intrinsic type (e.g. "extern int;") or declaration 1360*7c478bd9Sstevel@tonic-gate * or redeclaration of a struct, union, or enum type or tag. 1361*7c478bd9Sstevel@tonic-gate */ 1362*7c478bd9Sstevel@tonic-gate if (dsp->ds_ident == NULL) { 1363*7c478bd9Sstevel@tonic-gate if (ddp->dd_kind != CTF_K_STRUCT && 1364*7c478bd9Sstevel@tonic-gate ddp->dd_kind != CTF_K_UNION && ddp->dd_kind != CTF_K_ENUM) 1365*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_USELESS, "useless declaration\n"); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate dt_dprintf("type %s added as id %ld\n", dt_type_name( 1368*7c478bd9Sstevel@tonic-gate ddp->dd_ctfp, ddp->dd_type, n1, sizeof (n1)), ddp->dd_type); 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate return (NULL); 1371*7c478bd9Sstevel@tonic-gate } 1372*7c478bd9Sstevel@tonic-gate 1373*7c478bd9Sstevel@tonic-gate if (strchr(dsp->ds_ident, '`') != NULL) { 1374*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_SCOPE, "D scoping operator may not be used in " 1375*7c478bd9Sstevel@tonic-gate "a declaration name (%s)\n", dsp->ds_ident); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate /* 1379*7c478bd9Sstevel@tonic-gate * If we are nested inside of a C include file, add the declaration to 1380*7c478bd9Sstevel@tonic-gate * the C definition module; otherwise use the D definition module. 1381*7c478bd9Sstevel@tonic-gate */ 1382*7c478bd9Sstevel@tonic-gate if (yypcb->pcb_idepth != 0) 1383*7c478bd9Sstevel@tonic-gate dmp = dtp->dt_cdefs; 1384*7c478bd9Sstevel@tonic-gate else 1385*7c478bd9Sstevel@tonic-gate dmp = dtp->dt_ddefs; 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate /* 1388*7c478bd9Sstevel@tonic-gate * If we see a global or static declaration of a function prototype, 1389*7c478bd9Sstevel@tonic-gate * treat this as equivalent to a D extern declaration. 1390*7c478bd9Sstevel@tonic-gate */ 1391*7c478bd9Sstevel@tonic-gate if (ctf_type_kind(dtt.dtt_ctfp, dtt.dtt_type) == CTF_K_FUNCTION && 1392*7c478bd9Sstevel@tonic-gate (class == DT_DC_DEFAULT || class == DT_DC_STATIC)) 1393*7c478bd9Sstevel@tonic-gate class = DT_DC_EXTERN; 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate switch (class) { 1396*7c478bd9Sstevel@tonic-gate case DT_DC_AUTO: 1397*7c478bd9Sstevel@tonic-gate case DT_DC_REGISTER: 1398*7c478bd9Sstevel@tonic-gate case DT_DC_STATIC: 1399*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_BADCLASS, "specified storage class not " 1400*7c478bd9Sstevel@tonic-gate "appropriate in D\n"); 1401*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate case DT_DC_EXTERN: { 1404*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t ott; 1405*7c478bd9Sstevel@tonic-gate dtrace_syminfo_t dts; 1406*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 1407*7c478bd9Sstevel@tonic-gate 1408*7c478bd9Sstevel@tonic-gate int exists = dtrace_lookup_by_name(dtp, 1409*7c478bd9Sstevel@tonic-gate dmp->dm_name, dsp->ds_ident, &sym, &dts) == 0; 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate if (exists && (dtrace_symbol_type(dtp, &sym, &dts, &ott) != 0 || 1412*7c478bd9Sstevel@tonic-gate ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type, 1413*7c478bd9Sstevel@tonic-gate ott.dtt_ctfp, ott.dtt_type) != 0)) { 1414*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, "identifier redeclared: %s`%s\n" 1415*7c478bd9Sstevel@tonic-gate "\t current: %s\n\tprevious: %s\n", 1416*7c478bd9Sstevel@tonic-gate dmp->dm_name, dsp->ds_ident, 1417*7c478bd9Sstevel@tonic-gate dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, 1418*7c478bd9Sstevel@tonic-gate n1, sizeof (n1)), 1419*7c478bd9Sstevel@tonic-gate dt_type_name(ott.dtt_ctfp, ott.dtt_type, 1420*7c478bd9Sstevel@tonic-gate n2, sizeof (n2))); 1421*7c478bd9Sstevel@tonic-gate } else if (!exists && dt_module_extern(dtp, dmp, 1422*7c478bd9Sstevel@tonic-gate dsp->ds_ident, &dtt) == NULL) { 1423*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, 1424*7c478bd9Sstevel@tonic-gate "failed to extern %s: %s\n", dsp->ds_ident, 1425*7c478bd9Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp))); 1426*7c478bd9Sstevel@tonic-gate } else { 1427*7c478bd9Sstevel@tonic-gate dt_dprintf("extern %s`%s type=<%s>\n", 1428*7c478bd9Sstevel@tonic-gate dmp->dm_name, dsp->ds_ident, 1429*7c478bd9Sstevel@tonic-gate dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, 1430*7c478bd9Sstevel@tonic-gate n1, sizeof (n1))); 1431*7c478bd9Sstevel@tonic-gate } 1432*7c478bd9Sstevel@tonic-gate break; 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate case DT_DC_TYPEDEF: 1436*7c478bd9Sstevel@tonic-gate /* 1437*7c478bd9Sstevel@tonic-gate * If the source type for the typedef is not defined in the 1438*7c478bd9Sstevel@tonic-gate * target container or its parent, copy the type to the target 1439*7c478bd9Sstevel@tonic-gate * container and reset dtt_ctfp and dtt_type to the copy. 1440*7c478bd9Sstevel@tonic-gate */ 1441*7c478bd9Sstevel@tonic-gate if (dtt.dtt_ctfp != dmp->dm_ctfp && 1442*7c478bd9Sstevel@tonic-gate dtt.dtt_ctfp != ctf_parent_file(dmp->dm_ctfp)) { 1443*7c478bd9Sstevel@tonic-gate 1444*7c478bd9Sstevel@tonic-gate dtt.dtt_type = ctf_add_type(dmp->dm_ctfp, 1445*7c478bd9Sstevel@tonic-gate dtt.dtt_ctfp, dtt.dtt_type); 1446*7c478bd9Sstevel@tonic-gate dtt.dtt_ctfp = dmp->dm_ctfp; 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate if (dtt.dtt_type == CTF_ERR || 1449*7c478bd9Sstevel@tonic-gate ctf_update(dtt.dtt_ctfp) == CTF_ERR) { 1450*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "failed to copy typedef %s " 1451*7c478bd9Sstevel@tonic-gate "source type: %s\n", dsp->ds_ident, 1452*7c478bd9Sstevel@tonic-gate ctf_errmsg(ctf_errno(dtt.dtt_ctfp))); 1453*7c478bd9Sstevel@tonic-gate } 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate type = ctf_add_typedef(dmp->dm_ctfp, 1457*7c478bd9Sstevel@tonic-gate CTF_ADD_ROOT, dsp->ds_ident, dtt.dtt_type); 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) { 1460*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "failed to typedef %s: %s\n", 1461*7c478bd9Sstevel@tonic-gate dsp->ds_ident, ctf_errmsg(ctf_errno(dmp->dm_ctfp))); 1462*7c478bd9Sstevel@tonic-gate } 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate dt_dprintf("typedef %s added as id %ld\n", dsp->ds_ident, type); 1465*7c478bd9Sstevel@tonic-gate break; 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate default: { 1468*7c478bd9Sstevel@tonic-gate ctf_encoding_t cte; 1469*7c478bd9Sstevel@tonic-gate dt_idhash_t *dhp; 1470*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 1471*7c478bd9Sstevel@tonic-gate dt_node_t idn; 1472*7c478bd9Sstevel@tonic-gate int assc, idkind; 1473*7c478bd9Sstevel@tonic-gate uint_t id, kind; 1474*7c478bd9Sstevel@tonic-gate ushort_t idflags; 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate switch (class) { 1477*7c478bd9Sstevel@tonic-gate case DT_DC_THIS: 1478*7c478bd9Sstevel@tonic-gate dhp = yypcb->pcb_locals; 1479*7c478bd9Sstevel@tonic-gate idflags = DT_IDFLG_LOCAL; 1480*7c478bd9Sstevel@tonic-gate idp = dt_idhash_lookup(dhp, dsp->ds_ident); 1481*7c478bd9Sstevel@tonic-gate break; 1482*7c478bd9Sstevel@tonic-gate case DT_DC_SELF: 1483*7c478bd9Sstevel@tonic-gate dhp = dtp->dt_tls; 1484*7c478bd9Sstevel@tonic-gate idflags = DT_IDFLG_TLS; 1485*7c478bd9Sstevel@tonic-gate idp = dt_idhash_lookup(dhp, dsp->ds_ident); 1486*7c478bd9Sstevel@tonic-gate break; 1487*7c478bd9Sstevel@tonic-gate default: 1488*7c478bd9Sstevel@tonic-gate dhp = dtp->dt_globals; 1489*7c478bd9Sstevel@tonic-gate idflags = 0; 1490*7c478bd9Sstevel@tonic-gate idp = dt_idstack_lookup( 1491*7c478bd9Sstevel@tonic-gate &yypcb->pcb_globals, dsp->ds_ident); 1492*7c478bd9Sstevel@tonic-gate break; 1493*7c478bd9Sstevel@tonic-gate } 1494*7c478bd9Sstevel@tonic-gate 1495*7c478bd9Sstevel@tonic-gate if (ddp->dd_kind == CTF_K_ARRAY && ddp->dd_node == NULL) { 1496*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_ARRNULL, 1497*7c478bd9Sstevel@tonic-gate "array declaration requires array dimension or " 1498*7c478bd9Sstevel@tonic-gate "tuple signature: %s\n", dsp->ds_ident); 1499*7c478bd9Sstevel@tonic-gate } 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate if (idp != NULL && idp->di_gen == 0) { 1502*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, "built-in identifier " 1503*7c478bd9Sstevel@tonic-gate "redeclared: %s\n", idp->di_name); 1504*7c478bd9Sstevel@tonic-gate } 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate /* 1507*7c478bd9Sstevel@tonic-gate * Cache some attributes of the decl to make the rest of this 1508*7c478bd9Sstevel@tonic-gate * code simpler: if the decl is an array which is subscripted 1509*7c478bd9Sstevel@tonic-gate * by a type rather than an integer, then it's an associative 1510*7c478bd9Sstevel@tonic-gate * array (assc). We then expect to match either DT_IDENT_ARRAY 1511*7c478bd9Sstevel@tonic-gate * for associative arrays or DT_IDENT_SCALAR for anything else. 1512*7c478bd9Sstevel@tonic-gate */ 1513*7c478bd9Sstevel@tonic-gate assc = ddp->dd_kind == CTF_K_ARRAY && 1514*7c478bd9Sstevel@tonic-gate ddp->dd_node->dn_kind == DT_NODE_TYPE; 1515*7c478bd9Sstevel@tonic-gate 1516*7c478bd9Sstevel@tonic-gate idkind = assc ? DT_IDENT_ARRAY : DT_IDENT_SCALAR; 1517*7c478bd9Sstevel@tonic-gate 1518*7c478bd9Sstevel@tonic-gate /* 1519*7c478bd9Sstevel@tonic-gate * Create a fake dt_node_t on the stack so we can determine the 1520*7c478bd9Sstevel@tonic-gate * type of any matching identifier by assigning to this node. 1521*7c478bd9Sstevel@tonic-gate * If the pre-existing ident has its di_type set, propagate 1522*7c478bd9Sstevel@tonic-gate * the type by hand so as not to trigger a prototype check for 1523*7c478bd9Sstevel@tonic-gate * arrays (yet); otherwise we use dt_ident_cook() on the ident 1524*7c478bd9Sstevel@tonic-gate * to ensure it is fully initialized before looking at it. 1525*7c478bd9Sstevel@tonic-gate */ 1526*7c478bd9Sstevel@tonic-gate bzero(&idn, sizeof (dt_node_t)); 1527*7c478bd9Sstevel@tonic-gate 1528*7c478bd9Sstevel@tonic-gate if (idp != NULL && idp->di_type != CTF_ERR) 1529*7c478bd9Sstevel@tonic-gate dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type); 1530*7c478bd9Sstevel@tonic-gate else if (idp != NULL) 1531*7c478bd9Sstevel@tonic-gate (void) dt_ident_cook(&idn, idp, NULL); 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate if (assc) { 1534*7c478bd9Sstevel@tonic-gate if (class == DT_DC_THIS) { 1535*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_LOCASSC, "associative arrays " 1536*7c478bd9Sstevel@tonic-gate "may not be declared as local variables:" 1537*7c478bd9Sstevel@tonic-gate " %s\n", dsp->ds_ident); 1538*7c478bd9Sstevel@tonic-gate } 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate if (dt_decl_type(ddp->dd_next, &dtt) != 0) 1541*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate if (idp != NULL && (idp->di_kind != idkind || 1545*7c478bd9Sstevel@tonic-gate ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type, 1546*7c478bd9Sstevel@tonic-gate idn.dn_ctfp, idn.dn_type) != 0)) { 1547*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, "identifier redeclared: %s\n" 1548*7c478bd9Sstevel@tonic-gate "\t current: %s %s\n\tprevious: %s %s\n", 1549*7c478bd9Sstevel@tonic-gate dsp->ds_ident, dt_idkind_name(idkind), 1550*7c478bd9Sstevel@tonic-gate dt_type_name(dtt.dtt_ctfp, 1551*7c478bd9Sstevel@tonic-gate dtt.dtt_type, n1, sizeof (n1)), 1552*7c478bd9Sstevel@tonic-gate dt_idkind_name(idp->di_kind), 1553*7c478bd9Sstevel@tonic-gate dt_node_type_name(&idn, n2, sizeof (n2))); 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate } else if (idp != NULL && assc) { 1556*7c478bd9Sstevel@tonic-gate const dt_idsig_t *isp = idp->di_data; 1557*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = ddp->dd_node; 1558*7c478bd9Sstevel@tonic-gate int argc = 0; 1559*7c478bd9Sstevel@tonic-gate 1560*7c478bd9Sstevel@tonic-gate for (; dnp != NULL; dnp = dnp->dn_list, argc++) { 1561*7c478bd9Sstevel@tonic-gate const dt_node_t *pnp = &isp->dis_args[argc]; 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate if (argc >= isp->dis_argc) 1564*7c478bd9Sstevel@tonic-gate continue; /* tuple length mismatch */ 1565*7c478bd9Sstevel@tonic-gate 1566*7c478bd9Sstevel@tonic-gate if (ctf_type_cmp(dnp->dn_ctfp, dnp->dn_type, 1567*7c478bd9Sstevel@tonic-gate pnp->dn_ctfp, pnp->dn_type) == 0) 1568*7c478bd9Sstevel@tonic-gate continue; 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, 1571*7c478bd9Sstevel@tonic-gate "identifier redeclared: %s\n" 1572*7c478bd9Sstevel@tonic-gate "\t current: %s, key #%d of type %s\n" 1573*7c478bd9Sstevel@tonic-gate "\tprevious: %s, key #%d of type %s\n", 1574*7c478bd9Sstevel@tonic-gate dsp->ds_ident, 1575*7c478bd9Sstevel@tonic-gate dt_idkind_name(idkind), argc + 1, 1576*7c478bd9Sstevel@tonic-gate dt_node_type_name(dnp, n1, sizeof (n1)), 1577*7c478bd9Sstevel@tonic-gate dt_idkind_name(idp->di_kind), argc + 1, 1578*7c478bd9Sstevel@tonic-gate dt_node_type_name(pnp, n2, sizeof (n2))); 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate if (isp->dis_argc != argc) { 1582*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, 1583*7c478bd9Sstevel@tonic-gate "identifier redeclared: %s\n" 1584*7c478bd9Sstevel@tonic-gate "\t current: %s of %s, tuple length %d\n" 1585*7c478bd9Sstevel@tonic-gate "\tprevious: %s of %s, tuple length %d\n", 1586*7c478bd9Sstevel@tonic-gate dsp->ds_ident, dt_idkind_name(idkind), 1587*7c478bd9Sstevel@tonic-gate dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, 1588*7c478bd9Sstevel@tonic-gate n1, sizeof (n1)), argc, 1589*7c478bd9Sstevel@tonic-gate dt_idkind_name(idp->di_kind), 1590*7c478bd9Sstevel@tonic-gate dt_node_type_name(&idn, n2, sizeof (n2)), 1591*7c478bd9Sstevel@tonic-gate isp->dis_argc); 1592*7c478bd9Sstevel@tonic-gate } 1593*7c478bd9Sstevel@tonic-gate 1594*7c478bd9Sstevel@tonic-gate } else if (idp == NULL) { 1595*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type); 1596*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(dtt.dtt_ctfp, type); 1597*7c478bd9Sstevel@tonic-gate 1598*7c478bd9Sstevel@tonic-gate switch (kind) { 1599*7c478bd9Sstevel@tonic-gate case CTF_K_INTEGER: 1600*7c478bd9Sstevel@tonic-gate if (ctf_type_encoding(dtt.dtt_ctfp, type, 1601*7c478bd9Sstevel@tonic-gate &cte) == 0 && IS_VOID(cte)) { 1602*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_VOIDOBJ, "cannot have " 1603*7c478bd9Sstevel@tonic-gate "void object: %s\n", dsp->ds_ident); 1604*7c478bd9Sstevel@tonic-gate } 1605*7c478bd9Sstevel@tonic-gate break; 1606*7c478bd9Sstevel@tonic-gate case CTF_K_STRUCT: 1607*7c478bd9Sstevel@tonic-gate case CTF_K_UNION: 1608*7c478bd9Sstevel@tonic-gate if (ctf_type_size(dtt.dtt_ctfp, type) != 0) 1609*7c478bd9Sstevel@tonic-gate break; /* proceed to declaring */ 1610*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 1611*7c478bd9Sstevel@tonic-gate case CTF_K_FORWARD: 1612*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_INCOMPLETE, 1613*7c478bd9Sstevel@tonic-gate "incomplete struct/union/enum %s: %s\n", 1614*7c478bd9Sstevel@tonic-gate dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, 1615*7c478bd9Sstevel@tonic-gate n1, sizeof (n1)), dsp->ds_ident); 1616*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1617*7c478bd9Sstevel@tonic-gate } 1618*7c478bd9Sstevel@tonic-gate 1619*7c478bd9Sstevel@tonic-gate if (dt_idhash_nextid(dhp, &id) == -1) { 1620*7c478bd9Sstevel@tonic-gate xyerror(D_ID_OFLOW, "cannot create %s: limit " 1621*7c478bd9Sstevel@tonic-gate "on number of %s variables exceeded\n", 1622*7c478bd9Sstevel@tonic-gate dsp->ds_ident, dt_idhash_name(dhp)); 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate dt_dprintf("declare %s %s variable %s, id=%u\n", 1626*7c478bd9Sstevel@tonic-gate dt_idhash_name(dhp), dt_idkind_name(idkind), 1627*7c478bd9Sstevel@tonic-gate dsp->ds_ident, id); 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate idp = dt_idhash_insert(dhp, dsp->ds_ident, idkind, 1630*7c478bd9Sstevel@tonic-gate idflags | DT_IDFLG_WRITE | DT_IDFLG_DECL, id, 1631*7c478bd9Sstevel@tonic-gate _dtrace_defattr, 0, assc ? &dt_idops_assc : 1632*7c478bd9Sstevel@tonic-gate &dt_idops_thaw, NULL, dtp->dt_gen); 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate if (idp == NULL) 1635*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type); 1638*7c478bd9Sstevel@tonic-gate 1639*7c478bd9Sstevel@tonic-gate /* 1640*7c478bd9Sstevel@tonic-gate * If we are declaring an associative array, use our 1641*7c478bd9Sstevel@tonic-gate * fake parse node to cook the new assoc identifier. 1642*7c478bd9Sstevel@tonic-gate * This will force the ident code to instantiate the 1643*7c478bd9Sstevel@tonic-gate * array type signature corresponding to the list of 1644*7c478bd9Sstevel@tonic-gate * types pointed to by ddp->dd_node. We also reset 1645*7c478bd9Sstevel@tonic-gate * the identifier's attributes based upon the result. 1646*7c478bd9Sstevel@tonic-gate */ 1647*7c478bd9Sstevel@tonic-gate if (assc) { 1648*7c478bd9Sstevel@tonic-gate idp->di_attr = 1649*7c478bd9Sstevel@tonic-gate dt_ident_cook(&idn, idp, &ddp->dd_node); 1650*7c478bd9Sstevel@tonic-gate } 1651*7c478bd9Sstevel@tonic-gate } 1652*7c478bd9Sstevel@tonic-gate } 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate } /* end of switch */ 1655*7c478bd9Sstevel@tonic-gate 1656*7c478bd9Sstevel@tonic-gate free(dsp->ds_ident); 1657*7c478bd9Sstevel@tonic-gate dsp->ds_ident = NULL; 1658*7c478bd9Sstevel@tonic-gate 1659*7c478bd9Sstevel@tonic-gate return (NULL); 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate 1662*7c478bd9Sstevel@tonic-gate dt_node_t * 1663*7c478bd9Sstevel@tonic-gate dt_node_func(dt_node_t *dnp, dt_node_t *args) 1664*7c478bd9Sstevel@tonic-gate { 1665*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate if (dnp->dn_kind != DT_NODE_IDENT) { 1668*7c478bd9Sstevel@tonic-gate xyerror(D_FUNC_IDENT, 1669*7c478bd9Sstevel@tonic-gate "function designator is not of function type\n"); 1670*7c478bd9Sstevel@tonic-gate } 1671*7c478bd9Sstevel@tonic-gate 1672*7c478bd9Sstevel@tonic-gate idp = dt_idstack_lookup(&yypcb->pcb_globals, dnp->dn_string); 1673*7c478bd9Sstevel@tonic-gate 1674*7c478bd9Sstevel@tonic-gate if (idp == NULL) { 1675*7c478bd9Sstevel@tonic-gate xyerror(D_FUNC_UNDEF, 1676*7c478bd9Sstevel@tonic-gate "undefined function name: %s\n", dnp->dn_string); 1677*7c478bd9Sstevel@tonic-gate } 1678*7c478bd9Sstevel@tonic-gate 1679*7c478bd9Sstevel@tonic-gate if (idp->di_kind != DT_IDENT_FUNC && 1680*7c478bd9Sstevel@tonic-gate idp->di_kind != DT_IDENT_AGGFUNC && 1681*7c478bd9Sstevel@tonic-gate idp->di_kind != DT_IDENT_ACTFUNC) { 1682*7c478bd9Sstevel@tonic-gate xyerror(D_FUNC_IDKIND, "%s '%s' may not be referenced as a " 1683*7c478bd9Sstevel@tonic-gate "function\n", dt_idkind_name(idp->di_kind), idp->di_name); 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate free(dnp->dn_string); 1687*7c478bd9Sstevel@tonic-gate dnp->dn_string = NULL; 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate dnp->dn_kind = DT_NODE_FUNC; 1690*7c478bd9Sstevel@tonic-gate dnp->dn_flags &= ~DT_NF_COOKED; 1691*7c478bd9Sstevel@tonic-gate dnp->dn_ident = idp; 1692*7c478bd9Sstevel@tonic-gate dnp->dn_args = args; 1693*7c478bd9Sstevel@tonic-gate dnp->dn_list = NULL; 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate return (dnp); 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate /* 1699*7c478bd9Sstevel@tonic-gate * The offsetof() function is special because it takes a type name as an 1700*7c478bd9Sstevel@tonic-gate * argument. It does not actually construct its own node; after looking up the 1701*7c478bd9Sstevel@tonic-gate * structure or union offset, we just return an integer node with the offset. 1702*7c478bd9Sstevel@tonic-gate */ 1703*7c478bd9Sstevel@tonic-gate dt_node_t * 1704*7c478bd9Sstevel@tonic-gate dt_node_offsetof(dt_decl_t *ddp, char *s) 1705*7c478bd9Sstevel@tonic-gate { 1706*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 1707*7c478bd9Sstevel@tonic-gate dt_node_t dn; 1708*7c478bd9Sstevel@tonic-gate char *name; 1709*7c478bd9Sstevel@tonic-gate int err; 1710*7c478bd9Sstevel@tonic-gate 1711*7c478bd9Sstevel@tonic-gate ctf_membinfo_t ctm; 1712*7c478bd9Sstevel@tonic-gate ctf_id_t type; 1713*7c478bd9Sstevel@tonic-gate uint_t kind; 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate name = alloca(strlen(s) + 1); 1716*7c478bd9Sstevel@tonic-gate (void) strcpy(name, s); 1717*7c478bd9Sstevel@tonic-gate free(s); 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate err = dt_decl_type(ddp, &dtt); 1720*7c478bd9Sstevel@tonic-gate dt_decl_free(ddp); 1721*7c478bd9Sstevel@tonic-gate 1722*7c478bd9Sstevel@tonic-gate if (err != 0) 1723*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type); 1726*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(dtt.dtt_ctfp, type); 1727*7c478bd9Sstevel@tonic-gate 1728*7c478bd9Sstevel@tonic-gate if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) { 1729*7c478bd9Sstevel@tonic-gate xyerror(D_OFFSETOF_TYPE, 1730*7c478bd9Sstevel@tonic-gate "offsetof operand must be a struct or union type\n"); 1731*7c478bd9Sstevel@tonic-gate } 1732*7c478bd9Sstevel@tonic-gate 1733*7c478bd9Sstevel@tonic-gate if (ctf_member_info(dtt.dtt_ctfp, type, name, &ctm) == CTF_ERR) { 1734*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "failed to determine offset of %s: %s\n", 1735*7c478bd9Sstevel@tonic-gate name, ctf_errmsg(ctf_errno(dtt.dtt_ctfp))); 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate bzero(&dn, sizeof (dn)); 1739*7c478bd9Sstevel@tonic-gate dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type); 1740*7c478bd9Sstevel@tonic-gate 1741*7c478bd9Sstevel@tonic-gate if (dn.dn_flags & DT_NF_BITFIELD) { 1742*7c478bd9Sstevel@tonic-gate xyerror(D_OFFSETOF_BITFIELD, 1743*7c478bd9Sstevel@tonic-gate "cannot take offset of a bit-field: %s\n", name); 1744*7c478bd9Sstevel@tonic-gate } 1745*7c478bd9Sstevel@tonic-gate 1746*7c478bd9Sstevel@tonic-gate return (dt_node_int(ctm.ctm_offset / NBBY)); 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate dt_node_t * 1750*7c478bd9Sstevel@tonic-gate dt_node_op1(int op, dt_node_t *cp) 1751*7c478bd9Sstevel@tonic-gate { 1752*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 1753*7c478bd9Sstevel@tonic-gate 1754*7c478bd9Sstevel@tonic-gate if (cp->dn_kind == DT_NODE_INT) { 1755*7c478bd9Sstevel@tonic-gate switch (op) { 1756*7c478bd9Sstevel@tonic-gate case DT_TOK_INEG: 1757*7c478bd9Sstevel@tonic-gate /* 1758*7c478bd9Sstevel@tonic-gate * If we're negating an unsigned integer, zero out any 1759*7c478bd9Sstevel@tonic-gate * extra top bits to truncate the value to the size of 1760*7c478bd9Sstevel@tonic-gate * the effective type determined by dt_node_int(). 1761*7c478bd9Sstevel@tonic-gate */ 1762*7c478bd9Sstevel@tonic-gate cp->dn_value = -cp->dn_value; 1763*7c478bd9Sstevel@tonic-gate if (!(cp->dn_flags & DT_NF_SIGNED)) { 1764*7c478bd9Sstevel@tonic-gate cp->dn_value &= ~0ULL >> 1765*7c478bd9Sstevel@tonic-gate (64 - dt_node_type_size(cp) * NBBY); 1766*7c478bd9Sstevel@tonic-gate } 1767*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 1768*7c478bd9Sstevel@tonic-gate case DT_TOK_IPOS: 1769*7c478bd9Sstevel@tonic-gate return (cp); 1770*7c478bd9Sstevel@tonic-gate case DT_TOK_BNEG: 1771*7c478bd9Sstevel@tonic-gate cp->dn_value = ~cp->dn_value; 1772*7c478bd9Sstevel@tonic-gate return (cp); 1773*7c478bd9Sstevel@tonic-gate case DT_TOK_LNEG: 1774*7c478bd9Sstevel@tonic-gate cp->dn_value = !cp->dn_value; 1775*7c478bd9Sstevel@tonic-gate return (cp); 1776*7c478bd9Sstevel@tonic-gate } 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate 1779*7c478bd9Sstevel@tonic-gate /* 1780*7c478bd9Sstevel@tonic-gate * If sizeof is applied to a type_name or string constant, we can 1781*7c478bd9Sstevel@tonic-gate * transform 'cp' into an integer constant in the node construction 1782*7c478bd9Sstevel@tonic-gate * pass so that it can then be used for arithmetic in this pass. 1783*7c478bd9Sstevel@tonic-gate */ 1784*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_SIZEOF && 1785*7c478bd9Sstevel@tonic-gate (cp->dn_kind == DT_NODE_STRING || cp->dn_kind == DT_NODE_TYPE)) { 1786*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1787*7c478bd9Sstevel@tonic-gate size_t size = dt_node_type_size(cp); 1788*7c478bd9Sstevel@tonic-gate 1789*7c478bd9Sstevel@tonic-gate if (size == 0) { 1790*7c478bd9Sstevel@tonic-gate xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an " 1791*7c478bd9Sstevel@tonic-gate "operand of unknown size\n"); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp, 1795*7c478bd9Sstevel@tonic-gate ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t")); 1796*7c478bd9Sstevel@tonic-gate 1797*7c478bd9Sstevel@tonic-gate cp->dn_kind = DT_NODE_INT; 1798*7c478bd9Sstevel@tonic-gate cp->dn_op = DT_TOK_INT; 1799*7c478bd9Sstevel@tonic-gate cp->dn_value = size; 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate return (cp); 1802*7c478bd9Sstevel@tonic-gate } 1803*7c478bd9Sstevel@tonic-gate 1804*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_OP1); 1805*7c478bd9Sstevel@tonic-gate assert(op <= USHRT_MAX); 1806*7c478bd9Sstevel@tonic-gate dnp->dn_op = (ushort_t)op; 1807*7c478bd9Sstevel@tonic-gate dnp->dn_child = cp; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate return (dnp); 1810*7c478bd9Sstevel@tonic-gate } 1811*7c478bd9Sstevel@tonic-gate 1812*7c478bd9Sstevel@tonic-gate dt_node_t * 1813*7c478bd9Sstevel@tonic-gate dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp) 1814*7c478bd9Sstevel@tonic-gate { 1815*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 1816*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 1817*7c478bd9Sstevel@tonic-gate 1818*7c478bd9Sstevel@tonic-gate /* 1819*7c478bd9Sstevel@tonic-gate * First we check for operations that are illegal -- namely those that 1820*7c478bd9Sstevel@tonic-gate * might result in integer division by zero, and abort if one is found. 1821*7c478bd9Sstevel@tonic-gate */ 1822*7c478bd9Sstevel@tonic-gate if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0 && 1823*7c478bd9Sstevel@tonic-gate (op == DT_TOK_MOD || op == DT_TOK_DIV || 1824*7c478bd9Sstevel@tonic-gate op == DT_TOK_MOD_EQ || op == DT_TOK_DIV_EQ)) 1825*7c478bd9Sstevel@tonic-gate xyerror(D_DIV_ZERO, "expression contains division by zero\n"); 1826*7c478bd9Sstevel@tonic-gate 1827*7c478bd9Sstevel@tonic-gate /* 1828*7c478bd9Sstevel@tonic-gate * If both children are immediate values, we can just perform inline 1829*7c478bd9Sstevel@tonic-gate * calculation and return a new immediate node with the result. 1830*7c478bd9Sstevel@tonic-gate */ 1831*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_INT && rp->dn_kind == DT_NODE_INT) { 1832*7c478bd9Sstevel@tonic-gate uintmax_t l = lp->dn_value; 1833*7c478bd9Sstevel@tonic-gate uintmax_t r = rp->dn_value; 1834*7c478bd9Sstevel@tonic-gate 1835*7c478bd9Sstevel@tonic-gate dnp = dt_node_int(0); /* allocate new integer node for result */ 1836*7c478bd9Sstevel@tonic-gate 1837*7c478bd9Sstevel@tonic-gate switch (op) { 1838*7c478bd9Sstevel@tonic-gate case DT_TOK_LOR: 1839*7c478bd9Sstevel@tonic-gate dnp->dn_value = l || r; 1840*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1841*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1842*7c478bd9Sstevel@tonic-gate break; 1843*7c478bd9Sstevel@tonic-gate case DT_TOK_LXOR: 1844*7c478bd9Sstevel@tonic-gate dnp->dn_value = (l != 0) ^ (r != 0); 1845*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1846*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1847*7c478bd9Sstevel@tonic-gate break; 1848*7c478bd9Sstevel@tonic-gate case DT_TOK_LAND: 1849*7c478bd9Sstevel@tonic-gate dnp->dn_value = l && r; 1850*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1851*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1852*7c478bd9Sstevel@tonic-gate break; 1853*7c478bd9Sstevel@tonic-gate case DT_TOK_BOR: 1854*7c478bd9Sstevel@tonic-gate dnp->dn_value = l | r; 1855*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1856*7c478bd9Sstevel@tonic-gate break; 1857*7c478bd9Sstevel@tonic-gate case DT_TOK_XOR: 1858*7c478bd9Sstevel@tonic-gate dnp->dn_value = l ^ r; 1859*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1860*7c478bd9Sstevel@tonic-gate break; 1861*7c478bd9Sstevel@tonic-gate case DT_TOK_BAND: 1862*7c478bd9Sstevel@tonic-gate dnp->dn_value = l & r; 1863*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1864*7c478bd9Sstevel@tonic-gate break; 1865*7c478bd9Sstevel@tonic-gate case DT_TOK_EQU: 1866*7c478bd9Sstevel@tonic-gate dnp->dn_value = l == r; 1867*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1868*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1869*7c478bd9Sstevel@tonic-gate break; 1870*7c478bd9Sstevel@tonic-gate case DT_TOK_NEQ: 1871*7c478bd9Sstevel@tonic-gate dnp->dn_value = l != r; 1872*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1873*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1874*7c478bd9Sstevel@tonic-gate break; 1875*7c478bd9Sstevel@tonic-gate case DT_TOK_LT: 1876*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1877*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1878*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l < (intmax_t)r; 1879*7c478bd9Sstevel@tonic-gate else 1880*7c478bd9Sstevel@tonic-gate dnp->dn_value = l < r; 1881*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1882*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1883*7c478bd9Sstevel@tonic-gate break; 1884*7c478bd9Sstevel@tonic-gate case DT_TOK_LE: 1885*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1886*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1887*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l <= (intmax_t)r; 1888*7c478bd9Sstevel@tonic-gate else 1889*7c478bd9Sstevel@tonic-gate dnp->dn_value = l <= r; 1890*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1891*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1892*7c478bd9Sstevel@tonic-gate break; 1893*7c478bd9Sstevel@tonic-gate case DT_TOK_GT: 1894*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1895*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1896*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l > (intmax_t)r; 1897*7c478bd9Sstevel@tonic-gate else 1898*7c478bd9Sstevel@tonic-gate dnp->dn_value = l > r; 1899*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1900*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1901*7c478bd9Sstevel@tonic-gate break; 1902*7c478bd9Sstevel@tonic-gate case DT_TOK_GE: 1903*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1904*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1905*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l >= (intmax_t)r; 1906*7c478bd9Sstevel@tonic-gate else 1907*7c478bd9Sstevel@tonic-gate dnp->dn_value = l >= r; 1908*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 1909*7c478bd9Sstevel@tonic-gate DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 1910*7c478bd9Sstevel@tonic-gate break; 1911*7c478bd9Sstevel@tonic-gate case DT_TOK_LSH: 1912*7c478bd9Sstevel@tonic-gate dnp->dn_value = l << r; 1913*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, dnp); 1914*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(rp, 1915*7c478bd9Sstevel@tonic-gate dt_attr_min(lp->dn_attr, rp->dn_attr)); 1916*7c478bd9Sstevel@tonic-gate break; 1917*7c478bd9Sstevel@tonic-gate case DT_TOK_RSH: 1918*7c478bd9Sstevel@tonic-gate dnp->dn_value = l >> r; 1919*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, dnp); 1920*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(rp, 1921*7c478bd9Sstevel@tonic-gate dt_attr_min(lp->dn_attr, rp->dn_attr)); 1922*7c478bd9Sstevel@tonic-gate break; 1923*7c478bd9Sstevel@tonic-gate case DT_TOK_ADD: 1924*7c478bd9Sstevel@tonic-gate dnp->dn_value = l + r; 1925*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1926*7c478bd9Sstevel@tonic-gate break; 1927*7c478bd9Sstevel@tonic-gate case DT_TOK_SUB: 1928*7c478bd9Sstevel@tonic-gate dnp->dn_value = l - r; 1929*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1930*7c478bd9Sstevel@tonic-gate break; 1931*7c478bd9Sstevel@tonic-gate case DT_TOK_MUL: 1932*7c478bd9Sstevel@tonic-gate dnp->dn_value = l * r; 1933*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1934*7c478bd9Sstevel@tonic-gate break; 1935*7c478bd9Sstevel@tonic-gate case DT_TOK_DIV: 1936*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1937*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1938*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l / (intmax_t)r; 1939*7c478bd9Sstevel@tonic-gate else 1940*7c478bd9Sstevel@tonic-gate dnp->dn_value = l / r; 1941*7c478bd9Sstevel@tonic-gate break; 1942*7c478bd9Sstevel@tonic-gate case DT_TOK_MOD: 1943*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); 1944*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 1945*7c478bd9Sstevel@tonic-gate dnp->dn_value = (intmax_t)l % (intmax_t)r; 1946*7c478bd9Sstevel@tonic-gate else 1947*7c478bd9Sstevel@tonic-gate dnp->dn_value = l % r; 1948*7c478bd9Sstevel@tonic-gate break; 1949*7c478bd9Sstevel@tonic-gate default: 1950*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 1951*7c478bd9Sstevel@tonic-gate dnp = NULL; 1952*7c478bd9Sstevel@tonic-gate } 1953*7c478bd9Sstevel@tonic-gate 1954*7c478bd9Sstevel@tonic-gate if (dnp != NULL) { 1955*7c478bd9Sstevel@tonic-gate dt_node_free(lp); 1956*7c478bd9Sstevel@tonic-gate dt_node_free(rp); 1957*7c478bd9Sstevel@tonic-gate return (dnp); 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate } 1960*7c478bd9Sstevel@tonic-gate 1961*7c478bd9Sstevel@tonic-gate /* 1962*7c478bd9Sstevel@tonic-gate * If an integer constant is being cast to another integer type, we can 1963*7c478bd9Sstevel@tonic-gate * perform the cast as part of integer constant folding in this pass. 1964*7c478bd9Sstevel@tonic-gate * We must take action when the integer is being cast to a smaller type 1965*7c478bd9Sstevel@tonic-gate * or if it is changing signed-ness. If so, we first shift rp's bits 1966*7c478bd9Sstevel@tonic-gate * bits high (losing excess bits if narrowing) and then shift them down 1967*7c478bd9Sstevel@tonic-gate * with either a logical shift (unsigned) or arithmetic shift (signed). 1968*7c478bd9Sstevel@tonic-gate */ 1969*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT && 1970*7c478bd9Sstevel@tonic-gate dt_node_is_integer(lp)) { 1971*7c478bd9Sstevel@tonic-gate size_t srcsize = dt_node_type_size(rp); 1972*7c478bd9Sstevel@tonic-gate size_t dstsize = dt_node_type_size(lp); 1973*7c478bd9Sstevel@tonic-gate 1974*7c478bd9Sstevel@tonic-gate if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^ 1975*7c478bd9Sstevel@tonic-gate (rp->dn_flags & DT_NF_SIGNED))) { 1976*7c478bd9Sstevel@tonic-gate int n = dstsize < srcsize ? 1977*7c478bd9Sstevel@tonic-gate (sizeof (uint64_t) * NBBY - dstsize * NBBY) : 1978*7c478bd9Sstevel@tonic-gate (sizeof (uint64_t) * NBBY - srcsize * NBBY); 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate rp->dn_value <<= n; 1981*7c478bd9Sstevel@tonic-gate if (lp->dn_flags & DT_NF_SIGNED) 1982*7c478bd9Sstevel@tonic-gate rp->dn_value = (intmax_t)rp->dn_value >> n; 1983*7c478bd9Sstevel@tonic-gate else 1984*7c478bd9Sstevel@tonic-gate rp->dn_value = rp->dn_value >> n; 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, rp); 1988*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 1989*7c478bd9Sstevel@tonic-gate dt_node_free(lp); 1990*7c478bd9Sstevel@tonic-gate 1991*7c478bd9Sstevel@tonic-gate return (rp); 1992*7c478bd9Sstevel@tonic-gate } 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate /* 1995*7c478bd9Sstevel@tonic-gate * If no immediate optimizations are available, create an new OP2 node 1996*7c478bd9Sstevel@tonic-gate * and glue the left and right children into place and return. 1997*7c478bd9Sstevel@tonic-gate */ 1998*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_OP2); 1999*7c478bd9Sstevel@tonic-gate assert(op <= USHRT_MAX); 2000*7c478bd9Sstevel@tonic-gate dnp->dn_op = (ushort_t)op; 2001*7c478bd9Sstevel@tonic-gate dnp->dn_left = lp; 2002*7c478bd9Sstevel@tonic-gate dnp->dn_right = rp; 2003*7c478bd9Sstevel@tonic-gate 2004*7c478bd9Sstevel@tonic-gate return (dnp); 2005*7c478bd9Sstevel@tonic-gate } 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate dt_node_t * 2008*7c478bd9Sstevel@tonic-gate dt_node_op3(dt_node_t *expr, dt_node_t *lp, dt_node_t *rp) 2009*7c478bd9Sstevel@tonic-gate { 2010*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate if (expr->dn_kind == DT_NODE_INT) 2013*7c478bd9Sstevel@tonic-gate return (expr->dn_value != 0 ? lp : rp); 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_OP3); 2016*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_QUESTION; 2017*7c478bd9Sstevel@tonic-gate dnp->dn_expr = expr; 2018*7c478bd9Sstevel@tonic-gate dnp->dn_left = lp; 2019*7c478bd9Sstevel@tonic-gate dnp->dn_right = rp; 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate return (dnp); 2022*7c478bd9Sstevel@tonic-gate } 2023*7c478bd9Sstevel@tonic-gate 2024*7c478bd9Sstevel@tonic-gate dt_node_t * 2025*7c478bd9Sstevel@tonic-gate dt_node_statement(dt_node_t *expr) 2026*7c478bd9Sstevel@tonic-gate { 2027*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2028*7c478bd9Sstevel@tonic-gate 2029*7c478bd9Sstevel@tonic-gate if (expr->dn_kind == DT_NODE_AGG) 2030*7c478bd9Sstevel@tonic-gate return (expr); 2031*7c478bd9Sstevel@tonic-gate 2032*7c478bd9Sstevel@tonic-gate if (expr->dn_kind == DT_NODE_FUNC && 2033*7c478bd9Sstevel@tonic-gate expr->dn_ident->di_kind == DT_IDENT_ACTFUNC) 2034*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_DFUNC); 2035*7c478bd9Sstevel@tonic-gate else 2036*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_DEXPR); 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate dnp->dn_expr = expr; 2039*7c478bd9Sstevel@tonic-gate return (dnp); 2040*7c478bd9Sstevel@tonic-gate } 2041*7c478bd9Sstevel@tonic-gate 2042*7c478bd9Sstevel@tonic-gate dt_node_t * 2043*7c478bd9Sstevel@tonic-gate dt_node_pdesc_by_name(char *spec) 2044*7c478bd9Sstevel@tonic-gate { 2045*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2046*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2047*7c478bd9Sstevel@tonic-gate 2048*7c478bd9Sstevel@tonic-gate if (spec == NULL) 2049*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2050*7c478bd9Sstevel@tonic-gate 2051*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_PDESC); 2052*7c478bd9Sstevel@tonic-gate dnp->dn_spec = spec; 2053*7c478bd9Sstevel@tonic-gate dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t)); 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate if (dnp->dn_desc == NULL) 2056*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate if (dtrace_xstr2desc(dtp, yypcb->pcb_pspec, dnp->dn_spec, 2059*7c478bd9Sstevel@tonic-gate yypcb->pcb_sargc, yypcb->pcb_sargv, dnp->dn_desc) != 0) { 2060*7c478bd9Sstevel@tonic-gate xyerror(D_PDESC_INVAL, "invalid probe description \"%s\": %s\n", 2061*7c478bd9Sstevel@tonic-gate dnp->dn_spec, dtrace_errmsg(dtp, dtrace_errno(dtp))); 2062*7c478bd9Sstevel@tonic-gate } 2063*7c478bd9Sstevel@tonic-gate 2064*7c478bd9Sstevel@tonic-gate free(dnp->dn_spec); 2065*7c478bd9Sstevel@tonic-gate dnp->dn_spec = NULL; 2066*7c478bd9Sstevel@tonic-gate 2067*7c478bd9Sstevel@tonic-gate return (dnp); 2068*7c478bd9Sstevel@tonic-gate } 2069*7c478bd9Sstevel@tonic-gate 2070*7c478bd9Sstevel@tonic-gate dt_node_t * 2071*7c478bd9Sstevel@tonic-gate dt_node_pdesc_by_id(uintmax_t id) 2072*7c478bd9Sstevel@tonic-gate { 2073*7c478bd9Sstevel@tonic-gate static const char *const names[] = { 2074*7c478bd9Sstevel@tonic-gate "providers", "modules", "functions" 2075*7c478bd9Sstevel@tonic-gate }; 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2078*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_PDESC); 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate if ((dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t))) == NULL) 2081*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate if (id > UINT_MAX) { 2084*7c478bd9Sstevel@tonic-gate xyerror(D_PDESC_INVAL, "identifier %llu exceeds maximum " 2085*7c478bd9Sstevel@tonic-gate "probe id\n", (u_longlong_t)id); 2086*7c478bd9Sstevel@tonic-gate } 2087*7c478bd9Sstevel@tonic-gate 2088*7c478bd9Sstevel@tonic-gate if (yypcb->pcb_pspec != DTRACE_PROBESPEC_NAME) { 2089*7c478bd9Sstevel@tonic-gate xyerror(D_PDESC_INVAL, "probe identifier %llu not permitted " 2090*7c478bd9Sstevel@tonic-gate "when specifying %s\n", (u_longlong_t)id, 2091*7c478bd9Sstevel@tonic-gate names[yypcb->pcb_pspec]); 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate if (dtrace_id2desc(dtp, (dtrace_id_t)id, dnp->dn_desc) != 0) { 2095*7c478bd9Sstevel@tonic-gate xyerror(D_PDESC_INVAL, "invalid probe identifier %llu: %s\n", 2096*7c478bd9Sstevel@tonic-gate (u_longlong_t)id, dtrace_errmsg(dtp, dtrace_errno(dtp))); 2097*7c478bd9Sstevel@tonic-gate } 2098*7c478bd9Sstevel@tonic-gate 2099*7c478bd9Sstevel@tonic-gate return (dnp); 2100*7c478bd9Sstevel@tonic-gate } 2101*7c478bd9Sstevel@tonic-gate 2102*7c478bd9Sstevel@tonic-gate dt_node_t * 2103*7c478bd9Sstevel@tonic-gate dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts) 2104*7c478bd9Sstevel@tonic-gate { 2105*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_CLAUSE); 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate dnp->dn_pdescs = pdescs; 2108*7c478bd9Sstevel@tonic-gate dnp->dn_pred = pred; 2109*7c478bd9Sstevel@tonic-gate dnp->dn_acts = acts; 2110*7c478bd9Sstevel@tonic-gate 2111*7c478bd9Sstevel@tonic-gate yybegin(YYS_CLAUSE); 2112*7c478bd9Sstevel@tonic-gate return (dnp); 2113*7c478bd9Sstevel@tonic-gate } 2114*7c478bd9Sstevel@tonic-gate 2115*7c478bd9Sstevel@tonic-gate dt_node_t * 2116*7c478bd9Sstevel@tonic-gate dt_node_inline(dt_node_t *expr) 2117*7c478bd9Sstevel@tonic-gate { 2118*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2119*7c478bd9Sstevel@tonic-gate dt_scope_t *dsp = &yypcb->pcb_dstack; 2120*7c478bd9Sstevel@tonic-gate dt_decl_t *ddp = dt_decl_top(); 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate char n[DT_TYPE_NAMELEN]; 2123*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 2124*7c478bd9Sstevel@tonic-gate 2125*7c478bd9Sstevel@tonic-gate dt_ident_t *idp, *rdp; 2126*7c478bd9Sstevel@tonic-gate dt_idnode_t *inp; 2127*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2128*7c478bd9Sstevel@tonic-gate 2129*7c478bd9Sstevel@tonic-gate if (dt_decl_type(ddp, &dtt) != 0) 2130*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 2131*7c478bd9Sstevel@tonic-gate 2132*7c478bd9Sstevel@tonic-gate if (dsp->ds_class != DT_DC_DEFAULT) { 2133*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_BADCLASS, "specified storage class not " 2134*7c478bd9Sstevel@tonic-gate "appropriate for inline declaration\n"); 2135*7c478bd9Sstevel@tonic-gate } 2136*7c478bd9Sstevel@tonic-gate 2137*7c478bd9Sstevel@tonic-gate if (dsp->ds_ident == NULL) 2138*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_USELESS, "inline declaration requires a name\n"); 2139*7c478bd9Sstevel@tonic-gate 2140*7c478bd9Sstevel@tonic-gate if ((idp = dt_idstack_lookup( 2141*7c478bd9Sstevel@tonic-gate &yypcb->pcb_globals, dsp->ds_ident)) != NULL) { 2142*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_IDRED, "identifier redefined: %s\n\t current: " 2143*7c478bd9Sstevel@tonic-gate "inline definition\n\tprevious: %s %s\n", 2144*7c478bd9Sstevel@tonic-gate idp->di_name, dt_idkind_name(idp->di_kind), 2145*7c478bd9Sstevel@tonic-gate (idp->di_flags & DT_IDFLG_INLINE) ? "inline" : ""); 2146*7c478bd9Sstevel@tonic-gate } 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate /* 2149*7c478bd9Sstevel@tonic-gate * If we are declaring an inlined array, verify that we have a tuple 2150*7c478bd9Sstevel@tonic-gate * signature, and then recompute 'dtt' as the array's value type. 2151*7c478bd9Sstevel@tonic-gate */ 2152*7c478bd9Sstevel@tonic-gate if (ddp->dd_kind == CTF_K_ARRAY) { 2153*7c478bd9Sstevel@tonic-gate if (ddp->dd_node == NULL) { 2154*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_ARRNULL, "inline declaration requires " 2155*7c478bd9Sstevel@tonic-gate "array tuple signature: %s\n", dsp->ds_ident); 2156*7c478bd9Sstevel@tonic-gate } 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate if (ddp->dd_node->dn_kind != DT_NODE_TYPE) { 2159*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_ARRNULL, "inline declaration cannot be " 2160*7c478bd9Sstevel@tonic-gate "of scalar array type: %s\n", dsp->ds_ident); 2161*7c478bd9Sstevel@tonic-gate } 2162*7c478bd9Sstevel@tonic-gate 2163*7c478bd9Sstevel@tonic-gate if (dt_decl_type(ddp->dd_next, &dtt) != 0) 2164*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 2165*7c478bd9Sstevel@tonic-gate } 2166*7c478bd9Sstevel@tonic-gate 2167*7c478bd9Sstevel@tonic-gate /* 2168*7c478bd9Sstevel@tonic-gate * If the inline identifier is not defined, then create it with the 2169*7c478bd9Sstevel@tonic-gate * orphan flag set. We do not insert the identifier into dt_globals 2170*7c478bd9Sstevel@tonic-gate * until we have successfully cooked the right-hand expression, below. 2171*7c478bd9Sstevel@tonic-gate */ 2172*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_INLINE); 2173*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); 2174*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, _dtrace_defattr); 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate if (dt_node_is_void(dnp)) { 2177*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_VOIDOBJ, 2178*7c478bd9Sstevel@tonic-gate "cannot declare void inline: %s\n", dsp->ds_ident); 2179*7c478bd9Sstevel@tonic-gate } 2180*7c478bd9Sstevel@tonic-gate 2181*7c478bd9Sstevel@tonic-gate if (ctf_type_kind(dnp->dn_ctfp, ctf_type_resolve( 2182*7c478bd9Sstevel@tonic-gate dnp->dn_ctfp, dnp->dn_type)) == CTF_K_FORWARD) { 2183*7c478bd9Sstevel@tonic-gate xyerror(D_DECL_INCOMPLETE, 2184*7c478bd9Sstevel@tonic-gate "incomplete struct/union/enum %s: %s\n", 2185*7c478bd9Sstevel@tonic-gate dt_node_type_name(dnp, n, sizeof (n)), dsp->ds_ident); 2186*7c478bd9Sstevel@tonic-gate } 2187*7c478bd9Sstevel@tonic-gate 2188*7c478bd9Sstevel@tonic-gate if ((inp = malloc(sizeof (dt_idnode_t))) == NULL) 2189*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2190*7c478bd9Sstevel@tonic-gate 2191*7c478bd9Sstevel@tonic-gate bzero(inp, sizeof (dt_idnode_t)); 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate idp = dnp->dn_ident = dt_ident_create(dsp->ds_ident, 2194*7c478bd9Sstevel@tonic-gate ddp->dd_kind == CTF_K_ARRAY ? DT_IDENT_ARRAY : DT_IDENT_SCALAR, 2195*7c478bd9Sstevel@tonic-gate DT_IDFLG_INLINE | DT_IDFLG_REF | DT_IDFLG_DECL | DT_IDFLG_ORPHAN, 0, 2196*7c478bd9Sstevel@tonic-gate _dtrace_defattr, 0, &dt_idops_inline, inp, dtp->dt_gen); 2197*7c478bd9Sstevel@tonic-gate 2198*7c478bd9Sstevel@tonic-gate if (idp == NULL) { 2199*7c478bd9Sstevel@tonic-gate free(inp); 2200*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2201*7c478bd9Sstevel@tonic-gate } 2202*7c478bd9Sstevel@tonic-gate 2203*7c478bd9Sstevel@tonic-gate /* 2204*7c478bd9Sstevel@tonic-gate * If we're inlining an associative array, create a private identifier 2205*7c478bd9Sstevel@tonic-gate * hash containing the named parameters and store it in inp->din_hash. 2206*7c478bd9Sstevel@tonic-gate * We then push this hash on to the top of the pcb_globals stack. 2207*7c478bd9Sstevel@tonic-gate */ 2208*7c478bd9Sstevel@tonic-gate if (ddp->dd_kind == CTF_K_ARRAY) { 2209*7c478bd9Sstevel@tonic-gate dt_idnode_t *pinp; 2210*7c478bd9Sstevel@tonic-gate dt_ident_t *pidp; 2211*7c478bd9Sstevel@tonic-gate dt_node_t *pnp; 2212*7c478bd9Sstevel@tonic-gate uint_t i = 0; 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate for (pnp = ddp->dd_node; pnp != NULL; pnp = pnp->dn_list) 2215*7c478bd9Sstevel@tonic-gate i++; /* count up parameters for din_argv[] */ 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate inp->din_hash = dt_idhash_create("inline args", NULL, 0, 0); 2218*7c478bd9Sstevel@tonic-gate inp->din_argv = calloc(i, sizeof (dt_ident_t *)); 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate if (inp->din_hash == NULL || inp->din_argv == NULL) 2221*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2222*7c478bd9Sstevel@tonic-gate 2223*7c478bd9Sstevel@tonic-gate /* 2224*7c478bd9Sstevel@tonic-gate * Create an identifier for each parameter as a scalar inline, 2225*7c478bd9Sstevel@tonic-gate * and store it in din_hash and in position in din_argv[]. The 2226*7c478bd9Sstevel@tonic-gate * parameter identifiers also use dt_idops_inline, but we leave 2227*7c478bd9Sstevel@tonic-gate * the dt_idnode_t argument 'pinp' zeroed. This will be filled 2228*7c478bd9Sstevel@tonic-gate * in by the code generation pass with references to the args. 2229*7c478bd9Sstevel@tonic-gate */ 2230*7c478bd9Sstevel@tonic-gate for (i = 0, pnp = ddp->dd_node; 2231*7c478bd9Sstevel@tonic-gate pnp != NULL; pnp = pnp->dn_list, i++) { 2232*7c478bd9Sstevel@tonic-gate 2233*7c478bd9Sstevel@tonic-gate if (pnp->dn_string == NULL) 2234*7c478bd9Sstevel@tonic-gate continue; /* ignore anonymous parameters */ 2235*7c478bd9Sstevel@tonic-gate 2236*7c478bd9Sstevel@tonic-gate if ((pinp = malloc(sizeof (dt_idnode_t))) == NULL) 2237*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate pidp = dt_idhash_insert(inp->din_hash, pnp->dn_string, 2240*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, DT_IDFLG_DECL | DT_IDFLG_INLINE, 0, 2241*7c478bd9Sstevel@tonic-gate _dtrace_defattr, 0, &dt_idops_inline, 2242*7c478bd9Sstevel@tonic-gate pinp, dtp->dt_gen); 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate if (pidp == NULL) { 2245*7c478bd9Sstevel@tonic-gate free(pinp); 2246*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2247*7c478bd9Sstevel@tonic-gate } 2248*7c478bd9Sstevel@tonic-gate 2249*7c478bd9Sstevel@tonic-gate inp->din_argv[i] = pidp; 2250*7c478bd9Sstevel@tonic-gate bzero(pinp, sizeof (dt_idnode_t)); 2251*7c478bd9Sstevel@tonic-gate dt_ident_type_assign(pidp, pnp->dn_ctfp, pnp->dn_type); 2252*7c478bd9Sstevel@tonic-gate } 2253*7c478bd9Sstevel@tonic-gate 2254*7c478bd9Sstevel@tonic-gate dt_idstack_push(&yypcb->pcb_globals, inp->din_hash); 2255*7c478bd9Sstevel@tonic-gate } 2256*7c478bd9Sstevel@tonic-gate 2257*7c478bd9Sstevel@tonic-gate /* 2258*7c478bd9Sstevel@tonic-gate * Unlike most constructors, we need to explicitly cook the right-hand 2259*7c478bd9Sstevel@tonic-gate * side of the inline definition immediately to prevent recursion. If 2260*7c478bd9Sstevel@tonic-gate * the right-hand side uses the inline itself, the cook will fail. 2261*7c478bd9Sstevel@tonic-gate */ 2262*7c478bd9Sstevel@tonic-gate expr = dt_node_cook(expr, DT_IDFLG_REF); 2263*7c478bd9Sstevel@tonic-gate 2264*7c478bd9Sstevel@tonic-gate if (ddp->dd_kind == CTF_K_ARRAY) 2265*7c478bd9Sstevel@tonic-gate dt_idstack_pop(&yypcb->pcb_globals, inp->din_hash); 2266*7c478bd9Sstevel@tonic-gate 2267*7c478bd9Sstevel@tonic-gate /* 2268*7c478bd9Sstevel@tonic-gate * Set the type, attributes, and flags for the inline. If the right- 2269*7c478bd9Sstevel@tonic-gate * hand expression has an identifier, propagate its flags. Then cook 2270*7c478bd9Sstevel@tonic-gate * the identifier to fully initialize it: if we're declaring an inline 2271*7c478bd9Sstevel@tonic-gate * associative array this will construct a type signature from 'ddp'. 2272*7c478bd9Sstevel@tonic-gate */ 2273*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(expr)) 2274*7c478bd9Sstevel@tonic-gate rdp = dt_ident_resolve(expr->dn_ident); 2275*7c478bd9Sstevel@tonic-gate else if (expr->dn_kind == DT_NODE_VAR || expr->dn_kind == DT_NODE_SYM) 2276*7c478bd9Sstevel@tonic-gate rdp = expr->dn_ident; 2277*7c478bd9Sstevel@tonic-gate else 2278*7c478bd9Sstevel@tonic-gate rdp = NULL; 2279*7c478bd9Sstevel@tonic-gate 2280*7c478bd9Sstevel@tonic-gate if (rdp != NULL) { 2281*7c478bd9Sstevel@tonic-gate idp->di_flags |= (rdp->di_flags & 2282*7c478bd9Sstevel@tonic-gate (DT_IDFLG_WRITE | DT_IDFLG_USER | DT_IDFLG_PRIM)); 2283*7c478bd9Sstevel@tonic-gate } 2284*7c478bd9Sstevel@tonic-gate 2285*7c478bd9Sstevel@tonic-gate idp->di_attr = dt_attr_min(_dtrace_defattr, expr->dn_attr); 2286*7c478bd9Sstevel@tonic-gate dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type); 2287*7c478bd9Sstevel@tonic-gate (void) dt_ident_cook(dnp, idp, &ddp->dd_node); 2288*7c478bd9Sstevel@tonic-gate 2289*7c478bd9Sstevel@tonic-gate /* 2290*7c478bd9Sstevel@tonic-gate * Store the parse tree nodes for 'expr' inside of idp->di_data ('inp') 2291*7c478bd9Sstevel@tonic-gate * so that they will be preserved with this identifier. Then pop the 2292*7c478bd9Sstevel@tonic-gate * inline declaration from the declaration stack and restore the lexer. 2293*7c478bd9Sstevel@tonic-gate */ 2294*7c478bd9Sstevel@tonic-gate inp->din_list = yypcb->pcb_list; 2295*7c478bd9Sstevel@tonic-gate inp->din_root = expr; 2296*7c478bd9Sstevel@tonic-gate 2297*7c478bd9Sstevel@tonic-gate dt_decl_free(dt_decl_pop()); 2298*7c478bd9Sstevel@tonic-gate yybegin(YYS_CLAUSE); 2299*7c478bd9Sstevel@tonic-gate 2300*7c478bd9Sstevel@tonic-gate /* 2301*7c478bd9Sstevel@tonic-gate * Finally, insert the inline identifier into dt_globals to make it 2302*7c478bd9Sstevel@tonic-gate * visible, and then cook 'dnp' to check its type against 'expr'. 2303*7c478bd9Sstevel@tonic-gate */ 2304*7c478bd9Sstevel@tonic-gate dt_idhash_xinsert(dtp->dt_globals, idp); 2305*7c478bd9Sstevel@tonic-gate return (dt_node_cook(dnp, DT_IDFLG_REF)); 2306*7c478bd9Sstevel@tonic-gate } 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate dt_node_t * 2309*7c478bd9Sstevel@tonic-gate dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr) 2310*7c478bd9Sstevel@tonic-gate { 2311*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 2312*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2313*7c478bd9Sstevel@tonic-gate int err; 2314*7c478bd9Sstevel@tonic-gate 2315*7c478bd9Sstevel@tonic-gate if (ddp != NULL) { 2316*7c478bd9Sstevel@tonic-gate err = dt_decl_type(ddp, &dtt); 2317*7c478bd9Sstevel@tonic-gate dt_decl_free(ddp); 2318*7c478bd9Sstevel@tonic-gate 2319*7c478bd9Sstevel@tonic-gate if (err != 0) 2320*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 2321*7c478bd9Sstevel@tonic-gate } 2322*7c478bd9Sstevel@tonic-gate 2323*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_MEMBER); 2324*7c478bd9Sstevel@tonic-gate dnp->dn_membname = name; 2325*7c478bd9Sstevel@tonic-gate dnp->dn_membexpr = expr; 2326*7c478bd9Sstevel@tonic-gate 2327*7c478bd9Sstevel@tonic-gate if (ddp != NULL) 2328*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); 2329*7c478bd9Sstevel@tonic-gate 2330*7c478bd9Sstevel@tonic-gate return (dnp); 2331*7c478bd9Sstevel@tonic-gate } 2332*7c478bd9Sstevel@tonic-gate 2333*7c478bd9Sstevel@tonic-gate dt_node_t * 2334*7c478bd9Sstevel@tonic-gate dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members) 2335*7c478bd9Sstevel@tonic-gate { 2336*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2337*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t src, dst; 2338*7c478bd9Sstevel@tonic-gate dt_node_t sn, dn; 2339*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp; 2340*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2341*7c478bd9Sstevel@tonic-gate int edst, esrc; 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 2344*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 2345*7c478bd9Sstevel@tonic-gate 2346*7c478bd9Sstevel@tonic-gate edst = dt_decl_type(ddp, &dst); 2347*7c478bd9Sstevel@tonic-gate dt_decl_free(ddp); 2348*7c478bd9Sstevel@tonic-gate 2349*7c478bd9Sstevel@tonic-gate esrc = dt_decl_type(sdp, &src); 2350*7c478bd9Sstevel@tonic-gate dt_decl_free(sdp); 2351*7c478bd9Sstevel@tonic-gate 2352*7c478bd9Sstevel@tonic-gate if (edst != 0 || esrc != 0) { 2353*7c478bd9Sstevel@tonic-gate free(name); 2354*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 2355*7c478bd9Sstevel@tonic-gate } 2356*7c478bd9Sstevel@tonic-gate 2357*7c478bd9Sstevel@tonic-gate bzero(&sn, sizeof (sn)); 2358*7c478bd9Sstevel@tonic-gate dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type); 2359*7c478bd9Sstevel@tonic-gate 2360*7c478bd9Sstevel@tonic-gate bzero(&dn, sizeof (dn)); 2361*7c478bd9Sstevel@tonic-gate dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type); 2362*7c478bd9Sstevel@tonic-gate 2363*7c478bd9Sstevel@tonic-gate if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) { 2364*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_REDECL, 2365*7c478bd9Sstevel@tonic-gate "translator from %s to %s has already been declared\n", 2366*7c478bd9Sstevel@tonic-gate dt_node_type_name(&sn, n1, sizeof (n1)), 2367*7c478bd9Sstevel@tonic-gate dt_node_type_name(&dn, n2, sizeof (n2))); 2368*7c478bd9Sstevel@tonic-gate } 2369*7c478bd9Sstevel@tonic-gate 2370*7c478bd9Sstevel@tonic-gate dxp = dt_xlator_create(dtp, &src, &dst, name, members, yypcb->pcb_list); 2371*7c478bd9Sstevel@tonic-gate yybegin(YYS_CLAUSE); 2372*7c478bd9Sstevel@tonic-gate free(name); 2373*7c478bd9Sstevel@tonic-gate 2374*7c478bd9Sstevel@tonic-gate if (dxp == NULL) 2375*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_XLATOR); 2378*7c478bd9Sstevel@tonic-gate dnp->dn_xlator = dxp; 2379*7c478bd9Sstevel@tonic-gate dnp->dn_members = members; 2380*7c478bd9Sstevel@tonic-gate 2381*7c478bd9Sstevel@tonic-gate return (dt_node_cook(dnp, DT_IDFLG_REF)); 2382*7c478bd9Sstevel@tonic-gate } 2383*7c478bd9Sstevel@tonic-gate 2384*7c478bd9Sstevel@tonic-gate dt_node_t * 2385*7c478bd9Sstevel@tonic-gate dt_node_probe(char *s, dt_node_t *nargs, dt_node_t *xargs) 2386*7c478bd9Sstevel@tonic-gate { 2387*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2388*7c478bd9Sstevel@tonic-gate int nargc, xargc; 2389*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 2390*7c478bd9Sstevel@tonic-gate 2391*7c478bd9Sstevel@tonic-gate size_t len = strlen(s) + 3; /* +3 for :: and \0 */ 2392*7c478bd9Sstevel@tonic-gate char *name = alloca(len); 2393*7c478bd9Sstevel@tonic-gate 2394*7c478bd9Sstevel@tonic-gate (void) snprintf(name, len, "::%s", s); 2395*7c478bd9Sstevel@tonic-gate (void) strhyphenate(name); 2396*7c478bd9Sstevel@tonic-gate free(s); 2397*7c478bd9Sstevel@tonic-gate 2398*7c478bd9Sstevel@tonic-gate if (strchr(name, '`') != NULL) { 2399*7c478bd9Sstevel@tonic-gate xyerror(D_PROV_BADNAME, "probe name may not " 2400*7c478bd9Sstevel@tonic-gate "contain scoping operator: %s\n", name); 2401*7c478bd9Sstevel@tonic-gate } 2402*7c478bd9Sstevel@tonic-gate 2403*7c478bd9Sstevel@tonic-gate if (strlen(name) - 2 >= DTRACE_NAMELEN) { 2404*7c478bd9Sstevel@tonic-gate xyerror(D_PROV_BADNAME, "probe name may not exceed %d " 2405*7c478bd9Sstevel@tonic-gate "characters: %s\n", DTRACE_NAMELEN - 1, name); 2406*7c478bd9Sstevel@tonic-gate } 2407*7c478bd9Sstevel@tonic-gate 2408*7c478bd9Sstevel@tonic-gate dnp = dt_node_alloc(DT_NODE_PROBE); 2409*7c478bd9Sstevel@tonic-gate 2410*7c478bd9Sstevel@tonic-gate dnp->dn_ident = dt_ident_create(name, DT_IDENT_PROBE, 2411*7c478bd9Sstevel@tonic-gate DT_IDFLG_ORPHAN, DTRACE_IDNONE, _dtrace_defattr, 0, 2412*7c478bd9Sstevel@tonic-gate &dt_idops_probe, NULL, dtp->dt_gen); 2413*7c478bd9Sstevel@tonic-gate 2414*7c478bd9Sstevel@tonic-gate nargc = dt_decl_prototype(nargs, nargs, 2415*7c478bd9Sstevel@tonic-gate "probe input", DT_DP_VOID | DT_DP_ANON); 2416*7c478bd9Sstevel@tonic-gate 2417*7c478bd9Sstevel@tonic-gate xargc = dt_decl_prototype(xargs, nargs, 2418*7c478bd9Sstevel@tonic-gate "probe output", DT_DP_VOID); 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate if (nargc > UINT8_MAX) { 2421*7c478bd9Sstevel@tonic-gate xyerror(D_PROV_PRARGLEN, "probe %s input prototype exceeds %u " 2422*7c478bd9Sstevel@tonic-gate "parameters: %d params used\n", name, UINT8_MAX, nargc); 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate if (xargc > UINT8_MAX) { 2426*7c478bd9Sstevel@tonic-gate xyerror(D_PROV_PRARGLEN, "probe %s output prototype exceeds %u " 2427*7c478bd9Sstevel@tonic-gate "parameters: %d params used\n", name, UINT8_MAX, xargc); 2428*7c478bd9Sstevel@tonic-gate } 2429*7c478bd9Sstevel@tonic-gate 2430*7c478bd9Sstevel@tonic-gate if (dnp->dn_ident == NULL || dt_probe_create(dtp, 2431*7c478bd9Sstevel@tonic-gate dnp->dn_ident, nargs, nargc, xargs, xargc) == NULL) 2432*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2433*7c478bd9Sstevel@tonic-gate 2434*7c478bd9Sstevel@tonic-gate return (dnp); 2435*7c478bd9Sstevel@tonic-gate } 2436*7c478bd9Sstevel@tonic-gate 2437*7c478bd9Sstevel@tonic-gate dt_node_t * 2438*7c478bd9Sstevel@tonic-gate dt_node_provider(char *name, dt_node_t *probes) 2439*7c478bd9Sstevel@tonic-gate { 2440*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2441*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_PROVIDER); 2442*7c478bd9Sstevel@tonic-gate 2443*7c478bd9Sstevel@tonic-gate dnp->dn_provname = name; 2444*7c478bd9Sstevel@tonic-gate dnp->dn_probes = probes; 2445*7c478bd9Sstevel@tonic-gate 2446*7c478bd9Sstevel@tonic-gate if (strchr(name, '`') != NULL) { 2447*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_PROV_BADNAME, "provider name may not " 2448*7c478bd9Sstevel@tonic-gate "contain scoping operator: %s\n", name); 2449*7c478bd9Sstevel@tonic-gate } 2450*7c478bd9Sstevel@tonic-gate 2451*7c478bd9Sstevel@tonic-gate if (strlen(name) >= DTRACE_PROVNAMELEN) { 2452*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_PROV_BADNAME, "provider name may not exceed %d " 2453*7c478bd9Sstevel@tonic-gate "characters: %s\n", DTRACE_PROVNAMELEN - 1, name); 2454*7c478bd9Sstevel@tonic-gate } 2455*7c478bd9Sstevel@tonic-gate 2456*7c478bd9Sstevel@tonic-gate /* 2457*7c478bd9Sstevel@tonic-gate * Check to see if the provider is already defined or visible through 2458*7c478bd9Sstevel@tonic-gate * dtrace(7D). If so, set dn_provred to treat it as a re-declaration. 2459*7c478bd9Sstevel@tonic-gate * If not, create a new provider and set its interface-only flag. This 2460*7c478bd9Sstevel@tonic-gate * flag may be cleared later by calls made to dt_probe_declare(). 2461*7c478bd9Sstevel@tonic-gate */ 2462*7c478bd9Sstevel@tonic-gate if ((dnp->dn_provider = dt_provider_lookup(dtp, name)) != NULL) 2463*7c478bd9Sstevel@tonic-gate dnp->dn_provred = B_TRUE; 2464*7c478bd9Sstevel@tonic-gate else if ((dnp->dn_provider = dt_provider_create(dtp, name)) == NULL) 2465*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2466*7c478bd9Sstevel@tonic-gate else 2467*7c478bd9Sstevel@tonic-gate dnp->dn_provider->pv_flags |= DT_PROVIDER_INTF; 2468*7c478bd9Sstevel@tonic-gate 2469*7c478bd9Sstevel@tonic-gate /* 2470*7c478bd9Sstevel@tonic-gate * If the provider is being redeclared, put the pcb_list back on to the 2471*7c478bd9Sstevel@tonic-gate * hold list (undo the effect of YYS_DEFINE on allocation). Otherwise 2472*7c478bd9Sstevel@tonic-gate * store all parse nodes created since we consumed the DT_KEY_PROVIDER 2473*7c478bd9Sstevel@tonic-gate * token with the provider and then restore our lexing state to CLAUSE. 2474*7c478bd9Sstevel@tonic-gate */ 2475*7c478bd9Sstevel@tonic-gate if (dnp->dn_provred) { 2476*7c478bd9Sstevel@tonic-gate while (yypcb->pcb_list != NULL) { 2477*7c478bd9Sstevel@tonic-gate dt_node_t *pnp = yypcb->pcb_list; 2478*7c478bd9Sstevel@tonic-gate yypcb->pcb_list = pnp->dn_link; 2479*7c478bd9Sstevel@tonic-gate pnp->dn_link = yypcb->pcb_hold; 2480*7c478bd9Sstevel@tonic-gate yypcb->pcb_hold = pnp; 2481*7c478bd9Sstevel@tonic-gate } 2482*7c478bd9Sstevel@tonic-gate } else { 2483*7c478bd9Sstevel@tonic-gate assert(dnp->dn_provider->pv_nodes == NULL); 2484*7c478bd9Sstevel@tonic-gate dnp->dn_provider->pv_nodes = yypcb->pcb_list; 2485*7c478bd9Sstevel@tonic-gate } 2486*7c478bd9Sstevel@tonic-gate 2487*7c478bd9Sstevel@tonic-gate yybegin(YYS_CLAUSE); 2488*7c478bd9Sstevel@tonic-gate return (dnp); 2489*7c478bd9Sstevel@tonic-gate } 2490*7c478bd9Sstevel@tonic-gate 2491*7c478bd9Sstevel@tonic-gate dt_node_t * 2492*7c478bd9Sstevel@tonic-gate dt_node_program(dt_node_t *lnp) 2493*7c478bd9Sstevel@tonic-gate { 2494*7c478bd9Sstevel@tonic-gate dt_node_t *dnp = dt_node_alloc(DT_NODE_PROG); 2495*7c478bd9Sstevel@tonic-gate dnp->dn_list = lnp; 2496*7c478bd9Sstevel@tonic-gate return (dnp); 2497*7c478bd9Sstevel@tonic-gate } 2498*7c478bd9Sstevel@tonic-gate 2499*7c478bd9Sstevel@tonic-gate /* 2500*7c478bd9Sstevel@tonic-gate * This function provides the underlying implementation of cooking an 2501*7c478bd9Sstevel@tonic-gate * identifier given its node, a hash of dynamic identifiers, an identifier 2502*7c478bd9Sstevel@tonic-gate * kind, and a boolean flag indicating whether we are allowed to instantiate 2503*7c478bd9Sstevel@tonic-gate * a new identifier if the string is not found. This function is either 2504*7c478bd9Sstevel@tonic-gate * called from dt_cook_ident(), below, or directly by the various cooking 2505*7c478bd9Sstevel@tonic-gate * routines that are allowed to instantiate identifiers (e.g. op2 TOK_ASGN). 2506*7c478bd9Sstevel@tonic-gate */ 2507*7c478bd9Sstevel@tonic-gate static void 2508*7c478bd9Sstevel@tonic-gate dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create) 2509*7c478bd9Sstevel@tonic-gate { 2510*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2511*7c478bd9Sstevel@tonic-gate const char *sname = dt_idhash_name(dhp); 2512*7c478bd9Sstevel@tonic-gate int uref = 0; 2513*7c478bd9Sstevel@tonic-gate 2514*7c478bd9Sstevel@tonic-gate dtrace_attribute_t attr = _dtrace_defattr; 2515*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 2516*7c478bd9Sstevel@tonic-gate dtrace_syminfo_t dts; 2517*7c478bd9Sstevel@tonic-gate GElf_Sym sym; 2518*7c478bd9Sstevel@tonic-gate 2519*7c478bd9Sstevel@tonic-gate const char *scope, *mark; 2520*7c478bd9Sstevel@tonic-gate uchar_t dnkind; 2521*7c478bd9Sstevel@tonic-gate char *name; 2522*7c478bd9Sstevel@tonic-gate 2523*7c478bd9Sstevel@tonic-gate /* 2524*7c478bd9Sstevel@tonic-gate * Look for scoping marks in the identifier. If one is found, set our 2525*7c478bd9Sstevel@tonic-gate * scope to either DTRACE_OBJ_KMODS or UMODS or to the first part of 2526*7c478bd9Sstevel@tonic-gate * the string that specifies the scope using an explicit module name. 2527*7c478bd9Sstevel@tonic-gate * If two marks in a row are found, set 'uref' (user symbol reference). 2528*7c478bd9Sstevel@tonic-gate * Otherwise we set scope to DTRACE_OBJ_EXEC, indicating that normal 2529*7c478bd9Sstevel@tonic-gate * scope is desired and we should search the specified idhash. 2530*7c478bd9Sstevel@tonic-gate */ 2531*7c478bd9Sstevel@tonic-gate if ((name = strrchr(dnp->dn_string, '`')) != NULL) { 2532*7c478bd9Sstevel@tonic-gate if (name > dnp->dn_string && name[-1] == '`') { 2533*7c478bd9Sstevel@tonic-gate uref++; 2534*7c478bd9Sstevel@tonic-gate name[-1] = '\0'; 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate if (name == dnp->dn_string + uref) 2538*7c478bd9Sstevel@tonic-gate scope = uref ? DTRACE_OBJ_UMODS : DTRACE_OBJ_KMODS; 2539*7c478bd9Sstevel@tonic-gate else 2540*7c478bd9Sstevel@tonic-gate scope = dnp->dn_string; 2541*7c478bd9Sstevel@tonic-gate 2542*7c478bd9Sstevel@tonic-gate *name++ = '\0'; /* leave name pointing after scoping mark */ 2543*7c478bd9Sstevel@tonic-gate dnkind = DT_NODE_VAR; 2544*7c478bd9Sstevel@tonic-gate 2545*7c478bd9Sstevel@tonic-gate } else if (idkind == DT_IDENT_AGG) { 2546*7c478bd9Sstevel@tonic-gate scope = DTRACE_OBJ_EXEC; 2547*7c478bd9Sstevel@tonic-gate name = dnp->dn_string + 1; 2548*7c478bd9Sstevel@tonic-gate dnkind = DT_NODE_AGG; 2549*7c478bd9Sstevel@tonic-gate } else { 2550*7c478bd9Sstevel@tonic-gate scope = DTRACE_OBJ_EXEC; 2551*7c478bd9Sstevel@tonic-gate name = dnp->dn_string; 2552*7c478bd9Sstevel@tonic-gate dnkind = DT_NODE_VAR; 2553*7c478bd9Sstevel@tonic-gate } 2554*7c478bd9Sstevel@tonic-gate 2555*7c478bd9Sstevel@tonic-gate /* 2556*7c478bd9Sstevel@tonic-gate * If create is set to false, and we fail our idhash lookup, preset 2557*7c478bd9Sstevel@tonic-gate * the errno code to EDT_NOVAR for our final error message below. 2558*7c478bd9Sstevel@tonic-gate * If we end up calling dtrace_lookup_by_name(), it will reset the 2559*7c478bd9Sstevel@tonic-gate * errno appropriately and that error will be reported instead. 2560*7c478bd9Sstevel@tonic-gate */ 2561*7c478bd9Sstevel@tonic-gate (void) dt_set_errno(dtp, EDT_NOVAR); 2562*7c478bd9Sstevel@tonic-gate mark = uref ? "``" : "`"; 2563*7c478bd9Sstevel@tonic-gate 2564*7c478bd9Sstevel@tonic-gate if (scope == DTRACE_OBJ_EXEC && ( 2565*7c478bd9Sstevel@tonic-gate (dhp != dtp->dt_globals && 2566*7c478bd9Sstevel@tonic-gate (idp = dt_idhash_lookup(dhp, name)) != NULL) || 2567*7c478bd9Sstevel@tonic-gate (dhp == dtp->dt_globals && 2568*7c478bd9Sstevel@tonic-gate (idp = dt_idstack_lookup(&yypcb->pcb_globals, name)) != NULL))) { 2569*7c478bd9Sstevel@tonic-gate /* 2570*7c478bd9Sstevel@tonic-gate * Check that we are referencing the ident in the manner that 2571*7c478bd9Sstevel@tonic-gate * matches its type if this is a global lookup. In the TLS or 2572*7c478bd9Sstevel@tonic-gate * local case, we don't know how the ident will be used until 2573*7c478bd9Sstevel@tonic-gate * the time operator -> is seen; more parsing is needed. 2574*7c478bd9Sstevel@tonic-gate */ 2575*7c478bd9Sstevel@tonic-gate if (idp->di_kind != idkind && dhp == dtp->dt_globals) { 2576*7c478bd9Sstevel@tonic-gate xyerror(D_IDENT_BADREF, "%s '%s' may not be referenced " 2577*7c478bd9Sstevel@tonic-gate "as %s\n", dt_idkind_name(idp->di_kind), 2578*7c478bd9Sstevel@tonic-gate idp->di_name, dt_idkind_name(idkind)); 2579*7c478bd9Sstevel@tonic-gate } 2580*7c478bd9Sstevel@tonic-gate 2581*7c478bd9Sstevel@tonic-gate /* 2582*7c478bd9Sstevel@tonic-gate * Arrays and aggregations are not cooked individually. They 2583*7c478bd9Sstevel@tonic-gate * have dynamic types and must be referenced using operator []. 2584*7c478bd9Sstevel@tonic-gate * This is handled explicitly by the code for DT_TOK_LBRAC. 2585*7c478bd9Sstevel@tonic-gate */ 2586*7c478bd9Sstevel@tonic-gate if (idp->di_kind != DT_IDENT_ARRAY && 2587*7c478bd9Sstevel@tonic-gate idp->di_kind != DT_IDENT_AGG) 2588*7c478bd9Sstevel@tonic-gate attr = dt_ident_cook(dnp, idp, NULL); 2589*7c478bd9Sstevel@tonic-gate else { 2590*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 2591*7c478bd9Sstevel@tonic-gate DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 2592*7c478bd9Sstevel@tonic-gate attr = idp->di_attr; 2593*7c478bd9Sstevel@tonic-gate } 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate free(dnp->dn_string); 2596*7c478bd9Sstevel@tonic-gate dnp->dn_string = NULL; 2597*7c478bd9Sstevel@tonic-gate dnp->dn_kind = dnkind; 2598*7c478bd9Sstevel@tonic-gate dnp->dn_ident = idp; 2599*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE; 2600*7c478bd9Sstevel@tonic-gate 2601*7c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_WRITE) 2602*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_WRITABLE; 2603*7c478bd9Sstevel@tonic-gate 2604*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, attr); 2605*7c478bd9Sstevel@tonic-gate 2606*7c478bd9Sstevel@tonic-gate } else if (dhp == dtp->dt_globals && scope != DTRACE_OBJ_EXEC && 2607*7c478bd9Sstevel@tonic-gate dtrace_lookup_by_name(dtp, scope, name, &sym, &dts) == 0) { 2608*7c478bd9Sstevel@tonic-gate 2609*7c478bd9Sstevel@tonic-gate dt_module_t *mp = dt_module_lookup_by_name(dtp, dts.dts_object); 2610*7c478bd9Sstevel@tonic-gate int umod = (mp->dm_flags & DT_DM_KERNEL) == 0; 2611*7c478bd9Sstevel@tonic-gate static const char *const kunames[] = { "kernel", "user" }; 2612*7c478bd9Sstevel@tonic-gate 2613*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 2614*7c478bd9Sstevel@tonic-gate dtrace_syminfo_t *sip; 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate if (uref ^ umod) { 2617*7c478bd9Sstevel@tonic-gate xyerror(D_SYM_BADREF, "%s module '%s' symbol '%s' may " 2618*7c478bd9Sstevel@tonic-gate "not be referenced as a %s symbol\n", kunames[umod], 2619*7c478bd9Sstevel@tonic-gate dts.dts_object, dts.dts_name, kunames[uref]); 2620*7c478bd9Sstevel@tonic-gate } 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate if (dtrace_symbol_type(dtp, &sym, &dts, &dtt) != 0) { 2623*7c478bd9Sstevel@tonic-gate /* 2624*7c478bd9Sstevel@tonic-gate * For now, we special-case EDT_DATAMODEL to clarify 2625*7c478bd9Sstevel@tonic-gate * that mixed data models are not currently supported. 2626*7c478bd9Sstevel@tonic-gate */ 2627*7c478bd9Sstevel@tonic-gate if (dtp->dt_errno == EDT_DATAMODEL) { 2628*7c478bd9Sstevel@tonic-gate xyerror(D_SYM_MODEL, "cannot use %s symbol " 2629*7c478bd9Sstevel@tonic-gate "%s%s%s in a %s D program\n", 2630*7c478bd9Sstevel@tonic-gate dt_module_modelname(mp), 2631*7c478bd9Sstevel@tonic-gate dts.dts_object, mark, dts.dts_name, 2632*7c478bd9Sstevel@tonic-gate dt_module_modelname(dtp->dt_ddefs)); 2633*7c478bd9Sstevel@tonic-gate } 2634*7c478bd9Sstevel@tonic-gate 2635*7c478bd9Sstevel@tonic-gate xyerror(D_SYM_NOTYPES, 2636*7c478bd9Sstevel@tonic-gate "no symbolic type information is available for " 2637*7c478bd9Sstevel@tonic-gate "%s%s%s: %s\n", dts.dts_object, mark, dts.dts_name, 2638*7c478bd9Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp))); 2639*7c478bd9Sstevel@tonic-gate } 2640*7c478bd9Sstevel@tonic-gate 2641*7c478bd9Sstevel@tonic-gate idp = dt_ident_create(name, DT_IDENT_SYMBOL, 0, 0, 2642*7c478bd9Sstevel@tonic-gate _dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); 2643*7c478bd9Sstevel@tonic-gate 2644*7c478bd9Sstevel@tonic-gate if (idp == NULL) 2645*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2646*7c478bd9Sstevel@tonic-gate 2647*7c478bd9Sstevel@tonic-gate if (mp->dm_flags & DT_DM_PRIMARY) 2648*7c478bd9Sstevel@tonic-gate idp->di_flags |= DT_IDFLG_PRIM; 2649*7c478bd9Sstevel@tonic-gate 2650*7c478bd9Sstevel@tonic-gate idp->di_next = dtp->dt_externs; 2651*7c478bd9Sstevel@tonic-gate dtp->dt_externs = idp; 2652*7c478bd9Sstevel@tonic-gate 2653*7c478bd9Sstevel@tonic-gate if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL) 2654*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2655*7c478bd9Sstevel@tonic-gate 2656*7c478bd9Sstevel@tonic-gate bcopy(&dts, sip, sizeof (dtrace_syminfo_t)); 2657*7c478bd9Sstevel@tonic-gate idp->di_data = sip; 2658*7c478bd9Sstevel@tonic-gate idp->di_ctfp = dtt.dtt_ctfp; 2659*7c478bd9Sstevel@tonic-gate idp->di_type = dtt.dtt_type; 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate free(dnp->dn_string); 2662*7c478bd9Sstevel@tonic-gate dnp->dn_string = NULL; 2663*7c478bd9Sstevel@tonic-gate dnp->dn_kind = DT_NODE_SYM; 2664*7c478bd9Sstevel@tonic-gate dnp->dn_ident = idp; 2665*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE; 2666*7c478bd9Sstevel@tonic-gate 2667*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); 2668*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, _dtrace_symattr); 2669*7c478bd9Sstevel@tonic-gate 2670*7c478bd9Sstevel@tonic-gate if (uref) { 2671*7c478bd9Sstevel@tonic-gate idp->di_flags |= DT_IDFLG_USER; 2672*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_USERLAND; 2673*7c478bd9Sstevel@tonic-gate } 2674*7c478bd9Sstevel@tonic-gate 2675*7c478bd9Sstevel@tonic-gate } else if (scope == DTRACE_OBJ_EXEC && create == B_TRUE) { 2676*7c478bd9Sstevel@tonic-gate uint_t flags = DT_IDFLG_WRITE; 2677*7c478bd9Sstevel@tonic-gate uint_t id; 2678*7c478bd9Sstevel@tonic-gate 2679*7c478bd9Sstevel@tonic-gate if (dt_idhash_nextid(dhp, &id) == -1) { 2680*7c478bd9Sstevel@tonic-gate xyerror(D_ID_OFLOW, "cannot create %s: limit on number " 2681*7c478bd9Sstevel@tonic-gate "of %s variables exceeded\n", name, sname); 2682*7c478bd9Sstevel@tonic-gate } 2683*7c478bd9Sstevel@tonic-gate 2684*7c478bd9Sstevel@tonic-gate if (dhp == yypcb->pcb_locals) 2685*7c478bd9Sstevel@tonic-gate flags |= DT_IDFLG_LOCAL; 2686*7c478bd9Sstevel@tonic-gate else if (dhp == dtp->dt_tls) 2687*7c478bd9Sstevel@tonic-gate flags |= DT_IDFLG_TLS; 2688*7c478bd9Sstevel@tonic-gate 2689*7c478bd9Sstevel@tonic-gate dt_dprintf("create %s %s variable %s, id=%u\n", 2690*7c478bd9Sstevel@tonic-gate sname, dt_idkind_name(idkind), name, id); 2691*7c478bd9Sstevel@tonic-gate 2692*7c478bd9Sstevel@tonic-gate if (idkind == DT_IDENT_ARRAY || idkind == DT_IDENT_AGG) { 2693*7c478bd9Sstevel@tonic-gate idp = dt_idhash_insert(dhp, name, 2694*7c478bd9Sstevel@tonic-gate idkind, flags, id, _dtrace_defattr, 0, 2695*7c478bd9Sstevel@tonic-gate &dt_idops_assc, NULL, dtp->dt_gen); 2696*7c478bd9Sstevel@tonic-gate } else { 2697*7c478bd9Sstevel@tonic-gate idp = dt_idhash_insert(dhp, name, 2698*7c478bd9Sstevel@tonic-gate idkind, flags, id, _dtrace_defattr, 0, 2699*7c478bd9Sstevel@tonic-gate &dt_idops_thaw, NULL, dtp->dt_gen); 2700*7c478bd9Sstevel@tonic-gate } 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate if (idp == NULL) 2703*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); 2704*7c478bd9Sstevel@tonic-gate 2705*7c478bd9Sstevel@tonic-gate /* 2706*7c478bd9Sstevel@tonic-gate * Arrays and aggregations are not cooked individually. They 2707*7c478bd9Sstevel@tonic-gate * have dynamic types and must be referenced using operator []. 2708*7c478bd9Sstevel@tonic-gate * This is handled explicitly by the code for DT_TOK_LBRAC. 2709*7c478bd9Sstevel@tonic-gate */ 2710*7c478bd9Sstevel@tonic-gate if (idp->di_kind != DT_IDENT_ARRAY && 2711*7c478bd9Sstevel@tonic-gate idp->di_kind != DT_IDENT_AGG) 2712*7c478bd9Sstevel@tonic-gate attr = dt_ident_cook(dnp, idp, NULL); 2713*7c478bd9Sstevel@tonic-gate else { 2714*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 2715*7c478bd9Sstevel@tonic-gate DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 2716*7c478bd9Sstevel@tonic-gate attr = idp->di_attr; 2717*7c478bd9Sstevel@tonic-gate } 2718*7c478bd9Sstevel@tonic-gate 2719*7c478bd9Sstevel@tonic-gate free(dnp->dn_string); 2720*7c478bd9Sstevel@tonic-gate dnp->dn_string = NULL; 2721*7c478bd9Sstevel@tonic-gate dnp->dn_kind = dnkind; 2722*7c478bd9Sstevel@tonic-gate dnp->dn_ident = idp; 2723*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE | DT_NF_WRITABLE; 2724*7c478bd9Sstevel@tonic-gate 2725*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, attr); 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate } else if (scope != DTRACE_OBJ_EXEC) { 2728*7c478bd9Sstevel@tonic-gate xyerror(D_IDENT_UNDEF, "failed to resolve %s%s%s: %s\n", 2729*7c478bd9Sstevel@tonic-gate dnp->dn_string, mark, name, 2730*7c478bd9Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp))); 2731*7c478bd9Sstevel@tonic-gate } else { 2732*7c478bd9Sstevel@tonic-gate xyerror(D_IDENT_UNDEF, "failed to resolve %s: %s\n", 2733*7c478bd9Sstevel@tonic-gate dnp->dn_string, dtrace_errmsg(dtp, dtrace_errno(dtp))); 2734*7c478bd9Sstevel@tonic-gate } 2735*7c478bd9Sstevel@tonic-gate } 2736*7c478bd9Sstevel@tonic-gate 2737*7c478bd9Sstevel@tonic-gate static dt_node_t * 2738*7c478bd9Sstevel@tonic-gate dt_cook_ident(dt_node_t *dnp, uint_t idflags) 2739*7c478bd9Sstevel@tonic-gate { 2740*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2741*7c478bd9Sstevel@tonic-gate 2742*7c478bd9Sstevel@tonic-gate if (dnp->dn_op == DT_TOK_AGG) 2743*7c478bd9Sstevel@tonic-gate dt_xcook_ident(dnp, dtp->dt_aggs, DT_IDENT_AGG, B_FALSE); 2744*7c478bd9Sstevel@tonic-gate else 2745*7c478bd9Sstevel@tonic-gate dt_xcook_ident(dnp, dtp->dt_globals, DT_IDENT_SCALAR, B_FALSE); 2746*7c478bd9Sstevel@tonic-gate 2747*7c478bd9Sstevel@tonic-gate return (dt_node_cook(dnp, idflags)); 2748*7c478bd9Sstevel@tonic-gate } 2749*7c478bd9Sstevel@tonic-gate 2750*7c478bd9Sstevel@tonic-gate /* 2751*7c478bd9Sstevel@tonic-gate * Since operators [ and -> can instantiate new variables before we know 2752*7c478bd9Sstevel@tonic-gate * whether the reference is for a read or a write, we need to check read 2753*7c478bd9Sstevel@tonic-gate * references to determine if the identifier is currently dt_ident_unref(). 2754*7c478bd9Sstevel@tonic-gate * If so, we report that this first access was to an undefined variable. 2755*7c478bd9Sstevel@tonic-gate */ 2756*7c478bd9Sstevel@tonic-gate static dt_node_t * 2757*7c478bd9Sstevel@tonic-gate dt_cook_var(dt_node_t *dnp, uint_t idflags) 2758*7c478bd9Sstevel@tonic-gate { 2759*7c478bd9Sstevel@tonic-gate dt_ident_t *idp = dnp->dn_ident; 2760*7c478bd9Sstevel@tonic-gate 2761*7c478bd9Sstevel@tonic-gate if ((idflags & DT_IDFLG_REF) && dt_ident_unref(idp)) { 2762*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_VAR_UNDEF, 2763*7c478bd9Sstevel@tonic-gate "%s%s has not yet been declared or assigned\n", 2764*7c478bd9Sstevel@tonic-gate (idp->di_flags & DT_IDFLG_LOCAL) ? "this->" : 2765*7c478bd9Sstevel@tonic-gate (idp->di_flags & DT_IDFLG_TLS) ? "self->" : "", 2766*7c478bd9Sstevel@tonic-gate idp->di_name); 2767*7c478bd9Sstevel@tonic-gate } 2768*7c478bd9Sstevel@tonic-gate 2769*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_ident_cook(dnp, idp, &dnp->dn_args)); 2770*7c478bd9Sstevel@tonic-gate return (dnp); 2771*7c478bd9Sstevel@tonic-gate } 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2774*7c478bd9Sstevel@tonic-gate static dt_node_t * 2775*7c478bd9Sstevel@tonic-gate dt_cook_func(dt_node_t *dnp, uint_t idflags) 2776*7c478bd9Sstevel@tonic-gate { 2777*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, 2778*7c478bd9Sstevel@tonic-gate dt_ident_cook(dnp, dnp->dn_ident, &dnp->dn_args)); 2779*7c478bd9Sstevel@tonic-gate 2780*7c478bd9Sstevel@tonic-gate return (dnp); 2781*7c478bd9Sstevel@tonic-gate } 2782*7c478bd9Sstevel@tonic-gate 2783*7c478bd9Sstevel@tonic-gate static dt_node_t * 2784*7c478bd9Sstevel@tonic-gate dt_cook_op1(dt_node_t *dnp, uint_t idflags) 2785*7c478bd9Sstevel@tonic-gate { 2786*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 2787*7c478bd9Sstevel@tonic-gate dt_node_t *cp = dnp->dn_child; 2788*7c478bd9Sstevel@tonic-gate 2789*7c478bd9Sstevel@tonic-gate char n[DT_TYPE_NAMELEN]; 2790*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 2791*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate ctf_encoding_t e; 2794*7c478bd9Sstevel@tonic-gate ctf_arinfo_t r; 2795*7c478bd9Sstevel@tonic-gate ctf_id_t type, base; 2796*7c478bd9Sstevel@tonic-gate uint_t kind; 2797*7c478bd9Sstevel@tonic-gate 2798*7c478bd9Sstevel@tonic-gate if (dnp->dn_op == DT_TOK_PREINC || dnp->dn_op == DT_TOK_POSTINC || 2799*7c478bd9Sstevel@tonic-gate dnp->dn_op == DT_TOK_PREDEC || dnp->dn_op == DT_TOK_POSTDEC) 2800*7c478bd9Sstevel@tonic-gate idflags = DT_IDFLG_REF | DT_IDFLG_MOD; 2801*7c478bd9Sstevel@tonic-gate else 2802*7c478bd9Sstevel@tonic-gate idflags = DT_IDFLG_REF; 2803*7c478bd9Sstevel@tonic-gate 2804*7c478bd9Sstevel@tonic-gate /* 2805*7c478bd9Sstevel@tonic-gate * We allow the unary ++ and -- operators to instantiate new scalar 2806*7c478bd9Sstevel@tonic-gate * variables if applied to an identifier; otherwise just cook as usual. 2807*7c478bd9Sstevel@tonic-gate */ 2808*7c478bd9Sstevel@tonic-gate if (cp->dn_kind == DT_NODE_IDENT && (idflags & DT_IDFLG_MOD)) 2809*7c478bd9Sstevel@tonic-gate dt_xcook_ident(cp, dtp->dt_globals, DT_IDENT_SCALAR, B_TRUE); 2810*7c478bd9Sstevel@tonic-gate 2811*7c478bd9Sstevel@tonic-gate cp = dnp->dn_child = dt_node_cook(cp, 0); /* don't set idflags yet */ 2812*7c478bd9Sstevel@tonic-gate 2813*7c478bd9Sstevel@tonic-gate if (cp->dn_kind == DT_NODE_VAR && dt_ident_unref(cp->dn_ident)) { 2814*7c478bd9Sstevel@tonic-gate if (dt_type_lookup("int64_t", &dtt) != 0) 2815*7c478bd9Sstevel@tonic-gate xyerror(D_TYPE_ERR, "failed to lookup int64_t\n"); 2816*7c478bd9Sstevel@tonic-gate 2817*7c478bd9Sstevel@tonic-gate dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type); 2818*7c478bd9Sstevel@tonic-gate dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type); 2819*7c478bd9Sstevel@tonic-gate } 2820*7c478bd9Sstevel@tonic-gate 2821*7c478bd9Sstevel@tonic-gate if (cp->dn_kind == DT_NODE_VAR) 2822*7c478bd9Sstevel@tonic-gate cp->dn_ident->di_flags |= idflags; 2823*7c478bd9Sstevel@tonic-gate 2824*7c478bd9Sstevel@tonic-gate switch (dnp->dn_op) { 2825*7c478bd9Sstevel@tonic-gate case DT_TOK_DEREF: 2826*7c478bd9Sstevel@tonic-gate /* 2827*7c478bd9Sstevel@tonic-gate * If the deref operator is applied to a translated pointer, 2828*7c478bd9Sstevel@tonic-gate * we can just set our output type to the base translation. 2829*7c478bd9Sstevel@tonic-gate */ 2830*7c478bd9Sstevel@tonic-gate if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) { 2831*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp = idp->di_data; 2832*7c478bd9Sstevel@tonic-gate 2833*7c478bd9Sstevel@tonic-gate dnp->dn_ident = &dxp->dx_souid; 2834*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, 2835*7c478bd9Sstevel@tonic-gate DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 2836*7c478bd9Sstevel@tonic-gate break; 2837*7c478bd9Sstevel@tonic-gate } 2838*7c478bd9Sstevel@tonic-gate 2839*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(cp->dn_ctfp, cp->dn_type); 2840*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(cp->dn_ctfp, type); 2841*7c478bd9Sstevel@tonic-gate 2842*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_ARRAY) { 2843*7c478bd9Sstevel@tonic-gate if (ctf_array_info(cp->dn_ctfp, type, &r) != 0) { 2844*7c478bd9Sstevel@tonic-gate dtp->dt_ctferr = ctf_errno(cp->dn_ctfp); 2845*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF); 2846*7c478bd9Sstevel@tonic-gate } else 2847*7c478bd9Sstevel@tonic-gate type = r.ctr_contents; 2848*7c478bd9Sstevel@tonic-gate } else if (kind == CTF_K_POINTER) { 2849*7c478bd9Sstevel@tonic-gate type = ctf_type_reference(cp->dn_ctfp, type); 2850*7c478bd9Sstevel@tonic-gate } else { 2851*7c478bd9Sstevel@tonic-gate xyerror(D_DEREF_NONPTR, 2852*7c478bd9Sstevel@tonic-gate "cannot dereference non-pointer type\n"); 2853*7c478bd9Sstevel@tonic-gate } 2854*7c478bd9Sstevel@tonic-gate 2855*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, cp->dn_ctfp, type); 2856*7c478bd9Sstevel@tonic-gate base = ctf_type_resolve(cp->dn_ctfp, type); 2857*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(cp->dn_ctfp, base); 2858*7c478bd9Sstevel@tonic-gate 2859*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_INTEGER && ctf_type_encoding(cp->dn_ctfp, 2860*7c478bd9Sstevel@tonic-gate base, &e) == 0 && IS_VOID(e)) { 2861*7c478bd9Sstevel@tonic-gate xyerror(D_DEREF_VOID, 2862*7c478bd9Sstevel@tonic-gate "cannot dereference pointer to void\n"); 2863*7c478bd9Sstevel@tonic-gate } 2864*7c478bd9Sstevel@tonic-gate 2865*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_FUNCTION) { 2866*7c478bd9Sstevel@tonic-gate xyerror(D_DEREF_FUNC, 2867*7c478bd9Sstevel@tonic-gate "cannot dereference pointer to function\n"); 2868*7c478bd9Sstevel@tonic-gate } 2869*7c478bd9Sstevel@tonic-gate 2870*7c478bd9Sstevel@tonic-gate if (kind != CTF_K_ARRAY || dt_node_is_string(dnp)) 2871*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.4.3] */ 2872*7c478bd9Sstevel@tonic-gate 2873*7c478bd9Sstevel@tonic-gate /* 2874*7c478bd9Sstevel@tonic-gate * If we propagated the l-value bit and the child operand was 2875*7c478bd9Sstevel@tonic-gate * a writable D variable or a binary operation of the form 2876*7c478bd9Sstevel@tonic-gate * a + b where a is writable, then propagate the writable bit. 2877*7c478bd9Sstevel@tonic-gate * This is necessary to permit assignments to scalar arrays, 2878*7c478bd9Sstevel@tonic-gate * which are converted to expressions of the form *(a + i). 2879*7c478bd9Sstevel@tonic-gate */ 2880*7c478bd9Sstevel@tonic-gate if ((cp->dn_flags & DT_NF_WRITABLE) || 2881*7c478bd9Sstevel@tonic-gate (cp->dn_kind == DT_NODE_OP2 && cp->dn_op == DT_TOK_ADD && 2882*7c478bd9Sstevel@tonic-gate (cp->dn_left->dn_flags & DT_NF_WRITABLE))) 2883*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_WRITABLE; 2884*7c478bd9Sstevel@tonic-gate 2885*7c478bd9Sstevel@tonic-gate if ((cp->dn_flags & DT_NF_USERLAND) && 2886*7c478bd9Sstevel@tonic-gate (kind == CTF_K_POINTER || (dnp->dn_flags & DT_NF_REF))) 2887*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_USERLAND; 2888*7c478bd9Sstevel@tonic-gate break; 2889*7c478bd9Sstevel@tonic-gate 2890*7c478bd9Sstevel@tonic-gate case DT_TOK_IPOS: 2891*7c478bd9Sstevel@tonic-gate case DT_TOK_INEG: 2892*7c478bd9Sstevel@tonic-gate if (!dt_node_is_arith(cp)) { 2893*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ARITH, "operator %s requires an operand " 2894*7c478bd9Sstevel@tonic-gate "of arithmetic type\n", opstr(dnp->dn_op)); 2895*7c478bd9Sstevel@tonic-gate } 2896*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.4-6] */ 2897*7c478bd9Sstevel@tonic-gate break; 2898*7c478bd9Sstevel@tonic-gate 2899*7c478bd9Sstevel@tonic-gate case DT_TOK_BNEG: 2900*7c478bd9Sstevel@tonic-gate if (!dt_node_is_integer(cp)) { 2901*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INT, "operator %s requires an operand of " 2902*7c478bd9Sstevel@tonic-gate "integral type\n", opstr(dnp->dn_op)); 2903*7c478bd9Sstevel@tonic-gate } 2904*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.4-6] */ 2905*7c478bd9Sstevel@tonic-gate break; 2906*7c478bd9Sstevel@tonic-gate 2907*7c478bd9Sstevel@tonic-gate case DT_TOK_LNEG: 2908*7c478bd9Sstevel@tonic-gate if (!dt_node_is_scalar(cp)) { 2909*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SCALAR, "operator %s requires an operand " 2910*7c478bd9Sstevel@tonic-gate "of scalar type\n", opstr(dnp->dn_op)); 2911*7c478bd9Sstevel@tonic-gate } 2912*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 2913*7c478bd9Sstevel@tonic-gate break; 2914*7c478bd9Sstevel@tonic-gate 2915*7c478bd9Sstevel@tonic-gate case DT_TOK_ADDROF: 2916*7c478bd9Sstevel@tonic-gate if (cp->dn_kind == DT_NODE_VAR || cp->dn_kind == DT_NODE_AGG) { 2917*7c478bd9Sstevel@tonic-gate xyerror(D_ADDROF_VAR, 2918*7c478bd9Sstevel@tonic-gate "cannot take address of dynamic variable\n"); 2919*7c478bd9Sstevel@tonic-gate } 2920*7c478bd9Sstevel@tonic-gate 2921*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(cp)) { 2922*7c478bd9Sstevel@tonic-gate xyerror(D_ADDROF_VAR, 2923*7c478bd9Sstevel@tonic-gate "cannot take address of dynamic object\n"); 2924*7c478bd9Sstevel@tonic-gate } 2925*7c478bd9Sstevel@tonic-gate 2926*7c478bd9Sstevel@tonic-gate if (!(cp->dn_flags & DT_NF_LVALUE)) { 2927*7c478bd9Sstevel@tonic-gate xyerror(D_ADDROF_LVAL, /* see K&R[A7.4.2] */ 2928*7c478bd9Sstevel@tonic-gate "unacceptable operand for unary & operator\n"); 2929*7c478bd9Sstevel@tonic-gate } 2930*7c478bd9Sstevel@tonic-gate 2931*7c478bd9Sstevel@tonic-gate if (cp->dn_flags & DT_NF_BITFIELD) { 2932*7c478bd9Sstevel@tonic-gate xyerror(D_ADDROF_BITFIELD, 2933*7c478bd9Sstevel@tonic-gate "cannot take address of bit-field\n"); 2934*7c478bd9Sstevel@tonic-gate } 2935*7c478bd9Sstevel@tonic-gate 2936*7c478bd9Sstevel@tonic-gate dtt.dtt_object = NULL; 2937*7c478bd9Sstevel@tonic-gate dtt.dtt_ctfp = cp->dn_ctfp; 2938*7c478bd9Sstevel@tonic-gate dtt.dtt_type = cp->dn_type; 2939*7c478bd9Sstevel@tonic-gate 2940*7c478bd9Sstevel@tonic-gate if (dt_type_pointer(&dtt) == -1) { 2941*7c478bd9Sstevel@tonic-gate xyerror(D_TYPE_ERR, "cannot find type for \"&\": %s*\n", 2942*7c478bd9Sstevel@tonic-gate dt_node_type_name(cp, n, sizeof (n))); 2943*7c478bd9Sstevel@tonic-gate } 2944*7c478bd9Sstevel@tonic-gate 2945*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type); 2946*7c478bd9Sstevel@tonic-gate 2947*7c478bd9Sstevel@tonic-gate if (cp->dn_flags & DT_NF_USERLAND) 2948*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_USERLAND; 2949*7c478bd9Sstevel@tonic-gate break; 2950*7c478bd9Sstevel@tonic-gate 2951*7c478bd9Sstevel@tonic-gate case DT_TOK_SIZEOF: 2952*7c478bd9Sstevel@tonic-gate if (cp->dn_flags & DT_NF_BITFIELD) { 2953*7c478bd9Sstevel@tonic-gate xyerror(D_SIZEOF_BITFIELD, 2954*7c478bd9Sstevel@tonic-gate "cannot apply sizeof to a bit-field\n"); 2955*7c478bd9Sstevel@tonic-gate } 2956*7c478bd9Sstevel@tonic-gate 2957*7c478bd9Sstevel@tonic-gate if (dt_node_sizeof(cp) == 0) { 2958*7c478bd9Sstevel@tonic-gate xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an " 2959*7c478bd9Sstevel@tonic-gate "operand of unknown size\n"); 2960*7c478bd9Sstevel@tonic-gate } 2961*7c478bd9Sstevel@tonic-gate 2962*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp, 2963*7c478bd9Sstevel@tonic-gate ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t")); 2964*7c478bd9Sstevel@tonic-gate break; 2965*7c478bd9Sstevel@tonic-gate 2966*7c478bd9Sstevel@tonic-gate case DT_TOK_STRINGOF: 2967*7c478bd9Sstevel@tonic-gate if (!dt_node_is_scalar(cp) && !dt_node_is_pointer(cp) && 2968*7c478bd9Sstevel@tonic-gate !dt_node_is_strcompat(cp)) { 2969*7c478bd9Sstevel@tonic-gate xyerror(D_STRINGOF_TYPE, 2970*7c478bd9Sstevel@tonic-gate "cannot apply stringof to a value of type %s\n", 2971*7c478bd9Sstevel@tonic-gate dt_node_type_name(cp, n, sizeof (n))); 2972*7c478bd9Sstevel@tonic-gate } 2973*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp)); 2974*7c478bd9Sstevel@tonic-gate break; 2975*7c478bd9Sstevel@tonic-gate 2976*7c478bd9Sstevel@tonic-gate case DT_TOK_PREINC: 2977*7c478bd9Sstevel@tonic-gate case DT_TOK_POSTINC: 2978*7c478bd9Sstevel@tonic-gate case DT_TOK_PREDEC: 2979*7c478bd9Sstevel@tonic-gate case DT_TOK_POSTDEC: 2980*7c478bd9Sstevel@tonic-gate if (dt_node_is_scalar(cp) == 0) { 2981*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SCALAR, "operator %s requires operand of " 2982*7c478bd9Sstevel@tonic-gate "scalar type\n", opstr(dnp->dn_op)); 2983*7c478bd9Sstevel@tonic-gate } 2984*7c478bd9Sstevel@tonic-gate 2985*7c478bd9Sstevel@tonic-gate if (dt_node_is_vfptr(cp)) { 2986*7c478bd9Sstevel@tonic-gate xyerror(D_OP_VFPTR, "operator %s requires an operand " 2987*7c478bd9Sstevel@tonic-gate "of known size\n", opstr(dnp->dn_op)); 2988*7c478bd9Sstevel@tonic-gate } 2989*7c478bd9Sstevel@tonic-gate 2990*7c478bd9Sstevel@tonic-gate if (!(cp->dn_flags & DT_NF_LVALUE)) { 2991*7c478bd9Sstevel@tonic-gate xyerror(D_OP_LVAL, "operator %s requires modifiable " 2992*7c478bd9Sstevel@tonic-gate "lvalue as an operand\n", opstr(dnp->dn_op)); 2993*7c478bd9Sstevel@tonic-gate } 2994*7c478bd9Sstevel@tonic-gate 2995*7c478bd9Sstevel@tonic-gate if (!(cp->dn_flags & DT_NF_WRITABLE)) { 2996*7c478bd9Sstevel@tonic-gate xyerror(D_OP_WRITE, "operator %s can only be applied " 2997*7c478bd9Sstevel@tonic-gate "to a writable variable\n", opstr(dnp->dn_op)); 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate 3000*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.1] */ 3001*7c478bd9Sstevel@tonic-gate break; 3002*7c478bd9Sstevel@tonic-gate 3003*7c478bd9Sstevel@tonic-gate default: 3004*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "invalid unary op %s\n", opstr(dnp->dn_op)); 3005*7c478bd9Sstevel@tonic-gate } 3006*7c478bd9Sstevel@tonic-gate 3007*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, cp->dn_attr); 3008*7c478bd9Sstevel@tonic-gate return (dnp); 3009*7c478bd9Sstevel@tonic-gate } 3010*7c478bd9Sstevel@tonic-gate 3011*7c478bd9Sstevel@tonic-gate static dt_node_t * 3012*7c478bd9Sstevel@tonic-gate dt_cook_op2(dt_node_t *dnp, uint_t idflags) 3013*7c478bd9Sstevel@tonic-gate { 3014*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 3015*7c478bd9Sstevel@tonic-gate dt_node_t *lp = dnp->dn_left; 3016*7c478bd9Sstevel@tonic-gate dt_node_t *rp = dnp->dn_right; 3017*7c478bd9Sstevel@tonic-gate int op = dnp->dn_op; 3018*7c478bd9Sstevel@tonic-gate 3019*7c478bd9Sstevel@tonic-gate ctf_membinfo_t m; 3020*7c478bd9Sstevel@tonic-gate ctf_file_t *ctfp; 3021*7c478bd9Sstevel@tonic-gate ctf_id_t type; 3022*7c478bd9Sstevel@tonic-gate int kind, val, uref; 3023*7c478bd9Sstevel@tonic-gate dt_ident_t *idp; 3024*7c478bd9Sstevel@tonic-gate 3025*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 3026*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 3027*7c478bd9Sstevel@tonic-gate 3028*7c478bd9Sstevel@tonic-gate /* 3029*7c478bd9Sstevel@tonic-gate * The expression E1[E2] is identical by definition to *((E1)+(E2)) so 3030*7c478bd9Sstevel@tonic-gate * we convert "[" to "+" and glue on "*" at the end (see K&R[A7.3.1]) 3031*7c478bd9Sstevel@tonic-gate * unless the left-hand side is an untyped D scalar, associative array, 3032*7c478bd9Sstevel@tonic-gate * or aggregation. In these cases, we proceed to case DT_TOK_LBRAC and 3033*7c478bd9Sstevel@tonic-gate * handle associative array and aggregation references there. 3034*7c478bd9Sstevel@tonic-gate */ 3035*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_LBRAC) { 3036*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT) { 3037*7c478bd9Sstevel@tonic-gate dt_idhash_t *dhp; 3038*7c478bd9Sstevel@tonic-gate uint_t idkind; 3039*7c478bd9Sstevel@tonic-gate 3040*7c478bd9Sstevel@tonic-gate if (lp->dn_op == DT_TOK_AGG) { 3041*7c478bd9Sstevel@tonic-gate dhp = dtp->dt_aggs; 3042*7c478bd9Sstevel@tonic-gate idp = dt_idhash_lookup(dhp, lp->dn_string + 1); 3043*7c478bd9Sstevel@tonic-gate idkind = DT_IDENT_AGG; 3044*7c478bd9Sstevel@tonic-gate } else { 3045*7c478bd9Sstevel@tonic-gate dhp = dtp->dt_globals; 3046*7c478bd9Sstevel@tonic-gate idp = dt_idstack_lookup( 3047*7c478bd9Sstevel@tonic-gate &yypcb->pcb_globals, lp->dn_string); 3048*7c478bd9Sstevel@tonic-gate idkind = DT_IDENT_ARRAY; 3049*7c478bd9Sstevel@tonic-gate } 3050*7c478bd9Sstevel@tonic-gate 3051*7c478bd9Sstevel@tonic-gate if (idp == NULL || dt_ident_unref(idp)) 3052*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dhp, idkind, B_TRUE); 3053*7c478bd9Sstevel@tonic-gate else 3054*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE); 3055*7c478bd9Sstevel@tonic-gate } else 3056*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, 0); 3057*7c478bd9Sstevel@tonic-gate 3058*7c478bd9Sstevel@tonic-gate /* 3059*7c478bd9Sstevel@tonic-gate * Switch op to '+' for *(E1 + E2) array mode in these cases: 3060*7c478bd9Sstevel@tonic-gate * (a) lp is a DT_IDENT_ARRAY variable that has already been 3061*7c478bd9Sstevel@tonic-gate * referenced using [] notation (dn_args != NULL). 3062*7c478bd9Sstevel@tonic-gate * (b) lp is a non-ARRAY variable that has already been given 3063*7c478bd9Sstevel@tonic-gate * a type by assignment or declaration (!dt_ident_unref()) 3064*7c478bd9Sstevel@tonic-gate * (c) lp is neither a variable nor an aggregation 3065*7c478bd9Sstevel@tonic-gate */ 3066*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_VAR) { 3067*7c478bd9Sstevel@tonic-gate if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) { 3068*7c478bd9Sstevel@tonic-gate if (lp->dn_args != NULL) 3069*7c478bd9Sstevel@tonic-gate op = DT_TOK_ADD; 3070*7c478bd9Sstevel@tonic-gate } else if (!dt_ident_unref(lp->dn_ident)) 3071*7c478bd9Sstevel@tonic-gate op = DT_TOK_ADD; 3072*7c478bd9Sstevel@tonic-gate } else if (lp->dn_kind != DT_NODE_AGG) 3073*7c478bd9Sstevel@tonic-gate op = DT_TOK_ADD; 3074*7c478bd9Sstevel@tonic-gate } 3075*7c478bd9Sstevel@tonic-gate 3076*7c478bd9Sstevel@tonic-gate switch (op) { 3077*7c478bd9Sstevel@tonic-gate case DT_TOK_BAND: 3078*7c478bd9Sstevel@tonic-gate case DT_TOK_XOR: 3079*7c478bd9Sstevel@tonic-gate case DT_TOK_BOR: 3080*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3081*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3082*7c478bd9Sstevel@tonic-gate 3083*7c478bd9Sstevel@tonic-gate if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) { 3084*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INT, "operator %s requires operands of " 3085*7c478bd9Sstevel@tonic-gate "integral type\n", opstr(op)); 3086*7c478bd9Sstevel@tonic-gate } 3087*7c478bd9Sstevel@tonic-gate 3088*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); /* see K&R[A7.11-13] */ 3089*7c478bd9Sstevel@tonic-gate break; 3090*7c478bd9Sstevel@tonic-gate 3091*7c478bd9Sstevel@tonic-gate case DT_TOK_LSH: 3092*7c478bd9Sstevel@tonic-gate case DT_TOK_RSH: 3093*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3094*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3095*7c478bd9Sstevel@tonic-gate 3096*7c478bd9Sstevel@tonic-gate if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) { 3097*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INT, "operator %s requires operands of " 3098*7c478bd9Sstevel@tonic-gate "integral type\n", opstr(op)); 3099*7c478bd9Sstevel@tonic-gate } 3100*7c478bd9Sstevel@tonic-gate 3101*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, dnp); /* see K&R[A7.8] */ 3102*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3103*7c478bd9Sstevel@tonic-gate break; 3104*7c478bd9Sstevel@tonic-gate 3105*7c478bd9Sstevel@tonic-gate case DT_TOK_MOD: 3106*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3107*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3108*7c478bd9Sstevel@tonic-gate 3109*7c478bd9Sstevel@tonic-gate if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) { 3110*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INT, "operator %s requires operands of " 3111*7c478bd9Sstevel@tonic-gate "integral type\n", opstr(op)); 3112*7c478bd9Sstevel@tonic-gate } 3113*7c478bd9Sstevel@tonic-gate 3114*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); /* see K&R[A7.6] */ 3115*7c478bd9Sstevel@tonic-gate break; 3116*7c478bd9Sstevel@tonic-gate 3117*7c478bd9Sstevel@tonic-gate case DT_TOK_MUL: 3118*7c478bd9Sstevel@tonic-gate case DT_TOK_DIV: 3119*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3120*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3121*7c478bd9Sstevel@tonic-gate 3122*7c478bd9Sstevel@tonic-gate if (!dt_node_is_arith(lp) || !dt_node_is_arith(rp)) { 3123*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ARITH, "operator %s requires operands of " 3124*7c478bd9Sstevel@tonic-gate "arithmetic type\n", opstr(op)); 3125*7c478bd9Sstevel@tonic-gate } 3126*7c478bd9Sstevel@tonic-gate 3127*7c478bd9Sstevel@tonic-gate dt_node_promote(lp, rp, dnp); /* see K&R[A7.6] */ 3128*7c478bd9Sstevel@tonic-gate break; 3129*7c478bd9Sstevel@tonic-gate 3130*7c478bd9Sstevel@tonic-gate case DT_TOK_LAND: 3131*7c478bd9Sstevel@tonic-gate case DT_TOK_LXOR: 3132*7c478bd9Sstevel@tonic-gate case DT_TOK_LOR: 3133*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3134*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3135*7c478bd9Sstevel@tonic-gate 3136*7c478bd9Sstevel@tonic-gate if (!dt_node_is_scalar(lp) || !dt_node_is_scalar(rp)) { 3137*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SCALAR, "operator %s requires operands " 3138*7c478bd9Sstevel@tonic-gate "of scalar type\n", opstr(op)); 3139*7c478bd9Sstevel@tonic-gate } 3140*7c478bd9Sstevel@tonic-gate 3141*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 3142*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3143*7c478bd9Sstevel@tonic-gate break; 3144*7c478bd9Sstevel@tonic-gate 3145*7c478bd9Sstevel@tonic-gate case DT_TOK_LT: 3146*7c478bd9Sstevel@tonic-gate case DT_TOK_LE: 3147*7c478bd9Sstevel@tonic-gate case DT_TOK_GT: 3148*7c478bd9Sstevel@tonic-gate case DT_TOK_GE: 3149*7c478bd9Sstevel@tonic-gate case DT_TOK_EQU: 3150*7c478bd9Sstevel@tonic-gate case DT_TOK_NEQ: 3151*7c478bd9Sstevel@tonic-gate /* 3152*7c478bd9Sstevel@tonic-gate * The D comparison operators provide the ability to transform 3153*7c478bd9Sstevel@tonic-gate * a right-hand identifier into a corresponding enum tag value 3154*7c478bd9Sstevel@tonic-gate * if the left-hand side is an enum type. To do this, we cook 3155*7c478bd9Sstevel@tonic-gate * the left-hand side, and then see if the right-hand side is 3156*7c478bd9Sstevel@tonic-gate * an unscoped identifier defined in the enum. If so, we 3157*7c478bd9Sstevel@tonic-gate * convert into an integer constant node with the tag's value. 3158*7c478bd9Sstevel@tonic-gate */ 3159*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3160*7c478bd9Sstevel@tonic-gate 3161*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(lp->dn_ctfp, 3162*7c478bd9Sstevel@tonic-gate ctf_type_resolve(lp->dn_ctfp, lp->dn_type)); 3163*7c478bd9Sstevel@tonic-gate 3164*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_ENUM && rp->dn_kind == DT_NODE_IDENT && 3165*7c478bd9Sstevel@tonic-gate strchr(rp->dn_string, '`') == NULL && ctf_enum_value( 3166*7c478bd9Sstevel@tonic-gate lp->dn_ctfp, lp->dn_type, rp->dn_string, &val) == 0) { 3167*7c478bd9Sstevel@tonic-gate 3168*7c478bd9Sstevel@tonic-gate if ((idp = dt_idstack_lookup(&yypcb->pcb_globals, 3169*7c478bd9Sstevel@tonic-gate rp->dn_string)) != NULL) { 3170*7c478bd9Sstevel@tonic-gate xyerror(D_IDENT_AMBIG, 3171*7c478bd9Sstevel@tonic-gate "ambiguous use of operator %s: %s is " 3172*7c478bd9Sstevel@tonic-gate "both a %s enum tag and a global %s\n", 3173*7c478bd9Sstevel@tonic-gate opstr(op), rp->dn_string, 3174*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), 3175*7c478bd9Sstevel@tonic-gate dt_idkind_name(idp->di_kind)); 3176*7c478bd9Sstevel@tonic-gate } 3177*7c478bd9Sstevel@tonic-gate 3178*7c478bd9Sstevel@tonic-gate free(rp->dn_string); 3179*7c478bd9Sstevel@tonic-gate rp->dn_string = NULL; 3180*7c478bd9Sstevel@tonic-gate rp->dn_kind = DT_NODE_INT; 3181*7c478bd9Sstevel@tonic-gate rp->dn_flags |= DT_NF_COOKED; 3182*7c478bd9Sstevel@tonic-gate rp->dn_op = DT_TOK_INT; 3183*7c478bd9Sstevel@tonic-gate rp->dn_value = (intmax_t)val; 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type); 3186*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(rp, _dtrace_symattr); 3187*7c478bd9Sstevel@tonic-gate } 3188*7c478bd9Sstevel@tonic-gate 3189*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3190*7c478bd9Sstevel@tonic-gate 3191*7c478bd9Sstevel@tonic-gate /* 3192*7c478bd9Sstevel@tonic-gate * The rules for type checking for the relational operators are 3193*7c478bd9Sstevel@tonic-gate * described in the ANSI-C spec (see K&R[A7.9-10]). We perform 3194*7c478bd9Sstevel@tonic-gate * the various tests in order from least to most expensive. We 3195*7c478bd9Sstevel@tonic-gate * also allow derived strings to be compared as a first-class 3196*7c478bd9Sstevel@tonic-gate * type (resulting in a strcmp(3C)-style comparison), and we 3197*7c478bd9Sstevel@tonic-gate * slightly relax the A7.9 rules to permit void pointer 3198*7c478bd9Sstevel@tonic-gate * comparisons as in A7.10. Our users won't be confused by 3199*7c478bd9Sstevel@tonic-gate * this since they understand pointers are just numbers, and 3200*7c478bd9Sstevel@tonic-gate * relaxing this constraint simplifies the implementation. 3201*7c478bd9Sstevel@tonic-gate */ 3202*7c478bd9Sstevel@tonic-gate if (ctf_type_compat(lp->dn_ctfp, lp->dn_type, 3203*7c478bd9Sstevel@tonic-gate rp->dn_ctfp, rp->dn_type)) 3204*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3205*7c478bd9Sstevel@tonic-gate else if (dt_node_is_integer(lp) && dt_node_is_integer(rp)) 3206*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3207*7c478bd9Sstevel@tonic-gate else if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp) && 3208*7c478bd9Sstevel@tonic-gate (dt_node_is_string(lp) || dt_node_is_string(rp))) 3209*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3210*7c478bd9Sstevel@tonic-gate else if (dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) { 3211*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, "operands have " 3212*7c478bd9Sstevel@tonic-gate "incompatible types: \"%s\" %s \"%s\"\n", 3213*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), opstr(op), 3214*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n2, sizeof (n2))); 3215*7c478bd9Sstevel@tonic-gate } 3216*7c478bd9Sstevel@tonic-gate 3217*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); 3218*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3219*7c478bd9Sstevel@tonic-gate break; 3220*7c478bd9Sstevel@tonic-gate 3221*7c478bd9Sstevel@tonic-gate case DT_TOK_ADD: 3222*7c478bd9Sstevel@tonic-gate case DT_TOK_SUB: { 3223*7c478bd9Sstevel@tonic-gate /* 3224*7c478bd9Sstevel@tonic-gate * The rules for type checking for the additive operators are 3225*7c478bd9Sstevel@tonic-gate * described in the ANSI-C spec (see K&R[A7.7]). Pointers and 3226*7c478bd9Sstevel@tonic-gate * integers may be manipulated according to specific rules. 3227*7c478bd9Sstevel@tonic-gate */ 3228*7c478bd9Sstevel@tonic-gate int lp_is_ptr, lp_is_int, rp_is_ptr, rp_is_int; 3229*7c478bd9Sstevel@tonic-gate 3230*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3231*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3232*7c478bd9Sstevel@tonic-gate 3233*7c478bd9Sstevel@tonic-gate lp_is_ptr = dt_node_is_pointer(lp) && !dt_node_is_vfptr(lp); 3234*7c478bd9Sstevel@tonic-gate lp_is_int = dt_node_is_integer(lp); 3235*7c478bd9Sstevel@tonic-gate 3236*7c478bd9Sstevel@tonic-gate rp_is_ptr = dt_node_is_pointer(rp) && !dt_node_is_vfptr(rp); 3237*7c478bd9Sstevel@tonic-gate rp_is_int = dt_node_is_integer(rp); 3238*7c478bd9Sstevel@tonic-gate 3239*7c478bd9Sstevel@tonic-gate if (lp_is_int && rp_is_int) { 3240*7c478bd9Sstevel@tonic-gate dt_type_promote(lp, rp, &ctfp, &type); 3241*7c478bd9Sstevel@tonic-gate uref = 0; 3242*7c478bd9Sstevel@tonic-gate } else if (lp_is_ptr && rp_is_int) { 3243*7c478bd9Sstevel@tonic-gate ctfp = lp->dn_ctfp; 3244*7c478bd9Sstevel@tonic-gate type = lp->dn_type; 3245*7c478bd9Sstevel@tonic-gate uref = lp->dn_flags & DT_NF_USERLAND; 3246*7c478bd9Sstevel@tonic-gate } else if (lp_is_int && rp_is_ptr && op == DT_TOK_ADD) { 3247*7c478bd9Sstevel@tonic-gate ctfp = rp->dn_ctfp; 3248*7c478bd9Sstevel@tonic-gate type = rp->dn_type; 3249*7c478bd9Sstevel@tonic-gate uref = rp->dn_flags & DT_NF_USERLAND; 3250*7c478bd9Sstevel@tonic-gate } else if (lp_is_ptr && rp_is_ptr && op == DT_TOK_SUB && 3251*7c478bd9Sstevel@tonic-gate dt_node_is_ptrcompat(lp, rp, NULL, NULL)) { 3252*7c478bd9Sstevel@tonic-gate ctfp = dtp->dt_ddefs->dm_ctfp; 3253*7c478bd9Sstevel@tonic-gate type = ctf_lookup_by_name(ctfp, "ptrdiff_t"); 3254*7c478bd9Sstevel@tonic-gate uref = 0; 3255*7c478bd9Sstevel@tonic-gate } else { 3256*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, "operands have incompatible " 3257*7c478bd9Sstevel@tonic-gate "types: \"%s\" %s \"%s\"\n", 3258*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), opstr(op), 3259*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n2, sizeof (n2))); 3260*7c478bd9Sstevel@tonic-gate } 3261*7c478bd9Sstevel@tonic-gate 3262*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, ctfp, type); 3263*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3264*7c478bd9Sstevel@tonic-gate 3265*7c478bd9Sstevel@tonic-gate if (uref) 3266*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_USERLAND; 3267*7c478bd9Sstevel@tonic-gate break; 3268*7c478bd9Sstevel@tonic-gate } 3269*7c478bd9Sstevel@tonic-gate 3270*7c478bd9Sstevel@tonic-gate case DT_TOK_OR_EQ: 3271*7c478bd9Sstevel@tonic-gate case DT_TOK_XOR_EQ: 3272*7c478bd9Sstevel@tonic-gate case DT_TOK_AND_EQ: 3273*7c478bd9Sstevel@tonic-gate case DT_TOK_LSH_EQ: 3274*7c478bd9Sstevel@tonic-gate case DT_TOK_RSH_EQ: 3275*7c478bd9Sstevel@tonic-gate case DT_TOK_MOD_EQ: 3276*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT) { 3277*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dtp->dt_globals, 3278*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3279*7c478bd9Sstevel@tonic-gate } 3280*7c478bd9Sstevel@tonic-gate 3281*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = 3282*7c478bd9Sstevel@tonic-gate dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD); 3283*7c478bd9Sstevel@tonic-gate 3284*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = 3285*7c478bd9Sstevel@tonic-gate dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD); 3286*7c478bd9Sstevel@tonic-gate 3287*7c478bd9Sstevel@tonic-gate if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) { 3288*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INT, "operator %s requires operands of " 3289*7c478bd9Sstevel@tonic-gate "integral type\n", opstr(op)); 3290*7c478bd9Sstevel@tonic-gate } 3291*7c478bd9Sstevel@tonic-gate goto asgn_common; 3292*7c478bd9Sstevel@tonic-gate 3293*7c478bd9Sstevel@tonic-gate case DT_TOK_MUL_EQ: 3294*7c478bd9Sstevel@tonic-gate case DT_TOK_DIV_EQ: 3295*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT) { 3296*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dtp->dt_globals, 3297*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3298*7c478bd9Sstevel@tonic-gate } 3299*7c478bd9Sstevel@tonic-gate 3300*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = 3301*7c478bd9Sstevel@tonic-gate dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD); 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = 3304*7c478bd9Sstevel@tonic-gate dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD); 3305*7c478bd9Sstevel@tonic-gate 3306*7c478bd9Sstevel@tonic-gate if (!dt_node_is_arith(lp) || !dt_node_is_arith(rp)) { 3307*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ARITH, "operator %s requires operands of " 3308*7c478bd9Sstevel@tonic-gate "arithmetic type\n", opstr(op)); 3309*7c478bd9Sstevel@tonic-gate } 3310*7c478bd9Sstevel@tonic-gate goto asgn_common; 3311*7c478bd9Sstevel@tonic-gate 3312*7c478bd9Sstevel@tonic-gate case DT_TOK_ASGN: 3313*7c478bd9Sstevel@tonic-gate /* 3314*7c478bd9Sstevel@tonic-gate * If the left-hand side is an identifier, attempt to resolve 3315*7c478bd9Sstevel@tonic-gate * it as either an aggregation or scalar variable. We pass 3316*7c478bd9Sstevel@tonic-gate * B_TRUE to dt_xcook_ident to indicate that a new variable can 3317*7c478bd9Sstevel@tonic-gate * be created if no matching variable exists in the namespace. 3318*7c478bd9Sstevel@tonic-gate */ 3319*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT) { 3320*7c478bd9Sstevel@tonic-gate if (lp->dn_op == DT_TOK_AGG) { 3321*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dtp->dt_aggs, 3322*7c478bd9Sstevel@tonic-gate DT_IDENT_AGG, B_TRUE); 3323*7c478bd9Sstevel@tonic-gate } else { 3324*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dtp->dt_globals, 3325*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3326*7c478bd9Sstevel@tonic-gate } 3327*7c478bd9Sstevel@tonic-gate } 3328*7c478bd9Sstevel@tonic-gate 3329*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, 0); /* don't set mod yet */ 3330*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3331*7c478bd9Sstevel@tonic-gate 3332*7c478bd9Sstevel@tonic-gate /* 3333*7c478bd9Sstevel@tonic-gate * If the left-hand side is an aggregation, verify that we are 3334*7c478bd9Sstevel@tonic-gate * assigning it the result of an aggregating function. Once 3335*7c478bd9Sstevel@tonic-gate * we've done so, hide the func node in the aggregation and 3336*7c478bd9Sstevel@tonic-gate * return the aggregation itself up to the parse tree parent. 3337*7c478bd9Sstevel@tonic-gate * This transformation is legal since the assigned function 3338*7c478bd9Sstevel@tonic-gate * cannot change identity across disjoint cooking passes and 3339*7c478bd9Sstevel@tonic-gate * the argument list subtree is retained for later cooking. 3340*7c478bd9Sstevel@tonic-gate */ 3341*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_AGG) { 3342*7c478bd9Sstevel@tonic-gate const char *aname = lp->dn_ident->di_name; 3343*7c478bd9Sstevel@tonic-gate dt_ident_t *oid = lp->dn_ident->di_iarg; 3344*7c478bd9Sstevel@tonic-gate 3345*7c478bd9Sstevel@tonic-gate if (rp->dn_kind != DT_NODE_FUNC || 3346*7c478bd9Sstevel@tonic-gate rp->dn_ident->di_kind != DT_IDENT_AGGFUNC) { 3347*7c478bd9Sstevel@tonic-gate xyerror(D_AGG_FUNC, 3348*7c478bd9Sstevel@tonic-gate "@%s must be assigned the result of " 3349*7c478bd9Sstevel@tonic-gate "an aggregating function\n", aname); 3350*7c478bd9Sstevel@tonic-gate } 3351*7c478bd9Sstevel@tonic-gate 3352*7c478bd9Sstevel@tonic-gate if (oid != NULL && oid != rp->dn_ident) { 3353*7c478bd9Sstevel@tonic-gate xyerror(D_AGG_REDEF, 3354*7c478bd9Sstevel@tonic-gate "aggregation redefined: @%s\n\t " 3355*7c478bd9Sstevel@tonic-gate "current: @%s = %s( )\n\tprevious: @%s = " 3356*7c478bd9Sstevel@tonic-gate "%s( ) : line %d\n", aname, aname, 3357*7c478bd9Sstevel@tonic-gate rp->dn_ident->di_name, aname, oid->di_name, 3358*7c478bd9Sstevel@tonic-gate lp->dn_ident->di_lineno); 3359*7c478bd9Sstevel@tonic-gate } else if (oid == NULL) 3360*7c478bd9Sstevel@tonic-gate lp->dn_ident->di_iarg = rp->dn_ident; 3361*7c478bd9Sstevel@tonic-gate 3362*7c478bd9Sstevel@tonic-gate /* 3363*7c478bd9Sstevel@tonic-gate * Do not allow multiple aggregation assignments in a 3364*7c478bd9Sstevel@tonic-gate * single statement, e.g. (@a = count()) = count(); 3365*7c478bd9Sstevel@tonic-gate * We produce a message as if the result of aggregating 3366*7c478bd9Sstevel@tonic-gate * function does not propagate DT_NF_LVALUE. 3367*7c478bd9Sstevel@tonic-gate */ 3368*7c478bd9Sstevel@tonic-gate if (lp->dn_aggfun != NULL) { 3369*7c478bd9Sstevel@tonic-gate xyerror(D_OP_LVAL, "operator = requires " 3370*7c478bd9Sstevel@tonic-gate "modifiable lvalue as an operand\n"); 3371*7c478bd9Sstevel@tonic-gate } 3372*7c478bd9Sstevel@tonic-gate 3373*7c478bd9Sstevel@tonic-gate lp->dn_aggfun = rp; 3374*7c478bd9Sstevel@tonic-gate lp = dt_node_cook(lp, DT_IDFLG_MOD); 3375*7c478bd9Sstevel@tonic-gate 3376*7c478bd9Sstevel@tonic-gate dnp->dn_left = dnp->dn_right = NULL; 3377*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 3378*7c478bd9Sstevel@tonic-gate 3379*7c478bd9Sstevel@tonic-gate return (lp); 3380*7c478bd9Sstevel@tonic-gate } 3381*7c478bd9Sstevel@tonic-gate 3382*7c478bd9Sstevel@tonic-gate /* 3383*7c478bd9Sstevel@tonic-gate * If the right-hand side is a dynamic variable that is the 3384*7c478bd9Sstevel@tonic-gate * output of a translator, our result is the translated type. 3385*7c478bd9Sstevel@tonic-gate */ 3386*7c478bd9Sstevel@tonic-gate if ((idp = dt_node_resolve(rp, DT_IDENT_XLSOU)) != NULL) { 3387*7c478bd9Sstevel@tonic-gate ctfp = idp->di_ctfp; 3388*7c478bd9Sstevel@tonic-gate type = idp->di_type; 3389*7c478bd9Sstevel@tonic-gate uref = idp->di_flags & DT_IDFLG_USER; 3390*7c478bd9Sstevel@tonic-gate } else { 3391*7c478bd9Sstevel@tonic-gate ctfp = rp->dn_ctfp; 3392*7c478bd9Sstevel@tonic-gate type = rp->dn_type; 3393*7c478bd9Sstevel@tonic-gate uref = rp->dn_flags & DT_NF_USERLAND; 3394*7c478bd9Sstevel@tonic-gate } 3395*7c478bd9Sstevel@tonic-gate 3396*7c478bd9Sstevel@tonic-gate /* 3397*7c478bd9Sstevel@tonic-gate * If the left-hand side of an assignment statement is a virgin 3398*7c478bd9Sstevel@tonic-gate * variable created by this compilation pass, reset the type of 3399*7c478bd9Sstevel@tonic-gate * this variable to the type of the right-hand side. 3400*7c478bd9Sstevel@tonic-gate */ 3401*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_VAR && 3402*7c478bd9Sstevel@tonic-gate dt_ident_unref(lp->dn_ident)) { 3403*7c478bd9Sstevel@tonic-gate dt_node_type_assign(lp, ctfp, type); 3404*7c478bd9Sstevel@tonic-gate dt_ident_type_assign(lp->dn_ident, ctfp, type); 3405*7c478bd9Sstevel@tonic-gate 3406*7c478bd9Sstevel@tonic-gate if (uref) { 3407*7c478bd9Sstevel@tonic-gate lp->dn_flags |= DT_NF_USERLAND; 3408*7c478bd9Sstevel@tonic-gate lp->dn_ident->di_flags |= DT_IDFLG_USER; 3409*7c478bd9Sstevel@tonic-gate } 3410*7c478bd9Sstevel@tonic-gate } 3411*7c478bd9Sstevel@tonic-gate 3412*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_VAR) 3413*7c478bd9Sstevel@tonic-gate lp->dn_ident->di_flags |= DT_IDFLG_MOD; 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate /* 3416*7c478bd9Sstevel@tonic-gate * The rules for type checking for the assignment operators are 3417*7c478bd9Sstevel@tonic-gate * described in the ANSI-C spec (see K&R[A7.17]). We share 3418*7c478bd9Sstevel@tonic-gate * most of this code with the argument list checking code. 3419*7c478bd9Sstevel@tonic-gate */ 3420*7c478bd9Sstevel@tonic-gate if (!dt_node_is_string(lp)) { 3421*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(lp->dn_ctfp, 3422*7c478bd9Sstevel@tonic-gate ctf_type_resolve(lp->dn_ctfp, lp->dn_type)); 3423*7c478bd9Sstevel@tonic-gate 3424*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION) { 3425*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ARRFUN, "operator %s may not be " 3426*7c478bd9Sstevel@tonic-gate "applied to operand of type \"%s\"\n", 3427*7c478bd9Sstevel@tonic-gate opstr(op), 3428*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1))); 3429*7c478bd9Sstevel@tonic-gate } 3430*7c478bd9Sstevel@tonic-gate } 3431*7c478bd9Sstevel@tonic-gate 3432*7c478bd9Sstevel@tonic-gate if (idp != NULL && idp->di_kind == DT_IDENT_XLSOU && 3433*7c478bd9Sstevel@tonic-gate ctf_type_compat(lp->dn_ctfp, lp->dn_type, ctfp, type)) 3434*7c478bd9Sstevel@tonic-gate goto asgn_common; 3435*7c478bd9Sstevel@tonic-gate 3436*7c478bd9Sstevel@tonic-gate if (dt_node_is_argcompat(lp, rp)) 3437*7c478bd9Sstevel@tonic-gate goto asgn_common; 3438*7c478bd9Sstevel@tonic-gate 3439*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, 3440*7c478bd9Sstevel@tonic-gate "operands have incompatible types: \"%s\" %s \"%s\"\n", 3441*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), opstr(op), 3442*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n2, sizeof (n2))); 3443*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3444*7c478bd9Sstevel@tonic-gate 3445*7c478bd9Sstevel@tonic-gate case DT_TOK_ADD_EQ: 3446*7c478bd9Sstevel@tonic-gate case DT_TOK_SUB_EQ: 3447*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT) { 3448*7c478bd9Sstevel@tonic-gate dt_xcook_ident(lp, dtp->dt_globals, 3449*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3450*7c478bd9Sstevel@tonic-gate } 3451*7c478bd9Sstevel@tonic-gate 3452*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = 3453*7c478bd9Sstevel@tonic-gate dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD); 3454*7c478bd9Sstevel@tonic-gate 3455*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = 3456*7c478bd9Sstevel@tonic-gate dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD); 3457*7c478bd9Sstevel@tonic-gate 3458*7c478bd9Sstevel@tonic-gate if (dt_node_is_string(lp) || dt_node_is_string(rp)) { 3459*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, "operands have " 3460*7c478bd9Sstevel@tonic-gate "incompatible types: \"%s\" %s \"%s\"\n", 3461*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), opstr(op), 3462*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n2, sizeof (n2))); 3463*7c478bd9Sstevel@tonic-gate } 3464*7c478bd9Sstevel@tonic-gate 3465*7c478bd9Sstevel@tonic-gate /* 3466*7c478bd9Sstevel@tonic-gate * The rules for type checking for the assignment operators are 3467*7c478bd9Sstevel@tonic-gate * described in the ANSI-C spec (see K&R[A7.17]). To these 3468*7c478bd9Sstevel@tonic-gate * rules we add that only writable D nodes can be modified. 3469*7c478bd9Sstevel@tonic-gate */ 3470*7c478bd9Sstevel@tonic-gate if (dt_node_is_integer(lp) == 0 || 3471*7c478bd9Sstevel@tonic-gate dt_node_is_integer(rp) == 0) { 3472*7c478bd9Sstevel@tonic-gate if (!dt_node_is_pointer(lp) || dt_node_is_vfptr(lp)) { 3473*7c478bd9Sstevel@tonic-gate xyerror(D_OP_VFPTR, 3474*7c478bd9Sstevel@tonic-gate "operator %s requires left-hand scalar " 3475*7c478bd9Sstevel@tonic-gate "operand of known size\n", opstr(op)); 3476*7c478bd9Sstevel@tonic-gate } else if (dt_node_is_integer(rp) == 0 && 3477*7c478bd9Sstevel@tonic-gate dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) { 3478*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, "operands have " 3479*7c478bd9Sstevel@tonic-gate "incompatible types: \"%s\" %s \"%s\"\n", 3480*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n1, sizeof (n1)), 3481*7c478bd9Sstevel@tonic-gate opstr(op), 3482*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n2, sizeof (n2))); 3483*7c478bd9Sstevel@tonic-gate } 3484*7c478bd9Sstevel@tonic-gate } 3485*7c478bd9Sstevel@tonic-gate asgn_common: 3486*7c478bd9Sstevel@tonic-gate if (!(lp->dn_flags & DT_NF_LVALUE)) { 3487*7c478bd9Sstevel@tonic-gate xyerror(D_OP_LVAL, "operator %s requires modifiable " 3488*7c478bd9Sstevel@tonic-gate "lvalue as an operand\n", opstr(op)); 3489*7c478bd9Sstevel@tonic-gate /* see K&R[A7.17] */ 3490*7c478bd9Sstevel@tonic-gate } 3491*7c478bd9Sstevel@tonic-gate 3492*7c478bd9Sstevel@tonic-gate if (!(lp->dn_flags & DT_NF_WRITABLE)) { 3493*7c478bd9Sstevel@tonic-gate xyerror(D_OP_WRITE, "operator %s can only be applied " 3494*7c478bd9Sstevel@tonic-gate "to a writable variable\n", opstr(op)); 3495*7c478bd9Sstevel@tonic-gate } 3496*7c478bd9Sstevel@tonic-gate 3497*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */ 3498*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3499*7c478bd9Sstevel@tonic-gate break; 3500*7c478bd9Sstevel@tonic-gate 3501*7c478bd9Sstevel@tonic-gate case DT_TOK_PTR: 3502*7c478bd9Sstevel@tonic-gate /* 3503*7c478bd9Sstevel@tonic-gate * If the left-hand side of operator -> is the name "self", 3504*7c478bd9Sstevel@tonic-gate * then we permit a TLS variable to be created or referenced. 3505*7c478bd9Sstevel@tonic-gate */ 3506*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT && 3507*7c478bd9Sstevel@tonic-gate strcmp(lp->dn_string, "self") == 0) { 3508*7c478bd9Sstevel@tonic-gate if (rp->dn_kind != DT_NODE_VAR) { 3509*7c478bd9Sstevel@tonic-gate dt_xcook_ident(rp, dtp->dt_tls, 3510*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3511*7c478bd9Sstevel@tonic-gate } 3512*7c478bd9Sstevel@tonic-gate 3513*7c478bd9Sstevel@tonic-gate if (idflags != 0) 3514*7c478bd9Sstevel@tonic-gate rp = dt_node_cook(rp, idflags); 3515*7c478bd9Sstevel@tonic-gate 3516*7c478bd9Sstevel@tonic-gate dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ 3517*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 3518*7c478bd9Sstevel@tonic-gate return (rp); 3519*7c478bd9Sstevel@tonic-gate } 3520*7c478bd9Sstevel@tonic-gate 3521*7c478bd9Sstevel@tonic-gate /* 3522*7c478bd9Sstevel@tonic-gate * If the left-hand side of operator -> is the name "this", 3523*7c478bd9Sstevel@tonic-gate * then we permit a local variable to be created or referenced. 3524*7c478bd9Sstevel@tonic-gate */ 3525*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_IDENT && 3526*7c478bd9Sstevel@tonic-gate strcmp(lp->dn_string, "this") == 0) { 3527*7c478bd9Sstevel@tonic-gate if (rp->dn_kind != DT_NODE_VAR) { 3528*7c478bd9Sstevel@tonic-gate dt_xcook_ident(rp, yypcb->pcb_locals, 3529*7c478bd9Sstevel@tonic-gate DT_IDENT_SCALAR, B_TRUE); 3530*7c478bd9Sstevel@tonic-gate } 3531*7c478bd9Sstevel@tonic-gate 3532*7c478bd9Sstevel@tonic-gate if (idflags != 0) 3533*7c478bd9Sstevel@tonic-gate rp = dt_node_cook(rp, idflags); 3534*7c478bd9Sstevel@tonic-gate 3535*7c478bd9Sstevel@tonic-gate dnp->dn_right = dnp->dn_left; /* avoid freeing rp */ 3536*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 3537*7c478bd9Sstevel@tonic-gate return (rp); 3538*7c478bd9Sstevel@tonic-gate } 3539*7c478bd9Sstevel@tonic-gate 3540*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 3541*7c478bd9Sstevel@tonic-gate 3542*7c478bd9Sstevel@tonic-gate case DT_TOK_DOT: 3543*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3544*7c478bd9Sstevel@tonic-gate 3545*7c478bd9Sstevel@tonic-gate if (rp->dn_kind != DT_NODE_IDENT) { 3546*7c478bd9Sstevel@tonic-gate xyerror(D_OP_IDENT, "operator %s must be followed by " 3547*7c478bd9Sstevel@tonic-gate "an identifier\n", opstr(op)); 3548*7c478bd9Sstevel@tonic-gate } 3549*7c478bd9Sstevel@tonic-gate 3550*7c478bd9Sstevel@tonic-gate if ((idp = dt_node_resolve(lp, DT_IDENT_XLSOU)) != NULL || 3551*7c478bd9Sstevel@tonic-gate (idp = dt_node_resolve(lp, DT_IDENT_XLPTR)) != NULL) { 3552*7c478bd9Sstevel@tonic-gate /* 3553*7c478bd9Sstevel@tonic-gate * If the left-hand side is a translated struct or ptr, 3554*7c478bd9Sstevel@tonic-gate * the type of the left is the translation output type. 3555*7c478bd9Sstevel@tonic-gate */ 3556*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp = idp->di_data; 3557*7c478bd9Sstevel@tonic-gate 3558*7c478bd9Sstevel@tonic-gate if (dt_xlator_member(dxp, rp->dn_string) == NULL) { 3559*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_NOCONV, 3560*7c478bd9Sstevel@tonic-gate "translator does not define conversion " 3561*7c478bd9Sstevel@tonic-gate "for member: %s\n", rp->dn_string); 3562*7c478bd9Sstevel@tonic-gate } 3563*7c478bd9Sstevel@tonic-gate 3564*7c478bd9Sstevel@tonic-gate ctfp = idp->di_ctfp; 3565*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, idp->di_type); 3566*7c478bd9Sstevel@tonic-gate uref = idp->di_flags & DT_IDFLG_USER; 3567*7c478bd9Sstevel@tonic-gate } else { 3568*7c478bd9Sstevel@tonic-gate ctfp = lp->dn_ctfp; 3569*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, lp->dn_type); 3570*7c478bd9Sstevel@tonic-gate uref = lp->dn_flags & DT_NF_USERLAND; 3571*7c478bd9Sstevel@tonic-gate } 3572*7c478bd9Sstevel@tonic-gate 3573*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(ctfp, type); 3574*7c478bd9Sstevel@tonic-gate 3575*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_PTR) { 3576*7c478bd9Sstevel@tonic-gate if (kind != CTF_K_POINTER) { 3577*7c478bd9Sstevel@tonic-gate xyerror(D_OP_PTR, "operator %s must be " 3578*7c478bd9Sstevel@tonic-gate "applied to a pointer\n", opstr(op)); 3579*7c478bd9Sstevel@tonic-gate } 3580*7c478bd9Sstevel@tonic-gate type = ctf_type_reference(ctfp, type); 3581*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, type); 3582*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(ctfp, type); 3583*7c478bd9Sstevel@tonic-gate } 3584*7c478bd9Sstevel@tonic-gate 3585*7c478bd9Sstevel@tonic-gate /* 3586*7c478bd9Sstevel@tonic-gate * If we follow a reference to a forward declaration tag, 3587*7c478bd9Sstevel@tonic-gate * search the entire type space for the actual definition. 3588*7c478bd9Sstevel@tonic-gate */ 3589*7c478bd9Sstevel@tonic-gate while (kind == CTF_K_FORWARD) { 3590*7c478bd9Sstevel@tonic-gate char *tag = ctf_type_name(ctfp, type, n1, sizeof (n1)); 3591*7c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt; 3592*7c478bd9Sstevel@tonic-gate 3593*7c478bd9Sstevel@tonic-gate if (tag != NULL && dt_type_lookup(tag, &dtt) == 0 && 3594*7c478bd9Sstevel@tonic-gate (dtt.dtt_ctfp != ctfp || dtt.dtt_type != type)) { 3595*7c478bd9Sstevel@tonic-gate ctfp = dtt.dtt_ctfp; 3596*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, dtt.dtt_type); 3597*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(ctfp, type); 3598*7c478bd9Sstevel@tonic-gate } else { 3599*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPLETE, 3600*7c478bd9Sstevel@tonic-gate "operator %s cannot be applied to a " 3601*7c478bd9Sstevel@tonic-gate "forward declaration: no %s definition " 3602*7c478bd9Sstevel@tonic-gate "is available\n", opstr(op), tag); 3603*7c478bd9Sstevel@tonic-gate } 3604*7c478bd9Sstevel@tonic-gate } 3605*7c478bd9Sstevel@tonic-gate 3606*7c478bd9Sstevel@tonic-gate if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) { 3607*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_PTR) { 3608*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SOU, "operator -> cannot be " 3609*7c478bd9Sstevel@tonic-gate "applied to pointer to type \"%s\"; must " 3610*7c478bd9Sstevel@tonic-gate "be applied to a struct or union pointer\n", 3611*7c478bd9Sstevel@tonic-gate ctf_type_name(ctfp, type, n1, sizeof (n1))); 3612*7c478bd9Sstevel@tonic-gate } else { 3613*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SOU, "operator %s cannot be " 3614*7c478bd9Sstevel@tonic-gate "applied to type \"%s\"; must be applied " 3615*7c478bd9Sstevel@tonic-gate "to a struct or union\n", opstr(op), 3616*7c478bd9Sstevel@tonic-gate ctf_type_name(ctfp, type, n1, sizeof (n1))); 3617*7c478bd9Sstevel@tonic-gate } 3618*7c478bd9Sstevel@tonic-gate } 3619*7c478bd9Sstevel@tonic-gate 3620*7c478bd9Sstevel@tonic-gate if (ctf_member_info(ctfp, type, rp->dn_string, &m) == CTF_ERR) { 3621*7c478bd9Sstevel@tonic-gate xyerror(D_TYPE_MEMBER, 3622*7c478bd9Sstevel@tonic-gate "%s is not a member of %s\n", rp->dn_string, 3623*7c478bd9Sstevel@tonic-gate ctf_type_name(ctfp, type, n1, sizeof (n1))); 3624*7c478bd9Sstevel@tonic-gate } 3625*7c478bd9Sstevel@tonic-gate 3626*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, m.ctm_type); 3627*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(ctfp, type); 3628*7c478bd9Sstevel@tonic-gate 3629*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, ctfp, m.ctm_type); 3630*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, lp->dn_attr); 3631*7c478bd9Sstevel@tonic-gate 3632*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY || 3633*7c478bd9Sstevel@tonic-gate dt_node_is_string(dnp))) 3634*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.3.3] */ 3635*7c478bd9Sstevel@tonic-gate 3636*7c478bd9Sstevel@tonic-gate if (op == DT_TOK_DOT && (lp->dn_flags & DT_NF_LVALUE) && 3637*7c478bd9Sstevel@tonic-gate (kind != CTF_K_ARRAY || dt_node_is_string(dnp))) 3638*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.3.3] */ 3639*7c478bd9Sstevel@tonic-gate 3640*7c478bd9Sstevel@tonic-gate if (lp->dn_flags & DT_NF_WRITABLE) 3641*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_WRITABLE; 3642*7c478bd9Sstevel@tonic-gate 3643*7c478bd9Sstevel@tonic-gate if (uref && (kind == CTF_K_POINTER || 3644*7c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_REF))) 3645*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_USERLAND; 3646*7c478bd9Sstevel@tonic-gate break; 3647*7c478bd9Sstevel@tonic-gate 3648*7c478bd9Sstevel@tonic-gate case DT_TOK_LBRAC: { 3649*7c478bd9Sstevel@tonic-gate /* 3650*7c478bd9Sstevel@tonic-gate * If op is DT_TOK_LBRAC, we know from the special-case code at 3651*7c478bd9Sstevel@tonic-gate * the top that lp is either a D variable or an aggregation. 3652*7c478bd9Sstevel@tonic-gate */ 3653*7c478bd9Sstevel@tonic-gate dt_node_t *lnp; 3654*7c478bd9Sstevel@tonic-gate 3655*7c478bd9Sstevel@tonic-gate /* 3656*7c478bd9Sstevel@tonic-gate * If the left-hand side is an aggregation, just set dn_aggtup 3657*7c478bd9Sstevel@tonic-gate * to the right-hand side and return the cooked aggregation. 3658*7c478bd9Sstevel@tonic-gate * This transformation is legal since we are just collapsing 3659*7c478bd9Sstevel@tonic-gate * nodes to simplify later processing, and the entire aggtup 3660*7c478bd9Sstevel@tonic-gate * parse subtree is retained for subsequent cooking passes. 3661*7c478bd9Sstevel@tonic-gate */ 3662*7c478bd9Sstevel@tonic-gate if (lp->dn_kind == DT_NODE_AGG) { 3663*7c478bd9Sstevel@tonic-gate if (lp->dn_aggtup != NULL) { 3664*7c478bd9Sstevel@tonic-gate xyerror(D_AGG_MDIM, "improper attempt to " 3665*7c478bd9Sstevel@tonic-gate "reference @%s as a multi-dimensional " 3666*7c478bd9Sstevel@tonic-gate "array\n", lp->dn_ident->di_name); 3667*7c478bd9Sstevel@tonic-gate } 3668*7c478bd9Sstevel@tonic-gate 3669*7c478bd9Sstevel@tonic-gate lp->dn_aggtup = rp; 3670*7c478bd9Sstevel@tonic-gate lp = dt_node_cook(lp, 0); 3671*7c478bd9Sstevel@tonic-gate 3672*7c478bd9Sstevel@tonic-gate dnp->dn_left = dnp->dn_right = NULL; 3673*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 3674*7c478bd9Sstevel@tonic-gate 3675*7c478bd9Sstevel@tonic-gate return (lp); 3676*7c478bd9Sstevel@tonic-gate } 3677*7c478bd9Sstevel@tonic-gate 3678*7c478bd9Sstevel@tonic-gate assert(lp->dn_kind == DT_NODE_VAR); 3679*7c478bd9Sstevel@tonic-gate idp = lp->dn_ident; 3680*7c478bd9Sstevel@tonic-gate 3681*7c478bd9Sstevel@tonic-gate /* 3682*7c478bd9Sstevel@tonic-gate * If the left-hand side is a non-global scalar that hasn't yet 3683*7c478bd9Sstevel@tonic-gate * been referenced or modified, it was just created by self-> 3684*7c478bd9Sstevel@tonic-gate * or this-> and we can convert it from scalar to assoc array. 3685*7c478bd9Sstevel@tonic-gate */ 3686*7c478bd9Sstevel@tonic-gate if (idp->di_kind == DT_IDENT_SCALAR && dt_ident_unref(idp) && 3687*7c478bd9Sstevel@tonic-gate (idp->di_flags & (DT_IDFLG_LOCAL | DT_IDFLG_TLS)) != 0) { 3688*7c478bd9Sstevel@tonic-gate 3689*7c478bd9Sstevel@tonic-gate if (idp->di_flags & DT_IDFLG_LOCAL) { 3690*7c478bd9Sstevel@tonic-gate xyerror(D_ARR_LOCAL, 3691*7c478bd9Sstevel@tonic-gate "local variables may not be used as " 3692*7c478bd9Sstevel@tonic-gate "associative arrays: %s\n", idp->di_name); 3693*7c478bd9Sstevel@tonic-gate } 3694*7c478bd9Sstevel@tonic-gate 3695*7c478bd9Sstevel@tonic-gate dt_dprintf("morph variable %s (id %u) from scalar to " 3696*7c478bd9Sstevel@tonic-gate "array\n", idp->di_name, idp->di_id); 3697*7c478bd9Sstevel@tonic-gate 3698*7c478bd9Sstevel@tonic-gate dt_ident_morph(idp, DT_IDENT_ARRAY, 3699*7c478bd9Sstevel@tonic-gate &dt_idops_assc, NULL); 3700*7c478bd9Sstevel@tonic-gate } 3701*7c478bd9Sstevel@tonic-gate 3702*7c478bd9Sstevel@tonic-gate if (idp->di_kind != DT_IDENT_ARRAY) { 3703*7c478bd9Sstevel@tonic-gate xyerror(D_IDENT_BADREF, "%s '%s' may not be referenced " 3704*7c478bd9Sstevel@tonic-gate "as %s\n", dt_idkind_name(idp->di_kind), 3705*7c478bd9Sstevel@tonic-gate idp->di_name, dt_idkind_name(DT_IDENT_ARRAY)); 3706*7c478bd9Sstevel@tonic-gate } 3707*7c478bd9Sstevel@tonic-gate 3708*7c478bd9Sstevel@tonic-gate /* 3709*7c478bd9Sstevel@tonic-gate * Now that we've confirmed our left-hand side is a DT_NODE_VAR 3710*7c478bd9Sstevel@tonic-gate * of idkind DT_IDENT_ARRAY, we need to splice the [ node from 3711*7c478bd9Sstevel@tonic-gate * the parse tree and leave a cooked DT_NODE_VAR in its place 3712*7c478bd9Sstevel@tonic-gate * where dn_args for the VAR node is the right-hand 'rp' tree, 3713*7c478bd9Sstevel@tonic-gate * as shown in the parse tree diagram below: 3714*7c478bd9Sstevel@tonic-gate * 3715*7c478bd9Sstevel@tonic-gate * / / 3716*7c478bd9Sstevel@tonic-gate * [ OP2 "[" ]=dnp [ VAR ]=dnp 3717*7c478bd9Sstevel@tonic-gate * / \ => | 3718*7c478bd9Sstevel@tonic-gate * / \ +- dn_args -> [ ??? ]=rp 3719*7c478bd9Sstevel@tonic-gate * [ VAR ]=lp [ ??? ]=rp 3720*7c478bd9Sstevel@tonic-gate * 3721*7c478bd9Sstevel@tonic-gate * Since the final dt_node_cook(dnp) can fail using longjmp we 3722*7c478bd9Sstevel@tonic-gate * must perform the transformations as a group first by over- 3723*7c478bd9Sstevel@tonic-gate * writing 'dnp' to become the VAR node, so that the parse tree 3724*7c478bd9Sstevel@tonic-gate * is guaranteed to be in a consistent state if the cook fails. 3725*7c478bd9Sstevel@tonic-gate */ 3726*7c478bd9Sstevel@tonic-gate assert(lp->dn_kind == DT_NODE_VAR); 3727*7c478bd9Sstevel@tonic-gate assert(lp->dn_args == NULL); 3728*7c478bd9Sstevel@tonic-gate 3729*7c478bd9Sstevel@tonic-gate lnp = dnp->dn_link; 3730*7c478bd9Sstevel@tonic-gate bcopy(lp, dnp, sizeof (dt_node_t)); 3731*7c478bd9Sstevel@tonic-gate dnp->dn_link = lnp; 3732*7c478bd9Sstevel@tonic-gate 3733*7c478bd9Sstevel@tonic-gate dnp->dn_args = rp; 3734*7c478bd9Sstevel@tonic-gate dnp->dn_list = NULL; 3735*7c478bd9Sstevel@tonic-gate 3736*7c478bd9Sstevel@tonic-gate dt_node_free(lp); 3737*7c478bd9Sstevel@tonic-gate return (dt_node_cook(dnp, idflags)); 3738*7c478bd9Sstevel@tonic-gate } 3739*7c478bd9Sstevel@tonic-gate 3740*7c478bd9Sstevel@tonic-gate case DT_TOK_XLATE: { 3741*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp; 3742*7c478bd9Sstevel@tonic-gate 3743*7c478bd9Sstevel@tonic-gate assert(lp->dn_kind == DT_NODE_TYPE); 3744*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3745*7c478bd9Sstevel@tonic-gate dxp = dt_xlator_lookup(dtp, rp, lp, DT_XLATE_FUZZY); 3746*7c478bd9Sstevel@tonic-gate 3747*7c478bd9Sstevel@tonic-gate if (dxp == NULL) { 3748*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_NONE, 3749*7c478bd9Sstevel@tonic-gate "cannot translate from \"%s\" to \"%s\"\n", 3750*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n1, sizeof (n1)), 3751*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n2, sizeof (n2))); 3752*7c478bd9Sstevel@tonic-gate } 3753*7c478bd9Sstevel@tonic-gate 3754*7c478bd9Sstevel@tonic-gate dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type); 3755*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 3756*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, 3757*7c478bd9Sstevel@tonic-gate dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr)); 3758*7c478bd9Sstevel@tonic-gate break; 3759*7c478bd9Sstevel@tonic-gate } 3760*7c478bd9Sstevel@tonic-gate 3761*7c478bd9Sstevel@tonic-gate case DT_TOK_LPAR: { 3762*7c478bd9Sstevel@tonic-gate ctf_id_t ltype, rtype; 3763*7c478bd9Sstevel@tonic-gate uint_t lkind, rkind; 3764*7c478bd9Sstevel@tonic-gate 3765*7c478bd9Sstevel@tonic-gate assert(lp->dn_kind == DT_NODE_TYPE); 3766*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3767*7c478bd9Sstevel@tonic-gate 3768*7c478bd9Sstevel@tonic-gate ltype = ctf_type_resolve(lp->dn_ctfp, lp->dn_type); 3769*7c478bd9Sstevel@tonic-gate lkind = ctf_type_kind(lp->dn_ctfp, ltype); 3770*7c478bd9Sstevel@tonic-gate 3771*7c478bd9Sstevel@tonic-gate rtype = ctf_type_resolve(rp->dn_ctfp, rp->dn_type); 3772*7c478bd9Sstevel@tonic-gate rkind = ctf_type_kind(rp->dn_ctfp, rtype); 3773*7c478bd9Sstevel@tonic-gate 3774*7c478bd9Sstevel@tonic-gate /* 3775*7c478bd9Sstevel@tonic-gate * The rules for casting are loosely explained in K&R[A7.5] 3776*7c478bd9Sstevel@tonic-gate * and K&R[A6]. Basically, we can cast to the same type or 3777*7c478bd9Sstevel@tonic-gate * same base type, between any kind of scalar values, from 3778*7c478bd9Sstevel@tonic-gate * arrays to pointers, and we can cast anything to void. 3779*7c478bd9Sstevel@tonic-gate * To these rules D adds casts from scalars to strings. 3780*7c478bd9Sstevel@tonic-gate */ 3781*7c478bd9Sstevel@tonic-gate if (ctf_type_compat(lp->dn_ctfp, lp->dn_type, 3782*7c478bd9Sstevel@tonic-gate rp->dn_ctfp, rp->dn_type)) 3783*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3784*7c478bd9Sstevel@tonic-gate else if (dt_node_is_scalar(lp) && 3785*7c478bd9Sstevel@tonic-gate (dt_node_is_scalar(rp) || rkind == CTF_K_FUNCTION)) 3786*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3787*7c478bd9Sstevel@tonic-gate else if (dt_node_is_void(lp)) 3788*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3789*7c478bd9Sstevel@tonic-gate else if (lkind == CTF_K_POINTER && dt_node_is_pointer(rp)) 3790*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3791*7c478bd9Sstevel@tonic-gate else if (dt_node_is_string(lp) && (dt_node_is_scalar(rp) || 3792*7c478bd9Sstevel@tonic-gate dt_node_is_pointer(rp) || dt_node_is_strcompat(rp))) 3793*7c478bd9Sstevel@tonic-gate /*EMPTY*/; 3794*7c478bd9Sstevel@tonic-gate else { 3795*7c478bd9Sstevel@tonic-gate xyerror(D_CAST_INVAL, 3796*7c478bd9Sstevel@tonic-gate "invalid cast expression: \"%s\" to \"%s\"\n", 3797*7c478bd9Sstevel@tonic-gate dt_node_type_name(rp, n1, sizeof (n1)), 3798*7c478bd9Sstevel@tonic-gate dt_node_type_name(lp, n2, sizeof (n2))); 3799*7c478bd9Sstevel@tonic-gate } 3800*7c478bd9Sstevel@tonic-gate 3801*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */ 3802*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3803*7c478bd9Sstevel@tonic-gate break; 3804*7c478bd9Sstevel@tonic-gate } 3805*7c478bd9Sstevel@tonic-gate 3806*7c478bd9Sstevel@tonic-gate case DT_TOK_COMMA: 3807*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF); 3808*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF); 3809*7c478bd9Sstevel@tonic-gate 3810*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp)) { 3811*7c478bd9Sstevel@tonic-gate xyerror(D_OP_DYN, "operator %s operands " 3812*7c478bd9Sstevel@tonic-gate "cannot be of dynamic type\n", opstr(op)); 3813*7c478bd9Sstevel@tonic-gate } 3814*7c478bd9Sstevel@tonic-gate 3815*7c478bd9Sstevel@tonic-gate if (dt_node_is_actfunc(lp) || dt_node_is_actfunc(rp)) { 3816*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ACT, "operator %s operands " 3817*7c478bd9Sstevel@tonic-gate "cannot be actions\n", opstr(op)); 3818*7c478bd9Sstevel@tonic-gate } 3819*7c478bd9Sstevel@tonic-gate 3820*7c478bd9Sstevel@tonic-gate dt_node_type_propagate(rp, dnp); /* see K&R[A7.18] */ 3821*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr)); 3822*7c478bd9Sstevel@tonic-gate break; 3823*7c478bd9Sstevel@tonic-gate 3824*7c478bd9Sstevel@tonic-gate default: 3825*7c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "invalid binary op %s\n", opstr(op)); 3826*7c478bd9Sstevel@tonic-gate } 3827*7c478bd9Sstevel@tonic-gate 3828*7c478bd9Sstevel@tonic-gate /* 3829*7c478bd9Sstevel@tonic-gate * Complete the conversion of E1[E2] to *((E1)+(E2)) that we started 3830*7c478bd9Sstevel@tonic-gate * at the top of our switch() above (see K&R[A7.3.1]). Since E2 is 3831*7c478bd9Sstevel@tonic-gate * parsed as an argument_expression_list by dt_grammar.y, we can 3832*7c478bd9Sstevel@tonic-gate * end up with a comma-separated list inside of a non-associative 3833*7c478bd9Sstevel@tonic-gate * array reference. We check for this and report an appropriate error. 3834*7c478bd9Sstevel@tonic-gate */ 3835*7c478bd9Sstevel@tonic-gate if (dnp->dn_op == DT_TOK_LBRAC && op == DT_TOK_ADD) { 3836*7c478bd9Sstevel@tonic-gate dt_node_t *pnp; 3837*7c478bd9Sstevel@tonic-gate 3838*7c478bd9Sstevel@tonic-gate if (rp->dn_list != NULL) { 3839*7c478bd9Sstevel@tonic-gate xyerror(D_ARR_BADREF, 3840*7c478bd9Sstevel@tonic-gate "cannot access %s as an associative array\n", 3841*7c478bd9Sstevel@tonic-gate dt_node_name(lp, n1, sizeof (n1))); 3842*7c478bd9Sstevel@tonic-gate } 3843*7c478bd9Sstevel@tonic-gate 3844*7c478bd9Sstevel@tonic-gate dnp->dn_op = DT_TOK_ADD; 3845*7c478bd9Sstevel@tonic-gate pnp = dt_node_op1(DT_TOK_DEREF, dnp); 3846*7c478bd9Sstevel@tonic-gate 3847*7c478bd9Sstevel@tonic-gate /* 3848*7c478bd9Sstevel@tonic-gate * Cook callbacks are not typically permitted to allocate nodes. 3849*7c478bd9Sstevel@tonic-gate * When we do, we must insert them in the middle of an existing 3850*7c478bd9Sstevel@tonic-gate * allocation list rather than having them appended to the pcb 3851*7c478bd9Sstevel@tonic-gate * list because the sub-expression may be part of a definition. 3852*7c478bd9Sstevel@tonic-gate */ 3853*7c478bd9Sstevel@tonic-gate assert(yypcb->pcb_list == pnp); 3854*7c478bd9Sstevel@tonic-gate yypcb->pcb_list = pnp->dn_link; 3855*7c478bd9Sstevel@tonic-gate 3856*7c478bd9Sstevel@tonic-gate pnp->dn_link = dnp->dn_link; 3857*7c478bd9Sstevel@tonic-gate dnp->dn_link = pnp; 3858*7c478bd9Sstevel@tonic-gate 3859*7c478bd9Sstevel@tonic-gate return (dt_node_cook(pnp, DT_IDFLG_REF)); 3860*7c478bd9Sstevel@tonic-gate } 3861*7c478bd9Sstevel@tonic-gate 3862*7c478bd9Sstevel@tonic-gate return (dnp); 3863*7c478bd9Sstevel@tonic-gate } 3864*7c478bd9Sstevel@tonic-gate 3865*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3866*7c478bd9Sstevel@tonic-gate static dt_node_t * 3867*7c478bd9Sstevel@tonic-gate dt_cook_op3(dt_node_t *dnp, uint_t idflags) 3868*7c478bd9Sstevel@tonic-gate { 3869*7c478bd9Sstevel@tonic-gate dt_node_t *lp, *rp; 3870*7c478bd9Sstevel@tonic-gate ctf_file_t *ctfp; 3871*7c478bd9Sstevel@tonic-gate ctf_id_t type; 3872*7c478bd9Sstevel@tonic-gate 3873*7c478bd9Sstevel@tonic-gate dnp->dn_expr = dt_node_cook(dnp->dn_expr, DT_IDFLG_REF); 3874*7c478bd9Sstevel@tonic-gate lp = dnp->dn_left = dt_node_cook(dnp->dn_left, DT_IDFLG_REF); 3875*7c478bd9Sstevel@tonic-gate rp = dnp->dn_right = dt_node_cook(dnp->dn_right, DT_IDFLG_REF); 3876*7c478bd9Sstevel@tonic-gate 3877*7c478bd9Sstevel@tonic-gate if (!dt_node_is_scalar(dnp->dn_expr)) { 3878*7c478bd9Sstevel@tonic-gate xyerror(D_OP_SCALAR, 3879*7c478bd9Sstevel@tonic-gate "operator ?: expression must be of scalar type\n"); 3880*7c478bd9Sstevel@tonic-gate } 3881*7c478bd9Sstevel@tonic-gate 3882*7c478bd9Sstevel@tonic-gate if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp)) { 3883*7c478bd9Sstevel@tonic-gate xyerror(D_OP_DYN, 3884*7c478bd9Sstevel@tonic-gate "operator ?: operands cannot be of dynamic type\n"); 3885*7c478bd9Sstevel@tonic-gate } 3886*7c478bd9Sstevel@tonic-gate 3887*7c478bd9Sstevel@tonic-gate /* 3888*7c478bd9Sstevel@tonic-gate * The rules for type checking for the ternary operator are complex and 3889*7c478bd9Sstevel@tonic-gate * are described in the ANSI-C spec (see K&R[A7.16]). We implement 3890*7c478bd9Sstevel@tonic-gate * the various tests in order from least to most expensive. 3891*7c478bd9Sstevel@tonic-gate */ 3892*7c478bd9Sstevel@tonic-gate if (ctf_type_compat(lp->dn_ctfp, lp->dn_type, 3893*7c478bd9Sstevel@tonic-gate rp->dn_ctfp, rp->dn_type)) { 3894*7c478bd9Sstevel@tonic-gate ctfp = lp->dn_ctfp; 3895*7c478bd9Sstevel@tonic-gate type = lp->dn_type; 3896*7c478bd9Sstevel@tonic-gate } else if (dt_node_is_integer(lp) && dt_node_is_integer(rp)) { 3897*7c478bd9Sstevel@tonic-gate dt_type_promote(lp, rp, &ctfp, &type); 3898*7c478bd9Sstevel@tonic-gate } else if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp) && 3899*7c478bd9Sstevel@tonic-gate (dt_node_is_string(lp) || dt_node_is_string(rp))) { 3900*7c478bd9Sstevel@tonic-gate ctfp = DT_STR_CTFP(yypcb->pcb_hdl); 3901*7c478bd9Sstevel@tonic-gate type = DT_STR_TYPE(yypcb->pcb_hdl); 3902*7c478bd9Sstevel@tonic-gate } else if (dt_node_is_ptrcompat(lp, rp, &ctfp, &type) == 0) { 3903*7c478bd9Sstevel@tonic-gate xyerror(D_OP_INCOMPAT, 3904*7c478bd9Sstevel@tonic-gate "operator ?: operands must have compatible types\n"); 3905*7c478bd9Sstevel@tonic-gate } 3906*7c478bd9Sstevel@tonic-gate 3907*7c478bd9Sstevel@tonic-gate if (dt_node_is_actfunc(lp) || dt_node_is_actfunc(rp)) { 3908*7c478bd9Sstevel@tonic-gate xyerror(D_OP_ACT, "action cannot be " 3909*7c478bd9Sstevel@tonic-gate "used in a conditional context\n"); 3910*7c478bd9Sstevel@tonic-gate } 3911*7c478bd9Sstevel@tonic-gate 3912*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, ctfp, type); 3913*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr, 3914*7c478bd9Sstevel@tonic-gate dt_attr_min(lp->dn_attr, rp->dn_attr))); 3915*7c478bd9Sstevel@tonic-gate 3916*7c478bd9Sstevel@tonic-gate return (dnp); 3917*7c478bd9Sstevel@tonic-gate } 3918*7c478bd9Sstevel@tonic-gate 3919*7c478bd9Sstevel@tonic-gate static dt_node_t * 3920*7c478bd9Sstevel@tonic-gate dt_cook_statement(dt_node_t *dnp, uint_t idflags) 3921*7c478bd9Sstevel@tonic-gate { 3922*7c478bd9Sstevel@tonic-gate dnp->dn_expr = dt_node_cook(dnp->dn_expr, idflags); 3923*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dnp->dn_expr->dn_attr); 3924*7c478bd9Sstevel@tonic-gate 3925*7c478bd9Sstevel@tonic-gate return (dnp); 3926*7c478bd9Sstevel@tonic-gate } 3927*7c478bd9Sstevel@tonic-gate 3928*7c478bd9Sstevel@tonic-gate /* 3929*7c478bd9Sstevel@tonic-gate * If dn_aggfun is set, this node is a collapsed aggregation assignment (see 3930*7c478bd9Sstevel@tonic-gate * the special case code for DT_TOK_ASGN in dt_cook_op2() above), in which 3931*7c478bd9Sstevel@tonic-gate * case we cook both the tuple and the function call. If dn_aggfun is NULL, 3932*7c478bd9Sstevel@tonic-gate * this node is just a reference to the aggregation's type and attributes. 3933*7c478bd9Sstevel@tonic-gate */ 3934*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3935*7c478bd9Sstevel@tonic-gate static dt_node_t * 3936*7c478bd9Sstevel@tonic-gate dt_cook_aggregation(dt_node_t *dnp, uint_t idflags) 3937*7c478bd9Sstevel@tonic-gate { 3938*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 3939*7c478bd9Sstevel@tonic-gate 3940*7c478bd9Sstevel@tonic-gate if (dnp->dn_aggfun != NULL) { 3941*7c478bd9Sstevel@tonic-gate dnp->dn_aggfun = dt_node_cook(dnp->dn_aggfun, DT_IDFLG_REF); 3942*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dt_ident_cook(dnp, 3943*7c478bd9Sstevel@tonic-gate dnp->dn_ident, &dnp->dn_aggtup)); 3944*7c478bd9Sstevel@tonic-gate } else { 3945*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 3946*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dnp->dn_ident->di_attr); 3947*7c478bd9Sstevel@tonic-gate } 3948*7c478bd9Sstevel@tonic-gate 3949*7c478bd9Sstevel@tonic-gate return (dnp); 3950*7c478bd9Sstevel@tonic-gate } 3951*7c478bd9Sstevel@tonic-gate 3952*7c478bd9Sstevel@tonic-gate /* 3953*7c478bd9Sstevel@tonic-gate * Since D permits new variable identifiers to be instantiated in any program 3954*7c478bd9Sstevel@tonic-gate * expression, we may need to cook a clause's predicate either before or after 3955*7c478bd9Sstevel@tonic-gate * the action list depending on the program code in question. Consider: 3956*7c478bd9Sstevel@tonic-gate * 3957*7c478bd9Sstevel@tonic-gate * probe-description-list probe-description-list 3958*7c478bd9Sstevel@tonic-gate * /x++/ /x == 0/ 3959*7c478bd9Sstevel@tonic-gate * { { 3960*7c478bd9Sstevel@tonic-gate * trace(x); trace(x++); 3961*7c478bd9Sstevel@tonic-gate * } } 3962*7c478bd9Sstevel@tonic-gate * 3963*7c478bd9Sstevel@tonic-gate * In the left-hand example, the predicate uses operator ++ to instantiate 'x' 3964*7c478bd9Sstevel@tonic-gate * as a variable of type int64_t. The predicate must be cooked first because 3965*7c478bd9Sstevel@tonic-gate * otherwise the statement trace(x) refers to an unknown identifier. In the 3966*7c478bd9Sstevel@tonic-gate * right-hand example, the action list uses ++ to instantiate 'x'; the action 3967*7c478bd9Sstevel@tonic-gate * list must be cooked first because otherwise the predicate x == 0 refers to 3968*7c478bd9Sstevel@tonic-gate * an unknown identifier. In order to simplify programming, we support both. 3969*7c478bd9Sstevel@tonic-gate * 3970*7c478bd9Sstevel@tonic-gate * When cooking a clause, we cook the action statements before the predicate by 3971*7c478bd9Sstevel@tonic-gate * default, since it seems more common to create or modify identifiers in the 3972*7c478bd9Sstevel@tonic-gate * action list. If cooking fails due to an unknown identifier, we attempt to 3973*7c478bd9Sstevel@tonic-gate * cook the predicate (i.e. do it first) and then go back and cook the actions. 3974*7c478bd9Sstevel@tonic-gate * If this, too, fails (or if we get an error other than D_IDENT_UNDEF) we give 3975*7c478bd9Sstevel@tonic-gate * up and report failure back to the user. There are five possible paths: 3976*7c478bd9Sstevel@tonic-gate * 3977*7c478bd9Sstevel@tonic-gate * cook actions = OK, cook predicate = OK -> OK 3978*7c478bd9Sstevel@tonic-gate * cook actions = OK, cook predicate = ERR -> ERR 3979*7c478bd9Sstevel@tonic-gate * cook actions = ERR, cook predicate = ERR -> ERR 3980*7c478bd9Sstevel@tonic-gate * cook actions = ERR, cook predicate = OK, cook actions = OK -> OK 3981*7c478bd9Sstevel@tonic-gate * cook actions = ERR, cook predicate = OK, cook actions = ERR -> ERR 3982*7c478bd9Sstevel@tonic-gate * 3983*7c478bd9Sstevel@tonic-gate * The programmer can still defeat our scheme by creating circular definition 3984*7c478bd9Sstevel@tonic-gate * dependencies between predicates and actions, as in this example clause: 3985*7c478bd9Sstevel@tonic-gate * 3986*7c478bd9Sstevel@tonic-gate * probe-description-list 3987*7c478bd9Sstevel@tonic-gate * /x++ && y == 0/ 3988*7c478bd9Sstevel@tonic-gate * { 3989*7c478bd9Sstevel@tonic-gate * trace(x + y++); 3990*7c478bd9Sstevel@tonic-gate * } 3991*7c478bd9Sstevel@tonic-gate * 3992*7c478bd9Sstevel@tonic-gate * but it doesn't seem worth the complexity to handle such rare cases. The 3993*7c478bd9Sstevel@tonic-gate * user can simply use the D variable declaration syntax to work around them. 3994*7c478bd9Sstevel@tonic-gate */ 3995*7c478bd9Sstevel@tonic-gate static dt_node_t * 3996*7c478bd9Sstevel@tonic-gate dt_cook_clause(dt_node_t *dnp, uint_t idflags) 3997*7c478bd9Sstevel@tonic-gate { 3998*7c478bd9Sstevel@tonic-gate volatile int err, tries; 3999*7c478bd9Sstevel@tonic-gate jmp_buf ojb; 4000*7c478bd9Sstevel@tonic-gate 4001*7c478bd9Sstevel@tonic-gate /* 4002*7c478bd9Sstevel@tonic-gate * Before assigning dn_ctxattr, temporarily assign the probe attribute 4003*7c478bd9Sstevel@tonic-gate * to 'dnp' itself to force an attribute check and minimum violation. 4004*7c478bd9Sstevel@tonic-gate */ 4005*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, yypcb->pcb_pinfo.dtp_attr); 4006*7c478bd9Sstevel@tonic-gate dnp->dn_ctxattr = yypcb->pcb_pinfo.dtp_attr; 4007*7c478bd9Sstevel@tonic-gate 4008*7c478bd9Sstevel@tonic-gate bcopy(yypcb->pcb_jmpbuf, ojb, sizeof (jmp_buf)); 4009*7c478bd9Sstevel@tonic-gate tries = 0; 4010*7c478bd9Sstevel@tonic-gate 4011*7c478bd9Sstevel@tonic-gate if (dnp->dn_pred != NULL && (err = setjmp(yypcb->pcb_jmpbuf)) != 0) { 4012*7c478bd9Sstevel@tonic-gate bcopy(ojb, yypcb->pcb_jmpbuf, sizeof (jmp_buf)); 4013*7c478bd9Sstevel@tonic-gate if (tries++ != 0 || err != EDT_COMPILER || ( 4014*7c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_errtag != dt_errtag(D_IDENT_UNDEF) && 4015*7c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_errtag != dt_errtag(D_VAR_UNDEF))) 4016*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, err); 4017*7c478bd9Sstevel@tonic-gate } 4018*7c478bd9Sstevel@tonic-gate 4019*7c478bd9Sstevel@tonic-gate if (tries == 0) { 4020*7c478bd9Sstevel@tonic-gate yylabel("action list"); 4021*7c478bd9Sstevel@tonic-gate 4022*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, 4023*7c478bd9Sstevel@tonic-gate dt_node_list_cook(&dnp->dn_acts, idflags)); 4024*7c478bd9Sstevel@tonic-gate 4025*7c478bd9Sstevel@tonic-gate bcopy(ojb, yypcb->pcb_jmpbuf, sizeof (jmp_buf)); 4026*7c478bd9Sstevel@tonic-gate yylabel(NULL); 4027*7c478bd9Sstevel@tonic-gate } 4028*7c478bd9Sstevel@tonic-gate 4029*7c478bd9Sstevel@tonic-gate if (dnp->dn_pred != NULL) { 4030*7c478bd9Sstevel@tonic-gate yylabel("predicate"); 4031*7c478bd9Sstevel@tonic-gate 4032*7c478bd9Sstevel@tonic-gate dnp->dn_pred = dt_node_cook(dnp->dn_pred, idflags); 4033*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, 4034*7c478bd9Sstevel@tonic-gate dt_attr_min(dnp->dn_attr, dnp->dn_pred->dn_attr)); 4035*7c478bd9Sstevel@tonic-gate 4036*7c478bd9Sstevel@tonic-gate if (!dt_node_is_scalar(dnp->dn_pred)) { 4037*7c478bd9Sstevel@tonic-gate xyerror(D_PRED_SCALAR, 4038*7c478bd9Sstevel@tonic-gate "predicate result must be of scalar type\n"); 4039*7c478bd9Sstevel@tonic-gate } 4040*7c478bd9Sstevel@tonic-gate 4041*7c478bd9Sstevel@tonic-gate yylabel(NULL); 4042*7c478bd9Sstevel@tonic-gate } 4043*7c478bd9Sstevel@tonic-gate 4044*7c478bd9Sstevel@tonic-gate if (tries != 0) { 4045*7c478bd9Sstevel@tonic-gate yylabel("action list"); 4046*7c478bd9Sstevel@tonic-gate 4047*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, 4048*7c478bd9Sstevel@tonic-gate dt_node_list_cook(&dnp->dn_acts, idflags)); 4049*7c478bd9Sstevel@tonic-gate 4050*7c478bd9Sstevel@tonic-gate yylabel(NULL); 4051*7c478bd9Sstevel@tonic-gate } 4052*7c478bd9Sstevel@tonic-gate 4053*7c478bd9Sstevel@tonic-gate return (dnp); 4054*7c478bd9Sstevel@tonic-gate } 4055*7c478bd9Sstevel@tonic-gate 4056*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4057*7c478bd9Sstevel@tonic-gate static dt_node_t * 4058*7c478bd9Sstevel@tonic-gate dt_cook_inline(dt_node_t *dnp, uint_t idflags) 4059*7c478bd9Sstevel@tonic-gate { 4060*7c478bd9Sstevel@tonic-gate dt_idnode_t *inp = dnp->dn_ident->di_iarg; 4061*7c478bd9Sstevel@tonic-gate dt_ident_t *rdp; 4062*7c478bd9Sstevel@tonic-gate 4063*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 4064*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 4065*7c478bd9Sstevel@tonic-gate 4066*7c478bd9Sstevel@tonic-gate assert(dnp->dn_ident->di_flags & DT_IDFLG_INLINE); 4067*7c478bd9Sstevel@tonic-gate assert(inp->din_root->dn_flags & DT_NF_COOKED); 4068*7c478bd9Sstevel@tonic-gate 4069*7c478bd9Sstevel@tonic-gate /* 4070*7c478bd9Sstevel@tonic-gate * If we are inlining a translation, verify that the inline declaration 4071*7c478bd9Sstevel@tonic-gate * type exactly matches the type that is returned by the translation. 4072*7c478bd9Sstevel@tonic-gate * Otherwise just use dt_node_is_argcompat() to check the types. 4073*7c478bd9Sstevel@tonic-gate */ 4074*7c478bd9Sstevel@tonic-gate if ((rdp = dt_node_resolve(inp->din_root, DT_IDENT_XLSOU)) != NULL || 4075*7c478bd9Sstevel@tonic-gate (rdp = dt_node_resolve(inp->din_root, DT_IDENT_XLPTR)) != NULL) { 4076*7c478bd9Sstevel@tonic-gate 4077*7c478bd9Sstevel@tonic-gate ctf_file_t *lctfp = dnp->dn_ctfp; 4078*7c478bd9Sstevel@tonic-gate ctf_id_t ltype = ctf_type_resolve(lctfp, dnp->dn_type); 4079*7c478bd9Sstevel@tonic-gate 4080*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp = rdp->di_data; 4081*7c478bd9Sstevel@tonic-gate ctf_file_t *rctfp = dxp->dx_dst_ctfp; 4082*7c478bd9Sstevel@tonic-gate ctf_id_t rtype = dxp->dx_dst_base; 4083*7c478bd9Sstevel@tonic-gate 4084*7c478bd9Sstevel@tonic-gate if (ctf_type_kind(lctfp, ltype) == CTF_K_POINTER) { 4085*7c478bd9Sstevel@tonic-gate ltype = ctf_type_reference(lctfp, ltype); 4086*7c478bd9Sstevel@tonic-gate ltype = ctf_type_resolve(lctfp, ltype); 4087*7c478bd9Sstevel@tonic-gate } 4088*7c478bd9Sstevel@tonic-gate 4089*7c478bd9Sstevel@tonic-gate if (ctf_type_compat(lctfp, ltype, rctfp, rtype) == 0) { 4090*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_OP_INCOMPAT, 4091*7c478bd9Sstevel@tonic-gate "inline %s definition uses incompatible types: " 4092*7c478bd9Sstevel@tonic-gate "\"%s\" = \"%s\"\n", dnp->dn_ident->di_name, 4093*7c478bd9Sstevel@tonic-gate dt_type_name(lctfp, ltype, n1, sizeof (n1)), 4094*7c478bd9Sstevel@tonic-gate dt_type_name(rctfp, rtype, n2, sizeof (n2))); 4095*7c478bd9Sstevel@tonic-gate } 4096*7c478bd9Sstevel@tonic-gate 4097*7c478bd9Sstevel@tonic-gate } else if (dt_node_is_argcompat(dnp, inp->din_root) == 0) { 4098*7c478bd9Sstevel@tonic-gate dnerror(dnp, D_OP_INCOMPAT, 4099*7c478bd9Sstevel@tonic-gate "inline %s definition uses incompatible types: " 4100*7c478bd9Sstevel@tonic-gate "\"%s\" = \"%s\"\n", dnp->dn_ident->di_name, 4101*7c478bd9Sstevel@tonic-gate dt_node_type_name(dnp, n1, sizeof (n1)), 4102*7c478bd9Sstevel@tonic-gate dt_node_type_name(inp->din_root, n2, sizeof (n2))); 4103*7c478bd9Sstevel@tonic-gate } 4104*7c478bd9Sstevel@tonic-gate 4105*7c478bd9Sstevel@tonic-gate return (dnp); 4106*7c478bd9Sstevel@tonic-gate } 4107*7c478bd9Sstevel@tonic-gate 4108*7c478bd9Sstevel@tonic-gate static dt_node_t * 4109*7c478bd9Sstevel@tonic-gate dt_cook_member(dt_node_t *dnp, uint_t idflags) 4110*7c478bd9Sstevel@tonic-gate { 4111*7c478bd9Sstevel@tonic-gate dnp->dn_membexpr = dt_node_cook(dnp->dn_membexpr, idflags); 4112*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, dnp->dn_membexpr->dn_attr); 4113*7c478bd9Sstevel@tonic-gate return (dnp); 4114*7c478bd9Sstevel@tonic-gate } 4115*7c478bd9Sstevel@tonic-gate 4116*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4117*7c478bd9Sstevel@tonic-gate static dt_node_t * 4118*7c478bd9Sstevel@tonic-gate dt_cook_xlator(dt_node_t *dnp, uint_t idflags) 4119*7c478bd9Sstevel@tonic-gate { 4120*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 4121*7c478bd9Sstevel@tonic-gate dt_xlator_t *dxp = dnp->dn_xlator; 4122*7c478bd9Sstevel@tonic-gate dt_node_t *mnp; 4123*7c478bd9Sstevel@tonic-gate 4124*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 4125*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 4126*7c478bd9Sstevel@tonic-gate 4127*7c478bd9Sstevel@tonic-gate dtrace_attribute_t attr = _dtrace_maxattr; 4128*7c478bd9Sstevel@tonic-gate ctf_membinfo_t ctm; 4129*7c478bd9Sstevel@tonic-gate ctf_id_t type; 4130*7c478bd9Sstevel@tonic-gate uint_t kind; 4131*7c478bd9Sstevel@tonic-gate 4132*7c478bd9Sstevel@tonic-gate type = ctf_type_resolve(dxp->dx_dst_ctfp, dxp->dx_dst_type); 4133*7c478bd9Sstevel@tonic-gate kind = ctf_type_kind(dxp->dx_dst_ctfp, type); 4134*7c478bd9Sstevel@tonic-gate 4135*7c478bd9Sstevel@tonic-gate if (kind == CTF_K_FORWARD) { 4136*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_SOU, "incomplete struct/union/enum %s\n", 4137*7c478bd9Sstevel@tonic-gate dt_type_name(dxp->dx_dst_ctfp, type, n1, sizeof (n1))); 4138*7c478bd9Sstevel@tonic-gate } 4139*7c478bd9Sstevel@tonic-gate 4140*7c478bd9Sstevel@tonic-gate if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) { 4141*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_SOU, 4142*7c478bd9Sstevel@tonic-gate "translator output type must be a struct or union\n"); 4143*7c478bd9Sstevel@tonic-gate } 4144*7c478bd9Sstevel@tonic-gate 4145*7c478bd9Sstevel@tonic-gate /* 4146*7c478bd9Sstevel@tonic-gate * Before cooking each translator member, we push a reference to the 4147*7c478bd9Sstevel@tonic-gate * hash containing translator-local identifiers on to pcb_globals to 4148*7c478bd9Sstevel@tonic-gate * temporarily interpose these identifiers in front of other globals. 4149*7c478bd9Sstevel@tonic-gate */ 4150*7c478bd9Sstevel@tonic-gate dt_idstack_push(&yypcb->pcb_globals, dxp->dx_locals); 4151*7c478bd9Sstevel@tonic-gate 4152*7c478bd9Sstevel@tonic-gate for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) { 4153*7c478bd9Sstevel@tonic-gate if (ctf_member_info(dxp->dx_dst_ctfp, dxp->dx_dst_type, 4154*7c478bd9Sstevel@tonic-gate mnp->dn_membname, &ctm) == CTF_ERR) { 4155*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_MEMB, 4156*7c478bd9Sstevel@tonic-gate "translator member %s is not a member of %s\n", 4157*7c478bd9Sstevel@tonic-gate mnp->dn_membname, ctf_type_name(dxp->dx_dst_ctfp, 4158*7c478bd9Sstevel@tonic-gate dxp->dx_dst_type, n1, sizeof (n1))); 4159*7c478bd9Sstevel@tonic-gate } 4160*7c478bd9Sstevel@tonic-gate 4161*7c478bd9Sstevel@tonic-gate (void) dt_node_cook(mnp, DT_IDFLG_REF); 4162*7c478bd9Sstevel@tonic-gate dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type); 4163*7c478bd9Sstevel@tonic-gate attr = dt_attr_min(attr, mnp->dn_attr); 4164*7c478bd9Sstevel@tonic-gate 4165*7c478bd9Sstevel@tonic-gate if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) { 4166*7c478bd9Sstevel@tonic-gate xyerror(D_XLATE_INCOMPAT, 4167*7c478bd9Sstevel@tonic-gate "translator member %s definition uses " 4168*7c478bd9Sstevel@tonic-gate "incompatible types: \"%s\" = \"%s\"\n", 4169*7c478bd9Sstevel@tonic-gate mnp->dn_membname, 4170*7c478bd9Sstevel@tonic-gate dt_node_type_name(mnp, n1, sizeof (n1)), 4171*7c478bd9Sstevel@tonic-gate dt_node_type_name(mnp->dn_membexpr, 4172*7c478bd9Sstevel@tonic-gate n2, sizeof (n2))); 4173*7c478bd9Sstevel@tonic-gate } 4174*7c478bd9Sstevel@tonic-gate } 4175*7c478bd9Sstevel@tonic-gate 4176*7c478bd9Sstevel@tonic-gate dt_idstack_pop(&yypcb->pcb_globals, dxp->dx_locals); 4177*7c478bd9Sstevel@tonic-gate 4178*7c478bd9Sstevel@tonic-gate dxp->dx_souid.di_attr = attr; 4179*7c478bd9Sstevel@tonic-gate dxp->dx_ptrid.di_attr = attr; 4180*7c478bd9Sstevel@tonic-gate 4181*7c478bd9Sstevel@tonic-gate dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp)); 4182*7c478bd9Sstevel@tonic-gate dt_node_attr_assign(dnp, _dtrace_defattr); 4183*7c478bd9Sstevel@tonic-gate 4184*7c478bd9Sstevel@tonic-gate return (dnp); 4185*7c478bd9Sstevel@tonic-gate } 4186*7c478bd9Sstevel@tonic-gate 4187*7c478bd9Sstevel@tonic-gate static void 4188*7c478bd9Sstevel@tonic-gate dt_node_provider_cmp_argv(dt_provider_t *pvp, dt_node_t *pnp, const char *kind, 4189*7c478bd9Sstevel@tonic-gate uint_t old_argc, dt_node_t *old_argv, uint_t new_argc, dt_node_t *new_argv) 4190*7c478bd9Sstevel@tonic-gate { 4191*7c478bd9Sstevel@tonic-gate dt_probe_t *prp = pnp->dn_ident->di_data; 4192*7c478bd9Sstevel@tonic-gate uint_t i; 4193*7c478bd9Sstevel@tonic-gate 4194*7c478bd9Sstevel@tonic-gate char n1[DT_TYPE_NAMELEN]; 4195*7c478bd9Sstevel@tonic-gate char n2[DT_TYPE_NAMELEN]; 4196*7c478bd9Sstevel@tonic-gate 4197*7c478bd9Sstevel@tonic-gate if (old_argc != new_argc) { 4198*7c478bd9Sstevel@tonic-gate dnerror(pnp, D_PROV_INCOMPAT, 4199*7c478bd9Sstevel@tonic-gate "probe %s:%s %s prototype mismatch:\n" 4200*7c478bd9Sstevel@tonic-gate "\t current: %u arg%s\n\tprevious: %u arg%s\n", 4201*7c478bd9Sstevel@tonic-gate pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, kind, 4202*7c478bd9Sstevel@tonic-gate new_argc, new_argc != 1 ? "s" : "", 4203*7c478bd9Sstevel@tonic-gate old_argc, old_argc != 1 ? "s" : ""); 4204*7c478bd9Sstevel@tonic-gate } 4205*7c478bd9Sstevel@tonic-gate 4206*7c478bd9Sstevel@tonic-gate for (i = 0; i < old_argc; i++, 4207*7c478bd9Sstevel@tonic-gate old_argv = old_argv->dn_list, new_argv = new_argv->dn_list) { 4208*7c478bd9Sstevel@tonic-gate if (ctf_type_cmp(old_argv->dn_ctfp, old_argv->dn_type, 4209*7c478bd9Sstevel@tonic-gate new_argv->dn_ctfp, new_argv->dn_type) == 0) 4210*7c478bd9Sstevel@tonic-gate continue; 4211*7c478bd9Sstevel@tonic-gate 4212*7c478bd9Sstevel@tonic-gate dnerror(pnp, D_PROV_INCOMPAT, 4213*7c478bd9Sstevel@tonic-gate "probe %s:%s %s prototype argument #%u mismatch:\n" 4214*7c478bd9Sstevel@tonic-gate "\t current: %s\n\tprevious: %s\n", 4215*7c478bd9Sstevel@tonic-gate pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, kind, i + 1, 4216*7c478bd9Sstevel@tonic-gate dt_node_type_name(new_argv, n1, sizeof (n1)), 4217*7c478bd9Sstevel@tonic-gate dt_node_type_name(old_argv, n2, sizeof (n2))); 4218*7c478bd9Sstevel@tonic-gate } 4219*7c478bd9Sstevel@tonic-gate } 4220*7c478bd9Sstevel@tonic-gate 4221*7c478bd9Sstevel@tonic-gate /* 4222*7c478bd9Sstevel@tonic-gate * Compare a new probe declaration with an existing probe definition (either 4223*7c478bd9Sstevel@tonic-gate * from a previous declaration or cached from the kernel). If the new decl has 4224*7c478bd9Sstevel@tonic-gate * both an input and output parameter list, compare both lists. If the new 4225*7c478bd9Sstevel@tonic-gate * decl has only one list, only compare the output lists (i.e. assume the new 4226*7c478bd9Sstevel@tonic-gate * declaration is a probe interface and does not specify implementation). 4227*7c478bd9Sstevel@tonic-gate */ 4228*7c478bd9Sstevel@tonic-gate static void 4229*7c478bd9Sstevel@tonic-gate dt_node_provider_cmp(dt_provider_t *pvp, dt_node_t *pnp, 4230*7c478bd9Sstevel@tonic-gate dt_probe_t *old, dt_probe_t *new) 4231*7c478bd9Sstevel@tonic-gate { 4232*7c478bd9Sstevel@tonic-gate dt_node_provider_cmp_argv(pvp, pnp, "output", 4233*7c478bd9Sstevel@tonic-gate old->pr_xargc, old->pr_xargs, new->pr_xargc, new->pr_xargs); 4234*7c478bd9Sstevel@tonic-gate 4235*7c478bd9Sstevel@tonic-gate if (new->pr_nargs != new->pr_xargs) { 4236*7c478bd9Sstevel@tonic-gate dt_node_provider_cmp_argv(pvp, pnp, "input", 4237*7c478bd9Sstevel@tonic-gate old->pr_nargc, old->pr_nargs, new->pr_nargc, new->pr_nargs); 4238*7c478bd9Sstevel@tonic-gate } 4239*7c478bd9Sstevel@tonic-gate } 4240*7c478bd9Sstevel@tonic-gate 4241*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4242*7c478bd9Sstevel@tonic-gate static dt_node_t * 4243*7c478bd9Sstevel@tonic-gate dt_cook_provider(dt_node_t *dnp, uint_t idflags) 4244*7c478bd9Sstevel@tonic-gate { 4245*7c478bd9Sstevel@tonic-gate dt_provider_t *pvp = dnp->dn_provider; 4246*7c478bd9Sstevel@tonic-gate dt_node_t *pnp; 4247*7c478bd9Sstevel@tonic-gate 4248*7c478bd9Sstevel@tonic-gate /* 4249*7c478bd9Sstevel@tonic-gate * If we're declaring a provider for the first time and it is unknown 4250*7c478bd9Sstevel@tonic-gate * to dtrace(7D), insert the probe definitions into the provider's hash. 4251*7c478bd9Sstevel@tonic-gate * If we're redeclaring a known provider, verify the interface matches. 4252*7c478bd9Sstevel@tonic-gate */ 4253*7c478bd9Sstevel@tonic-gate for (pnp = dnp->dn_probes; pnp != NULL; pnp = pnp->dn_list) { 4254*7c478bd9Sstevel@tonic-gate const char *probename = pnp->dn_ident->di_name; 4255*7c478bd9Sstevel@tonic-gate dt_probe_t *prp = dt_probe_lookup(pvp, probename); 4256*7c478bd9Sstevel@tonic-gate 4257*7c478bd9Sstevel@tonic-gate assert(pnp->dn_kind == DT_NODE_PROBE); 4258*7c478bd9Sstevel@tonic-gate 4259*7c478bd9Sstevel@tonic-gate if (prp != NULL && dnp->dn_provred) { 4260*7c478bd9Sstevel@tonic-gate dt_node_provider_cmp(pvp, pnp, 4261*7c478bd9Sstevel@tonic-gate prp, pnp->dn_ident->di_data); 4262*7c478bd9Sstevel@tonic-gate } else if (prp == NULL && dnp->dn_provred) { 4263*7c478bd9Sstevel@tonic-gate dnerror(pnp, D_PROV_INCOMPAT, 4264*7c478bd9Sstevel@tonic-gate "provider interface mismatch: %s\n" 4265*7c478bd9Sstevel@tonic-gate "\t current: probe %s:%s defined\n" 4266*7c478bd9Sstevel@tonic-gate "\tprevious: probe %s:%s not defined\n", 4267*7c478bd9Sstevel@tonic-gate dnp->dn_provname, dnp->dn_provname, 4268*7c478bd9Sstevel@tonic-gate probename, dnp->dn_provname, probename); 4269*7c478bd9Sstevel@tonic-gate } else if (prp != NULL) { 4270*7c478bd9Sstevel@tonic-gate dnerror(pnp, D_PROV_PRDUP, "probe redeclared: %s:%s\n", 4271*7c478bd9Sstevel@tonic-gate dnp->dn_provname, probename); 4272*7c478bd9Sstevel@tonic-gate } else 4273*7c478bd9Sstevel@tonic-gate dt_probe_declare(pvp, pnp->dn_ident->di_data); 4274*7c478bd9Sstevel@tonic-gate } 4275*7c478bd9Sstevel@tonic-gate 4276*7c478bd9Sstevel@tonic-gate return (dnp); 4277*7c478bd9Sstevel@tonic-gate } 4278*7c478bd9Sstevel@tonic-gate 4279*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4280*7c478bd9Sstevel@tonic-gate static dt_node_t * 4281*7c478bd9Sstevel@tonic-gate dt_cook_none(dt_node_t *dnp, uint_t idflags) 4282*7c478bd9Sstevel@tonic-gate { 4283*7c478bd9Sstevel@tonic-gate return (dnp); 4284*7c478bd9Sstevel@tonic-gate } 4285*7c478bd9Sstevel@tonic-gate 4286*7c478bd9Sstevel@tonic-gate static dt_node_t *(*dt_cook_funcs[])(dt_node_t *, uint_t) = { 4287*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_FREE */ 4288*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_INT */ 4289*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_STRING */ 4290*7c478bd9Sstevel@tonic-gate dt_cook_ident, /* DT_NODE_IDENT */ 4291*7c478bd9Sstevel@tonic-gate dt_cook_var, /* DT_NODE_VAR */ 4292*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_SYM */ 4293*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_TYPE */ 4294*7c478bd9Sstevel@tonic-gate dt_cook_func, /* DT_NODE_FUNC */ 4295*7c478bd9Sstevel@tonic-gate dt_cook_op1, /* DT_NODE_OP1 */ 4296*7c478bd9Sstevel@tonic-gate dt_cook_op2, /* DT_NODE_OP2 */ 4297*7c478bd9Sstevel@tonic-gate dt_cook_op3, /* DT_NODE_OP3 */ 4298*7c478bd9Sstevel@tonic-gate dt_cook_statement, /* DT_NODE_DEXPR */ 4299*7c478bd9Sstevel@tonic-gate dt_cook_statement, /* DT_NODE_DFUNC */ 4300*7c478bd9Sstevel@tonic-gate dt_cook_aggregation, /* DT_NODE_AGG */ 4301*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_PDESC */ 4302*7c478bd9Sstevel@tonic-gate dt_cook_clause, /* DT_NODE_CLAUSE */ 4303*7c478bd9Sstevel@tonic-gate dt_cook_inline, /* DT_NODE_INLINE */ 4304*7c478bd9Sstevel@tonic-gate dt_cook_member, /* DT_NODE_MEMBER */ 4305*7c478bd9Sstevel@tonic-gate dt_cook_xlator, /* DT_NODE_XLATOR */ 4306*7c478bd9Sstevel@tonic-gate dt_cook_none, /* DT_NODE_PROBE */ 4307*7c478bd9Sstevel@tonic-gate dt_cook_provider, /* DT_NODE_PROVIDER */ 4308*7c478bd9Sstevel@tonic-gate dt_cook_none /* DT_NODE_PROG */ 4309*7c478bd9Sstevel@tonic-gate }; 4310*7c478bd9Sstevel@tonic-gate 4311*7c478bd9Sstevel@tonic-gate /* 4312*7c478bd9Sstevel@tonic-gate * Recursively cook the parse tree starting at the specified node. The idflags 4313*7c478bd9Sstevel@tonic-gate * parameter is used to indicate the type of reference (r/w) and is applied to 4314*7c478bd9Sstevel@tonic-gate * the resulting identifier if it is a D variable or D aggregation. 4315*7c478bd9Sstevel@tonic-gate */ 4316*7c478bd9Sstevel@tonic-gate dt_node_t * 4317*7c478bd9Sstevel@tonic-gate dt_node_cook(dt_node_t *dnp, uint_t idflags) 4318*7c478bd9Sstevel@tonic-gate { 4319*7c478bd9Sstevel@tonic-gate int oldlineno = yylineno; 4320*7c478bd9Sstevel@tonic-gate 4321*7c478bd9Sstevel@tonic-gate yylineno = dnp->dn_line; 4322*7c478bd9Sstevel@tonic-gate 4323*7c478bd9Sstevel@tonic-gate dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags); 4324*7c478bd9Sstevel@tonic-gate dnp->dn_flags |= DT_NF_COOKED; 4325*7c478bd9Sstevel@tonic-gate 4326*7c478bd9Sstevel@tonic-gate if (dnp->dn_kind == DT_NODE_VAR || dnp->dn_kind == DT_NODE_AGG) 4327*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_flags |= idflags; 4328*7c478bd9Sstevel@tonic-gate 4329*7c478bd9Sstevel@tonic-gate yylineno = oldlineno; 4330*7c478bd9Sstevel@tonic-gate return (dnp); 4331*7c478bd9Sstevel@tonic-gate } 4332*7c478bd9Sstevel@tonic-gate 4333*7c478bd9Sstevel@tonic-gate dtrace_attribute_t 4334*7c478bd9Sstevel@tonic-gate dt_node_list_cook(dt_node_t **pnp, uint_t idflags) 4335*7c478bd9Sstevel@tonic-gate { 4336*7c478bd9Sstevel@tonic-gate dtrace_attribute_t attr = _dtrace_defattr; 4337*7c478bd9Sstevel@tonic-gate dt_node_t *dnp, *nnp; 4338*7c478bd9Sstevel@tonic-gate 4339*7c478bd9Sstevel@tonic-gate for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) { 4340*7c478bd9Sstevel@tonic-gate nnp = dnp->dn_list; 4341*7c478bd9Sstevel@tonic-gate dnp = *pnp = dt_node_cook(dnp, idflags); 4342*7c478bd9Sstevel@tonic-gate attr = dt_attr_min(attr, dnp->dn_attr); 4343*7c478bd9Sstevel@tonic-gate dnp->dn_list = nnp; 4344*7c478bd9Sstevel@tonic-gate pnp = &dnp->dn_list; 4345*7c478bd9Sstevel@tonic-gate } 4346*7c478bd9Sstevel@tonic-gate 4347*7c478bd9Sstevel@tonic-gate return (attr); 4348*7c478bd9Sstevel@tonic-gate } 4349*7c478bd9Sstevel@tonic-gate 4350*7c478bd9Sstevel@tonic-gate void 4351*7c478bd9Sstevel@tonic-gate dt_node_list_free(dt_node_t **pnp) 4352*7c478bd9Sstevel@tonic-gate { 4353*7c478bd9Sstevel@tonic-gate dt_node_t *dnp, *nnp; 4354*7c478bd9Sstevel@tonic-gate 4355*7c478bd9Sstevel@tonic-gate for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) { 4356*7c478bd9Sstevel@tonic-gate nnp = dnp->dn_list; 4357*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 4358*7c478bd9Sstevel@tonic-gate } 4359*7c478bd9Sstevel@tonic-gate 4360*7c478bd9Sstevel@tonic-gate if (pnp != NULL) 4361*7c478bd9Sstevel@tonic-gate *pnp = NULL; 4362*7c478bd9Sstevel@tonic-gate } 4363*7c478bd9Sstevel@tonic-gate 4364*7c478bd9Sstevel@tonic-gate void 4365*7c478bd9Sstevel@tonic-gate dt_node_link_free(dt_node_t **pnp) 4366*7c478bd9Sstevel@tonic-gate { 4367*7c478bd9Sstevel@tonic-gate dt_node_t *dnp, *nnp; 4368*7c478bd9Sstevel@tonic-gate 4369*7c478bd9Sstevel@tonic-gate for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) { 4370*7c478bd9Sstevel@tonic-gate nnp = dnp->dn_link; 4371*7c478bd9Sstevel@tonic-gate dt_node_free(dnp); 4372*7c478bd9Sstevel@tonic-gate } 4373*7c478bd9Sstevel@tonic-gate 4374*7c478bd9Sstevel@tonic-gate for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) { 4375*7c478bd9Sstevel@tonic-gate nnp = dnp->dn_link; 4376*7c478bd9Sstevel@tonic-gate free(dnp); 4377*7c478bd9Sstevel@tonic-gate } 4378*7c478bd9Sstevel@tonic-gate 4379*7c478bd9Sstevel@tonic-gate if (pnp != NULL) 4380*7c478bd9Sstevel@tonic-gate *pnp = NULL; 4381*7c478bd9Sstevel@tonic-gate } 4382*7c478bd9Sstevel@tonic-gate 4383*7c478bd9Sstevel@tonic-gate dt_node_t * 4384*7c478bd9Sstevel@tonic-gate dt_node_link(dt_node_t *lp, dt_node_t *rp) 4385*7c478bd9Sstevel@tonic-gate { 4386*7c478bd9Sstevel@tonic-gate dt_node_t *dnp; 4387*7c478bd9Sstevel@tonic-gate 4388*7c478bd9Sstevel@tonic-gate if (lp == NULL) 4389*7c478bd9Sstevel@tonic-gate return (rp); 4390*7c478bd9Sstevel@tonic-gate else if (rp == NULL) 4391*7c478bd9Sstevel@tonic-gate return (lp); 4392*7c478bd9Sstevel@tonic-gate 4393*7c478bd9Sstevel@tonic-gate for (dnp = lp; dnp->dn_list != NULL; dnp = dnp->dn_list) 4394*7c478bd9Sstevel@tonic-gate continue; 4395*7c478bd9Sstevel@tonic-gate 4396*7c478bd9Sstevel@tonic-gate dnp->dn_list = rp; 4397*7c478bd9Sstevel@tonic-gate return (lp); 4398*7c478bd9Sstevel@tonic-gate } 4399*7c478bd9Sstevel@tonic-gate 4400*7c478bd9Sstevel@tonic-gate void 4401*7c478bd9Sstevel@tonic-gate dt_node_diftype(const dt_node_t *dnp, dtrace_diftype_t *tp) 4402*7c478bd9Sstevel@tonic-gate { 4403*7c478bd9Sstevel@tonic-gate if (dt_node_is_string(dnp)) { 4404*7c478bd9Sstevel@tonic-gate tp->dtdt_kind = DIF_TYPE_STRING; 4405*7c478bd9Sstevel@tonic-gate tp->dtdt_ckind = CTF_K_UNKNOWN; 4406*7c478bd9Sstevel@tonic-gate } else { 4407*7c478bd9Sstevel@tonic-gate tp->dtdt_kind = DIF_TYPE_CTF; 4408*7c478bd9Sstevel@tonic-gate tp->dtdt_ckind = ctf_type_kind(dnp->dn_ctfp, 4409*7c478bd9Sstevel@tonic-gate ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type)); 4410*7c478bd9Sstevel@tonic-gate } 4411*7c478bd9Sstevel@tonic-gate 4412*7c478bd9Sstevel@tonic-gate tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0; 4413*7c478bd9Sstevel@tonic-gate tp->dtdt_pad = 0; 4414*7c478bd9Sstevel@tonic-gate tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type); 4415*7c478bd9Sstevel@tonic-gate } 4416*7c478bd9Sstevel@tonic-gate 4417*7c478bd9Sstevel@tonic-gate void 4418*7c478bd9Sstevel@tonic-gate dt_node_printr(dt_node_t *dnp, FILE *fp, int depth) 4419*7c478bd9Sstevel@tonic-gate { 4420*7c478bd9Sstevel@tonic-gate char n[DT_TYPE_NAMELEN], buf[BUFSIZ], a[8]; 4421*7c478bd9Sstevel@tonic-gate const dtrace_syminfo_t *dts; 4422*7c478bd9Sstevel@tonic-gate const dt_idnode_t *inp; 4423*7c478bd9Sstevel@tonic-gate dt_node_t *arg; 4424*7c478bd9Sstevel@tonic-gate 4425*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s", depth * 2, ""); 4426*7c478bd9Sstevel@tonic-gate (void) dt_attr_str(dnp->dn_attr, a, sizeof (a)); 4427*7c478bd9Sstevel@tonic-gate 4428*7c478bd9Sstevel@tonic-gate if (dnp->dn_ctfp != NULL && dnp->dn_type != CTF_ERR && 4429*7c478bd9Sstevel@tonic-gate ctf_type_name(dnp->dn_ctfp, dnp->dn_type, n, sizeof (n)) != NULL) { 4430*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, BUFSIZ, "type=<%s> attr=%s flags=", n, a); 4431*7c478bd9Sstevel@tonic-gate } else { 4432*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, BUFSIZ, "type=<%ld> attr=%s flags=", 4433*7c478bd9Sstevel@tonic-gate dnp->dn_type, a); 4434*7c478bd9Sstevel@tonic-gate } 4435*7c478bd9Sstevel@tonic-gate 4436*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags != 0) { 4437*7c478bd9Sstevel@tonic-gate n[0] = '\0'; 4438*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) 4439*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",SIGN"); 4440*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_COOKED) 4441*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",COOK"); 4442*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_REF) 4443*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",REF"); 4444*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_LVALUE) 4445*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",LVAL"); 4446*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_WRITABLE) 4447*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",WRITE"); 4448*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_BITFIELD) 4449*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",BITF"); 4450*7c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_USERLAND) 4451*7c478bd9Sstevel@tonic-gate (void) strcat(n, ",USER"); 4452*7c478bd9Sstevel@tonic-gate (void) strcat(buf, n + 1); 4453*7c478bd9Sstevel@tonic-gate } else 4454*7c478bd9Sstevel@tonic-gate (void) strcat(buf, "0"); 4455*7c478bd9Sstevel@tonic-gate 4456*7c478bd9Sstevel@tonic-gate switch (dnp->dn_kind) { 4457*7c478bd9Sstevel@tonic-gate case DT_NODE_FREE: 4458*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "FREE <node %p>\n", (void *)dnp); 4459*7c478bd9Sstevel@tonic-gate break; 4460*7c478bd9Sstevel@tonic-gate 4461*7c478bd9Sstevel@tonic-gate case DT_NODE_INT: 4462*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "INT 0x%llx (%s)\n", 4463*7c478bd9Sstevel@tonic-gate (u_longlong_t)dnp->dn_value, buf); 4464*7c478bd9Sstevel@tonic-gate break; 4465*7c478bd9Sstevel@tonic-gate 4466*7c478bd9Sstevel@tonic-gate case DT_NODE_STRING: 4467*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "STRING \"%s\" (%s)\n", dnp->dn_string, buf); 4468*7c478bd9Sstevel@tonic-gate break; 4469*7c478bd9Sstevel@tonic-gate 4470*7c478bd9Sstevel@tonic-gate case DT_NODE_IDENT: 4471*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "IDENT %s (%s)\n", dnp->dn_string, buf); 4472*7c478bd9Sstevel@tonic-gate break; 4473*7c478bd9Sstevel@tonic-gate 4474*7c478bd9Sstevel@tonic-gate case DT_NODE_VAR: 4475*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "VARIABLE %s%s (%s)\n", 4476*7c478bd9Sstevel@tonic-gate (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" : 4477*7c478bd9Sstevel@tonic-gate (dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "", 4478*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_name, buf); 4479*7c478bd9Sstevel@tonic-gate 4480*7c478bd9Sstevel@tonic-gate if (dnp->dn_args != NULL) 4481*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s[\n", depth * 2, ""); 4482*7c478bd9Sstevel@tonic-gate 4483*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) { 4484*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4485*7c478bd9Sstevel@tonic-gate if (arg->dn_list != NULL) 4486*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s,\n", depth * 2, ""); 4487*7c478bd9Sstevel@tonic-gate } 4488*7c478bd9Sstevel@tonic-gate 4489*7c478bd9Sstevel@tonic-gate if (dnp->dn_args != NULL) 4490*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s]\n", depth * 2, ""); 4491*7c478bd9Sstevel@tonic-gate break; 4492*7c478bd9Sstevel@tonic-gate 4493*7c478bd9Sstevel@tonic-gate case DT_NODE_SYM: 4494*7c478bd9Sstevel@tonic-gate dts = dnp->dn_ident->di_data; 4495*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "SYMBOL %s`%s (%s)\n", 4496*7c478bd9Sstevel@tonic-gate dts->dts_object, dts->dts_name, buf); 4497*7c478bd9Sstevel@tonic-gate break; 4498*7c478bd9Sstevel@tonic-gate 4499*7c478bd9Sstevel@tonic-gate case DT_NODE_TYPE: 4500*7c478bd9Sstevel@tonic-gate if (dnp->dn_string != NULL) { 4501*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "TYPE (%s) %s\n", 4502*7c478bd9Sstevel@tonic-gate buf, dnp->dn_string); 4503*7c478bd9Sstevel@tonic-gate } else 4504*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "TYPE (%s)\n", buf); 4505*7c478bd9Sstevel@tonic-gate break; 4506*7c478bd9Sstevel@tonic-gate 4507*7c478bd9Sstevel@tonic-gate case DT_NODE_FUNC: 4508*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "FUNC %s (%s)\n", 4509*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_name, buf); 4510*7c478bd9Sstevel@tonic-gate 4511*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) { 4512*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4513*7c478bd9Sstevel@tonic-gate if (arg->dn_list != NULL) 4514*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s,\n", depth * 2, ""); 4515*7c478bd9Sstevel@tonic-gate } 4516*7c478bd9Sstevel@tonic-gate break; 4517*7c478bd9Sstevel@tonic-gate 4518*7c478bd9Sstevel@tonic-gate case DT_NODE_OP1: 4519*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "OP1 %s (%s)\n", opstr(dnp->dn_op), buf); 4520*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_child, fp, depth + 1); 4521*7c478bd9Sstevel@tonic-gate break; 4522*7c478bd9Sstevel@tonic-gate 4523*7c478bd9Sstevel@tonic-gate case DT_NODE_OP2: 4524*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf); 4525*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_left, fp, depth + 1); 4526*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_right, fp, depth + 1); 4527*7c478bd9Sstevel@tonic-gate break; 4528*7c478bd9Sstevel@tonic-gate 4529*7c478bd9Sstevel@tonic-gate case DT_NODE_OP3: 4530*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "OP3 (%s)\n", buf); 4531*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_expr, fp, depth + 1); 4532*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s?\n", depth * 2, ""); 4533*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_left, fp, depth + 1); 4534*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s:\n", depth * 2, ""); 4535*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_right, fp, depth + 1); 4536*7c478bd9Sstevel@tonic-gate break; 4537*7c478bd9Sstevel@tonic-gate 4538*7c478bd9Sstevel@tonic-gate case DT_NODE_DEXPR: 4539*7c478bd9Sstevel@tonic-gate case DT_NODE_DFUNC: 4540*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "D EXPRESSION attr=%s\n", a); 4541*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_expr, fp, depth + 1); 4542*7c478bd9Sstevel@tonic-gate break; 4543*7c478bd9Sstevel@tonic-gate 4544*7c478bd9Sstevel@tonic-gate case DT_NODE_AGG: 4545*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "AGGREGATE @%s attr=%s [\n", 4546*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_name, a); 4547*7c478bd9Sstevel@tonic-gate 4548*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_aggtup; arg != NULL; arg = arg->dn_list) { 4549*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4550*7c478bd9Sstevel@tonic-gate if (arg->dn_list != NULL) 4551*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s,\n", depth * 2, ""); 4552*7c478bd9Sstevel@tonic-gate } 4553*7c478bd9Sstevel@tonic-gate 4554*7c478bd9Sstevel@tonic-gate if (dnp->dn_aggfun) { 4555*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s] = ", depth * 2, ""); 4556*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_aggfun, fp, depth + 1); 4557*7c478bd9Sstevel@tonic-gate } else 4558*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s]\n", depth * 2, ""); 4559*7c478bd9Sstevel@tonic-gate 4560*7c478bd9Sstevel@tonic-gate if (dnp->dn_aggfun) 4561*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s)\n", depth * 2, ""); 4562*7c478bd9Sstevel@tonic-gate break; 4563*7c478bd9Sstevel@tonic-gate 4564*7c478bd9Sstevel@tonic-gate case DT_NODE_PDESC: 4565*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "PDESC %s:%s:%s:%s [%u]\n", 4566*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod, 4567*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name, 4568*7c478bd9Sstevel@tonic-gate dnp->dn_desc->dtpd_id); 4569*7c478bd9Sstevel@tonic-gate break; 4570*7c478bd9Sstevel@tonic-gate 4571*7c478bd9Sstevel@tonic-gate case DT_NODE_CLAUSE: 4572*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "CLAUSE attr=%s\n", a); 4573*7c478bd9Sstevel@tonic-gate 4574*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) 4575*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4576*7c478bd9Sstevel@tonic-gate 4577*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*sCTXATTR %s\n", depth * 2, "", 4578*7c478bd9Sstevel@tonic-gate dt_attr_str(dnp->dn_ctxattr, a, sizeof (a))); 4579*7c478bd9Sstevel@tonic-gate 4580*7c478bd9Sstevel@tonic-gate if (dnp->dn_pred != NULL) { 4581*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*sPREDICATE /\n", depth * 2, ""); 4582*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_pred, fp, depth + 1); 4583*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%*s/\n", depth * 2, ""); 4584*7c478bd9Sstevel@tonic-gate } 4585*7c478bd9Sstevel@tonic-gate 4586*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) 4587*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4588*7c478bd9Sstevel@tonic-gate break; 4589*7c478bd9Sstevel@tonic-gate 4590*7c478bd9Sstevel@tonic-gate case DT_NODE_INLINE: 4591*7c478bd9Sstevel@tonic-gate inp = dnp->dn_ident->di_iarg; 4592*7c478bd9Sstevel@tonic-gate 4593*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "INLINE %s (%s)\n", 4594*7c478bd9Sstevel@tonic-gate dnp->dn_ident->di_name, buf); 4595*7c478bd9Sstevel@tonic-gate dt_node_printr(inp->din_root, fp, depth + 1); 4596*7c478bd9Sstevel@tonic-gate break; 4597*7c478bd9Sstevel@tonic-gate 4598*7c478bd9Sstevel@tonic-gate case DT_NODE_MEMBER: 4599*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "MEMBER %s (%s)\n", dnp->dn_membname, buf); 4600*7c478bd9Sstevel@tonic-gate if (dnp->dn_membexpr) 4601*7c478bd9Sstevel@tonic-gate dt_node_printr(dnp->dn_membexpr, fp, depth + 1); 4602*7c478bd9Sstevel@tonic-gate break; 4603*7c478bd9Sstevel@tonic-gate 4604*7c478bd9Sstevel@tonic-gate case DT_NODE_XLATOR: 4605*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "XLATOR (%s)", buf); 4606*7c478bd9Sstevel@tonic-gate 4607*7c478bd9Sstevel@tonic-gate if (ctf_type_name(dnp->dn_xlator->dx_src_ctfp, 4608*7c478bd9Sstevel@tonic-gate dnp->dn_xlator->dx_src_type, n, sizeof (n)) != NULL) 4609*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " from <%s>", n); 4610*7c478bd9Sstevel@tonic-gate 4611*7c478bd9Sstevel@tonic-gate if (ctf_type_name(dnp->dn_xlator->dx_dst_ctfp, 4612*7c478bd9Sstevel@tonic-gate dnp->dn_xlator->dx_dst_type, n, sizeof (n)) != NULL) 4613*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, " to <%s>", n); 4614*7c478bd9Sstevel@tonic-gate 4615*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n"); 4616*7c478bd9Sstevel@tonic-gate 4617*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_members; arg != NULL; arg = arg->dn_list) 4618*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4619*7c478bd9Sstevel@tonic-gate break; 4620*7c478bd9Sstevel@tonic-gate 4621*7c478bd9Sstevel@tonic-gate case DT_NODE_PROBE: 4622*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "PROBE %s\n", dnp->dn_ident->di_name); 4623*7c478bd9Sstevel@tonic-gate break; 4624*7c478bd9Sstevel@tonic-gate 4625*7c478bd9Sstevel@tonic-gate case DT_NODE_PROVIDER: 4626*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "PROVIDER %s (%s)\n", 4627*7c478bd9Sstevel@tonic-gate dnp->dn_provname, dnp->dn_provred ? "redecl" : "decl"); 4628*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list) 4629*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4630*7c478bd9Sstevel@tonic-gate break; 4631*7c478bd9Sstevel@tonic-gate 4632*7c478bd9Sstevel@tonic-gate case DT_NODE_PROG: 4633*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "PROGRAM attr=%s\n", a); 4634*7c478bd9Sstevel@tonic-gate for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list) 4635*7c478bd9Sstevel@tonic-gate dt_node_printr(arg, fp, depth + 1); 4636*7c478bd9Sstevel@tonic-gate break; 4637*7c478bd9Sstevel@tonic-gate 4638*7c478bd9Sstevel@tonic-gate default: 4639*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "<bad node %p, kind %d>\n", 4640*7c478bd9Sstevel@tonic-gate (void *)dnp, dnp->dn_kind); 4641*7c478bd9Sstevel@tonic-gate } 4642*7c478bd9Sstevel@tonic-gate } 4643*7c478bd9Sstevel@tonic-gate 4644*7c478bd9Sstevel@tonic-gate int 4645*7c478bd9Sstevel@tonic-gate dt_node_root(dt_node_t *dnp) 4646*7c478bd9Sstevel@tonic-gate { 4647*7c478bd9Sstevel@tonic-gate yypcb->pcb_root = dnp; 4648*7c478bd9Sstevel@tonic-gate return (0); 4649*7c478bd9Sstevel@tonic-gate } 4650*7c478bd9Sstevel@tonic-gate 4651*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 4652*7c478bd9Sstevel@tonic-gate void 4653*7c478bd9Sstevel@tonic-gate dnerror(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...) 4654*7c478bd9Sstevel@tonic-gate { 4655*7c478bd9Sstevel@tonic-gate int oldlineno = yylineno; 4656*7c478bd9Sstevel@tonic-gate va_list ap; 4657*7c478bd9Sstevel@tonic-gate 4658*7c478bd9Sstevel@tonic-gate yylineno = dnp->dn_line; 4659*7c478bd9Sstevel@tonic-gate 4660*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4661*7c478bd9Sstevel@tonic-gate xyvwarn(tag, format, ap); 4662*7c478bd9Sstevel@tonic-gate va_end(ap); 4663*7c478bd9Sstevel@tonic-gate 4664*7c478bd9Sstevel@tonic-gate yylineno = oldlineno; 4665*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 4666*7c478bd9Sstevel@tonic-gate } 4667*7c478bd9Sstevel@tonic-gate 4668*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 4669*7c478bd9Sstevel@tonic-gate void 4670*7c478bd9Sstevel@tonic-gate dnwarn(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...) 4671*7c478bd9Sstevel@tonic-gate { 4672*7c478bd9Sstevel@tonic-gate int oldlineno = yylineno; 4673*7c478bd9Sstevel@tonic-gate va_list ap; 4674*7c478bd9Sstevel@tonic-gate 4675*7c478bd9Sstevel@tonic-gate yylineno = dnp->dn_line; 4676*7c478bd9Sstevel@tonic-gate 4677*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4678*7c478bd9Sstevel@tonic-gate xyvwarn(tag, format, ap); 4679*7c478bd9Sstevel@tonic-gate va_end(ap); 4680*7c478bd9Sstevel@tonic-gate 4681*7c478bd9Sstevel@tonic-gate yylineno = oldlineno; 4682*7c478bd9Sstevel@tonic-gate } 4683*7c478bd9Sstevel@tonic-gate 4684*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 4685*7c478bd9Sstevel@tonic-gate void 4686*7c478bd9Sstevel@tonic-gate xyerror(dt_errtag_t tag, const char *format, ...) 4687*7c478bd9Sstevel@tonic-gate { 4688*7c478bd9Sstevel@tonic-gate va_list ap; 4689*7c478bd9Sstevel@tonic-gate 4690*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4691*7c478bd9Sstevel@tonic-gate xyvwarn(tag, format, ap); 4692*7c478bd9Sstevel@tonic-gate va_end(ap); 4693*7c478bd9Sstevel@tonic-gate 4694*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 4695*7c478bd9Sstevel@tonic-gate } 4696*7c478bd9Sstevel@tonic-gate 4697*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 4698*7c478bd9Sstevel@tonic-gate void 4699*7c478bd9Sstevel@tonic-gate xywarn(dt_errtag_t tag, const char *format, ...) 4700*7c478bd9Sstevel@tonic-gate { 4701*7c478bd9Sstevel@tonic-gate va_list ap; 4702*7c478bd9Sstevel@tonic-gate 4703*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4704*7c478bd9Sstevel@tonic-gate xyvwarn(tag, format, ap); 4705*7c478bd9Sstevel@tonic-gate va_end(ap); 4706*7c478bd9Sstevel@tonic-gate } 4707*7c478bd9Sstevel@tonic-gate 4708*7c478bd9Sstevel@tonic-gate void 4709*7c478bd9Sstevel@tonic-gate xyvwarn(dt_errtag_t tag, const char *format, va_list ap) 4710*7c478bd9Sstevel@tonic-gate { 4711*7c478bd9Sstevel@tonic-gate if (yypcb == NULL) 4712*7c478bd9Sstevel@tonic-gate return; /* compiler is not currently active: act as a no-op */ 4713*7c478bd9Sstevel@tonic-gate 4714*7c478bd9Sstevel@tonic-gate dt_set_errmsg(yypcb->pcb_hdl, dt_errtag(tag), yypcb->pcb_region, 4715*7c478bd9Sstevel@tonic-gate yypcb->pcb_filetag, yypcb->pcb_fileptr ? yylineno : 0, format, ap); 4716*7c478bd9Sstevel@tonic-gate } 4717*7c478bd9Sstevel@tonic-gate 4718*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 4719*7c478bd9Sstevel@tonic-gate void 4720*7c478bd9Sstevel@tonic-gate yyerror(const char *format, ...) 4721*7c478bd9Sstevel@tonic-gate { 4722*7c478bd9Sstevel@tonic-gate va_list ap; 4723*7c478bd9Sstevel@tonic-gate 4724*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4725*7c478bd9Sstevel@tonic-gate yyvwarn(format, ap); 4726*7c478bd9Sstevel@tonic-gate va_end(ap); 4727*7c478bd9Sstevel@tonic-gate 4728*7c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); 4729*7c478bd9Sstevel@tonic-gate } 4730*7c478bd9Sstevel@tonic-gate 4731*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 4732*7c478bd9Sstevel@tonic-gate void 4733*7c478bd9Sstevel@tonic-gate yywarn(const char *format, ...) 4734*7c478bd9Sstevel@tonic-gate { 4735*7c478bd9Sstevel@tonic-gate va_list ap; 4736*7c478bd9Sstevel@tonic-gate 4737*7c478bd9Sstevel@tonic-gate va_start(ap, format); 4738*7c478bd9Sstevel@tonic-gate yyvwarn(format, ap); 4739*7c478bd9Sstevel@tonic-gate va_end(ap); 4740*7c478bd9Sstevel@tonic-gate } 4741*7c478bd9Sstevel@tonic-gate 4742*7c478bd9Sstevel@tonic-gate void 4743*7c478bd9Sstevel@tonic-gate yyvwarn(const char *format, va_list ap) 4744*7c478bd9Sstevel@tonic-gate { 4745*7c478bd9Sstevel@tonic-gate if (yypcb == NULL) 4746*7c478bd9Sstevel@tonic-gate return; /* compiler is not currently active: act as a no-op */ 4747*7c478bd9Sstevel@tonic-gate 4748*7c478bd9Sstevel@tonic-gate dt_set_errmsg(yypcb->pcb_hdl, dt_errtag(D_SYNTAX), yypcb->pcb_region, 4749*7c478bd9Sstevel@tonic-gate yypcb->pcb_filetag, yypcb->pcb_fileptr ? yylineno : 0, format, ap); 4750*7c478bd9Sstevel@tonic-gate 4751*7c478bd9Sstevel@tonic-gate if (strchr(format, '\n') == NULL) { 4752*7c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl; 4753*7c478bd9Sstevel@tonic-gate size_t len = strlen(dtp->dt_errmsg); 4754*7c478bd9Sstevel@tonic-gate char *p, *s = dtp->dt_errmsg + len; 4755*7c478bd9Sstevel@tonic-gate size_t n = sizeof (dtp->dt_errmsg) - len; 4756*7c478bd9Sstevel@tonic-gate 4757*7c478bd9Sstevel@tonic-gate if (yytext[0] == '\0') 4758*7c478bd9Sstevel@tonic-gate (void) snprintf(s, n, " near end of input"); 4759*7c478bd9Sstevel@tonic-gate else if (yytext[0] == '\n') 4760*7c478bd9Sstevel@tonic-gate (void) snprintf(s, n, " near end of line"); 4761*7c478bd9Sstevel@tonic-gate else { 4762*7c478bd9Sstevel@tonic-gate if ((p = strchr(yytext, '\n')) != NULL) 4763*7c478bd9Sstevel@tonic-gate *p = '\0'; /* crop at newline */ 4764*7c478bd9Sstevel@tonic-gate (void) snprintf(s, n, " near \"%s\"", yytext); 4765*7c478bd9Sstevel@tonic-gate } 4766*7c478bd9Sstevel@tonic-gate } 4767*7c478bd9Sstevel@tonic-gate } 4768*7c478bd9Sstevel@tonic-gate 4769*7c478bd9Sstevel@tonic-gate void 4770*7c478bd9Sstevel@tonic-gate yylabel(const char *label) 4771*7c478bd9Sstevel@tonic-gate { 4772*7c478bd9Sstevel@tonic-gate dt_dprintf("set label to <%s>\n", label ? label : "NULL"); 4773*7c478bd9Sstevel@tonic-gate yypcb->pcb_region = label; 4774*7c478bd9Sstevel@tonic-gate } 4775*7c478bd9Sstevel@tonic-gate 4776*7c478bd9Sstevel@tonic-gate int 4777*7c478bd9Sstevel@tonic-gate yywrap(void) 4778*7c478bd9Sstevel@tonic-gate { 4779*7c478bd9Sstevel@tonic-gate return (1); /* indicate that lex should return a zero token for EOF */ 4780*7c478bd9Sstevel@tonic-gate } 4781