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