Path: blob/main/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
39563 views
/*1* CDDL HEADER START2*3* The contents of this file are subject to the terms of the4* Common Development and Distribution License, Version 1.0 only5* (the "License"). You may not use this file except in compliance6* with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or http://www.opensolaris.org/os/licensing.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright 2006 Sun Microsystems, Inc. All rights reserved.24* Copyright (c) 2013, Joyent Inc. All rights reserved.25* Copyright (c) 2012, 2016 by Delphix. All rights reserved.26*/2728#pragma ident "%Z%%M% %I% %E% SMI"2930/*31* DTrace D Language Parser32*33* The D Parser is a lex/yacc parser consisting of the lexer dt_lex.l, the34* parsing grammar dt_grammar.y, and this file, dt_parser.c, which handles35* the construction of the parse tree nodes and their syntactic validation.36* The parse tree is constructed of dt_node_t structures (see <dt_parser.h>)37* that are built in two passes: (1) the "create" pass, where the parse tree38* nodes are allocated by calls from the grammar to dt_node_*() subroutines,39* and (2) the "cook" pass, where nodes are coalesced, assigned D types, and40* validated according to the syntactic rules of the language.41*42* All node allocations are performed using dt_node_alloc(). All node frees43* during the parsing phase are performed by dt_node_free(), which frees node-44* internal state but does not actually free the nodes. All final node frees45* are done as part of the end of dt_compile() or as part of destroying46* persistent identifiers or translators which have embedded nodes.47*48* The dt_node_* routines that implement pass (1) may allocate new nodes. The49* dt_cook_* routines that implement pass (2) may *not* allocate new nodes.50* They may free existing nodes using dt_node_free(), but they may not actually51* deallocate any dt_node_t's. Currently dt_cook_op2() is an exception to this52* rule: see the comments therein for how this issue is resolved.53*54* The dt_cook_* routines are responsible for (at minimum) setting the final55* node type (dn_ctfp/dn_type) and attributes (dn_attr). If dn_ctfp/dn_type56* are set manually (i.e. not by one of the type assignment functions), then57* the DT_NF_COOKED flag must be set manually on the node.58*59* The cooking pass can be applied to the same parse tree more than once (used60* in the case of a comma-separated list of probe descriptions). As such, the61* cook routines must not perform any parse tree transformations which would62* be invalid if the tree were subsequently cooked using a different context.63*64* The dn_ctfp and dn_type fields form the type of the node. This tuple can65* take on the following set of values, which form our type invariants:66*67* 1. dn_ctfp = NULL, dn_type = CTF_ERR68*69* In this state, the node has unknown type and is not yet cooked. The70* DT_NF_COOKED flag is not yet set on the node.71*72* 2. dn_ctfp = DT_DYN_CTFP(dtp), dn_type = DT_DYN_TYPE(dtp)73*74* In this state, the node is a dynamic D type. This means that generic75* operations are not valid on this node and only code that knows how to76* examine the inner details of the node can operate on it. A <DYN> node77* must have dn_ident set to point to an identifier describing the object78* and its type. The DT_NF_REF flag is set for all nodes of type <DYN>.79* At present, the D compiler uses the <DYN> type for:80*81* - associative arrays that do not yet have a value type defined82* - translated data (i.e. the result of the xlate operator)83* - aggregations84*85* 3. dn_ctfp = DT_STR_CTFP(dtp), dn_type = DT_STR_TYPE(dtp)86*87* In this state, the node is of type D string. The string type is really88* a char[0] typedef, but requires special handling throughout the compiler.89*90* 4. dn_ctfp != NULL, dn_type = any other type ID91*92* In this state, the node is of some known D/CTF type. The normal libctf93* APIs can be used to learn more about the type name or structure. When94* the type is assigned, the DT_NF_SIGNED, DT_NF_REF, and DT_NF_BITFIELD95* flags cache the corresponding attributes of the underlying CTF type.96*/9798#include <sys/param.h>99#include <sys/sysmacros.h>100#include <limits.h>101#include <setjmp.h>102#include <strings.h>103#include <assert.h>104#ifdef illumos105#include <alloca.h>106#endif107#include <stdlib.h>108#include <stdarg.h>109#include <stdio.h>110#include <errno.h>111#include <ctype.h>112113#include <dt_impl.h>114#include <dt_grammar.h>115#include <dt_module.h>116#include <dt_provider.h>117#include <dt_string.h>118#include <dt_as.h>119120dt_pcb_t *yypcb; /* current control block for parser */121dt_node_t *yypragma; /* lex token list for control lines */122char yyintprefix; /* int token macro prefix (+/-) */123char yyintsuffix[4]; /* int token suffix string [uU][lL] */124int yyintdecimal; /* int token format flag (1=decimal, 0=octal/hex) */125126static const char *127opstr(int op)128{129switch (op) {130case DT_TOK_COMMA: return (",");131case DT_TOK_ELLIPSIS: return ("...");132case DT_TOK_ASGN: return ("=");133case DT_TOK_ADD_EQ: return ("+=");134case DT_TOK_SUB_EQ: return ("-=");135case DT_TOK_MUL_EQ: return ("*=");136case DT_TOK_DIV_EQ: return ("/=");137case DT_TOK_MOD_EQ: return ("%=");138case DT_TOK_AND_EQ: return ("&=");139case DT_TOK_XOR_EQ: return ("^=");140case DT_TOK_OR_EQ: return ("|=");141case DT_TOK_LSH_EQ: return ("<<=");142case DT_TOK_RSH_EQ: return (">>=");143case DT_TOK_QUESTION: return ("?");144case DT_TOK_COLON: return (":");145case DT_TOK_LOR: return ("||");146case DT_TOK_LXOR: return ("^^");147case DT_TOK_LAND: return ("&&");148case DT_TOK_BOR: return ("|");149case DT_TOK_XOR: return ("^");150case DT_TOK_BAND: return ("&");151case DT_TOK_EQU: return ("==");152case DT_TOK_NEQ: return ("!=");153case DT_TOK_LT: return ("<");154case DT_TOK_LE: return ("<=");155case DT_TOK_GT: return (">");156case DT_TOK_GE: return (">=");157case DT_TOK_LSH: return ("<<");158case DT_TOK_RSH: return (">>");159case DT_TOK_ADD: return ("+");160case DT_TOK_SUB: return ("-");161case DT_TOK_MUL: return ("*");162case DT_TOK_DIV: return ("/");163case DT_TOK_MOD: return ("%");164case DT_TOK_LNEG: return ("!");165case DT_TOK_BNEG: return ("~");166case DT_TOK_ADDADD: return ("++");167case DT_TOK_PREINC: return ("++");168case DT_TOK_POSTINC: return ("++");169case DT_TOK_SUBSUB: return ("--");170case DT_TOK_PREDEC: return ("--");171case DT_TOK_POSTDEC: return ("--");172case DT_TOK_IPOS: return ("+");173case DT_TOK_INEG: return ("-");174case DT_TOK_DEREF: return ("*");175case DT_TOK_ADDROF: return ("&");176case DT_TOK_OFFSETOF: return ("offsetof");177case DT_TOK_SIZEOF: return ("sizeof");178case DT_TOK_STRINGOF: return ("stringof");179case DT_TOK_XLATE: return ("xlate");180case DT_TOK_LPAR: return ("(");181case DT_TOK_RPAR: return (")");182case DT_TOK_LBRAC: return ("[");183case DT_TOK_RBRAC: return ("]");184case DT_TOK_PTR: return ("->");185case DT_TOK_DOT: return (".");186case DT_TOK_STRING: return ("<string>");187case DT_TOK_IDENT: return ("<ident>");188case DT_TOK_TNAME: return ("<type>");189case DT_TOK_INT: return ("<int>");190default: return ("<?>");191}192}193194int195dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)196{197static const char delimiters[] = " \t\n\r\v\f*`";198dtrace_hdl_t *dtp = yypcb->pcb_hdl;199const char *p, *q, *r, *end, *obj;200201for (p = s, end = s + strlen(s); *p != '\0'; p = q) {202while (isspace(*p))203p++; /* skip leading whitespace prior to token */204205if (p == end || (q = strpbrk(p + 1, delimiters)) == NULL)206break; /* empty string or single token remaining */207208if (*q == '`') {209char *object = alloca((size_t)(q - p) + 1);210char *type = alloca((size_t)(end - s) + 1);211212/*213* Copy from the start of the token (p) to the location214* backquote (q) to extract the nul-terminated object.215*/216bcopy(p, object, (size_t)(q - p));217object[(size_t)(q - p)] = '\0';218219/*220* Copy the original string up to the start of this221* token (p) into type, and then concatenate everything222* after q. This is the type name without the object.223*/224bcopy(s, type, (size_t)(p - s));225bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);226227/*228* There may be at most three delimeters. The second229* delimeter is usually used to distinguish the type230* within a given module, however, there could be a link231* map id on the scene in which case that delimeter232* would be the third. We determine presence of the lmid233* if it rouglhly meets the from LM[0-9]234*/235if ((r = strchr(q + 1, '`')) != NULL &&236((r = strchr(r + 1, '`')) != NULL)) {237if (strchr(r + 1, '`') != NULL)238return (dt_set_errno(dtp,239EDT_BADSCOPE));240if (q[1] != 'L' || q[2] != 'M')241return (dt_set_errno(dtp,242EDT_BADSCOPE));243}244245return (dtrace_lookup_by_type(dtp, object, type, tip));246}247}248249if (yypcb->pcb_idepth != 0)250obj = DTRACE_OBJ_CDEFS;251else252obj = DTRACE_OBJ_EVERY;253254return (dtrace_lookup_by_type(dtp, obj, s, tip));255}256257/*258* When we parse type expressions or parse an expression with unary "&", we259* need to find a type that is a pointer to a previously known type.260* Unfortunately CTF is limited to a per-container view, so ctf_type_pointer()261* alone does not suffice for our needs. We provide a more intelligent wrapper262* for the compiler that attempts to compute a pointer to either the given type263* or its base (that is, we try both "foo_t *" and "struct foo *"), and also264* to potentially construct the required type on-the-fly.265*/266int267dt_type_pointer(dtrace_typeinfo_t *tip)268{269dtrace_hdl_t *dtp = yypcb->pcb_hdl;270ctf_file_t *ctfp = tip->dtt_ctfp;271ctf_id_t type = tip->dtt_type;272ctf_id_t base = ctf_type_resolve(ctfp, type);273uint_t bflags = tip->dtt_flags;274275dt_module_t *dmp;276ctf_id_t ptr;277278if ((ptr = ctf_type_pointer(ctfp, type)) != CTF_ERR ||279(ptr = ctf_type_pointer(ctfp, base)) != CTF_ERR) {280tip->dtt_type = ptr;281return (0);282}283284if (yypcb->pcb_idepth != 0)285dmp = dtp->dt_cdefs;286else287dmp = dtp->dt_ddefs;288289if (ctfp != dmp->dm_ctfp && ctfp != ctf_parent_file(dmp->dm_ctfp) &&290(type = ctf_add_type(dmp->dm_ctfp, ctfp, type)) == CTF_ERR) {291dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);292return (dt_set_errno(dtp, EDT_CTF));293}294295ptr = ctf_add_pointer(dmp->dm_ctfp, CTF_ADD_ROOT, type);296297if (ptr == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {298dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);299return (dt_set_errno(dtp, EDT_CTF));300}301302tip->dtt_object = dmp->dm_name;303tip->dtt_ctfp = dmp->dm_ctfp;304tip->dtt_type = ptr;305tip->dtt_flags = bflags;306307return (0);308}309310const char *311dt_type_name(ctf_file_t *ctfp, ctf_id_t type, char *buf, size_t len)312{313dtrace_hdl_t *dtp = yypcb->pcb_hdl;314315if (ctfp == DT_FPTR_CTFP(dtp) && type == DT_FPTR_TYPE(dtp))316(void) snprintf(buf, len, "function pointer");317else if (ctfp == DT_FUNC_CTFP(dtp) && type == DT_FUNC_TYPE(dtp))318(void) snprintf(buf, len, "function");319else if (ctfp == DT_DYN_CTFP(dtp) && type == DT_DYN_TYPE(dtp))320(void) snprintf(buf, len, "dynamic variable");321else if (ctfp == NULL)322(void) snprintf(buf, len, "<none>");323else if (ctf_type_name(ctfp, type, buf, len) == NULL)324(void) snprintf(buf, len, "unknown");325326return (buf);327}328329/*330* Perform the "usual arithmetic conversions" to determine which of the two331* input operand types should be promoted and used as a result type. The332* rules for this are described in ISOC[6.3.1.8] and K&R[A6.5].333*/334static void335dt_type_promote(dt_node_t *lp, dt_node_t *rp, ctf_file_t **ofp, ctf_id_t *otype)336{337ctf_file_t *lfp = lp->dn_ctfp;338ctf_id_t ltype = lp->dn_type;339340ctf_file_t *rfp = rp->dn_ctfp;341ctf_id_t rtype = rp->dn_type;342343ctf_id_t lbase = ctf_type_resolve(lfp, ltype);344uint_t lkind = ctf_type_kind(lfp, lbase);345346ctf_id_t rbase = ctf_type_resolve(rfp, rtype);347uint_t rkind = ctf_type_kind(rfp, rbase);348349dtrace_hdl_t *dtp = yypcb->pcb_hdl;350ctf_encoding_t le, re;351uint_t lrank, rrank;352353assert(lkind == CTF_K_INTEGER || lkind == CTF_K_ENUM);354assert(rkind == CTF_K_INTEGER || rkind == CTF_K_ENUM);355356if (lkind == CTF_K_ENUM) {357lfp = DT_INT_CTFP(dtp);358ltype = lbase = DT_INT_TYPE(dtp);359}360361if (rkind == CTF_K_ENUM) {362rfp = DT_INT_CTFP(dtp);363rtype = rbase = DT_INT_TYPE(dtp);364}365366if (ctf_type_encoding(lfp, lbase, &le) == CTF_ERR) {367yypcb->pcb_hdl->dt_ctferr = ctf_errno(lfp);368longjmp(yypcb->pcb_jmpbuf, EDT_CTF);369}370371if (ctf_type_encoding(rfp, rbase, &re) == CTF_ERR) {372yypcb->pcb_hdl->dt_ctferr = ctf_errno(rfp);373longjmp(yypcb->pcb_jmpbuf, EDT_CTF);374}375376/*377* Compute an integer rank based on the size and unsigned status.378* If rank is identical, pick the "larger" of the equivalent types379* which we define as having a larger base ctf_id_t. If rank is380* different, pick the type with the greater rank.381*/382lrank = le.cte_bits + ((le.cte_format & CTF_INT_SIGNED) == 0);383rrank = re.cte_bits + ((re.cte_format & CTF_INT_SIGNED) == 0);384385if (lrank == rrank) {386if (lbase - rbase < 0)387goto return_rtype;388else389goto return_ltype;390} else if (lrank > rrank) {391goto return_ltype;392} else393goto return_rtype;394395return_ltype:396*ofp = lfp;397*otype = ltype;398return;399400return_rtype:401*ofp = rfp;402*otype = rtype;403}404405void406dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)407{408dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);409dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);410dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));411}412413const char *414dt_node_name(const dt_node_t *dnp, char *buf, size_t len)415{416char n1[DT_TYPE_NAMELEN];417char n2[DT_TYPE_NAMELEN];418419const char *prefix = "", *suffix = "";420const dtrace_syminfo_t *dts;421char *s;422423switch (dnp->dn_kind) {424case DT_NODE_INT:425(void) snprintf(buf, len, "integer constant 0x%llx",426(u_longlong_t)dnp->dn_value);427break;428case DT_NODE_STRING:429s = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));430(void) snprintf(buf, len, "string constant \"%s\"",431s != NULL ? s : dnp->dn_string);432free(s);433break;434case DT_NODE_IDENT:435(void) snprintf(buf, len, "identifier %s", dnp->dn_string);436break;437case DT_NODE_VAR:438case DT_NODE_FUNC:439case DT_NODE_AGG:440case DT_NODE_INLINE:441switch (dnp->dn_ident->di_kind) {442case DT_IDENT_FUNC:443case DT_IDENT_AGGFUNC:444case DT_IDENT_ACTFUNC:445suffix = "( )";446break;447case DT_IDENT_AGG:448prefix = "@";449break;450}451(void) snprintf(buf, len, "%s %s%s%s",452dt_idkind_name(dnp->dn_ident->di_kind),453prefix, dnp->dn_ident->di_name, suffix);454break;455case DT_NODE_SYM:456dts = dnp->dn_ident->di_data;457(void) snprintf(buf, len, "symbol %s`%s",458dts->dts_object, dts->dts_name);459break;460case DT_NODE_TYPE:461(void) snprintf(buf, len, "type %s",462dt_node_type_name(dnp, n1, sizeof (n1)));463break;464case DT_NODE_OP1:465case DT_NODE_OP2:466case DT_NODE_OP3:467(void) snprintf(buf, len, "operator %s", opstr(dnp->dn_op));468break;469case DT_NODE_DEXPR:470case DT_NODE_DFUNC:471if (dnp->dn_expr)472return (dt_node_name(dnp->dn_expr, buf, len));473(void) snprintf(buf, len, "%s", "statement");474break;475case DT_NODE_PDESC:476if (dnp->dn_desc->dtpd_id == 0) {477(void) snprintf(buf, len,478"probe description %s:%s:%s:%s",479dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,480dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name);481} else {482(void) snprintf(buf, len, "probe description %u",483dnp->dn_desc->dtpd_id);484}485break;486case DT_NODE_CLAUSE:487(void) snprintf(buf, len, "%s", "clause");488break;489case DT_NODE_MEMBER:490(void) snprintf(buf, len, "member %s", dnp->dn_membname);491break;492case DT_NODE_XLATOR:493(void) snprintf(buf, len, "translator <%s> (%s)",494dt_type_name(dnp->dn_xlator->dx_dst_ctfp,495dnp->dn_xlator->dx_dst_type, n1, sizeof (n1)),496dt_type_name(dnp->dn_xlator->dx_src_ctfp,497dnp->dn_xlator->dx_src_type, n2, sizeof (n2)));498break;499case DT_NODE_PROG:500(void) snprintf(buf, len, "%s", "program");501break;502default:503(void) snprintf(buf, len, "node <%u>", dnp->dn_kind);504break;505}506507return (buf);508}509510/*511* dt_node_xalloc() can be used to create new parse nodes from any libdtrace512* caller. The caller is responsible for assigning dn_link appropriately.513*/514dt_node_t *515dt_node_xalloc(dtrace_hdl_t *dtp, int kind)516{517dt_node_t *dnp = dt_alloc(dtp, sizeof (dt_node_t));518519if (dnp == NULL)520return (NULL);521522dnp->dn_ctfp = NULL;523dnp->dn_type = CTF_ERR;524dnp->dn_kind = (uchar_t)kind;525dnp->dn_flags = 0;526dnp->dn_op = 0;527dnp->dn_line = -1;528dnp->dn_reg = -1;529dnp->dn_attr = _dtrace_defattr;530dnp->dn_list = NULL;531dnp->dn_link = NULL;532bzero(&dnp->dn_u, sizeof (dnp->dn_u));533534return (dnp);535}536537/*538* dt_node_alloc() is used to create new parse nodes from the parser. It539* assigns the node location based on the current lexer line number and places540* the new node on the default allocation list. If allocation fails, we541* automatically longjmp the caller back to the enclosing compilation call.542*/543static dt_node_t *544dt_node_alloc(int kind)545{546dt_node_t *dnp = dt_node_xalloc(yypcb->pcb_hdl, kind);547548if (dnp == NULL)549longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);550551dnp->dn_line = yylineno;552dnp->dn_link = yypcb->pcb_list;553yypcb->pcb_list = dnp;554555return (dnp);556}557558void559dt_node_free(dt_node_t *dnp)560{561uchar_t kind = dnp->dn_kind;562563dnp->dn_kind = DT_NODE_FREE;564565switch (kind) {566case DT_NODE_STRING:567case DT_NODE_IDENT:568case DT_NODE_TYPE:569free(dnp->dn_string);570dnp->dn_string = NULL;571break;572573case DT_NODE_VAR:574case DT_NODE_FUNC:575case DT_NODE_PROBE:576if (dnp->dn_ident != NULL) {577if (dnp->dn_ident->di_flags & DT_IDFLG_ORPHAN)578dt_ident_destroy(dnp->dn_ident);579dnp->dn_ident = NULL;580}581dt_node_list_free(&dnp->dn_args);582break;583584case DT_NODE_OP1:585if (dnp->dn_child != NULL) {586dt_node_free(dnp->dn_child);587dnp->dn_child = NULL;588}589break;590591case DT_NODE_OP3:592if (dnp->dn_expr != NULL) {593dt_node_free(dnp->dn_expr);594dnp->dn_expr = NULL;595}596/*FALLTHRU*/597case DT_NODE_OP2:598if (dnp->dn_left != NULL) {599dt_node_free(dnp->dn_left);600dnp->dn_left = NULL;601}602if (dnp->dn_right != NULL) {603dt_node_free(dnp->dn_right);604dnp->dn_right = NULL;605}606break;607608case DT_NODE_DEXPR:609case DT_NODE_DFUNC:610if (dnp->dn_expr != NULL) {611dt_node_free(dnp->dn_expr);612dnp->dn_expr = NULL;613}614break;615616case DT_NODE_AGG:617if (dnp->dn_aggfun != NULL) {618dt_node_free(dnp->dn_aggfun);619dnp->dn_aggfun = NULL;620}621dt_node_list_free(&dnp->dn_aggtup);622break;623624case DT_NODE_PDESC:625free(dnp->dn_spec);626dnp->dn_spec = NULL;627free(dnp->dn_desc);628dnp->dn_desc = NULL;629break;630631case DT_NODE_CLAUSE:632if (dnp->dn_pred != NULL)633dt_node_free(dnp->dn_pred);634if (dnp->dn_locals != NULL)635dt_idhash_destroy(dnp->dn_locals);636dt_node_list_free(&dnp->dn_pdescs);637dt_node_list_free(&dnp->dn_acts);638break;639640case DT_NODE_MEMBER:641free(dnp->dn_membname);642dnp->dn_membname = NULL;643if (dnp->dn_membexpr != NULL) {644dt_node_free(dnp->dn_membexpr);645dnp->dn_membexpr = NULL;646}647break;648649case DT_NODE_PROVIDER:650dt_node_list_free(&dnp->dn_probes);651free(dnp->dn_provname);652dnp->dn_provname = NULL;653break;654655case DT_NODE_PROG:656dt_node_list_free(&dnp->dn_list);657break;658}659}660661void662dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)663{664if ((yypcb->pcb_cflags & DTRACE_C_EATTR) &&665(dt_attr_cmp(attr, yypcb->pcb_amin) < 0)) {666char a[DTRACE_ATTR2STR_MAX];667char s[BUFSIZ];668669dnerror(dnp, D_ATTR_MIN, "attributes for %s (%s) are less than "670"predefined minimum\n", dt_node_name(dnp, s, sizeof (s)),671dtrace_attr2str(attr, a, sizeof (a)));672}673674dnp->dn_attr = attr;675}676677void678dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,679boolean_t user)680{681ctf_id_t base = ctf_type_resolve(fp, type);682uint_t kind = ctf_type_kind(fp, base);683ctf_encoding_t e;684685dnp->dn_flags &=686~(DT_NF_SIGNED | DT_NF_REF | DT_NF_BITFIELD | DT_NF_USERLAND);687688if (kind == CTF_K_INTEGER && ctf_type_encoding(fp, base, &e) == 0) {689size_t size = e.cte_bits / NBBY;690691if (size > 8 || (e.cte_bits % NBBY) != 0 || (size & (size - 1)))692dnp->dn_flags |= DT_NF_BITFIELD;693694if (e.cte_format & CTF_INT_SIGNED)695dnp->dn_flags |= DT_NF_SIGNED;696}697698if (kind == CTF_K_FLOAT && ctf_type_encoding(fp, base, &e) == 0) {699if (e.cte_bits / NBBY > sizeof (uint64_t))700dnp->dn_flags |= DT_NF_REF;701}702703if (kind == CTF_K_STRUCT || kind == CTF_K_UNION ||704kind == CTF_K_FORWARD ||705kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION)706dnp->dn_flags |= DT_NF_REF;707else if (yypcb != NULL && fp == DT_DYN_CTFP(yypcb->pcb_hdl) &&708type == DT_DYN_TYPE(yypcb->pcb_hdl))709dnp->dn_flags |= DT_NF_REF;710711if (user)712dnp->dn_flags |= DT_NF_USERLAND;713714dnp->dn_flags |= DT_NF_COOKED;715dnp->dn_ctfp = fp;716dnp->dn_type = type;717}718719void720dt_node_type_propagate(const dt_node_t *src, dt_node_t *dst)721{722assert(src->dn_flags & DT_NF_COOKED);723dst->dn_flags = src->dn_flags & ~DT_NF_LVALUE;724dst->dn_ctfp = src->dn_ctfp;725dst->dn_type = src->dn_type;726}727728const char *729dt_node_type_name(const dt_node_t *dnp, char *buf, size_t len)730{731if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL) {732(void) snprintf(buf, len, "%s",733dt_idkind_name(dt_ident_resolve(dnp->dn_ident)->di_kind));734return (buf);735}736737if (dnp->dn_flags & DT_NF_USERLAND) {738size_t n = snprintf(buf, len, "userland ");739len = len > n ? len - n : 0;740(void) dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf + n, len);741return (buf);742}743744return (dt_type_name(dnp->dn_ctfp, dnp->dn_type, buf, len));745}746747size_t748dt_node_type_size(const dt_node_t *dnp)749{750ctf_id_t base;751dtrace_hdl_t *dtp = yypcb->pcb_hdl;752753if (dnp->dn_kind == DT_NODE_STRING)754return (strlen(dnp->dn_string) + 1);755756if (dt_node_is_dynamic(dnp) && dnp->dn_ident != NULL)757return (dt_ident_size(dnp->dn_ident));758759base = ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type);760761if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)762return (0);763764/*765* Here we have a 32-bit user pointer that is being used with a 64-bit766* kernel. When we're using it and its tagged as a userland reference --767* then we need to keep it as a 32-bit pointer. However, if we are768* referring to it as a kernel address, eg. being used after a copyin()769* then we need to make sure that we actually return the kernel's size770* of a pointer, 8 bytes.771*/772if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&773ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&774!(dnp->dn_flags & DT_NF_USERLAND) &&775dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)776return (8);777778return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));779}780781/*782* Determine if the specified parse tree node references an identifier of the783* specified kind, and if so return a pointer to it; otherwise return NULL.784* This function resolves the identifier itself, following through any inlines.785*/786dt_ident_t *787dt_node_resolve(const dt_node_t *dnp, uint_t idkind)788{789dt_ident_t *idp;790791switch (dnp->dn_kind) {792case DT_NODE_VAR:793case DT_NODE_SYM:794case DT_NODE_FUNC:795case DT_NODE_AGG:796case DT_NODE_INLINE:797case DT_NODE_PROBE:798idp = dt_ident_resolve(dnp->dn_ident);799return (idp->di_kind == idkind ? idp : NULL);800}801802if (dt_node_is_dynamic(dnp)) {803idp = dt_ident_resolve(dnp->dn_ident);804return (idp->di_kind == idkind ? idp : NULL);805}806807return (NULL);808}809810size_t811dt_node_sizeof(const dt_node_t *dnp)812{813dtrace_syminfo_t *sip;814GElf_Sym sym;815dtrace_hdl_t *dtp = yypcb->pcb_hdl;816817/*818* The size of the node as used for the sizeof() operator depends on819* the kind of the node. If the node is a SYM, the size is obtained820* from the symbol table; if it is not a SYM, the size is determined821* from the node's type. This is slightly different from C's sizeof()822* operator in that (for example) when applied to a function, sizeof()823* will evaluate to the length of the function rather than the size of824* the function type.825*/826if (dnp->dn_kind != DT_NODE_SYM)827return (dt_node_type_size(dnp));828829sip = dnp->dn_ident->di_data;830831if (dtrace_lookup_by_name(dtp, sip->dts_object,832sip->dts_name, &sym, NULL) == -1)833return (0);834835return (sym.st_size);836}837838int839dt_node_is_integer(const dt_node_t *dnp)840{841ctf_file_t *fp = dnp->dn_ctfp;842ctf_encoding_t e;843ctf_id_t type;844uint_t kind;845846assert(dnp->dn_flags & DT_NF_COOKED);847848type = ctf_type_resolve(fp, dnp->dn_type);849kind = ctf_type_kind(fp, type);850851if (kind == CTF_K_INTEGER &&852ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))853return (0); /* void integer */854855return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM);856}857858int859dt_node_is_float(const dt_node_t *dnp)860{861ctf_file_t *fp = dnp->dn_ctfp;862ctf_encoding_t e;863ctf_id_t type;864uint_t kind;865866assert(dnp->dn_flags & DT_NF_COOKED);867868type = ctf_type_resolve(fp, dnp->dn_type);869kind = ctf_type_kind(fp, type);870871return (kind == CTF_K_FLOAT &&872ctf_type_encoding(dnp->dn_ctfp, type, &e) == 0 && (873e.cte_format == CTF_FP_SINGLE || e.cte_format == CTF_FP_DOUBLE ||874e.cte_format == CTF_FP_LDOUBLE));875}876877int878dt_node_is_scalar(const dt_node_t *dnp)879{880ctf_file_t *fp = dnp->dn_ctfp;881ctf_encoding_t e;882ctf_id_t type;883uint_t kind;884885assert(dnp->dn_flags & DT_NF_COOKED);886887type = ctf_type_resolve(fp, dnp->dn_type);888kind = ctf_type_kind(fp, type);889890if (kind == CTF_K_INTEGER &&891ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e))892return (0); /* void cannot be used as a scalar */893894return (kind == CTF_K_INTEGER || kind == CTF_K_ENUM ||895kind == CTF_K_POINTER);896}897898int899dt_node_is_arith(const dt_node_t *dnp)900{901ctf_file_t *fp = dnp->dn_ctfp;902ctf_encoding_t e;903ctf_id_t type;904uint_t kind;905906assert(dnp->dn_flags & DT_NF_COOKED);907908type = ctf_type_resolve(fp, dnp->dn_type);909kind = ctf_type_kind(fp, type);910911if (kind == CTF_K_INTEGER)912return (ctf_type_encoding(fp, type, &e) == 0 && !IS_VOID(e));913else914return (kind == CTF_K_ENUM);915}916917int918dt_node_is_vfptr(const dt_node_t *dnp)919{920ctf_file_t *fp = dnp->dn_ctfp;921ctf_encoding_t e;922ctf_id_t type;923uint_t kind;924925assert(dnp->dn_flags & DT_NF_COOKED);926927type = ctf_type_resolve(fp, dnp->dn_type);928if (ctf_type_kind(fp, type) != CTF_K_POINTER)929return (0); /* type is not a pointer */930931type = ctf_type_resolve(fp, ctf_type_reference(fp, type));932kind = ctf_type_kind(fp, type);933934return (kind == CTF_K_FUNCTION || (kind == CTF_K_INTEGER &&935ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e)));936}937938int939dt_node_is_dynamic(const dt_node_t *dnp)940{941if (dnp->dn_kind == DT_NODE_VAR &&942(dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {943const dt_idnode_t *inp = dnp->dn_ident->di_iarg;944return (inp->din_root ? dt_node_is_dynamic(inp->din_root) : 0);945}946947return (dnp->dn_ctfp == DT_DYN_CTFP(yypcb->pcb_hdl) &&948dnp->dn_type == DT_DYN_TYPE(yypcb->pcb_hdl));949}950951int952dt_node_is_string(const dt_node_t *dnp)953{954return (dnp->dn_ctfp == DT_STR_CTFP(yypcb->pcb_hdl) &&955dnp->dn_type == DT_STR_TYPE(yypcb->pcb_hdl));956}957958int959dt_node_is_stack(const dt_node_t *dnp)960{961return (dnp->dn_ctfp == DT_STACK_CTFP(yypcb->pcb_hdl) &&962dnp->dn_type == DT_STACK_TYPE(yypcb->pcb_hdl));963}964965int966dt_node_is_symaddr(const dt_node_t *dnp)967{968return (dnp->dn_ctfp == DT_SYMADDR_CTFP(yypcb->pcb_hdl) &&969dnp->dn_type == DT_SYMADDR_TYPE(yypcb->pcb_hdl));970}971972int973dt_node_is_usymaddr(const dt_node_t *dnp)974{975return (dnp->dn_ctfp == DT_USYMADDR_CTFP(yypcb->pcb_hdl) &&976dnp->dn_type == DT_USYMADDR_TYPE(yypcb->pcb_hdl));977}978979int980dt_node_is_strcompat(const dt_node_t *dnp)981{982ctf_file_t *fp = dnp->dn_ctfp;983ctf_encoding_t e;984ctf_arinfo_t r;985ctf_id_t base;986uint_t kind;987988assert(dnp->dn_flags & DT_NF_COOKED);989990base = ctf_type_resolve(fp, dnp->dn_type);991kind = ctf_type_kind(fp, base);992993if (kind == CTF_K_POINTER &&994(base = ctf_type_reference(fp, base)) != CTF_ERR &&995(base = ctf_type_resolve(fp, base)) != CTF_ERR &&996ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))997return (1); /* promote char pointer to string */998999if (kind == CTF_K_ARRAY && ctf_array_info(fp, base, &r) == 0 &&1000(base = ctf_type_resolve(fp, r.ctr_contents)) != CTF_ERR &&1001ctf_type_encoding(fp, base, &e) == 0 && IS_CHAR(e))1002return (1); /* promote char array to string */10031004return (0);1005}10061007int1008dt_node_is_pointer(const dt_node_t *dnp)1009{1010ctf_file_t *fp = dnp->dn_ctfp;1011uint_t kind;10121013assert(dnp->dn_flags & DT_NF_COOKED);10141015if (dt_node_is_string(dnp))1016return (0); /* string are pass-by-ref but act like structs */10171018kind = ctf_type_kind(fp, ctf_type_resolve(fp, dnp->dn_type));1019return (kind == CTF_K_POINTER || kind == CTF_K_ARRAY);1020}10211022int1023dt_node_is_void(const dt_node_t *dnp)1024{1025ctf_file_t *fp = dnp->dn_ctfp;1026ctf_encoding_t e;1027ctf_id_t type;10281029if (dt_node_is_dynamic(dnp))1030return (0); /* <DYN> is an alias for void but not the same */10311032if (dt_node_is_stack(dnp))1033return (0);10341035if (dt_node_is_symaddr(dnp) || dt_node_is_usymaddr(dnp))1036return (0);10371038type = ctf_type_resolve(fp, dnp->dn_type);10391040return (ctf_type_kind(fp, type) == CTF_K_INTEGER &&1041ctf_type_encoding(fp, type, &e) == 0 && IS_VOID(e));1042}10431044int1045dt_node_is_ptrcompat(const dt_node_t *lp, const dt_node_t *rp,1046ctf_file_t **fpp, ctf_id_t *tp)1047{1048ctf_file_t *lfp = lp->dn_ctfp;1049ctf_file_t *rfp = rp->dn_ctfp;10501051ctf_id_t lbase = CTF_ERR, rbase = CTF_ERR;1052ctf_id_t lref = CTF_ERR, rref = CTF_ERR;10531054int lp_is_void, rp_is_void, lp_is_int, rp_is_int, compat;1055uint_t lkind, rkind;1056ctf_encoding_t e;1057ctf_arinfo_t r;10581059assert(lp->dn_flags & DT_NF_COOKED);1060assert(rp->dn_flags & DT_NF_COOKED);10611062if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp))1063return (0); /* fail if either node is a dynamic variable */10641065lp_is_int = dt_node_is_integer(lp);1066rp_is_int = dt_node_is_integer(rp);10671068if (lp_is_int && rp_is_int)1069return (0); /* fail if both nodes are integers */10701071if (lp_is_int && (lp->dn_kind != DT_NODE_INT || lp->dn_value != 0))1072return (0); /* fail if lp is an integer that isn't 0 constant */10731074if (rp_is_int && (rp->dn_kind != DT_NODE_INT || rp->dn_value != 0))1075return (0); /* fail if rp is an integer that isn't 0 constant */10761077if ((lp_is_int == 0 && rp_is_int == 0) && (1078(lp->dn_flags & DT_NF_USERLAND) ^ (rp->dn_flags & DT_NF_USERLAND)))1079return (0); /* fail if only one pointer is a userland address */10801081/*1082* Resolve the left-hand and right-hand types to their base type, and1083* then resolve the referenced type as well (assuming the base type1084* is CTF_K_POINTER or CTF_K_ARRAY). Otherwise [lr]ref = CTF_ERR.1085*/1086if (!lp_is_int) {1087lbase = ctf_type_resolve(lfp, lp->dn_type);1088lkind = ctf_type_kind(lfp, lbase);10891090if (lkind == CTF_K_POINTER) {1091lref = ctf_type_resolve(lfp,1092ctf_type_reference(lfp, lbase));1093} else if (lkind == CTF_K_ARRAY &&1094ctf_array_info(lfp, lbase, &r) == 0) {1095lref = ctf_type_resolve(lfp, r.ctr_contents);1096}1097}10981099if (!rp_is_int) {1100rbase = ctf_type_resolve(rfp, rp->dn_type);1101rkind = ctf_type_kind(rfp, rbase);11021103if (rkind == CTF_K_POINTER) {1104rref = ctf_type_resolve(rfp,1105ctf_type_reference(rfp, rbase));1106} else if (rkind == CTF_K_ARRAY &&1107ctf_array_info(rfp, rbase, &r) == 0) {1108rref = ctf_type_resolve(rfp, r.ctr_contents);1109}1110}11111112/*1113* We know that one or the other type may still be a zero-valued1114* integer constant. To simplify the code below, set the integer1115* type variables equal to the non-integer types and proceed.1116*/1117if (lp_is_int) {1118lbase = rbase;1119lkind = rkind;1120lref = rref;1121lfp = rfp;1122} else if (rp_is_int) {1123rbase = lbase;1124rkind = lkind;1125rref = lref;1126rfp = lfp;1127}11281129lp_is_void = ctf_type_encoding(lfp, lref, &e) == 0 && IS_VOID(e);1130rp_is_void = ctf_type_encoding(rfp, rref, &e) == 0 && IS_VOID(e);11311132/*1133* Let a pointer to a forward declaration be compatible with a pointer1134* to a struct or union of the same name.1135*/1136if (lkind == CTF_K_POINTER && rkind == CTF_K_POINTER) {1137int lrkind, rrkind;11381139lrkind = ctf_type_kind(lfp, lref);1140rrkind = ctf_type_kind(rfp, rref);1141if (lrkind == CTF_K_FORWARD || rrkind == CTF_K_FORWARD) {1142const char *lname, *rname;1143char ln[DT_TYPE_NAMELEN], rn[DT_TYPE_NAMELEN];11441145lname = ctf_type_name(lfp, lref, ln, sizeof (ln));1146rname = ctf_type_name(rfp, rref, rn, sizeof (rn));1147if (lname != NULL && rname != NULL &&1148strcmp(lname, rname) == 0) {1149lp_is_void = lrkind == CTF_K_FORWARD;1150rp_is_void = rrkind == CTF_K_FORWARD;1151}1152}1153}11541155/*1156* The types are compatible if both are pointers to the same type, or1157* if either pointer is a void pointer. If they are compatible, set1158* tp to point to the more specific pointer type and return it.1159*/1160compat = (lkind == CTF_K_POINTER || lkind == CTF_K_ARRAY) &&1161(rkind == CTF_K_POINTER || rkind == CTF_K_ARRAY) &&1162(lp_is_void || rp_is_void || ctf_type_compat(lfp, lref, rfp, rref));11631164if (compat) {1165if (fpp != NULL)1166*fpp = rp_is_void ? lfp : rfp;1167if (tp != NULL)1168*tp = rp_is_void ? lbase : rbase;1169}11701171return (compat);1172}11731174/*1175* The rules for checking argument types against parameter types are described1176* in the ANSI-C spec (see K&R[A7.3.2] and K&R[A7.17]). We use the same rule1177* set to determine whether associative array arguments match the prototype.1178*/1179int1180dt_node_is_argcompat(const dt_node_t *lp, const dt_node_t *rp)1181{1182ctf_file_t *lfp = lp->dn_ctfp;1183ctf_file_t *rfp = rp->dn_ctfp;11841185assert(lp->dn_flags & DT_NF_COOKED);1186assert(rp->dn_flags & DT_NF_COOKED);11871188if (dt_node_is_integer(lp) && dt_node_is_integer(rp))1189return (1); /* integer types are compatible */11901191if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp))1192return (1); /* string types are compatible */11931194if (dt_node_is_stack(lp) && dt_node_is_stack(rp))1195return (1); /* stack types are compatible */11961197if (dt_node_is_symaddr(lp) && dt_node_is_symaddr(rp))1198return (1); /* symaddr types are compatible */11991200if (dt_node_is_usymaddr(lp) && dt_node_is_usymaddr(rp))1201return (1); /* usymaddr types are compatible */12021203switch (ctf_type_kind(lfp, ctf_type_resolve(lfp, lp->dn_type))) {1204case CTF_K_FUNCTION:1205case CTF_K_STRUCT:1206case CTF_K_UNION:1207return (ctf_type_compat(lfp, lp->dn_type, rfp, rp->dn_type));1208default:1209return (dt_node_is_ptrcompat(lp, rp, NULL, NULL));1210}1211}12121213/*1214* We provide dt_node_is_posconst() as a convenience routine for callers who1215* wish to verify that an argument is a positive non-zero integer constant.1216*/1217int1218dt_node_is_posconst(const dt_node_t *dnp)1219{1220return (dnp->dn_kind == DT_NODE_INT && dnp->dn_value != 0 && (1221(dnp->dn_flags & DT_NF_SIGNED) == 0 || (int64_t)dnp->dn_value > 0));1222}12231224int1225dt_node_is_actfunc(const dt_node_t *dnp)1226{1227return (dnp->dn_kind == DT_NODE_FUNC &&1228dnp->dn_ident->di_kind == DT_IDENT_ACTFUNC);1229}12301231/*1232* The original rules for integer constant typing are described in K&R[A2.5.1].1233* However, since we support long long, we instead use the rules from ISO C991234* clause 6.4.4.1 since that is where long longs are formally described. The1235* rules require us to know whether the constant was specified in decimal or1236* in octal or hex, which we do by looking at our lexer's 'yyintdecimal' flag.1237* The type of an integer constant is the first of the corresponding list in1238* which its value can be represented:1239*1240* unsuffixed decimal: int, long, long long1241* unsuffixed oct/hex: int, unsigned int, long, unsigned long,1242* long long, unsigned long long1243* suffix [uU]: unsigned int, unsigned long, unsigned long long1244* suffix [lL] decimal: long, long long1245* suffix [lL] oct/hex: long, unsigned long, long long, unsigned long long1246* suffix [uU][Ll]: unsigned long, unsigned long long1247* suffix ll/LL decimal: long long1248* suffix ll/LL oct/hex: long long, unsigned long long1249* suffix [uU][ll/LL]: unsigned long long1250*1251* Given that our lexer has already validated the suffixes by regexp matching,1252* there is an obvious way to concisely encode these rules: construct an array1253* of the types in the order int, unsigned int, long, unsigned long, long long,1254* unsigned long long. Compute an integer array starting index based on the1255* suffix (e.g. none = 0, u = 1, ull = 5), and compute an increment based on1256* the specifier (dec/oct/hex) and suffix (u). Then iterate from the starting1257* index to the end, advancing using the increment, and searching until we1258* find a limit that matches or we run out of choices (overflow). To make it1259* even faster, we precompute the table of type information in dtrace_open().1260*/1261dt_node_t *1262dt_node_int(uintmax_t value)1263{1264dt_node_t *dnp = dt_node_alloc(DT_NODE_INT);1265dtrace_hdl_t *dtp = yypcb->pcb_hdl;12661267int n = (yyintdecimal | (yyintsuffix[0] == 'u')) + 1;1268int i = 0;12691270const char *p;1271char c;12721273dnp->dn_op = DT_TOK_INT;1274dnp->dn_value = value;12751276for (p = yyintsuffix; (c = *p) != '\0'; p++) {1277if (c == 'U' || c == 'u')1278i += 1;1279else if (c == 'L' || c == 'l')1280i += 2;1281}12821283for (; i < sizeof (dtp->dt_ints) / sizeof (dtp->dt_ints[0]); i += n) {1284if (value <= dtp->dt_ints[i].did_limit) {1285dt_node_type_assign(dnp,1286dtp->dt_ints[i].did_ctfp,1287dtp->dt_ints[i].did_type, B_FALSE);12881289/*1290* If a prefix character is present in macro text, add1291* in the corresponding operator node (see dt_lex.l).1292*/1293switch (yyintprefix) {1294case '+':1295return (dt_node_op1(DT_TOK_IPOS, dnp));1296case '-':1297return (dt_node_op1(DT_TOK_INEG, dnp));1298default:1299return (dnp);1300}1301}1302}13031304xyerror(D_INT_OFLOW, "integer constant 0x%llx cannot be represented "1305"in any built-in integral type\n", (u_longlong_t)value);1306/*NOTREACHED*/1307return (NULL); /* keep gcc happy */1308}13091310dt_node_t *1311dt_node_string(char *string)1312{1313dtrace_hdl_t *dtp = yypcb->pcb_hdl;1314dt_node_t *dnp;13151316if (string == NULL)1317longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);13181319dnp = dt_node_alloc(DT_NODE_STRING);1320dnp->dn_op = DT_TOK_STRING;1321dnp->dn_string = string;1322dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);13231324return (dnp);1325}13261327dt_node_t *1328dt_node_ident(char *name)1329{1330dt_ident_t *idp;1331dt_node_t *dnp;13321333if (name == NULL)1334longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);13351336/*1337* If the identifier is an inlined integer constant, then create an INT1338* node that is a clone of the inline parse tree node and return that1339* immediately, allowing this inline to be used in parsing contexts1340* that require constant expressions (e.g. scalar array sizes).1341*/1342if ((idp = dt_idstack_lookup(&yypcb->pcb_globals, name)) != NULL &&1343(idp->di_flags & DT_IDFLG_INLINE)) {1344dt_idnode_t *inp = idp->di_iarg;13451346if (inp->din_root != NULL &&1347inp->din_root->dn_kind == DT_NODE_INT) {1348free(name);13491350dnp = dt_node_alloc(DT_NODE_INT);1351dnp->dn_op = DT_TOK_INT;1352dnp->dn_value = inp->din_root->dn_value;1353dt_node_type_propagate(inp->din_root, dnp);13541355return (dnp);1356}1357}13581359dnp = dt_node_alloc(DT_NODE_IDENT);1360dnp->dn_op = name[0] == '@' ? DT_TOK_AGG : DT_TOK_IDENT;1361dnp->dn_string = name;13621363return (dnp);1364}13651366/*1367* Create an empty node of type corresponding to the given declaration.1368* Explicit references to user types (C or D) are assigned the default1369* stability; references to other types are _dtrace_typattr (Private).1370*/1371dt_node_t *1372dt_node_type(dt_decl_t *ddp)1373{1374dtrace_hdl_t *dtp = yypcb->pcb_hdl;1375dtrace_typeinfo_t dtt;1376dt_node_t *dnp;1377char *name = NULL;1378int err;13791380/*1381* If 'ddp' is NULL, we get a decl by popping the decl stack. This1382* form of dt_node_type() is used by parameter rules in dt_grammar.y.1383*/1384if (ddp == NULL)1385ddp = dt_decl_pop_param(&name);13861387err = dt_decl_type(ddp, &dtt);1388dt_decl_free(ddp);13891390if (err != 0) {1391free(name);1392longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);1393}13941395dnp = dt_node_alloc(DT_NODE_TYPE);1396dnp->dn_op = DT_TOK_IDENT;1397dnp->dn_string = name;13981399dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);14001401if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||1402dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)1403dt_node_attr_assign(dnp, _dtrace_defattr);1404else1405dt_node_attr_assign(dnp, _dtrace_typattr);14061407return (dnp);1408}14091410/*1411* Create a type node corresponding to a varargs (...) parameter by just1412* assigning it type CTF_ERR. The decl processing code will handle this.1413*/1414dt_node_t *1415dt_node_vatype(void)1416{1417dt_node_t *dnp = dt_node_alloc(DT_NODE_TYPE);14181419dnp->dn_op = DT_TOK_IDENT;1420dnp->dn_ctfp = yypcb->pcb_hdl->dt_cdefs->dm_ctfp;1421dnp->dn_type = CTF_ERR;1422dnp->dn_attr = _dtrace_defattr;14231424return (dnp);1425}14261427/*1428* Instantiate a decl using the contents of the current declaration stack. As1429* we do not currently permit decls to be initialized, this function currently1430* returns NULL and no parse node is created. When this function is called,1431* the topmost scope's ds_ident pointer will be set to NULL (indicating no1432* init_declarator rule was matched) or will point to the identifier to use.1433*/1434dt_node_t *1435dt_node_decl(void)1436{1437dtrace_hdl_t *dtp = yypcb->pcb_hdl;1438dt_scope_t *dsp = &yypcb->pcb_dstack;1439dt_dclass_t class = dsp->ds_class;1440dt_decl_t *ddp = dt_decl_top();14411442dt_module_t *dmp;1443dtrace_typeinfo_t dtt;1444ctf_id_t type;14451446char n1[DT_TYPE_NAMELEN];1447char n2[DT_TYPE_NAMELEN];14481449if (dt_decl_type(ddp, &dtt) != 0)1450longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);14511452/*1453* If we have no declaration identifier, then this is either a spurious1454* declaration of an intrinsic type (e.g. "extern int;") or declaration1455* or redeclaration of a struct, union, or enum type or tag.1456*/1457if (dsp->ds_ident == NULL) {1458if (ddp->dd_kind != CTF_K_STRUCT &&1459ddp->dd_kind != CTF_K_UNION && ddp->dd_kind != CTF_K_ENUM)1460xyerror(D_DECL_USELESS, "useless declaration\n");14611462dt_dprintf("type %s added as id %ld\n", dt_type_name(1463ddp->dd_ctfp, ddp->dd_type, n1, sizeof (n1)), ddp->dd_type);14641465return (NULL);1466}14671468if (strchr(dsp->ds_ident, '`') != NULL) {1469xyerror(D_DECL_SCOPE, "D scoping operator may not be used in "1470"a declaration name (%s)\n", dsp->ds_ident);1471}14721473/*1474* If we are nested inside of a C include file, add the declaration to1475* the C definition module; otherwise use the D definition module.1476*/1477if (yypcb->pcb_idepth != 0)1478dmp = dtp->dt_cdefs;1479else1480dmp = dtp->dt_ddefs;14811482/*1483* If we see a global or static declaration of a function prototype,1484* treat this as equivalent to a D extern declaration.1485*/1486if (ctf_type_kind(dtt.dtt_ctfp, dtt.dtt_type) == CTF_K_FUNCTION &&1487(class == DT_DC_DEFAULT || class == DT_DC_STATIC))1488class = DT_DC_EXTERN;14891490switch (class) {1491case DT_DC_AUTO:1492case DT_DC_REGISTER:1493case DT_DC_STATIC:1494xyerror(D_DECL_BADCLASS, "specified storage class not "1495"appropriate in D\n");1496/*NOTREACHED*/14971498case DT_DC_EXTERN: {1499dtrace_typeinfo_t ott;1500dtrace_syminfo_t dts;1501GElf_Sym sym;15021503int exists = dtrace_lookup_by_name(dtp,1504dmp->dm_name, dsp->ds_ident, &sym, &dts) == 0;15051506if (exists && (dtrace_symbol_type(dtp, &sym, &dts, &ott) != 0 ||1507ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type,1508ott.dtt_ctfp, ott.dtt_type) != 0)) {1509xyerror(D_DECL_IDRED, "identifier redeclared: %s`%s\n"1510"\t current: %s\n\tprevious: %s\n",1511dmp->dm_name, dsp->ds_ident,1512dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,1513n1, sizeof (n1)),1514dt_type_name(ott.dtt_ctfp, ott.dtt_type,1515n2, sizeof (n2)));1516} else if (!exists && dt_module_extern(dtp, dmp,1517dsp->ds_ident, &dtt) == NULL) {1518xyerror(D_UNKNOWN,1519"failed to extern %s: %s\n", dsp->ds_ident,1520dtrace_errmsg(dtp, dtrace_errno(dtp)));1521} else {1522dt_dprintf("extern %s`%s type=<%s>\n",1523dmp->dm_name, dsp->ds_ident,1524dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,1525n1, sizeof (n1)));1526}1527break;1528}15291530case DT_DC_TYPEDEF:1531if (dt_idstack_lookup(&yypcb->pcb_globals, dsp->ds_ident)) {1532xyerror(D_DECL_IDRED, "global variable identifier "1533"redeclared: %s\n", dsp->ds_ident);1534}15351536if (ctf_lookup_by_name(dmp->dm_ctfp,1537dsp->ds_ident) != CTF_ERR) {1538xyerror(D_DECL_IDRED,1539"typedef redeclared: %s\n", dsp->ds_ident);1540}15411542/*1543* If the source type for the typedef is not defined in the1544* target container or its parent, copy the type to the target1545* container and reset dtt_ctfp and dtt_type to the copy.1546*/1547if (dtt.dtt_ctfp != dmp->dm_ctfp &&1548dtt.dtt_ctfp != ctf_parent_file(dmp->dm_ctfp)) {15491550dtt.dtt_type = ctf_add_type(dmp->dm_ctfp,1551dtt.dtt_ctfp, dtt.dtt_type);1552dtt.dtt_ctfp = dmp->dm_ctfp;15531554if (dtt.dtt_type == CTF_ERR ||1555ctf_update(dtt.dtt_ctfp) == CTF_ERR) {1556xyerror(D_UNKNOWN, "failed to copy typedef %s "1557"source type: %s\n", dsp->ds_ident,1558ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));1559}1560}15611562type = ctf_add_typedef(dmp->dm_ctfp,1563CTF_ADD_ROOT, dsp->ds_ident, dtt.dtt_type);15641565if (type == CTF_ERR || ctf_update(dmp->dm_ctfp) == CTF_ERR) {1566xyerror(D_UNKNOWN, "failed to typedef %s: %s\n",1567dsp->ds_ident, ctf_errmsg(ctf_errno(dmp->dm_ctfp)));1568}15691570dt_dprintf("typedef %s added as id %ld\n", dsp->ds_ident, type);1571break;15721573default: {1574ctf_encoding_t cte;1575dt_idhash_t *dhp;1576dt_ident_t *idp;1577dt_node_t idn;1578int assc, idkind;1579uint_t id, kind;1580ushort_t idflags;15811582switch (class) {1583case DT_DC_THIS:1584dhp = yypcb->pcb_locals;1585idflags = DT_IDFLG_LOCAL;1586idp = dt_idhash_lookup(dhp, dsp->ds_ident);1587break;1588case DT_DC_SELF:1589dhp = dtp->dt_tls;1590idflags = DT_IDFLG_TLS;1591idp = dt_idhash_lookup(dhp, dsp->ds_ident);1592break;1593default:1594dhp = dtp->dt_globals;1595idflags = 0;1596idp = dt_idstack_lookup(1597&yypcb->pcb_globals, dsp->ds_ident);1598break;1599}16001601if (ddp->dd_kind == CTF_K_ARRAY && ddp->dd_node == NULL) {1602xyerror(D_DECL_ARRNULL,1603"array declaration requires array dimension or "1604"tuple signature: %s\n", dsp->ds_ident);1605}16061607if (idp != NULL && idp->di_gen == 0) {1608xyerror(D_DECL_IDRED, "built-in identifier "1609"redeclared: %s\n", idp->di_name);1610}16111612if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_CDEFS,1613dsp->ds_ident, NULL) == 0 ||1614dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS,1615dsp->ds_ident, NULL) == 0) {1616xyerror(D_DECL_IDRED, "typedef identifier "1617"redeclared: %s\n", dsp->ds_ident);1618}16191620/*1621* Cache some attributes of the decl to make the rest of this1622* code simpler: if the decl is an array which is subscripted1623* by a type rather than an integer, then it's an associative1624* array (assc). We then expect to match either DT_IDENT_ARRAY1625* for associative arrays or DT_IDENT_SCALAR for anything else.1626*/1627assc = ddp->dd_kind == CTF_K_ARRAY &&1628ddp->dd_node->dn_kind == DT_NODE_TYPE;16291630idkind = assc ? DT_IDENT_ARRAY : DT_IDENT_SCALAR;16311632/*1633* Create a fake dt_node_t on the stack so we can determine the1634* type of any matching identifier by assigning to this node.1635* If the pre-existing ident has its di_type set, propagate1636* the type by hand so as not to trigger a prototype check for1637* arrays (yet); otherwise we use dt_ident_cook() on the ident1638* to ensure it is fully initialized before looking at it.1639*/1640bzero(&idn, sizeof (dt_node_t));16411642if (idp != NULL && idp->di_type != CTF_ERR)1643dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,1644B_FALSE);1645else if (idp != NULL)1646(void) dt_ident_cook(&idn, idp, NULL);16471648if (assc) {1649if (class == DT_DC_THIS) {1650xyerror(D_DECL_LOCASSC, "associative arrays "1651"may not be declared as local variables:"1652" %s\n", dsp->ds_ident);1653}16541655if (dt_decl_type(ddp->dd_next, &dtt) != 0)1656longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);1657}16581659if (idp != NULL && (idp->di_kind != idkind ||1660ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type,1661idn.dn_ctfp, idn.dn_type) != 0)) {1662xyerror(D_DECL_IDRED, "identifier redeclared: %s\n"1663"\t current: %s %s\n\tprevious: %s %s\n",1664dsp->ds_ident, dt_idkind_name(idkind),1665dt_type_name(dtt.dtt_ctfp,1666dtt.dtt_type, n1, sizeof (n1)),1667dt_idkind_name(idp->di_kind),1668dt_node_type_name(&idn, n2, sizeof (n2)));16691670} else if (idp != NULL && assc) {1671const dt_idsig_t *isp = idp->di_data;1672dt_node_t *dnp = ddp->dd_node;1673int argc = 0;16741675for (; dnp != NULL; dnp = dnp->dn_list, argc++) {1676const dt_node_t *pnp = &isp->dis_args[argc];16771678if (argc >= isp->dis_argc)1679continue; /* tuple length mismatch */16801681if (ctf_type_cmp(dnp->dn_ctfp, dnp->dn_type,1682pnp->dn_ctfp, pnp->dn_type) == 0)1683continue;16841685xyerror(D_DECL_IDRED,1686"identifier redeclared: %s\n"1687"\t current: %s, key #%d of type %s\n"1688"\tprevious: %s, key #%d of type %s\n",1689dsp->ds_ident,1690dt_idkind_name(idkind), argc + 1,1691dt_node_type_name(dnp, n1, sizeof (n1)),1692dt_idkind_name(idp->di_kind), argc + 1,1693dt_node_type_name(pnp, n2, sizeof (n2)));1694}16951696if (isp->dis_argc != argc) {1697xyerror(D_DECL_IDRED,1698"identifier redeclared: %s\n"1699"\t current: %s of %s, tuple length %d\n"1700"\tprevious: %s of %s, tuple length %d\n",1701dsp->ds_ident, dt_idkind_name(idkind),1702dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,1703n1, sizeof (n1)), argc,1704dt_idkind_name(idp->di_kind),1705dt_node_type_name(&idn, n2, sizeof (n2)),1706isp->dis_argc);1707}17081709} else if (idp == NULL) {1710type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);1711kind = ctf_type_kind(dtt.dtt_ctfp, type);17121713switch (kind) {1714case CTF_K_INTEGER:1715if (ctf_type_encoding(dtt.dtt_ctfp, type,1716&cte) == 0 && IS_VOID(cte)) {1717xyerror(D_DECL_VOIDOBJ, "cannot have "1718"void object: %s\n", dsp->ds_ident);1719}1720break;1721case CTF_K_STRUCT:1722case CTF_K_UNION:1723if (ctf_type_size(dtt.dtt_ctfp, type) != 0)1724break; /* proceed to declaring */1725/*FALLTHRU*/1726case CTF_K_FORWARD:1727xyerror(D_DECL_INCOMPLETE,1728"incomplete struct/union/enum %s: %s\n",1729dt_type_name(dtt.dtt_ctfp, dtt.dtt_type,1730n1, sizeof (n1)), dsp->ds_ident);1731/*NOTREACHED*/1732}17331734if (dt_idhash_nextid(dhp, &id) == -1) {1735xyerror(D_ID_OFLOW, "cannot create %s: limit "1736"on number of %s variables exceeded\n",1737dsp->ds_ident, dt_idhash_name(dhp));1738}17391740dt_dprintf("declare %s %s variable %s, id=%u\n",1741dt_idhash_name(dhp), dt_idkind_name(idkind),1742dsp->ds_ident, id);17431744idp = dt_idhash_insert(dhp, dsp->ds_ident, idkind,1745idflags | DT_IDFLG_WRITE | DT_IDFLG_DECL, id,1746_dtrace_defattr, 0, assc ? &dt_idops_assc :1747&dt_idops_thaw, NULL, dtp->dt_gen);17481749if (idp == NULL)1750longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);17511752dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type);17531754/*1755* If we are declaring an associative array, use our1756* fake parse node to cook the new assoc identifier.1757* This will force the ident code to instantiate the1758* array type signature corresponding to the list of1759* types pointed to by ddp->dd_node. We also reset1760* the identifier's attributes based upon the result.1761*/1762if (assc) {1763idp->di_attr =1764dt_ident_cook(&idn, idp, &ddp->dd_node);1765}1766}1767}17681769} /* end of switch */17701771free(dsp->ds_ident);1772dsp->ds_ident = NULL;17731774return (NULL);1775}17761777dt_node_t *1778dt_node_func(dt_node_t *dnp, dt_node_t *args)1779{1780dt_ident_t *idp;17811782if (dnp->dn_kind != DT_NODE_IDENT) {1783xyerror(D_FUNC_IDENT,1784"function designator is not of function type\n");1785}17861787idp = dt_idstack_lookup(&yypcb->pcb_globals, dnp->dn_string);17881789if (idp == NULL) {1790xyerror(D_FUNC_UNDEF,1791"undefined function name: %s\n", dnp->dn_string);1792}17931794if (idp->di_kind != DT_IDENT_FUNC &&1795idp->di_kind != DT_IDENT_AGGFUNC &&1796idp->di_kind != DT_IDENT_ACTFUNC) {1797xyerror(D_FUNC_IDKIND, "%s '%s' may not be referenced as a "1798"function\n", dt_idkind_name(idp->di_kind), idp->di_name);1799}18001801free(dnp->dn_string);1802dnp->dn_string = NULL;18031804dnp->dn_kind = DT_NODE_FUNC;1805dnp->dn_flags &= ~DT_NF_COOKED;1806dnp->dn_ident = idp;1807dnp->dn_args = args;1808dnp->dn_list = NULL;18091810return (dnp);1811}18121813/*1814* The offsetof() function is special because it takes a type name as an1815* argument. It does not actually construct its own node; after looking up the1816* structure or union offset, we just return an integer node with the offset.1817*/1818dt_node_t *1819dt_node_offsetof(dt_decl_t *ddp, char *s)1820{1821dtrace_typeinfo_t dtt;1822dt_node_t dn;1823char *name;1824int err;18251826ctf_membinfo_t ctm;1827ctf_id_t type;1828uint_t kind;18291830name = alloca(strlen(s) + 1);1831(void) strcpy(name, s);1832free(s);18331834err = dt_decl_type(ddp, &dtt);1835dt_decl_free(ddp);18361837if (err != 0)1838longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);18391840type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type);1841kind = ctf_type_kind(dtt.dtt_ctfp, type);18421843if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {1844xyerror(D_OFFSETOF_TYPE,1845"offsetof operand must be a struct or union type\n");1846}18471848if (ctf_member_info(dtt.dtt_ctfp, type, name, &ctm) == CTF_ERR) {1849xyerror(D_UNKNOWN, "failed to determine offset of %s: %s\n",1850name, ctf_errmsg(ctf_errno(dtt.dtt_ctfp)));1851}18521853bzero(&dn, sizeof (dn));1854dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);18551856if (dn.dn_flags & DT_NF_BITFIELD) {1857xyerror(D_OFFSETOF_BITFIELD,1858"cannot take offset of a bit-field: %s\n", name);1859}18601861return (dt_node_int(ctm.ctm_offset / NBBY));1862}18631864dt_node_t *1865dt_node_op1(int op, dt_node_t *cp)1866{1867dt_node_t *dnp;18681869if (cp->dn_kind == DT_NODE_INT) {1870switch (op) {1871case DT_TOK_INEG:1872/*1873* If we're negating an unsigned integer, zero out any1874* extra top bits to truncate the value to the size of1875* the effective type determined by dt_node_int().1876*/1877cp->dn_value = -cp->dn_value;1878if (!(cp->dn_flags & DT_NF_SIGNED)) {1879cp->dn_value &= ~0ULL >>1880(64 - dt_node_type_size(cp) * NBBY);1881}1882/*FALLTHRU*/1883case DT_TOK_IPOS:1884return (cp);1885case DT_TOK_BNEG:1886cp->dn_value = ~cp->dn_value;1887return (cp);1888case DT_TOK_LNEG:1889cp->dn_value = !cp->dn_value;1890return (cp);1891}1892}18931894/*1895* If sizeof is applied to a type_name or string constant, we can1896* transform 'cp' into an integer constant in the node construction1897* pass so that it can then be used for arithmetic in this pass.1898*/1899if (op == DT_TOK_SIZEOF &&1900(cp->dn_kind == DT_NODE_STRING || cp->dn_kind == DT_NODE_TYPE)) {1901dtrace_hdl_t *dtp = yypcb->pcb_hdl;1902size_t size = dt_node_type_size(cp);19031904if (size == 0) {1905xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an "1906"operand of unknown size\n");1907}19081909dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,1910ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),1911B_FALSE);19121913cp->dn_kind = DT_NODE_INT;1914cp->dn_op = DT_TOK_INT;1915cp->dn_value = size;19161917return (cp);1918}19191920/*1921* When applying the addressof operator to an identifier, it's okay if1922* we can't find type information for the identifier, so flag the node1923* to ensure that we don't raise an error.1924*/1925if (op == DT_TOK_ADDROF && cp->dn_kind == DT_NODE_IDENT)1926cp->dn_flags |= DT_NF_IDENTADDR;19271928dnp = dt_node_alloc(DT_NODE_OP1);1929assert(op <= USHRT_MAX);1930dnp->dn_op = (ushort_t)op;1931dnp->dn_child = cp;19321933return (dnp);1934}19351936/*1937* If an integer constant is being cast to another integer type, we can1938* perform the cast as part of integer constant folding in this pass. We must1939* take action when the integer is being cast to a smaller type or if it is1940* changing signed-ness. If so, we first shift rp's bits bits high (losing1941* excess bits if narrowing) and then shift them down with either a logical1942* shift (unsigned) or arithmetic shift (signed).1943*/1944static void1945dt_cast(dt_node_t *lp, dt_node_t *rp)1946{1947size_t srcsize = dt_node_type_size(rp);1948size_t dstsize = dt_node_type_size(lp);19491950if (dstsize < srcsize) {1951int n = (sizeof (uint64_t) - dstsize) * NBBY;1952rp->dn_value <<= n;1953rp->dn_value >>= n;1954} else if (dstsize > srcsize) {1955int n = (sizeof (uint64_t) - srcsize) * NBBY;1956int s = (dstsize - srcsize) * NBBY;19571958rp->dn_value <<= n;1959if (rp->dn_flags & DT_NF_SIGNED) {1960rp->dn_value = (intmax_t)rp->dn_value >> s;1961rp->dn_value >>= n - s;1962} else {1963rp->dn_value >>= n;1964}1965}1966}19671968dt_node_t *1969dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)1970{1971dtrace_hdl_t *dtp = yypcb->pcb_hdl;1972dt_node_t *dnp;19731974/*1975* First we check for operations that are illegal -- namely those that1976* might result in integer division by zero, and abort if one is found.1977*/1978if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0 &&1979(op == DT_TOK_MOD || op == DT_TOK_DIV ||1980op == DT_TOK_MOD_EQ || op == DT_TOK_DIV_EQ))1981xyerror(D_DIV_ZERO, "expression contains division by zero\n");19821983/*1984* If both children are immediate values, we can just perform inline1985* calculation and return a new immediate node with the result.1986*/1987if (lp->dn_kind == DT_NODE_INT && rp->dn_kind == DT_NODE_INT) {1988uintmax_t l = lp->dn_value;1989uintmax_t r = rp->dn_value;19901991dnp = dt_node_int(0); /* allocate new integer node for result */19921993switch (op) {1994case DT_TOK_LOR:1995dnp->dn_value = l || r;1996dt_node_type_assign(dnp,1997DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);1998break;1999case DT_TOK_LXOR:2000dnp->dn_value = (l != 0) ^ (r != 0);2001dt_node_type_assign(dnp,2002DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2003break;2004case DT_TOK_LAND:2005dnp->dn_value = l && r;2006dt_node_type_assign(dnp,2007DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2008break;2009case DT_TOK_BOR:2010dnp->dn_value = l | r;2011dt_node_promote(lp, rp, dnp);2012break;2013case DT_TOK_XOR:2014dnp->dn_value = l ^ r;2015dt_node_promote(lp, rp, dnp);2016break;2017case DT_TOK_BAND:2018dnp->dn_value = l & r;2019dt_node_promote(lp, rp, dnp);2020break;2021case DT_TOK_EQU:2022dnp->dn_value = l == r;2023dt_node_type_assign(dnp,2024DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2025break;2026case DT_TOK_NEQ:2027dnp->dn_value = l != r;2028dt_node_type_assign(dnp,2029DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2030break;2031case DT_TOK_LT:2032dt_node_promote(lp, rp, dnp);2033if (dnp->dn_flags & DT_NF_SIGNED)2034dnp->dn_value = (intmax_t)l < (intmax_t)r;2035else2036dnp->dn_value = l < r;2037dt_node_type_assign(dnp,2038DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2039break;2040case DT_TOK_LE:2041dt_node_promote(lp, rp, dnp);2042if (dnp->dn_flags & DT_NF_SIGNED)2043dnp->dn_value = (intmax_t)l <= (intmax_t)r;2044else2045dnp->dn_value = l <= r;2046dt_node_type_assign(dnp,2047DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2048break;2049case DT_TOK_GT:2050dt_node_promote(lp, rp, dnp);2051if (dnp->dn_flags & DT_NF_SIGNED)2052dnp->dn_value = (intmax_t)l > (intmax_t)r;2053else2054dnp->dn_value = l > r;2055dt_node_type_assign(dnp,2056DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2057break;2058case DT_TOK_GE:2059dt_node_promote(lp, rp, dnp);2060if (dnp->dn_flags & DT_NF_SIGNED)2061dnp->dn_value = (intmax_t)l >= (intmax_t)r;2062else2063dnp->dn_value = l >= r;2064dt_node_type_assign(dnp,2065DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);2066break;2067case DT_TOK_LSH:2068dnp->dn_value = l << r;2069dt_node_type_propagate(lp, dnp);2070dt_node_attr_assign(rp,2071dt_attr_min(lp->dn_attr, rp->dn_attr));2072break;2073case DT_TOK_RSH:2074dnp->dn_value = l >> r;2075dt_node_type_propagate(lp, dnp);2076dt_node_attr_assign(rp,2077dt_attr_min(lp->dn_attr, rp->dn_attr));2078break;2079case DT_TOK_ADD:2080dnp->dn_value = l + r;2081dt_node_promote(lp, rp, dnp);2082break;2083case DT_TOK_SUB:2084dnp->dn_value = l - r;2085dt_node_promote(lp, rp, dnp);2086break;2087case DT_TOK_MUL:2088dnp->dn_value = l * r;2089dt_node_promote(lp, rp, dnp);2090break;2091case DT_TOK_DIV:2092dt_node_promote(lp, rp, dnp);2093if (dnp->dn_flags & DT_NF_SIGNED)2094dnp->dn_value = (intmax_t)l / (intmax_t)r;2095else2096dnp->dn_value = l / r;2097break;2098case DT_TOK_MOD:2099dt_node_promote(lp, rp, dnp);2100if (dnp->dn_flags & DT_NF_SIGNED)2101dnp->dn_value = (intmax_t)l % (intmax_t)r;2102else2103dnp->dn_value = l % r;2104break;2105default:2106dt_node_free(dnp);2107dnp = NULL;2108}21092110if (dnp != NULL) {2111dt_node_free(lp);2112dt_node_free(rp);2113return (dnp);2114}2115}21162117if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&2118dt_node_is_integer(lp)) {2119dt_cast(lp, rp);2120dt_node_type_propagate(lp, rp);2121dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));2122dt_node_free(lp);21232124return (rp);2125}21262127/*2128* If no immediate optimizations are available, create an new OP2 node2129* and glue the left and right children into place and return.2130*/2131dnp = dt_node_alloc(DT_NODE_OP2);2132assert(op <= USHRT_MAX);2133dnp->dn_op = (ushort_t)op;2134dnp->dn_left = lp;2135dnp->dn_right = rp;21362137return (dnp);2138}21392140dt_node_t *2141dt_node_op3(dt_node_t *expr, dt_node_t *lp, dt_node_t *rp)2142{2143dt_node_t *dnp;21442145if (expr->dn_kind == DT_NODE_INT)2146return (expr->dn_value != 0 ? lp : rp);21472148dnp = dt_node_alloc(DT_NODE_OP3);2149dnp->dn_op = DT_TOK_QUESTION;2150dnp->dn_expr = expr;2151dnp->dn_left = lp;2152dnp->dn_right = rp;21532154return (dnp);2155}21562157dt_node_t *2158dt_node_statement(dt_node_t *expr)2159{2160dt_node_t *dnp;21612162if (expr->dn_kind == DT_NODE_AGG)2163return (expr);21642165if (expr->dn_kind == DT_NODE_FUNC &&2166expr->dn_ident->di_kind == DT_IDENT_ACTFUNC)2167dnp = dt_node_alloc(DT_NODE_DFUNC);2168else2169dnp = dt_node_alloc(DT_NODE_DEXPR);21702171dnp->dn_expr = expr;2172return (dnp);2173}21742175dt_node_t *2176dt_node_if(dt_node_t *pred, dt_node_t *acts, dt_node_t *else_acts)2177{2178dt_node_t *dnp = dt_node_alloc(DT_NODE_IF);2179dnp->dn_conditional = pred;2180dnp->dn_body = acts;2181dnp->dn_alternate_body = else_acts;21822183return (dnp);2184}21852186dt_node_t *2187dt_node_pdesc_by_name(char *spec)2188{2189dtrace_hdl_t *dtp = yypcb->pcb_hdl;2190dt_node_t *dnp;21912192if (spec == NULL)2193longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);21942195dnp = dt_node_alloc(DT_NODE_PDESC);2196dnp->dn_spec = spec;2197dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t));21982199if (dnp->dn_desc == NULL)2200longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);22012202if (dtrace_xstr2desc(dtp, yypcb->pcb_pspec, dnp->dn_spec,2203yypcb->pcb_sargc, yypcb->pcb_sargv, dnp->dn_desc) != 0) {2204xyerror(D_PDESC_INVAL, "invalid probe description \"%s\": %s\n",2205dnp->dn_spec, dtrace_errmsg(dtp, dtrace_errno(dtp)));2206}22072208free(dnp->dn_spec);2209dnp->dn_spec = NULL;22102211return (dnp);2212}22132214dt_node_t *2215dt_node_pdesc_by_id(uintmax_t id)2216{2217static const char *const names[] = {2218"providers", "modules", "functions"2219};22202221dtrace_hdl_t *dtp = yypcb->pcb_hdl;2222dt_node_t *dnp = dt_node_alloc(DT_NODE_PDESC);22232224if ((dnp->dn_desc = malloc(sizeof (dtrace_probedesc_t))) == NULL)2225longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);22262227if (id > UINT_MAX) {2228xyerror(D_PDESC_INVAL, "identifier %llu exceeds maximum "2229"probe id\n", (u_longlong_t)id);2230}22312232if (yypcb->pcb_pspec != DTRACE_PROBESPEC_NAME) {2233xyerror(D_PDESC_INVAL, "probe identifier %llu not permitted "2234"when specifying %s\n", (u_longlong_t)id,2235names[yypcb->pcb_pspec]);2236}22372238if (dtrace_id2desc(dtp, (dtrace_id_t)id, dnp->dn_desc) != 0) {2239xyerror(D_PDESC_INVAL, "invalid probe identifier %llu: %s\n",2240(u_longlong_t)id, dtrace_errmsg(dtp, dtrace_errno(dtp)));2241}22422243return (dnp);2244}22452246dt_node_t *2247dt_node_clause(dt_node_t *pdescs, dt_node_t *pred, dt_node_t *acts)2248{2249dt_node_t *dnp = dt_node_alloc(DT_NODE_CLAUSE);22502251dnp->dn_pdescs = pdescs;2252dnp->dn_pred = pred;2253dnp->dn_acts = acts;22542255return (dnp);2256}22572258dt_node_t *2259dt_node_inline(dt_node_t *expr)2260{2261dtrace_hdl_t *dtp = yypcb->pcb_hdl;2262dt_scope_t *dsp = &yypcb->pcb_dstack;2263dt_decl_t *ddp = dt_decl_top();22642265char n[DT_TYPE_NAMELEN];2266dtrace_typeinfo_t dtt;22672268dt_ident_t *idp, *rdp;2269dt_idnode_t *inp;2270dt_node_t *dnp;22712272if (dt_decl_type(ddp, &dtt) != 0)2273longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);22742275if (dsp->ds_class != DT_DC_DEFAULT) {2276xyerror(D_DECL_BADCLASS, "specified storage class not "2277"appropriate for inline declaration\n");2278}22792280if (dsp->ds_ident == NULL)2281xyerror(D_DECL_USELESS, "inline declaration requires a name\n");22822283if ((idp = dt_idstack_lookup(2284&yypcb->pcb_globals, dsp->ds_ident)) != NULL) {2285xyerror(D_DECL_IDRED, "identifier redefined: %s\n\t current: "2286"inline definition\n\tprevious: %s %s\n",2287idp->di_name, dt_idkind_name(idp->di_kind),2288(idp->di_flags & DT_IDFLG_INLINE) ? "inline" : "");2289}22902291/*2292* If we are declaring an inlined array, verify that we have a tuple2293* signature, and then recompute 'dtt' as the array's value type.2294*/2295if (ddp->dd_kind == CTF_K_ARRAY) {2296if (ddp->dd_node == NULL) {2297xyerror(D_DECL_ARRNULL, "inline declaration requires "2298"array tuple signature: %s\n", dsp->ds_ident);2299}23002301if (ddp->dd_node->dn_kind != DT_NODE_TYPE) {2302xyerror(D_DECL_ARRNULL, "inline declaration cannot be "2303"of scalar array type: %s\n", dsp->ds_ident);2304}23052306if (dt_decl_type(ddp->dd_next, &dtt) != 0)2307longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);2308}23092310/*2311* If the inline identifier is not defined, then create it with the2312* orphan flag set. We do not insert the identifier into dt_globals2313* until we have successfully cooked the right-hand expression, below.2314*/2315dnp = dt_node_alloc(DT_NODE_INLINE);2316dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);2317dt_node_attr_assign(dnp, _dtrace_defattr);23182319if (dt_node_is_void(dnp)) {2320xyerror(D_DECL_VOIDOBJ,2321"cannot declare void inline: %s\n", dsp->ds_ident);2322}23232324if (ctf_type_kind(dnp->dn_ctfp, ctf_type_resolve(2325dnp->dn_ctfp, dnp->dn_type)) == CTF_K_FORWARD) {2326xyerror(D_DECL_INCOMPLETE,2327"incomplete struct/union/enum %s: %s\n",2328dt_node_type_name(dnp, n, sizeof (n)), dsp->ds_ident);2329}23302331if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)2332longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);23332334bzero(inp, sizeof (dt_idnode_t));23352336idp = dnp->dn_ident = dt_ident_create(dsp->ds_ident,2337ddp->dd_kind == CTF_K_ARRAY ? DT_IDENT_ARRAY : DT_IDENT_SCALAR,2338DT_IDFLG_INLINE | DT_IDFLG_REF | DT_IDFLG_DECL | DT_IDFLG_ORPHAN, 0,2339_dtrace_defattr, 0, &dt_idops_inline, inp, dtp->dt_gen);23402341if (idp == NULL) {2342free(inp);2343longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);2344}23452346/*2347* If we're inlining an associative array, create a private identifier2348* hash containing the named parameters and store it in inp->din_hash.2349* We then push this hash on to the top of the pcb_globals stack.2350*/2351if (ddp->dd_kind == CTF_K_ARRAY) {2352dt_idnode_t *pinp;2353dt_ident_t *pidp;2354dt_node_t *pnp;2355uint_t i = 0;23562357for (pnp = ddp->dd_node; pnp != NULL; pnp = pnp->dn_list)2358i++; /* count up parameters for din_argv[] */23592360inp->din_hash = dt_idhash_create("inline args", NULL, 0, 0);2361inp->din_argv = calloc(i, sizeof (dt_ident_t *));23622363if (inp->din_hash == NULL || inp->din_argv == NULL)2364longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);23652366/*2367* Create an identifier for each parameter as a scalar inline,2368* and store it in din_hash and in position in din_argv[]. The2369* parameter identifiers also use dt_idops_inline, but we leave2370* the dt_idnode_t argument 'pinp' zeroed. This will be filled2371* in by the code generation pass with references to the args.2372*/2373for (i = 0, pnp = ddp->dd_node;2374pnp != NULL; pnp = pnp->dn_list, i++) {23752376if (pnp->dn_string == NULL)2377continue; /* ignore anonymous parameters */23782379if ((pinp = malloc(sizeof (dt_idnode_t))) == NULL)2380longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);23812382pidp = dt_idhash_insert(inp->din_hash, pnp->dn_string,2383DT_IDENT_SCALAR, DT_IDFLG_DECL | DT_IDFLG_INLINE, 0,2384_dtrace_defattr, 0, &dt_idops_inline,2385pinp, dtp->dt_gen);23862387if (pidp == NULL) {2388free(pinp);2389longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);2390}23912392inp->din_argv[i] = pidp;2393bzero(pinp, sizeof (dt_idnode_t));2394dt_ident_type_assign(pidp, pnp->dn_ctfp, pnp->dn_type);2395}23962397dt_idstack_push(&yypcb->pcb_globals, inp->din_hash);2398}23992400/*2401* Unlike most constructors, we need to explicitly cook the right-hand2402* side of the inline definition immediately to prevent recursion. If2403* the right-hand side uses the inline itself, the cook will fail.2404*/2405expr = dt_node_cook(expr, DT_IDFLG_REF);24062407if (ddp->dd_kind == CTF_K_ARRAY)2408dt_idstack_pop(&yypcb->pcb_globals, inp->din_hash);24092410/*2411* Set the type, attributes, and flags for the inline. If the right-2412* hand expression has an identifier, propagate its flags. Then cook2413* the identifier to fully initialize it: if we're declaring an inline2414* associative array this will construct a type signature from 'ddp'.2415*/2416if (dt_node_is_dynamic(expr))2417rdp = dt_ident_resolve(expr->dn_ident);2418else if (expr->dn_kind == DT_NODE_VAR || expr->dn_kind == DT_NODE_SYM)2419rdp = expr->dn_ident;2420else2421rdp = NULL;24222423if (rdp != NULL) {2424idp->di_flags |= (rdp->di_flags &2425(DT_IDFLG_WRITE | DT_IDFLG_USER | DT_IDFLG_PRIM));2426}24272428idp->di_attr = dt_attr_min(_dtrace_defattr, expr->dn_attr);2429dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type);2430(void) dt_ident_cook(dnp, idp, &ddp->dd_node);24312432/*2433* Store the parse tree nodes for 'expr' inside of idp->di_data ('inp')2434* so that they will be preserved with this identifier. Then pop the2435* inline declaration from the declaration stack and restore the lexer.2436*/2437inp->din_list = yypcb->pcb_list;2438inp->din_root = expr;24392440dt_decl_free(dt_decl_pop());2441yybegin(YYS_CLAUSE);24422443/*2444* Finally, insert the inline identifier into dt_globals to make it2445* visible, and then cook 'dnp' to check its type against 'expr'.2446*/2447dt_idhash_xinsert(dtp->dt_globals, idp);2448return (dt_node_cook(dnp, DT_IDFLG_REF));2449}24502451dt_node_t *2452dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr)2453{2454dtrace_typeinfo_t dtt;2455dt_node_t *dnp;2456int err;24572458if (ddp != NULL) {2459err = dt_decl_type(ddp, &dtt);2460dt_decl_free(ddp);24612462if (err != 0)2463longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);2464}24652466dnp = dt_node_alloc(DT_NODE_MEMBER);2467dnp->dn_membname = name;2468dnp->dn_membexpr = expr;24692470if (ddp != NULL)2471dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,2472dtt.dtt_flags);24732474return (dnp);2475}24762477dt_node_t *2478dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)2479{2480dtrace_hdl_t *dtp = yypcb->pcb_hdl;2481dtrace_typeinfo_t src, dst;2482dt_node_t sn, dn;2483dt_xlator_t *dxp;2484dt_node_t *dnp;2485int edst, esrc;2486uint_t kind;24872488char n1[DT_TYPE_NAMELEN];2489char n2[DT_TYPE_NAMELEN];24902491edst = dt_decl_type(ddp, &dst);2492dt_decl_free(ddp);24932494esrc = dt_decl_type(sdp, &src);2495dt_decl_free(sdp);24962497if (edst != 0 || esrc != 0) {2498free(name);2499longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);2500}25012502bzero(&sn, sizeof (sn));2503dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);25042505bzero(&dn, sizeof (dn));2506dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);25072508if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {2509xyerror(D_XLATE_REDECL,2510"translator from %s to %s has already been declared\n",2511dt_node_type_name(&sn, n1, sizeof (n1)),2512dt_node_type_name(&dn, n2, sizeof (n2)));2513}25142515kind = ctf_type_kind(dst.dtt_ctfp,2516ctf_type_resolve(dst.dtt_ctfp, dst.dtt_type));25172518if (kind == CTF_K_FORWARD) {2519xyerror(D_XLATE_SOU, "incomplete struct/union/enum %s\n",2520dt_type_name(dst.dtt_ctfp, dst.dtt_type, n1, sizeof (n1)));2521}25222523if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {2524xyerror(D_XLATE_SOU,2525"translator output type must be a struct or union\n");2526}25272528dxp = dt_xlator_create(dtp, &src, &dst, name, members, yypcb->pcb_list);2529yybegin(YYS_CLAUSE);2530free(name);25312532if (dxp == NULL)2533longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);25342535dnp = dt_node_alloc(DT_NODE_XLATOR);2536dnp->dn_xlator = dxp;2537dnp->dn_members = members;25382539return (dt_node_cook(dnp, DT_IDFLG_REF));2540}25412542dt_node_t *2543dt_node_probe(char *s, int protoc, dt_node_t *nargs, dt_node_t *xargs)2544{2545dtrace_hdl_t *dtp = yypcb->pcb_hdl;2546int nargc, xargc;2547dt_node_t *dnp;25482549size_t len = strlen(s) + 3; /* +3 for :: and \0 */2550char *name = alloca(len);25512552(void) snprintf(name, len, "::%s", s);2553(void) strhyphenate(name);2554free(s);25552556if (strchr(name, '`') != NULL) {2557xyerror(D_PROV_BADNAME, "probe name may not "2558"contain scoping operator: %s\n", name);2559}25602561if (strlen(name) - 2 >= DTRACE_NAMELEN) {2562xyerror(D_PROV_BADNAME, "probe name may not exceed %d "2563"characters: %s\n", DTRACE_NAMELEN - 1, name);2564}25652566dnp = dt_node_alloc(DT_NODE_PROBE);25672568dnp->dn_ident = dt_ident_create(name, DT_IDENT_PROBE,2569DT_IDFLG_ORPHAN, DTRACE_IDNONE, _dtrace_defattr, 0,2570&dt_idops_probe, NULL, dtp->dt_gen);25712572nargc = dt_decl_prototype(nargs, nargs,2573"probe input", DT_DP_VOID | DT_DP_ANON);25742575xargc = dt_decl_prototype(xargs, nargs,2576"probe output", DT_DP_VOID);25772578if (nargc > UINT8_MAX) {2579xyerror(D_PROV_PRARGLEN, "probe %s input prototype exceeds %u "2580"parameters: %d params used\n", name, UINT8_MAX, nargc);2581}25822583if (xargc > UINT8_MAX) {2584xyerror(D_PROV_PRARGLEN, "probe %s output prototype exceeds %u "2585"parameters: %d params used\n", name, UINT8_MAX, xargc);2586}25872588if (dnp->dn_ident == NULL || dt_probe_create(dtp,2589dnp->dn_ident, protoc, nargs, nargc, xargs, xargc) == NULL)2590longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);25912592return (dnp);2593}25942595dt_node_t *2596dt_node_provider(char *name, dt_node_t *probes)2597{2598dtrace_hdl_t *dtp = yypcb->pcb_hdl;2599dt_node_t *dnp = dt_node_alloc(DT_NODE_PROVIDER);2600dt_node_t *lnp;2601size_t len;26022603dnp->dn_provname = name;2604dnp->dn_probes = probes;26052606if (strchr(name, '`') != NULL) {2607dnerror(dnp, D_PROV_BADNAME, "provider name may not "2608"contain scoping operator: %s\n", name);2609}26102611if ((len = strlen(name)) >= DTRACE_PROVNAMELEN) {2612dnerror(dnp, D_PROV_BADNAME, "provider name may not exceed %d "2613"characters: %s\n", DTRACE_PROVNAMELEN - 1, name);2614}26152616if (isdigit(name[len - 1])) {2617dnerror(dnp, D_PROV_BADNAME, "provider name may not "2618"end with a digit: %s\n", name);2619}26202621/*2622* Check to see if the provider is already defined or visible through2623* dtrace(7D). If so, set dn_provred to treat it as a re-declaration.2624* If not, create a new provider and set its interface-only flag. This2625* flag may be cleared later by calls made to dt_probe_declare().2626*/2627if ((dnp->dn_provider = dt_provider_lookup(dtp, name)) != NULL)2628dnp->dn_provred = B_TRUE;2629else if ((dnp->dn_provider = dt_provider_create(dtp, name)) == NULL)2630longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);2631else2632dnp->dn_provider->pv_flags |= DT_PROVIDER_INTF;26332634/*2635* Store all parse nodes created since we consumed the DT_KEY_PROVIDER2636* token with the provider and then restore our lexing state to CLAUSE.2637* Note that if dnp->dn_provred is true, we may end up storing dups of2638* a provider's interface and implementation: we eat this space because2639* the implementation will likely need to redeclare probe members, and2640* therefore may result in those member nodes becoming persistent.2641*/2642for (lnp = yypcb->pcb_list; lnp->dn_link != NULL; lnp = lnp->dn_link)2643continue; /* skip to end of allocation list */26442645lnp->dn_link = dnp->dn_provider->pv_nodes;2646dnp->dn_provider->pv_nodes = yypcb->pcb_list;26472648yybegin(YYS_CLAUSE);2649return (dnp);2650}26512652dt_node_t *2653dt_node_program(dt_node_t *lnp)2654{2655dt_node_t *dnp = dt_node_alloc(DT_NODE_PROG);2656dnp->dn_list = lnp;2657return (dnp);2658}26592660/*2661* This function provides the underlying implementation of cooking an2662* identifier given its node, a hash of dynamic identifiers, an identifier2663* kind, and a boolean flag indicating whether we are allowed to instantiate2664* a new identifier if the string is not found. This function is either2665* called from dt_cook_ident(), below, or directly by the various cooking2666* routines that are allowed to instantiate identifiers (e.g. op2 TOK_ASGN).2667*/2668static void2669dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)2670{2671dtrace_hdl_t *dtp = yypcb->pcb_hdl;2672const char *sname = dt_idhash_name(dhp);2673int uref = 0;26742675dtrace_attribute_t attr = _dtrace_defattr;2676dt_ident_t *idp;2677dtrace_syminfo_t dts;2678GElf_Sym sym;26792680const char *scope, *mark;2681uchar_t dnkind;2682char *name;26832684/*2685* Look for scoping marks in the identifier. If one is found, set our2686* scope to either DTRACE_OBJ_KMODS or UMODS or to the first part of2687* the string that specifies the scope using an explicit module name.2688* If two marks in a row are found, set 'uref' (user symbol reference).2689* Otherwise we set scope to DTRACE_OBJ_EXEC, indicating that normal2690* scope is desired and we should search the specified idhash.2691*/2692if ((name = strrchr(dnp->dn_string, '`')) != NULL) {2693if (name > dnp->dn_string && name[-1] == '`') {2694uref++;2695name[-1] = '\0';2696}26972698if (name == dnp->dn_string + uref)2699scope = uref ? DTRACE_OBJ_UMODS : DTRACE_OBJ_KMODS;2700else2701scope = dnp->dn_string;27022703*name++ = '\0'; /* leave name pointing after scoping mark */2704dnkind = DT_NODE_VAR;27052706} else if (idkind == DT_IDENT_AGG) {2707scope = DTRACE_OBJ_EXEC;2708name = dnp->dn_string + 1;2709dnkind = DT_NODE_AGG;2710} else {2711scope = DTRACE_OBJ_EXEC;2712name = dnp->dn_string;2713dnkind = DT_NODE_VAR;2714}27152716/*2717* If create is set to false, and we fail our idhash lookup, preset2718* the errno code to EDT_NOVAR for our final error message below.2719* If we end up calling dtrace_lookup_by_name(), it will reset the2720* errno appropriately and that error will be reported instead.2721*/2722(void) dt_set_errno(dtp, EDT_NOVAR);2723mark = uref ? "``" : "`";27242725if (scope == DTRACE_OBJ_EXEC && (2726(dhp != dtp->dt_globals &&2727(idp = dt_idhash_lookup(dhp, name)) != NULL) ||2728(dhp == dtp->dt_globals &&2729(idp = dt_idstack_lookup(&yypcb->pcb_globals, name)) != NULL))) {2730/*2731* Check that we are referencing the ident in the manner that2732* matches its type if this is a global lookup. In the TLS or2733* local case, we don't know how the ident will be used until2734* the time operator -> is seen; more parsing is needed.2735*/2736if (idp->di_kind != idkind && dhp == dtp->dt_globals) {2737xyerror(D_IDENT_BADREF, "%s '%s' may not be referenced "2738"as %s\n", dt_idkind_name(idp->di_kind),2739idp->di_name, dt_idkind_name(idkind));2740}27412742/*2743* Arrays and aggregations are not cooked individually. They2744* have dynamic types and must be referenced using operator [].2745* This is handled explicitly by the code for DT_TOK_LBRAC.2746*/2747if (idp->di_kind != DT_IDENT_ARRAY &&2748idp->di_kind != DT_IDENT_AGG)2749attr = dt_ident_cook(dnp, idp, NULL);2750else {2751dt_node_type_assign(dnp,2752DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);2753attr = idp->di_attr;2754}27552756free(dnp->dn_string);2757dnp->dn_string = NULL;2758dnp->dn_kind = dnkind;2759dnp->dn_ident = idp;2760dnp->dn_flags |= DT_NF_LVALUE;27612762if (idp->di_flags & DT_IDFLG_WRITE)2763dnp->dn_flags |= DT_NF_WRITABLE;27642765dt_node_attr_assign(dnp, attr);27662767} else if (dhp == dtp->dt_globals && scope != DTRACE_OBJ_EXEC &&2768dtrace_lookup_by_name(dtp, scope, name, &sym, &dts) == 0) {27692770dt_module_t *mp = dt_module_lookup_by_name(dtp, dts.dts_object);2771int umod = (mp->dm_flags & DT_DM_KERNEL) == 0;2772static const char *const kunames[] = { "kernel", "user" };27732774dtrace_typeinfo_t dtt;2775dtrace_syminfo_t *sip;27762777if (uref ^ umod) {2778xyerror(D_SYM_BADREF, "%s module '%s' symbol '%s' may "2779"not be referenced as a %s symbol\n", kunames[umod],2780dts.dts_object, dts.dts_name, kunames[uref]);2781}27822783if (dtrace_symbol_type(dtp, &sym, &dts, &dtt) != 0) {2784/*2785* For now, we special-case EDT_DATAMODEL to clarify2786* that mixed data models are not currently supported.2787*/2788if (dtp->dt_errno == EDT_DATAMODEL) {2789xyerror(D_SYM_MODEL, "cannot use %s symbol "2790"%s%s%s in a %s D program\n",2791dt_module_modelname(mp),2792dts.dts_object, mark, dts.dts_name,2793dt_module_modelname(dtp->dt_ddefs));2794}27952796/*2797* If we're taking the address of an identifier that2798* doesn't have type info, try to make it a void *.2799* This lets us use identifiers that are defined in2800* assembly and don't have type information.2801*/2802if ((dnp->dn_flags & DT_NF_IDENTADDR) == 0 ||2803dtrace_lookup_by_type(dtp, DTRACE_OBJ_CDEFS,2804"void", &dtt) != 0) {2805xyerror(D_SYM_NOTYPES,2806"no symbolic type information is available for "2807"%s%s%s: %s\n", dts.dts_object, mark,2808dts.dts_name,2809dtrace_errmsg(dtp, dtrace_errno(dtp)));2810}2811}28122813idp = dt_ident_create(name, DT_IDENT_SYMBOL, 0, 0,2814_dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);28152816if (idp == NULL)2817longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);28182819if (mp->dm_flags & DT_DM_PRIMARY)2820idp->di_flags |= DT_IDFLG_PRIM;28212822idp->di_next = dtp->dt_externs;2823dtp->dt_externs = idp;28242825if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL)2826longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);28272828bcopy(&dts, sip, sizeof (dtrace_syminfo_t));2829idp->di_data = sip;2830idp->di_ctfp = dtt.dtt_ctfp;2831idp->di_type = dtt.dtt_type;28322833free(dnp->dn_string);2834dnp->dn_string = NULL;2835dnp->dn_kind = DT_NODE_SYM;2836dnp->dn_ident = idp;2837dnp->dn_flags |= DT_NF_LVALUE;28382839dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,2840dtt.dtt_flags);2841dt_node_attr_assign(dnp, _dtrace_symattr);28422843if (uref) {2844idp->di_flags |= DT_IDFLG_USER;2845dnp->dn_flags |= DT_NF_USERLAND;2846}28472848} else if (scope == DTRACE_OBJ_EXEC && create == B_TRUE) {2849uint_t flags = DT_IDFLG_WRITE;2850uint_t id;28512852if (dt_idhash_nextid(dhp, &id) == -1) {2853xyerror(D_ID_OFLOW, "cannot create %s: limit on number "2854"of %s variables exceeded\n", name, sname);2855}28562857if (dhp == yypcb->pcb_locals)2858flags |= DT_IDFLG_LOCAL;2859else if (dhp == dtp->dt_tls)2860flags |= DT_IDFLG_TLS;28612862dt_dprintf("create %s %s variable %s, id=%u\n",2863sname, dt_idkind_name(idkind), name, id);28642865if (idkind == DT_IDENT_ARRAY || idkind == DT_IDENT_AGG) {2866idp = dt_idhash_insert(dhp, name,2867idkind, flags, id, _dtrace_defattr, 0,2868&dt_idops_assc, NULL, dtp->dt_gen);2869} else {2870idp = dt_idhash_insert(dhp, name,2871idkind, flags, id, _dtrace_defattr, 0,2872&dt_idops_thaw, NULL, dtp->dt_gen);2873}28742875if (idp == NULL)2876longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);28772878/*2879* Arrays and aggregations are not cooked individually. They2880* have dynamic types and must be referenced using operator [].2881* This is handled explicitly by the code for DT_TOK_LBRAC.2882*/2883if (idp->di_kind != DT_IDENT_ARRAY &&2884idp->di_kind != DT_IDENT_AGG)2885attr = dt_ident_cook(dnp, idp, NULL);2886else {2887dt_node_type_assign(dnp,2888DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);2889attr = idp->di_attr;2890}28912892free(dnp->dn_string);2893dnp->dn_string = NULL;2894dnp->dn_kind = dnkind;2895dnp->dn_ident = idp;2896dnp->dn_flags |= DT_NF_LVALUE | DT_NF_WRITABLE;28972898dt_node_attr_assign(dnp, attr);28992900} else if (scope != DTRACE_OBJ_EXEC) {2901xyerror(D_IDENT_UNDEF, "failed to resolve %s%s%s: %s\n",2902dnp->dn_string, mark, name,2903dtrace_errmsg(dtp, dtrace_errno(dtp)));2904} else {2905xyerror(D_IDENT_UNDEF, "failed to resolve %s: %s\n",2906dnp->dn_string, dtrace_errmsg(dtp, dtrace_errno(dtp)));2907}2908}29092910static dt_node_t *2911dt_cook_ident(dt_node_t *dnp, uint_t idflags)2912{2913dtrace_hdl_t *dtp = yypcb->pcb_hdl;29142915if (dnp->dn_op == DT_TOK_AGG)2916dt_xcook_ident(dnp, dtp->dt_aggs, DT_IDENT_AGG, B_FALSE);2917else2918dt_xcook_ident(dnp, dtp->dt_globals, DT_IDENT_SCALAR, B_FALSE);29192920return (dt_node_cook(dnp, idflags));2921}29222923/*2924* Since operators [ and -> can instantiate new variables before we know2925* whether the reference is for a read or a write, we need to check read2926* references to determine if the identifier is currently dt_ident_unref().2927* If so, we report that this first access was to an undefined variable.2928*/2929static dt_node_t *2930dt_cook_var(dt_node_t *dnp, uint_t idflags)2931{2932dt_ident_t *idp = dnp->dn_ident;29332934if ((idflags & DT_IDFLG_REF) && dt_ident_unref(idp)) {2935dnerror(dnp, D_VAR_UNDEF,2936"%s%s has not yet been declared or assigned\n",2937(idp->di_flags & DT_IDFLG_LOCAL) ? "this->" :2938(idp->di_flags & DT_IDFLG_TLS) ? "self->" : "",2939idp->di_name);2940}29412942dt_node_attr_assign(dnp, dt_ident_cook(dnp, idp, &dnp->dn_args));2943return (dnp);2944}29452946/*ARGSUSED*/2947static dt_node_t *2948dt_cook_func(dt_node_t *dnp, uint_t idflags)2949{2950dt_node_attr_assign(dnp,2951dt_ident_cook(dnp, dnp->dn_ident, &dnp->dn_args));29522953return (dnp);2954}29552956static dt_node_t *2957dt_cook_op1(dt_node_t *dnp, uint_t idflags)2958{2959dtrace_hdl_t *dtp = yypcb->pcb_hdl;2960dt_node_t *cp = dnp->dn_child;29612962char n[DT_TYPE_NAMELEN];2963dtrace_typeinfo_t dtt;2964dt_ident_t *idp;29652966ctf_encoding_t e;2967ctf_arinfo_t r;2968ctf_id_t type, base;2969uint_t kind;29702971if (dnp->dn_op == DT_TOK_PREINC || dnp->dn_op == DT_TOK_POSTINC ||2972dnp->dn_op == DT_TOK_PREDEC || dnp->dn_op == DT_TOK_POSTDEC)2973idflags = DT_IDFLG_REF | DT_IDFLG_MOD;2974else2975idflags = DT_IDFLG_REF;29762977/*2978* We allow the unary ++ and -- operators to instantiate new scalar2979* variables if applied to an identifier; otherwise just cook as usual.2980*/2981if (cp->dn_kind == DT_NODE_IDENT && (idflags & DT_IDFLG_MOD))2982dt_xcook_ident(cp, dtp->dt_globals, DT_IDENT_SCALAR, B_TRUE);29832984cp = dnp->dn_child = dt_node_cook(cp, 0); /* don't set idflags yet */29852986if (cp->dn_kind == DT_NODE_VAR && dt_ident_unref(cp->dn_ident)) {2987if (dt_type_lookup("int64_t", &dtt) != 0)2988xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");29892990dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);2991dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,2992dtt.dtt_flags);2993}29942995if (cp->dn_kind == DT_NODE_VAR)2996cp->dn_ident->di_flags |= idflags;29972998switch (dnp->dn_op) {2999case DT_TOK_DEREF:3000/*3001* If the deref operator is applied to a translated pointer,3002* we set our output type to the output of the translation.3003*/3004if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {3005dt_xlator_t *dxp = idp->di_data;30063007dnp->dn_ident = &dxp->dx_souid;3008dt_node_type_assign(dnp,3009dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,3010cp->dn_flags & DT_NF_USERLAND);3011break;3012}30133014type = ctf_type_resolve(cp->dn_ctfp, cp->dn_type);3015kind = ctf_type_kind(cp->dn_ctfp, type);30163017if (kind == CTF_K_ARRAY) {3018if (ctf_array_info(cp->dn_ctfp, type, &r) != 0) {3019dtp->dt_ctferr = ctf_errno(cp->dn_ctfp);3020longjmp(yypcb->pcb_jmpbuf, EDT_CTF);3021} else3022type = r.ctr_contents;3023} else if (kind == CTF_K_POINTER) {3024type = ctf_type_reference(cp->dn_ctfp, type);3025} else {3026xyerror(D_DEREF_NONPTR,3027"cannot dereference non-pointer type\n");3028}30293030dt_node_type_assign(dnp, cp->dn_ctfp, type,3031cp->dn_flags & DT_NF_USERLAND);3032base = ctf_type_resolve(cp->dn_ctfp, type);3033kind = ctf_type_kind(cp->dn_ctfp, base);30343035if (kind == CTF_K_INTEGER && ctf_type_encoding(cp->dn_ctfp,3036base, &e) == 0 && IS_VOID(e)) {3037xyerror(D_DEREF_VOID,3038"cannot dereference pointer to void\n");3039}30403041if (kind == CTF_K_FUNCTION) {3042xyerror(D_DEREF_FUNC,3043"cannot dereference pointer to function\n");3044}30453046if (kind != CTF_K_ARRAY || dt_node_is_string(dnp))3047dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.4.3] */30483049/*3050* If we propagated the l-value bit and the child operand was3051* a writable D variable or a binary operation of the form3052* a + b where a is writable, then propagate the writable bit.3053* This is necessary to permit assignments to scalar arrays,3054* which are converted to expressions of the form *(a + i).3055*/3056if ((cp->dn_flags & DT_NF_WRITABLE) ||3057(cp->dn_kind == DT_NODE_OP2 && cp->dn_op == DT_TOK_ADD &&3058(cp->dn_left->dn_flags & DT_NF_WRITABLE)))3059dnp->dn_flags |= DT_NF_WRITABLE;30603061if ((cp->dn_flags & DT_NF_USERLAND) &&3062(kind == CTF_K_POINTER || (dnp->dn_flags & DT_NF_REF)))3063dnp->dn_flags |= DT_NF_USERLAND;3064break;30653066case DT_TOK_IPOS:3067case DT_TOK_INEG:3068if (!dt_node_is_arith(cp)) {3069xyerror(D_OP_ARITH, "operator %s requires an operand "3070"of arithmetic type\n", opstr(dnp->dn_op));3071}3072dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.4-6] */3073break;30743075case DT_TOK_BNEG:3076if (!dt_node_is_integer(cp)) {3077xyerror(D_OP_INT, "operator %s requires an operand of "3078"integral type\n", opstr(dnp->dn_op));3079}3080dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.4-6] */3081break;30823083case DT_TOK_LNEG:3084if (!dt_node_is_scalar(cp)) {3085xyerror(D_OP_SCALAR, "operator %s requires an operand "3086"of scalar type\n", opstr(dnp->dn_op));3087}3088dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),3089B_FALSE);3090break;30913092case DT_TOK_ADDROF:3093if (cp->dn_kind == DT_NODE_VAR || cp->dn_kind == DT_NODE_AGG) {3094xyerror(D_ADDROF_VAR,3095"cannot take address of dynamic variable\n");3096}30973098if (dt_node_is_dynamic(cp)) {3099xyerror(D_ADDROF_VAR,3100"cannot take address of dynamic object\n");3101}31023103if (!(cp->dn_flags & DT_NF_LVALUE)) {3104xyerror(D_ADDROF_LVAL, /* see K&R[A7.4.2] */3105"unacceptable operand for unary & operator\n");3106}31073108if (cp->dn_flags & DT_NF_BITFIELD) {3109xyerror(D_ADDROF_BITFIELD,3110"cannot take address of bit-field\n");3111}31123113dtt = (dtrace_typeinfo_t){3114.dtt_ctfp = cp->dn_ctfp,3115.dtt_type = cp->dn_type,3116};31173118if (dt_type_pointer(&dtt) == -1) {3119xyerror(D_TYPE_ERR, "cannot find type for \"&\": %s*\n",3120dt_node_type_name(cp, n, sizeof (n)));3121}31223123dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,3124cp->dn_flags & DT_NF_USERLAND);3125break;31263127case DT_TOK_SIZEOF:3128if (cp->dn_flags & DT_NF_BITFIELD) {3129xyerror(D_SIZEOF_BITFIELD,3130"cannot apply sizeof to a bit-field\n");3131}31323133if (dt_node_sizeof(cp) == 0) {3134xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an "3135"operand of unknown size\n");3136}31373138dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,3139ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),3140B_FALSE);3141break;31423143case DT_TOK_STRINGOF:3144if (!dt_node_is_scalar(cp) && !dt_node_is_pointer(cp) &&3145!dt_node_is_strcompat(cp)) {3146xyerror(D_STRINGOF_TYPE,3147"cannot apply stringof to a value of type %s\n",3148dt_node_type_name(cp, n, sizeof (n)));3149}3150dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),3151cp->dn_flags & DT_NF_USERLAND);3152break;31533154case DT_TOK_PREINC:3155case DT_TOK_POSTINC:3156case DT_TOK_PREDEC:3157case DT_TOK_POSTDEC:3158if (dt_node_is_scalar(cp) == 0) {3159xyerror(D_OP_SCALAR, "operator %s requires operand of "3160"scalar type\n", opstr(dnp->dn_op));3161}31623163if (dt_node_is_vfptr(cp)) {3164xyerror(D_OP_VFPTR, "operator %s requires an operand "3165"of known size\n", opstr(dnp->dn_op));3166}31673168if (!(cp->dn_flags & DT_NF_LVALUE)) {3169xyerror(D_OP_LVAL, "operator %s requires modifiable "3170"lvalue as an operand\n", opstr(dnp->dn_op));3171}31723173if (!(cp->dn_flags & DT_NF_WRITABLE)) {3174xyerror(D_OP_WRITE, "operator %s can only be applied "3175"to a writable variable\n", opstr(dnp->dn_op));3176}31773178dt_node_type_propagate(cp, dnp); /* see K&R[A7.4.1] */3179break;31803181default:3182xyerror(D_UNKNOWN, "invalid unary op %s\n", opstr(dnp->dn_op));3183}31843185dt_node_attr_assign(dnp, cp->dn_attr);3186return (dnp);3187}31883189static void3190dt_assign_common(dt_node_t *dnp)3191{3192dt_node_t *lp = dnp->dn_left;3193dt_node_t *rp = dnp->dn_right;3194int op = dnp->dn_op;31953196if (rp->dn_kind == DT_NODE_INT)3197dt_cast(lp, rp);31983199if (!(lp->dn_flags & DT_NF_LVALUE)) {3200xyerror(D_OP_LVAL, "operator %s requires modifiable "3201"lvalue as an operand\n", opstr(op));3202/* see K&R[A7.17] */3203}32043205if (!(lp->dn_flags & DT_NF_WRITABLE)) {3206xyerror(D_OP_WRITE, "operator %s can only be applied "3207"to a writable variable\n", opstr(op));3208}32093210dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */3211dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));3212}32133214static dt_node_t *3215dt_cook_op2(dt_node_t *dnp, uint_t idflags)3216{3217dtrace_hdl_t *dtp = yypcb->pcb_hdl;3218dt_node_t *lp = dnp->dn_left;3219dt_node_t *rp = dnp->dn_right;3220int op = dnp->dn_op;32213222ctf_membinfo_t m;3223ctf_file_t *ctfp;3224ctf_id_t type;3225int kind, val, uref;3226dt_ident_t *idp;32273228char n1[DT_TYPE_NAMELEN];3229char n2[DT_TYPE_NAMELEN];32303231/*3232* The expression E1[E2] is identical by definition to *((E1)+(E2)) so3233* we convert "[" to "+" and glue on "*" at the end (see K&R[A7.3.1])3234* unless the left-hand side is an untyped D scalar, associative array,3235* or aggregation. In these cases, we proceed to case DT_TOK_LBRAC and3236* handle associative array and aggregation references there.3237*/3238if (op == DT_TOK_LBRAC) {3239if (lp->dn_kind == DT_NODE_IDENT) {3240dt_idhash_t *dhp;3241uint_t idkind;32423243if (lp->dn_op == DT_TOK_AGG) {3244dhp = dtp->dt_aggs;3245idp = dt_idhash_lookup(dhp, lp->dn_string + 1);3246idkind = DT_IDENT_AGG;3247} else {3248dhp = dtp->dt_globals;3249idp = dt_idstack_lookup(3250&yypcb->pcb_globals, lp->dn_string);3251idkind = DT_IDENT_ARRAY;3252}32533254if (idp == NULL || dt_ident_unref(idp))3255dt_xcook_ident(lp, dhp, idkind, B_TRUE);3256else3257dt_xcook_ident(lp, dhp, idp->di_kind, B_FALSE);3258} else {3259lp = dnp->dn_left = dt_node_cook(lp, 0);3260}32613262/*3263* Switch op to '+' for *(E1 + E2) array mode in these cases:3264* (a) lp is a DT_IDENT_ARRAY variable that has already been3265* referenced using [] notation (dn_args != NULL).3266* (b) lp is a non-ARRAY variable that has already been given3267* a type by assignment or declaration (!dt_ident_unref())3268* (c) lp is neither a variable nor an aggregation3269*/3270if (lp->dn_kind == DT_NODE_VAR) {3271if (lp->dn_ident->di_kind == DT_IDENT_ARRAY) {3272if (lp->dn_args != NULL)3273op = DT_TOK_ADD;3274} else if (!dt_ident_unref(lp->dn_ident)) {3275op = DT_TOK_ADD;3276}3277} else if (lp->dn_kind != DT_NODE_AGG) {3278op = DT_TOK_ADD;3279}3280}32813282switch (op) {3283case DT_TOK_BAND:3284case DT_TOK_XOR:3285case DT_TOK_BOR:3286lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3287rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);32883289if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {3290xyerror(D_OP_INT, "operator %s requires operands of "3291"integral type\n", opstr(op));3292}32933294dt_node_promote(lp, rp, dnp); /* see K&R[A7.11-13] */3295break;32963297case DT_TOK_LSH:3298case DT_TOK_RSH:3299lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3300rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);33013302if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {3303xyerror(D_OP_INT, "operator %s requires operands of "3304"integral type\n", opstr(op));3305}33063307dt_node_type_propagate(lp, dnp); /* see K&R[A7.8] */3308dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));3309break;33103311case DT_TOK_MOD:3312lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3313rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);33143315if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {3316xyerror(D_OP_INT, "operator %s requires operands of "3317"integral type\n", opstr(op));3318}33193320dt_node_promote(lp, rp, dnp); /* see K&R[A7.6] */3321break;33223323case DT_TOK_MUL:3324case DT_TOK_DIV:3325lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3326rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);33273328if (!dt_node_is_arith(lp) || !dt_node_is_arith(rp)) {3329xyerror(D_OP_ARITH, "operator %s requires operands of "3330"arithmetic type\n", opstr(op));3331}33323333dt_node_promote(lp, rp, dnp); /* see K&R[A7.6] */3334break;33353336case DT_TOK_LAND:3337case DT_TOK_LXOR:3338case DT_TOK_LOR:3339lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3340rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);33413342if (!dt_node_is_scalar(lp) || !dt_node_is_scalar(rp)) {3343xyerror(D_OP_SCALAR, "operator %s requires operands "3344"of scalar type\n", opstr(op));3345}33463347dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),3348B_FALSE);3349dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));3350break;33513352case DT_TOK_LT:3353case DT_TOK_LE:3354case DT_TOK_GT:3355case DT_TOK_GE:3356case DT_TOK_EQU:3357case DT_TOK_NEQ:3358/*3359* The D comparison operators provide the ability to transform3360* a right-hand identifier into a corresponding enum tag value3361* if the left-hand side is an enum type. To do this, we cook3362* the left-hand side, and then see if the right-hand side is3363* an unscoped identifier defined in the enum. If so, we3364* convert into an integer constant node with the tag's value.3365*/3366lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);33673368kind = ctf_type_kind(lp->dn_ctfp,3369ctf_type_resolve(lp->dn_ctfp, lp->dn_type));33703371if (kind == CTF_K_ENUM && rp->dn_kind == DT_NODE_IDENT &&3372strchr(rp->dn_string, '`') == NULL && ctf_enum_value(3373lp->dn_ctfp, lp->dn_type, rp->dn_string, &val) == 0) {33743375if ((idp = dt_idstack_lookup(&yypcb->pcb_globals,3376rp->dn_string)) != NULL) {3377xyerror(D_IDENT_AMBIG,3378"ambiguous use of operator %s: %s is "3379"both a %s enum tag and a global %s\n",3380opstr(op), rp->dn_string,3381dt_node_type_name(lp, n1, sizeof (n1)),3382dt_idkind_name(idp->di_kind));3383}33843385free(rp->dn_string);3386rp->dn_string = NULL;3387rp->dn_kind = DT_NODE_INT;3388rp->dn_flags |= DT_NF_COOKED;3389rp->dn_op = DT_TOK_INT;3390rp->dn_value = (intmax_t)val;33913392dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,3393B_FALSE);3394dt_node_attr_assign(rp, _dtrace_symattr);3395}33963397rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);33983399/*3400* The rules for type checking for the relational operators are3401* described in the ANSI-C spec (see K&R[A7.9-10]). We perform3402* the various tests in order from least to most expensive. We3403* also allow derived strings to be compared as a first-class3404* type (resulting in a strcmp(3C)-style comparison), and we3405* slightly relax the A7.9 rules to permit void pointer3406* comparisons as in A7.10. Our users won't be confused by3407* this since they understand pointers are just numbers, and3408* relaxing this constraint simplifies the implementation.3409*/3410if (ctf_type_compat(lp->dn_ctfp, lp->dn_type,3411rp->dn_ctfp, rp->dn_type))3412/*EMPTY*/;3413else if (dt_node_is_integer(lp) && dt_node_is_integer(rp))3414/*EMPTY*/;3415else if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp) &&3416(dt_node_is_string(lp) || dt_node_is_string(rp)))3417/*EMPTY*/;3418else if (dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) {3419xyerror(D_OP_INCOMPAT, "operands have "3420"incompatible types: \"%s\" %s \"%s\"\n",3421dt_node_type_name(lp, n1, sizeof (n1)), opstr(op),3422dt_node_type_name(rp, n2, sizeof (n2)));3423}34243425dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),3426B_FALSE);3427dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));3428break;34293430case DT_TOK_ADD:3431case DT_TOK_SUB: {3432/*3433* The rules for type checking for the additive operators are3434* described in the ANSI-C spec (see K&R[A7.7]). Pointers and3435* integers may be manipulated according to specific rules. In3436* these cases D permits strings to be treated as pointers.3437*/3438int lp_is_ptr, lp_is_int, rp_is_ptr, rp_is_int;34393440lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);3441rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);34423443lp_is_ptr = dt_node_is_string(lp) ||3444(dt_node_is_pointer(lp) && !dt_node_is_vfptr(lp));3445lp_is_int = dt_node_is_integer(lp);34463447rp_is_ptr = dt_node_is_string(rp) ||3448(dt_node_is_pointer(rp) && !dt_node_is_vfptr(rp));3449rp_is_int = dt_node_is_integer(rp);34503451if (lp_is_int && rp_is_int) {3452dt_type_promote(lp, rp, &ctfp, &type);3453uref = 0;3454} else if (lp_is_ptr && rp_is_int) {3455ctfp = lp->dn_ctfp;3456type = lp->dn_type;3457uref = lp->dn_flags & DT_NF_USERLAND;3458} else if (lp_is_int && rp_is_ptr && op == DT_TOK_ADD) {3459ctfp = rp->dn_ctfp;3460type = rp->dn_type;3461uref = rp->dn_flags & DT_NF_USERLAND;3462} else if (lp_is_ptr && rp_is_ptr && op == DT_TOK_SUB &&3463dt_node_is_ptrcompat(lp, rp, NULL, NULL)) {3464ctfp = dtp->dt_ddefs->dm_ctfp;3465type = ctf_lookup_by_name(ctfp, "ptrdiff_t");3466uref = 0;3467} else {3468xyerror(D_OP_INCOMPAT, "operands have incompatible "3469"types: \"%s\" %s \"%s\"\n",3470dt_node_type_name(lp, n1, sizeof (n1)), opstr(op),3471dt_node_type_name(rp, n2, sizeof (n2)));3472}34733474dt_node_type_assign(dnp, ctfp, type, B_FALSE);3475dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));34763477if (uref)3478dnp->dn_flags |= DT_NF_USERLAND;3479break;3480}34813482case DT_TOK_OR_EQ:3483case DT_TOK_XOR_EQ:3484case DT_TOK_AND_EQ:3485case DT_TOK_LSH_EQ:3486case DT_TOK_RSH_EQ:3487case DT_TOK_MOD_EQ:3488if (lp->dn_kind == DT_NODE_IDENT) {3489dt_xcook_ident(lp, dtp->dt_globals,3490DT_IDENT_SCALAR, B_TRUE);3491}34923493lp = dnp->dn_left =3494dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD);34953496rp = dnp->dn_right =3497dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD);34983499if (!dt_node_is_integer(lp) || !dt_node_is_integer(rp)) {3500xyerror(D_OP_INT, "operator %s requires operands of "3501"integral type\n", opstr(op));3502}3503goto asgn_common;35043505case DT_TOK_MUL_EQ:3506case DT_TOK_DIV_EQ:3507if (lp->dn_kind == DT_NODE_IDENT) {3508dt_xcook_ident(lp, dtp->dt_globals,3509DT_IDENT_SCALAR, B_TRUE);3510}35113512lp = dnp->dn_left =3513dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD);35143515rp = dnp->dn_right =3516dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD);35173518if (!dt_node_is_arith(lp) || !dt_node_is_arith(rp)) {3519xyerror(D_OP_ARITH, "operator %s requires operands of "3520"arithmetic type\n", opstr(op));3521}3522goto asgn_common;35233524case DT_TOK_ASGN:3525/*3526* If the left-hand side is an identifier, attempt to resolve3527* it as either an aggregation or scalar variable. We pass3528* B_TRUE to dt_xcook_ident to indicate that a new variable can3529* be created if no matching variable exists in the namespace.3530*/3531if (lp->dn_kind == DT_NODE_IDENT) {3532if (lp->dn_op == DT_TOK_AGG) {3533dt_xcook_ident(lp, dtp->dt_aggs,3534DT_IDENT_AGG, B_TRUE);3535} else {3536dt_xcook_ident(lp, dtp->dt_globals,3537DT_IDENT_SCALAR, B_TRUE);3538}3539}35403541lp = dnp->dn_left = dt_node_cook(lp, 0); /* don't set mod yet */3542rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);35433544/*3545* If the left-hand side is an aggregation, verify that we are3546* assigning it the result of an aggregating function. Once3547* we've done so, hide the func node in the aggregation and3548* return the aggregation itself up to the parse tree parent.3549* This transformation is legal since the assigned function3550* cannot change identity across disjoint cooking passes and3551* the argument list subtree is retained for later cooking.3552*/3553if (lp->dn_kind == DT_NODE_AGG) {3554const char *aname = lp->dn_ident->di_name;3555dt_ident_t *oid = lp->dn_ident->di_iarg;35563557if (rp->dn_kind != DT_NODE_FUNC ||3558rp->dn_ident->di_kind != DT_IDENT_AGGFUNC) {3559xyerror(D_AGG_FUNC,3560"@%s must be assigned the result of "3561"an aggregating function\n", aname);3562}35633564if (oid != NULL && oid != rp->dn_ident) {3565xyerror(D_AGG_REDEF,3566"aggregation redefined: @%s\n\t "3567"current: @%s = %s( )\n\tprevious: @%s = "3568"%s( ) : line %d\n", aname, aname,3569rp->dn_ident->di_name, aname, oid->di_name,3570lp->dn_ident->di_lineno);3571} else if (oid == NULL)3572lp->dn_ident->di_iarg = rp->dn_ident;35733574/*3575* Do not allow multiple aggregation assignments in a3576* single statement, e.g. (@a = count()) = count();3577* We produce a message as if the result of aggregating3578* function does not propagate DT_NF_LVALUE.3579*/3580if (lp->dn_aggfun != NULL) {3581xyerror(D_OP_LVAL, "operator = requires "3582"modifiable lvalue as an operand\n");3583}35843585lp->dn_aggfun = rp;3586lp = dt_node_cook(lp, DT_IDFLG_MOD);35873588dnp->dn_left = dnp->dn_right = NULL;3589dt_node_free(dnp);35903591return (lp);3592}35933594/*3595* If the right-hand side is a dynamic variable that is the3596* output of a translator, our result is the translated type.3597*/3598if ((idp = dt_node_resolve(rp, DT_IDENT_XLSOU)) != NULL) {3599ctfp = idp->di_ctfp;3600type = idp->di_type;3601uref = idp->di_flags & DT_IDFLG_USER;3602} else {3603ctfp = rp->dn_ctfp;3604type = rp->dn_type;3605uref = rp->dn_flags & DT_NF_USERLAND;3606}36073608/*3609* If the left-hand side of an assignment statement is a virgin3610* variable created by this compilation pass, reset the type of3611* this variable to the type of the right-hand side.3612*/3613if (lp->dn_kind == DT_NODE_VAR &&3614dt_ident_unref(lp->dn_ident)) {3615dt_node_type_assign(lp, ctfp, type, B_FALSE);3616dt_ident_type_assign(lp->dn_ident, ctfp, type);36173618if (uref) {3619lp->dn_flags |= DT_NF_USERLAND;3620lp->dn_ident->di_flags |= DT_IDFLG_USER;3621}3622}36233624if (lp->dn_kind == DT_NODE_VAR)3625lp->dn_ident->di_flags |= DT_IDFLG_MOD;36263627/*3628* The rules for type checking for the assignment operators are3629* described in the ANSI-C spec (see K&R[A7.17]). We share3630* most of this code with the argument list checking code.3631*/3632if (!dt_node_is_string(lp)) {3633kind = ctf_type_kind(lp->dn_ctfp,3634ctf_type_resolve(lp->dn_ctfp, lp->dn_type));36353636if (kind == CTF_K_ARRAY || kind == CTF_K_FUNCTION) {3637xyerror(D_OP_ARRFUN, "operator %s may not be "3638"applied to operand of type \"%s\"\n",3639opstr(op),3640dt_node_type_name(lp, n1, sizeof (n1)));3641}3642}36433644if (idp != NULL && idp->di_kind == DT_IDENT_XLSOU &&3645ctf_type_compat(lp->dn_ctfp, lp->dn_type, ctfp, type))3646goto asgn_common;36473648if (dt_node_is_argcompat(lp, rp))3649goto asgn_common;36503651xyerror(D_OP_INCOMPAT,3652"operands have incompatible types: \"%s\" %s \"%s\"\n",3653dt_node_type_name(lp, n1, sizeof (n1)), opstr(op),3654dt_node_type_name(rp, n2, sizeof (n2)));3655/*NOTREACHED*/36563657case DT_TOK_ADD_EQ:3658case DT_TOK_SUB_EQ:3659if (lp->dn_kind == DT_NODE_IDENT) {3660dt_xcook_ident(lp, dtp->dt_globals,3661DT_IDENT_SCALAR, B_TRUE);3662}36633664lp = dnp->dn_left =3665dt_node_cook(lp, DT_IDFLG_REF | DT_IDFLG_MOD);36663667rp = dnp->dn_right =3668dt_node_cook(rp, DT_IDFLG_REF | DT_IDFLG_MOD);36693670if (dt_node_is_string(lp) || dt_node_is_string(rp)) {3671xyerror(D_OP_INCOMPAT, "operands have "3672"incompatible types: \"%s\" %s \"%s\"\n",3673dt_node_type_name(lp, n1, sizeof (n1)), opstr(op),3674dt_node_type_name(rp, n2, sizeof (n2)));3675}36763677/*3678* The rules for type checking for the assignment operators are3679* described in the ANSI-C spec (see K&R[A7.17]). To these3680* rules we add that only writable D nodes can be modified.3681*/3682if (dt_node_is_integer(lp) == 0 ||3683dt_node_is_integer(rp) == 0) {3684if (!dt_node_is_pointer(lp) || dt_node_is_vfptr(lp)) {3685xyerror(D_OP_VFPTR,3686"operator %s requires left-hand scalar "3687"operand of known size\n", opstr(op));3688} else if (dt_node_is_integer(rp) == 0 &&3689dt_node_is_ptrcompat(lp, rp, NULL, NULL) == 0) {3690xyerror(D_OP_INCOMPAT, "operands have "3691"incompatible types: \"%s\" %s \"%s\"\n",3692dt_node_type_name(lp, n1, sizeof (n1)),3693opstr(op),3694dt_node_type_name(rp, n2, sizeof (n2)));3695}3696}3697asgn_common:3698dt_assign_common(dnp);3699break;37003701case DT_TOK_PTR:3702/*3703* If the left-hand side of operator -> is one of the scoping3704* keywords, permit a local or thread variable to be created or3705* referenced.3706*/3707if (lp->dn_kind == DT_NODE_IDENT) {3708dt_idhash_t *dhp = NULL;37093710if (strcmp(lp->dn_string, "self") == 0) {3711dhp = dtp->dt_tls;3712} else if (strcmp(lp->dn_string, "this") == 0) {3713dhp = yypcb->pcb_locals;3714}3715if (dhp != NULL) {3716if (rp->dn_kind != DT_NODE_VAR) {3717dt_xcook_ident(rp, dhp,3718DT_IDENT_SCALAR, B_TRUE);3719}37203721if (idflags != 0)3722rp = dt_node_cook(rp, idflags);37233724/* avoid freeing rp */3725dnp->dn_right = dnp->dn_left;3726dt_node_free(dnp);3727return (rp);3728}3729}3730/*FALLTHRU*/3731case DT_TOK_DOT:3732lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);37333734if (rp->dn_kind != DT_NODE_IDENT) {3735xyerror(D_OP_IDENT, "operator %s must be followed by "3736"an identifier\n", opstr(op));3737}37383739if ((idp = dt_node_resolve(lp, DT_IDENT_XLSOU)) != NULL ||3740(idp = dt_node_resolve(lp, DT_IDENT_XLPTR)) != NULL) {3741/*3742* If the left-hand side is a translated struct or ptr,3743* the type of the left is the translation output type.3744*/3745dt_xlator_t *dxp = idp->di_data;37463747if (dt_xlator_member(dxp, rp->dn_string) == NULL) {3748xyerror(D_XLATE_NOCONV,3749"translator does not define conversion "3750"for member: %s\n", rp->dn_string);3751}37523753ctfp = idp->di_ctfp;3754type = ctf_type_resolve(ctfp, idp->di_type);3755uref = idp->di_flags & DT_IDFLG_USER;3756} else {3757ctfp = lp->dn_ctfp;3758type = ctf_type_resolve(ctfp, lp->dn_type);3759uref = lp->dn_flags & DT_NF_USERLAND;3760}37613762kind = ctf_type_kind(ctfp, type);37633764if (op == DT_TOK_PTR) {3765if (kind != CTF_K_POINTER) {3766xyerror(D_OP_PTR, "operator %s must be "3767"applied to a pointer\n", opstr(op));3768}3769type = ctf_type_reference(ctfp, type);3770type = ctf_type_resolve(ctfp, type);3771kind = ctf_type_kind(ctfp, type);3772}37733774/*3775* If we follow a reference to a forward declaration tag,3776* search the entire type space for the actual definition.3777*/3778while (kind == CTF_K_FORWARD) {3779char *tag = ctf_type_name(ctfp, type, n1, sizeof (n1));3780dtrace_typeinfo_t dtt;37813782if (tag != NULL && dt_type_lookup(tag, &dtt) == 0 &&3783(dtt.dtt_ctfp != ctfp || dtt.dtt_type != type)) {3784ctfp = dtt.dtt_ctfp;3785type = ctf_type_resolve(ctfp, dtt.dtt_type);3786kind = ctf_type_kind(ctfp, type);3787} else {3788xyerror(D_OP_INCOMPLETE,3789"operator %s cannot be applied to a "3790"forward declaration: no %s definition "3791"is available\n", opstr(op), tag);3792}3793}37943795if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) {3796if (op == DT_TOK_PTR) {3797xyerror(D_OP_SOU, "operator -> cannot be "3798"applied to pointer to type \"%s\"; must "3799"be applied to a struct or union pointer\n",3800ctf_type_name(ctfp, type, n1, sizeof (n1)));3801} else {3802xyerror(D_OP_SOU, "operator %s cannot be "3803"applied to type \"%s\"; must be applied "3804"to a struct or union\n", opstr(op),3805ctf_type_name(ctfp, type, n1, sizeof (n1)));3806}3807}38083809if (ctf_member_info(ctfp, type, rp->dn_string, &m) == CTF_ERR) {3810xyerror(D_TYPE_MEMBER,3811"%s is not a member of %s\n", rp->dn_string,3812ctf_type_name(ctfp, type, n1, sizeof (n1)));3813}38143815type = ctf_type_resolve(ctfp, m.ctm_type);3816kind = ctf_type_kind(ctfp, type);38173818dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);3819dt_node_attr_assign(dnp, lp->dn_attr);38203821if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||3822dt_node_is_string(dnp)))3823dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.3.3] */38243825if (op == DT_TOK_DOT && (lp->dn_flags & DT_NF_LVALUE) &&3826(kind != CTF_K_ARRAY || dt_node_is_string(dnp)))3827dnp->dn_flags |= DT_NF_LVALUE; /* see K&R[A7.3.3] */38283829if (lp->dn_flags & DT_NF_WRITABLE)3830dnp->dn_flags |= DT_NF_WRITABLE;38313832if (uref && (kind == CTF_K_POINTER ||3833(dnp->dn_flags & DT_NF_REF)))3834dnp->dn_flags |= DT_NF_USERLAND;3835break;38363837case DT_TOK_LBRAC: {3838/*3839* If op is DT_TOK_LBRAC, we know from the special-case code at3840* the top that lp is either a D variable or an aggregation.3841*/3842dt_node_t *lnp;38433844/*3845* If the left-hand side is an aggregation, just set dn_aggtup3846* to the right-hand side and return the cooked aggregation.3847* This transformation is legal since we are just collapsing3848* nodes to simplify later processing, and the entire aggtup3849* parse subtree is retained for subsequent cooking passes.3850*/3851if (lp->dn_kind == DT_NODE_AGG) {3852if (lp->dn_aggtup != NULL) {3853xyerror(D_AGG_MDIM, "improper attempt to "3854"reference @%s as a multi-dimensional "3855"array\n", lp->dn_ident->di_name);3856}38573858lp->dn_aggtup = rp;3859lp = dt_node_cook(lp, 0);38603861dnp->dn_left = dnp->dn_right = NULL;3862dt_node_free(dnp);38633864return (lp);3865}38663867assert(lp->dn_kind == DT_NODE_VAR);3868idp = lp->dn_ident;38693870/*3871* If the left-hand side is a non-global scalar that hasn't yet3872* been referenced or modified, it was just created by self->3873* or this-> and we can convert it from scalar to assoc array.3874*/3875if (idp->di_kind == DT_IDENT_SCALAR && dt_ident_unref(idp) &&3876(idp->di_flags & (DT_IDFLG_LOCAL | DT_IDFLG_TLS)) != 0) {38773878if (idp->di_flags & DT_IDFLG_LOCAL) {3879xyerror(D_ARR_LOCAL,3880"local variables may not be used as "3881"associative arrays: %s\n", idp->di_name);3882}38833884dt_dprintf("morph variable %s (id %u) from scalar to "3885"array\n", idp->di_name, idp->di_id);38863887dt_ident_morph(idp, DT_IDENT_ARRAY,3888&dt_idops_assc, NULL);3889}38903891if (idp->di_kind != DT_IDENT_ARRAY) {3892xyerror(D_IDENT_BADREF, "%s '%s' may not be referenced "3893"as %s\n", dt_idkind_name(idp->di_kind),3894idp->di_name, dt_idkind_name(DT_IDENT_ARRAY));3895}38963897/*3898* Now that we've confirmed our left-hand side is a DT_NODE_VAR3899* of idkind DT_IDENT_ARRAY, we need to splice the [ node from3900* the parse tree and leave a cooked DT_NODE_VAR in its place3901* where dn_args for the VAR node is the right-hand 'rp' tree,3902* as shown in the parse tree diagram below:3903*3904* / /3905* [ OP2 "[" ]=dnp [ VAR ]=dnp3906* / \ => |3907* / \ +- dn_args -> [ ??? ]=rp3908* [ VAR ]=lp [ ??? ]=rp3909*3910* Since the final dt_node_cook(dnp) can fail using longjmp we3911* must perform the transformations as a group first by over-3912* writing 'dnp' to become the VAR node, so that the parse tree3913* is guaranteed to be in a consistent state if the cook fails.3914*/3915assert(lp->dn_kind == DT_NODE_VAR);3916assert(lp->dn_args == NULL);39173918lnp = dnp->dn_link;3919bcopy(lp, dnp, sizeof (dt_node_t));3920dnp->dn_link = lnp;39213922dnp->dn_args = rp;3923dnp->dn_list = NULL;39243925dt_node_free(lp);3926return (dt_node_cook(dnp, idflags));3927}39283929case DT_TOK_XLATE: {3930dt_xlator_t *dxp;39313932assert(lp->dn_kind == DT_NODE_TYPE);3933rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);3934dxp = dt_xlator_lookup(dtp, rp, lp, DT_XLATE_FUZZY);39353936if (dxp == NULL) {3937xyerror(D_XLATE_NONE,3938"cannot translate from \"%s\" to \"%s\"\n",3939dt_node_type_name(rp, n1, sizeof (n1)),3940dt_node_type_name(lp, n2, sizeof (n2)));3941}39423943dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);3944dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),3945B_FALSE);3946dt_node_attr_assign(dnp,3947dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));3948break;3949}39503951case DT_TOK_LPAR: {3952ctf_id_t ltype, rtype;3953uint_t lkind, rkind;39543955assert(lp->dn_kind == DT_NODE_TYPE);3956rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);39573958ltype = ctf_type_resolve(lp->dn_ctfp, lp->dn_type);3959lkind = ctf_type_kind(lp->dn_ctfp, ltype);39603961rtype = ctf_type_resolve(rp->dn_ctfp, rp->dn_type);3962rkind = ctf_type_kind(rp->dn_ctfp, rtype);39633964/*3965* The rules for casting are loosely explained in K&R[A7.5]3966* and K&R[A6]. Basically, we can cast to the same type or3967* same base type, between any kind of scalar values, from3968* arrays to pointers, and we can cast anything to void.3969* To these rules D adds casts from scalars to strings.3970*/3971if (ctf_type_compat(lp->dn_ctfp, lp->dn_type,3972rp->dn_ctfp, rp->dn_type))3973/*EMPTY*/;3974else if (dt_node_is_scalar(lp) &&3975(dt_node_is_scalar(rp) || rkind == CTF_K_FUNCTION))3976/*EMPTY*/;3977else if (dt_node_is_void(lp))3978/*EMPTY*/;3979else if (lkind == CTF_K_POINTER && dt_node_is_pointer(rp))3980/*EMPTY*/;3981else if (dt_node_is_string(lp) && (dt_node_is_scalar(rp) ||3982dt_node_is_pointer(rp) || dt_node_is_strcompat(rp)))3983/*EMPTY*/;3984else {3985xyerror(D_CAST_INVAL,3986"invalid cast expression: \"%s\" to \"%s\"\n",3987dt_node_type_name(rp, n1, sizeof (n1)),3988dt_node_type_name(lp, n2, sizeof (n2)));3989}39903991dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */3992dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));39933994/*3995* If it's a pointer then should be able to (attempt to)3996* assign to it.3997*/3998if (lkind == CTF_K_POINTER)3999dnp->dn_flags |= DT_NF_WRITABLE;40004001break;4002}40034004case DT_TOK_COMMA:4005lp = dnp->dn_left = dt_node_cook(lp, DT_IDFLG_REF);4006rp = dnp->dn_right = dt_node_cook(rp, DT_IDFLG_REF);40074008if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp)) {4009xyerror(D_OP_DYN, "operator %s operands "4010"cannot be of dynamic type\n", opstr(op));4011}40124013if (dt_node_is_actfunc(lp) || dt_node_is_actfunc(rp)) {4014xyerror(D_OP_ACT, "operator %s operands "4015"cannot be actions\n", opstr(op));4016}40174018dt_node_type_propagate(rp, dnp); /* see K&R[A7.18] */4019dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));4020break;40214022default:4023xyerror(D_UNKNOWN, "invalid binary op %s\n", opstr(op));4024}40254026/*4027* Complete the conversion of E1[E2] to *((E1)+(E2)) that we started4028* at the top of our switch() above (see K&R[A7.3.1]). Since E2 is4029* parsed as an argument_expression_list by dt_grammar.y, we can4030* end up with a comma-separated list inside of a non-associative4031* array reference. We check for this and report an appropriate error.4032*/4033if (dnp->dn_op == DT_TOK_LBRAC && op == DT_TOK_ADD) {4034dt_node_t *pnp;40354036if (rp->dn_list != NULL) {4037xyerror(D_ARR_BADREF,4038"cannot access %s as an associative array\n",4039dt_node_name(lp, n1, sizeof (n1)));4040}40414042dnp->dn_op = DT_TOK_ADD;4043pnp = dt_node_op1(DT_TOK_DEREF, dnp);40444045/*4046* Cook callbacks are not typically permitted to allocate nodes.4047* When we do, we must insert them in the middle of an existing4048* allocation list rather than having them appended to the pcb4049* list because the sub-expression may be part of a definition.4050*/4051assert(yypcb->pcb_list == pnp);4052yypcb->pcb_list = pnp->dn_link;40534054pnp->dn_link = dnp->dn_link;4055dnp->dn_link = pnp;40564057return (dt_node_cook(pnp, DT_IDFLG_REF));4058}40594060return (dnp);4061}40624063/*ARGSUSED*/4064static dt_node_t *4065dt_cook_op3(dt_node_t *dnp, uint_t idflags)4066{4067dt_node_t *lp, *rp;4068ctf_file_t *ctfp;4069ctf_id_t type;40704071dnp->dn_expr = dt_node_cook(dnp->dn_expr, DT_IDFLG_REF);4072lp = dnp->dn_left = dt_node_cook(dnp->dn_left, DT_IDFLG_REF);4073rp = dnp->dn_right = dt_node_cook(dnp->dn_right, DT_IDFLG_REF);40744075if (!dt_node_is_scalar(dnp->dn_expr)) {4076xyerror(D_OP_SCALAR,4077"operator ?: expression must be of scalar type\n");4078}40794080if (dt_node_is_dynamic(lp) || dt_node_is_dynamic(rp)) {4081xyerror(D_OP_DYN,4082"operator ?: operands cannot be of dynamic type\n");4083}40844085/*4086* The rules for type checking for the ternary operator are complex and4087* are described in the ANSI-C spec (see K&R[A7.16]). We implement4088* the various tests in order from least to most expensive.4089*/4090if (ctf_type_compat(lp->dn_ctfp, lp->dn_type,4091rp->dn_ctfp, rp->dn_type)) {4092ctfp = lp->dn_ctfp;4093type = lp->dn_type;4094} else if (dt_node_is_integer(lp) && dt_node_is_integer(rp)) {4095dt_type_promote(lp, rp, &ctfp, &type);4096} else if (dt_node_is_strcompat(lp) && dt_node_is_strcompat(rp) &&4097(dt_node_is_string(lp) || dt_node_is_string(rp))) {4098ctfp = DT_STR_CTFP(yypcb->pcb_hdl);4099type = DT_STR_TYPE(yypcb->pcb_hdl);4100} else if (dt_node_is_ptrcompat(lp, rp, &ctfp, &type) == 0) {4101xyerror(D_OP_INCOMPAT,4102"operator ?: operands must have compatible types\n");4103}41044105if (dt_node_is_actfunc(lp) || dt_node_is_actfunc(rp)) {4106xyerror(D_OP_ACT, "action cannot be "4107"used in a conditional context\n");4108}41094110dt_node_type_assign(dnp, ctfp, type, B_FALSE);4111dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,4112dt_attr_min(lp->dn_attr, rp->dn_attr)));41134114return (dnp);4115}41164117static dt_node_t *4118dt_cook_statement(dt_node_t *dnp, uint_t idflags)4119{4120dnp->dn_expr = dt_node_cook(dnp->dn_expr, idflags);4121dt_node_attr_assign(dnp, dnp->dn_expr->dn_attr);41224123return (dnp);4124}41254126/*4127* If dn_aggfun is set, this node is a collapsed aggregation assignment (see4128* the special case code for DT_TOK_ASGN in dt_cook_op2() above), in which4129* case we cook both the tuple and the function call. If dn_aggfun is NULL,4130* this node is just a reference to the aggregation's type and attributes.4131*/4132/*ARGSUSED*/4133static dt_node_t *4134dt_cook_aggregation(dt_node_t *dnp, uint_t idflags)4135{4136dtrace_hdl_t *dtp = yypcb->pcb_hdl;41374138if (dnp->dn_aggfun != NULL) {4139dnp->dn_aggfun = dt_node_cook(dnp->dn_aggfun, DT_IDFLG_REF);4140dt_node_attr_assign(dnp, dt_ident_cook(dnp,4141dnp->dn_ident, &dnp->dn_aggtup));4142} else {4143dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),4144B_FALSE);4145dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);4146}41474148return (dnp);4149}41504151/*4152* Since D permits new variable identifiers to be instantiated in any program4153* expression, we may need to cook a clause's predicate either before or after4154* the action list depending on the program code in question. Consider:4155*4156* probe-description-list probe-description-list4157* /x++/ /x == 0/4158* { {4159* trace(x); trace(x++);4160* } }4161*4162* In the left-hand example, the predicate uses operator ++ to instantiate 'x'4163* as a variable of type int64_t. The predicate must be cooked first because4164* otherwise the statement trace(x) refers to an unknown identifier. In the4165* right-hand example, the action list uses ++ to instantiate 'x'; the action4166* list must be cooked first because otherwise the predicate x == 0 refers to4167* an unknown identifier. In order to simplify programming, we support both.4168*4169* When cooking a clause, we cook the action statements before the predicate by4170* default, since it seems more common to create or modify identifiers in the4171* action list. If cooking fails due to an unknown identifier, we attempt to4172* cook the predicate (i.e. do it first) and then go back and cook the actions.4173* If this, too, fails (or if we get an error other than D_IDENT_UNDEF) we give4174* up and report failure back to the user. There are five possible paths:4175*4176* cook actions = OK, cook predicate = OK -> OK4177* cook actions = OK, cook predicate = ERR -> ERR4178* cook actions = ERR, cook predicate = ERR -> ERR4179* cook actions = ERR, cook predicate = OK, cook actions = OK -> OK4180* cook actions = ERR, cook predicate = OK, cook actions = ERR -> ERR4181*4182* The programmer can still defeat our scheme by creating circular definition4183* dependencies between predicates and actions, as in this example clause:4184*4185* probe-description-list4186* /x++ && y == 0/4187* {4188* trace(x + y++);4189* }4190*4191* but it doesn't seem worth the complexity to handle such rare cases. The4192* user can simply use the D variable declaration syntax to work around them.4193*/4194static dt_node_t *4195dt_cook_clause(dt_node_t *dnp, uint_t idflags)4196{4197volatile int err, tries;4198jmp_buf ojb;41994200/*4201* Before assigning dn_ctxattr, temporarily assign the probe attribute4202* to 'dnp' itself to force an attribute check and minimum violation.4203*/4204dt_node_attr_assign(dnp, yypcb->pcb_pinfo.dtp_attr);4205dnp->dn_ctxattr = yypcb->pcb_pinfo.dtp_attr;42064207bcopy(yypcb->pcb_jmpbuf, ojb, sizeof (jmp_buf));4208tries = 0;42094210if (dnp->dn_pred != NULL && (err = setjmp(yypcb->pcb_jmpbuf)) != 0) {4211bcopy(ojb, yypcb->pcb_jmpbuf, sizeof (jmp_buf));4212if (tries++ != 0 || err != EDT_COMPILER || (4213yypcb->pcb_hdl->dt_errtag != dt_errtag(D_IDENT_UNDEF) &&4214yypcb->pcb_hdl->dt_errtag != dt_errtag(D_VAR_UNDEF)))4215longjmp(yypcb->pcb_jmpbuf, err);4216}42174218if (tries == 0) {4219yylabel("action list");42204221dt_node_attr_assign(dnp,4222dt_node_list_cook(&dnp->dn_acts, idflags));42234224bcopy(ojb, yypcb->pcb_jmpbuf, sizeof (jmp_buf));4225yylabel(NULL);4226}42274228if (dnp->dn_pred != NULL) {4229yylabel("predicate");42304231dnp->dn_pred = dt_node_cook(dnp->dn_pred, idflags);4232dt_node_attr_assign(dnp,4233dt_attr_min(dnp->dn_attr, dnp->dn_pred->dn_attr));42344235if (!dt_node_is_scalar(dnp->dn_pred)) {4236xyerror(D_PRED_SCALAR,4237"predicate result must be of scalar type\n");4238}42394240yylabel(NULL);4241}42424243if (tries != 0) {4244yylabel("action list");42454246dt_node_attr_assign(dnp,4247dt_node_list_cook(&dnp->dn_acts, idflags));42484249yylabel(NULL);4250}42514252return (dnp);4253}42544255/*ARGSUSED*/4256static dt_node_t *4257dt_cook_inline(dt_node_t *dnp, uint_t idflags)4258{4259dt_idnode_t *inp = dnp->dn_ident->di_iarg;4260dt_ident_t *rdp;42614262char n1[DT_TYPE_NAMELEN];4263char n2[DT_TYPE_NAMELEN];42644265assert(dnp->dn_ident->di_flags & DT_IDFLG_INLINE);4266assert(inp->din_root->dn_flags & DT_NF_COOKED);42674268/*4269* If we are inlining a translation, verify that the inline declaration4270* type exactly matches the type that is returned by the translation.4271* Otherwise just use dt_node_is_argcompat() to check the types.4272*/4273if ((rdp = dt_node_resolve(inp->din_root, DT_IDENT_XLSOU)) != NULL ||4274(rdp = dt_node_resolve(inp->din_root, DT_IDENT_XLPTR)) != NULL) {42754276ctf_file_t *lctfp = dnp->dn_ctfp;4277ctf_id_t ltype = ctf_type_resolve(lctfp, dnp->dn_type);42784279dt_xlator_t *dxp = rdp->di_data;4280ctf_file_t *rctfp = dxp->dx_dst_ctfp;4281ctf_id_t rtype = dxp->dx_dst_base;42824283if (ctf_type_kind(lctfp, ltype) == CTF_K_POINTER) {4284ltype = ctf_type_reference(lctfp, ltype);4285ltype = ctf_type_resolve(lctfp, ltype);4286}42874288if (ctf_type_compat(lctfp, ltype, rctfp, rtype) == 0) {4289dnerror(dnp, D_OP_INCOMPAT,4290"inline %s definition uses incompatible types: "4291"\"%s\" = \"%s\"\n", dnp->dn_ident->di_name,4292dt_type_name(lctfp, ltype, n1, sizeof (n1)),4293dt_type_name(rctfp, rtype, n2, sizeof (n2)));4294}42954296} else if (dt_node_is_argcompat(dnp, inp->din_root) == 0) {4297dnerror(dnp, D_OP_INCOMPAT,4298"inline %s definition uses incompatible types: "4299"\"%s\" = \"%s\"\n", dnp->dn_ident->di_name,4300dt_node_type_name(dnp, n1, sizeof (n1)),4301dt_node_type_name(inp->din_root, n2, sizeof (n2)));4302}43034304return (dnp);4305}43064307static dt_node_t *4308dt_cook_member(dt_node_t *dnp, uint_t idflags)4309{4310dnp->dn_membexpr = dt_node_cook(dnp->dn_membexpr, idflags);4311dt_node_attr_assign(dnp, dnp->dn_membexpr->dn_attr);4312return (dnp);4313}43144315/*ARGSUSED*/4316static dt_node_t *4317dt_cook_xlator(dt_node_t *dnp, uint_t idflags)4318{4319dtrace_hdl_t *dtp = yypcb->pcb_hdl;4320dt_xlator_t *dxp = dnp->dn_xlator;4321dt_node_t *mnp;43224323char n1[DT_TYPE_NAMELEN];4324char n2[DT_TYPE_NAMELEN];43254326dtrace_attribute_t attr = _dtrace_maxattr;4327ctf_membinfo_t ctm;43284329/*4330* Before cooking each translator member, we push a reference to the4331* hash containing translator-local identifiers on to pcb_globals to4332* temporarily interpose these identifiers in front of other globals.4333*/4334dt_idstack_push(&yypcb->pcb_globals, dxp->dx_locals);43354336for (mnp = dnp->dn_members; mnp != NULL; mnp = mnp->dn_list) {4337if (ctf_member_info(dxp->dx_dst_ctfp, dxp->dx_dst_type,4338mnp->dn_membname, &ctm) == CTF_ERR) {4339xyerror(D_XLATE_MEMB,4340"translator member %s is not a member of %s\n",4341mnp->dn_membname, ctf_type_name(dxp->dx_dst_ctfp,4342dxp->dx_dst_type, n1, sizeof (n1)));4343}43444345(void) dt_node_cook(mnp, DT_IDFLG_REF);4346dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,4347B_FALSE);4348attr = dt_attr_min(attr, mnp->dn_attr);43494350if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {4351xyerror(D_XLATE_INCOMPAT,4352"translator member %s definition uses "4353"incompatible types: \"%s\" = \"%s\"\n",4354mnp->dn_membname,4355dt_node_type_name(mnp, n1, sizeof (n1)),4356dt_node_type_name(mnp->dn_membexpr,4357n2, sizeof (n2)));4358}4359}43604361dt_idstack_pop(&yypcb->pcb_globals, dxp->dx_locals);43624363dxp->dx_souid.di_attr = attr;4364dxp->dx_ptrid.di_attr = attr;43654366dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);4367dt_node_attr_assign(dnp, _dtrace_defattr);43684369return (dnp);4370}43714372static void4373dt_node_provider_cmp_argv(dt_provider_t *pvp, dt_node_t *pnp, const char *kind,4374uint_t old_argc, dt_node_t *old_argv, uint_t new_argc, dt_node_t *new_argv)4375{4376dt_probe_t *prp = pnp->dn_ident->di_data;4377uint_t i;43784379char n1[DT_TYPE_NAMELEN];4380char n2[DT_TYPE_NAMELEN];43814382if (old_argc != new_argc) {4383dnerror(pnp, D_PROV_INCOMPAT,4384"probe %s:%s %s prototype mismatch:\n"4385"\t current: %u arg%s\n\tprevious: %u arg%s\n",4386pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, kind,4387new_argc, new_argc != 1 ? "s" : "",4388old_argc, old_argc != 1 ? "s" : "");4389}43904391for (i = 0; i < old_argc; i++,4392old_argv = old_argv->dn_list, new_argv = new_argv->dn_list) {4393if (ctf_type_cmp(old_argv->dn_ctfp, old_argv->dn_type,4394new_argv->dn_ctfp, new_argv->dn_type) == 0)4395continue;43964397dnerror(pnp, D_PROV_INCOMPAT,4398"probe %s:%s %s prototype argument #%u mismatch:\n"4399"\t current: %s\n\tprevious: %s\n",4400pvp->pv_desc.dtvd_name, prp->pr_ident->di_name, kind, i + 1,4401dt_node_type_name(new_argv, n1, sizeof (n1)),4402dt_node_type_name(old_argv, n2, sizeof (n2)));4403}4404}44054406/*4407* Compare a new probe declaration with an existing probe definition (either4408* from a previous declaration or cached from the kernel). If the existing4409* definition and declaration both have an input and output parameter list,4410* compare both lists. Otherwise compare only the output parameter lists.4411*/4412static void4413dt_node_provider_cmp(dt_provider_t *pvp, dt_node_t *pnp,4414dt_probe_t *old, dt_probe_t *new)4415{4416dt_node_provider_cmp_argv(pvp, pnp, "output",4417old->pr_xargc, old->pr_xargs, new->pr_xargc, new->pr_xargs);44184419if (old->pr_nargs != old->pr_xargs && new->pr_nargs != new->pr_xargs) {4420dt_node_provider_cmp_argv(pvp, pnp, "input",4421old->pr_nargc, old->pr_nargs, new->pr_nargc, new->pr_nargs);4422}44234424if (old->pr_nargs == old->pr_xargs && new->pr_nargs != new->pr_xargs) {4425if (pvp->pv_flags & DT_PROVIDER_IMPL) {4426dnerror(pnp, D_PROV_INCOMPAT,4427"provider interface mismatch: %s\n"4428"\t current: probe %s:%s has an output prototype\n"4429"\tprevious: probe %s:%s has no output prototype\n",4430pvp->pv_desc.dtvd_name, pvp->pv_desc.dtvd_name,4431new->pr_ident->di_name, pvp->pv_desc.dtvd_name,4432old->pr_ident->di_name);4433}44344435if (old->pr_ident->di_gen == yypcb->pcb_hdl->dt_gen)4436old->pr_ident->di_flags |= DT_IDFLG_ORPHAN;44374438dt_idhash_delete(pvp->pv_probes, old->pr_ident);4439dt_probe_declare(pvp, new);4440}4441}44424443static void4444dt_cook_probe(dt_node_t *dnp, dt_provider_t *pvp)4445{4446dtrace_hdl_t *dtp = yypcb->pcb_hdl;4447dt_probe_t *prp = dnp->dn_ident->di_data;44484449dt_xlator_t *dxp;4450uint_t i;44514452char n1[DT_TYPE_NAMELEN];4453char n2[DT_TYPE_NAMELEN];44544455if (prp->pr_nargs == prp->pr_xargs)4456return;44574458for (i = 0; i < prp->pr_xargc; i++) {4459dt_node_t *xnp = prp->pr_xargv[i];4460dt_node_t *nnp = prp->pr_nargv[prp->pr_mapping[i]];44614462if ((dxp = dt_xlator_lookup(dtp,4463nnp, xnp, DT_XLATE_FUZZY)) != NULL) {4464if (dt_provider_xref(dtp, pvp, dxp->dx_id) != 0)4465longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);4466continue;4467}44684469if (dt_node_is_argcompat(nnp, xnp))4470continue; /* no translator defined and none required */44714472dnerror(dnp, D_PROV_PRXLATOR, "translator for %s:%s output "4473"argument #%u from %s to %s is not defined\n",4474pvp->pv_desc.dtvd_name, dnp->dn_ident->di_name, i + 1,4475dt_node_type_name(nnp, n1, sizeof (n1)),4476dt_node_type_name(xnp, n2, sizeof (n2)));4477}4478}44794480/*ARGSUSED*/4481static dt_node_t *4482dt_cook_provider(dt_node_t *dnp, uint_t idflags)4483{4484dt_provider_t *pvp = dnp->dn_provider;4485dt_node_t *pnp;44864487/*4488* If we're declaring a provider for the first time and it is unknown4489* to dtrace(7D), insert the probe definitions into the provider's hash.4490* If we're redeclaring a known provider, verify the interface matches.4491*/4492for (pnp = dnp->dn_probes; pnp != NULL; pnp = pnp->dn_list) {4493const char *probename = pnp->dn_ident->di_name;4494dt_probe_t *prp = dt_probe_lookup(pvp, probename);44954496assert(pnp->dn_kind == DT_NODE_PROBE);44974498if (prp != NULL && dnp->dn_provred) {4499dt_node_provider_cmp(pvp, pnp,4500prp, pnp->dn_ident->di_data);4501} else if (prp == NULL && dnp->dn_provred) {4502dnerror(pnp, D_PROV_INCOMPAT,4503"provider interface mismatch: %s\n"4504"\t current: probe %s:%s defined\n"4505"\tprevious: probe %s:%s not defined\n",4506dnp->dn_provname, dnp->dn_provname,4507probename, dnp->dn_provname, probename);4508} else if (prp != NULL) {4509dnerror(pnp, D_PROV_PRDUP, "probe redeclared: %s:%s\n",4510dnp->dn_provname, probename);4511} else4512dt_probe_declare(pvp, pnp->dn_ident->di_data);45134514dt_cook_probe(pnp, pvp);4515}45164517return (dnp);4518}45194520/*ARGSUSED*/4521static dt_node_t *4522dt_cook_none(dt_node_t *dnp, uint_t idflags)4523{4524return (dnp);4525}45264527static dt_node_t *(* const dt_cook_funcs[])(dt_node_t *, uint_t) = {4528[DT_NODE_FREE] = dt_cook_none,4529[DT_NODE_INT] = dt_cook_none,4530[DT_NODE_STRING] = dt_cook_none,4531[DT_NODE_IDENT] = dt_cook_ident,4532[DT_NODE_VAR] = dt_cook_var,4533[DT_NODE_SYM] = dt_cook_none,4534[DT_NODE_TYPE] = dt_cook_none,4535[DT_NODE_FUNC] = dt_cook_func,4536[DT_NODE_OP1] = dt_cook_op1,4537[DT_NODE_OP2] = dt_cook_op2,4538[DT_NODE_OP3] = dt_cook_op3,4539[DT_NODE_DEXPR] = dt_cook_statement,4540[DT_NODE_DFUNC] = dt_cook_statement,4541[DT_NODE_AGG] = dt_cook_aggregation,4542[DT_NODE_PDESC] = dt_cook_none,4543[DT_NODE_CLAUSE] = dt_cook_clause,4544[DT_NODE_INLINE] = dt_cook_inline,4545[DT_NODE_MEMBER] = dt_cook_member,4546[DT_NODE_XLATOR] = dt_cook_xlator,4547[DT_NODE_PROBE] = dt_cook_none,4548[DT_NODE_PROVIDER] = dt_cook_provider,4549[DT_NODE_PROG] = dt_cook_none,4550[DT_NODE_IF] = dt_cook_none,4551};45524553/*4554* Recursively cook the parse tree starting at the specified node. The idflags4555* parameter is used to indicate the type of reference (r/w) and is applied to4556* the resulting identifier if it is a D variable or D aggregation.4557*/4558dt_node_t *4559dt_node_cook(dt_node_t *dnp, uint_t idflags)4560{4561int oldlineno = yylineno;45624563yylineno = dnp->dn_line;45644565assert(dnp->dn_kind <4566sizeof (dt_cook_funcs) / sizeof (dt_cook_funcs[0]));4567dnp = dt_cook_funcs[dnp->dn_kind](dnp, idflags);4568dnp->dn_flags |= DT_NF_COOKED;45694570if (dnp->dn_kind == DT_NODE_VAR || dnp->dn_kind == DT_NODE_AGG)4571dnp->dn_ident->di_flags |= idflags;45724573yylineno = oldlineno;4574return (dnp);4575}45764577dtrace_attribute_t4578dt_node_list_cook(dt_node_t **pnp, uint_t idflags)4579{4580dtrace_attribute_t attr = _dtrace_defattr;4581dt_node_t *dnp, *nnp;45824583for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {4584nnp = dnp->dn_list;4585dnp = *pnp = dt_node_cook(dnp, idflags);4586attr = dt_attr_min(attr, dnp->dn_attr);4587dnp->dn_list = nnp;4588pnp = &dnp->dn_list;4589}45904591return (attr);4592}45934594void4595dt_node_list_free(dt_node_t **pnp)4596{4597dt_node_t *dnp, *nnp;45984599for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {4600nnp = dnp->dn_list;4601dt_node_free(dnp);4602}46034604if (pnp != NULL)4605*pnp = NULL;4606}46074608void4609dt_node_link_free(dt_node_t **pnp)4610{4611dt_node_t *dnp, *nnp;46124613for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {4614nnp = dnp->dn_link;4615dt_node_free(dnp);4616}46174618for (dnp = (pnp != NULL ? *pnp : NULL); dnp != NULL; dnp = nnp) {4619nnp = dnp->dn_link;4620free(dnp);4621}46224623if (pnp != NULL)4624*pnp = NULL;4625}46264627dt_node_t *4628dt_node_link(dt_node_t *lp, dt_node_t *rp)4629{4630dt_node_t *dnp;46314632if (lp == NULL)4633return (rp);4634else if (rp == NULL)4635return (lp);46364637for (dnp = lp; dnp->dn_list != NULL; dnp = dnp->dn_list)4638continue;46394640dnp->dn_list = rp;4641return (lp);4642}46434644/*4645* Compute the DOF dtrace_diftype_t representation of a node's type. This is4646* called from a variety of places in the library so it cannot assume yypcb4647* is valid: any references to handle-specific data must be made through 'dtp'.4648*/4649void4650dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)4651{4652if (dnp->dn_ctfp == DT_STR_CTFP(dtp) &&4653dnp->dn_type == DT_STR_TYPE(dtp)) {4654tp->dtdt_kind = DIF_TYPE_STRING;4655tp->dtdt_ckind = CTF_K_UNKNOWN;4656} else {4657tp->dtdt_kind = DIF_TYPE_CTF;4658tp->dtdt_ckind = ctf_type_kind(dnp->dn_ctfp,4659ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));4660}46614662tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?4663(dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :4664DIF_TF_BYREF : 0;4665tp->dtdt_pad = 0;4666tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);4667}46684669/*4670* Output the parse tree as D. The "-xtree=8" argument will call this4671* function to print out the program after any syntactic sugar4672* transformations have been applied (e.g. to implement "if"). The4673* resulting output can be used to understand the transformations4674* applied by these features, or to run such a script on a system that4675* does not support these features4676*4677* Note that the output does not express precisely the same program as4678* the input. In particular:4679* - Only the clauses are output. #pragma options, variable4680* declarations, etc. are excluded.4681* - Command argument substitution has already been done, so the output4682* will not contain e.g. $$1, but rather the substituted string.4683*/4684void4685dt_printd(dt_node_t *dnp, FILE *fp, int depth)4686{4687dt_node_t *arg;46884689switch (dnp->dn_kind) {4690case DT_NODE_INT:4691(void) fprintf(fp, "0x%llx", (u_longlong_t)dnp->dn_value);4692if (!(dnp->dn_flags & DT_NF_SIGNED))4693(void) fprintf(fp, "u");4694break;46954696case DT_NODE_STRING: {4697char *escd = strchr2esc(dnp->dn_string, strlen(dnp->dn_string));4698(void) fprintf(fp, "\"%s\"", escd);4699free(escd);4700break;4701}47024703case DT_NODE_IDENT:4704(void) fprintf(fp, "%s", dnp->dn_string);4705break;47064707case DT_NODE_VAR:4708(void) fprintf(fp, "%s%s",4709(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" :4710(dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "",4711dnp->dn_ident->di_name);47124713if (dnp->dn_args != NULL) {4714(void) fprintf(fp, "[");47154716for (arg = dnp->dn_args; arg != NULL;4717arg = arg->dn_list) {4718dt_printd(arg, fp, 0);4719if (arg->dn_list != NULL)4720(void) fprintf(fp, ", ");4721}47224723(void) fprintf(fp, "]");4724}4725break;47264727case DT_NODE_SYM: {4728const dtrace_syminfo_t *dts = dnp->dn_ident->di_data;4729(void) fprintf(fp, "%s`%s", dts->dts_object, dts->dts_name);4730break;4731}4732case DT_NODE_FUNC:4733(void) fprintf(fp, "%s(", dnp->dn_ident->di_name);47344735for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {4736dt_printd(arg, fp, 0);4737if (arg->dn_list != NULL)4738(void) fprintf(fp, ", ");4739}4740(void) fprintf(fp, ")");4741break;47424743case DT_NODE_OP1:4744(void) fprintf(fp, "%s(", opstr(dnp->dn_op));4745dt_printd(dnp->dn_child, fp, 0);4746(void) fprintf(fp, ")");4747break;47484749case DT_NODE_OP2:4750(void) fprintf(fp, "(");4751dt_printd(dnp->dn_left, fp, 0);4752if (dnp->dn_op == DT_TOK_LPAR) {4753(void) fprintf(fp, ")");4754dt_printd(dnp->dn_right, fp, 0);4755break;4756}4757if (dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT ||4758dnp->dn_op == DT_TOK_LBRAC)4759(void) fprintf(fp, "%s", opstr(dnp->dn_op));4760else4761(void) fprintf(fp, " %s ", opstr(dnp->dn_op));4762dt_printd(dnp->dn_right, fp, 0);4763if (dnp->dn_op == DT_TOK_LBRAC) {4764dt_node_t *ln = dnp->dn_right;4765while (ln->dn_list != NULL) {4766(void) fprintf(fp, ", ");4767dt_printd(ln->dn_list, fp, depth);4768ln = ln->dn_list;4769}4770(void) fprintf(fp, "]");4771}4772(void) fprintf(fp, ")");4773break;47744775case DT_NODE_OP3:4776(void) fprintf(fp, "(");4777dt_printd(dnp->dn_expr, fp, 0);4778(void) fprintf(fp, " ? ");4779dt_printd(dnp->dn_left, fp, 0);4780(void) fprintf(fp, " : ");4781dt_printd(dnp->dn_right, fp, 0);4782(void) fprintf(fp, ")");4783break;47844785case DT_NODE_DEXPR:4786case DT_NODE_DFUNC:4787(void) fprintf(fp, "%*s", depth * 8, "");4788dt_printd(dnp->dn_expr, fp, depth + 1);4789(void) fprintf(fp, ";\n");4790break;47914792case DT_NODE_PDESC:4793(void) fprintf(fp, "%s:%s:%s:%s",4794dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,4795dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name);4796break;47974798case DT_NODE_CLAUSE:4799for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list) {4800dt_printd(arg, fp, 0);4801if (arg->dn_list != NULL)4802(void) fprintf(fp, ",");4803(void) fprintf(fp, "\n");4804}48054806if (dnp->dn_pred != NULL) {4807(void) fprintf(fp, "/");4808dt_printd(dnp->dn_pred, fp, 0);4809(void) fprintf(fp, "/\n");4810}48114812(void) fprintf(fp, "{\n");4813for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list)4814dt_printd(arg, fp, depth + 1);4815(void) fprintf(fp, "}\n");4816(void) fprintf(fp, "\n");4817break;48184819case DT_NODE_IF:4820(void) fprintf(fp, "%*sif (", depth * 8, "");4821dt_printd(dnp->dn_conditional, fp, 0);4822(void) fprintf(fp, ") {\n");48234824for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list)4825dt_printd(arg, fp, depth + 1);4826if (dnp->dn_alternate_body == NULL) {4827(void) fprintf(fp, "%*s}\n", depth * 8, "");4828} else {4829(void) fprintf(fp, "%*s} else {\n", depth * 8, "");4830for (arg = dnp->dn_alternate_body; arg != NULL;4831arg = arg->dn_list)4832dt_printd(arg, fp, depth + 1);4833(void) fprintf(fp, "%*s}\n", depth * 8, "");4834}48354836break;48374838default:4839(void) fprintf(fp, "/* bad node %p, kind %d */\n",4840(void *)dnp, dnp->dn_kind);4841}4842}48434844void4845dt_node_printr(dt_node_t *dnp, FILE *fp, int depth)4846{4847char n[DT_TYPE_NAMELEN], buf[BUFSIZ], a[8];4848const dtrace_syminfo_t *dts;4849const dt_idnode_t *inp;4850dt_node_t *arg;48514852(void) fprintf(fp, "%*s", depth * 2, "");4853(void) dt_attr_str(dnp->dn_attr, a, sizeof (a));48544855if (dnp->dn_ctfp != NULL && dnp->dn_type != CTF_ERR &&4856ctf_type_name(dnp->dn_ctfp, dnp->dn_type, n, sizeof (n)) != NULL) {4857(void) snprintf(buf, BUFSIZ, "type=<%s> attr=%s flags=", n, a);4858} else {4859(void) snprintf(buf, BUFSIZ, "type=<%ld> attr=%s flags=",4860dnp->dn_type, a);4861}48624863if (dnp->dn_flags != 0) {4864n[0] = '\0';4865if (dnp->dn_flags & DT_NF_SIGNED)4866(void) strcat(n, ",SIGN");4867if (dnp->dn_flags & DT_NF_COOKED)4868(void) strcat(n, ",COOK");4869if (dnp->dn_flags & DT_NF_REF)4870(void) strcat(n, ",REF");4871if (dnp->dn_flags & DT_NF_LVALUE)4872(void) strcat(n, ",LVAL");4873if (dnp->dn_flags & DT_NF_WRITABLE)4874(void) strcat(n, ",WRITE");4875if (dnp->dn_flags & DT_NF_BITFIELD)4876(void) strcat(n, ",BITF");4877if (dnp->dn_flags & DT_NF_USERLAND)4878(void) strcat(n, ",USER");4879(void) strcat(buf, n + 1);4880} else4881(void) strcat(buf, "0");48824883switch (dnp->dn_kind) {4884case DT_NODE_FREE:4885(void) fprintf(fp, "FREE <node %p>\n", (void *)dnp);4886break;48874888case DT_NODE_INT:4889(void) fprintf(fp, "INT 0x%llx (%s)\n",4890(u_longlong_t)dnp->dn_value, buf);4891break;48924893case DT_NODE_STRING:4894(void) fprintf(fp, "STRING \"%s\" (%s)\n", dnp->dn_string, buf);4895break;48964897case DT_NODE_IDENT:4898(void) fprintf(fp, "IDENT %s (%s)\n", dnp->dn_string, buf);4899break;49004901case DT_NODE_VAR:4902(void) fprintf(fp, "VARIABLE %s%s (%s)\n",4903(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL) ? "this->" :4904(dnp->dn_ident->di_flags & DT_IDFLG_TLS) ? "self->" : "",4905dnp->dn_ident->di_name, buf);49064907if (dnp->dn_args != NULL)4908(void) fprintf(fp, "%*s[\n", depth * 2, "");49094910for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {4911dt_node_printr(arg, fp, depth + 1);4912if (arg->dn_list != NULL)4913(void) fprintf(fp, "%*s,\n", depth * 2, "");4914}49154916if (dnp->dn_args != NULL)4917(void) fprintf(fp, "%*s]\n", depth * 2, "");4918break;49194920case DT_NODE_SYM:4921dts = dnp->dn_ident->di_data;4922(void) fprintf(fp, "SYMBOL %s`%s (%s)\n",4923dts->dts_object, dts->dts_name, buf);4924break;49254926case DT_NODE_TYPE:4927if (dnp->dn_string != NULL) {4928(void) fprintf(fp, "TYPE (%s) %s\n",4929buf, dnp->dn_string);4930} else4931(void) fprintf(fp, "TYPE (%s)\n", buf);4932break;49334934case DT_NODE_FUNC:4935(void) fprintf(fp, "FUNC %s (%s)\n",4936dnp->dn_ident->di_name, buf);49374938for (arg = dnp->dn_args; arg != NULL; arg = arg->dn_list) {4939dt_node_printr(arg, fp, depth + 1);4940if (arg->dn_list != NULL)4941(void) fprintf(fp, "%*s,\n", depth * 2, "");4942}4943break;49444945case DT_NODE_OP1:4946(void) fprintf(fp, "OP1 %s (%s)\n", opstr(dnp->dn_op), buf);4947dt_node_printr(dnp->dn_child, fp, depth + 1);4948break;49494950case DT_NODE_OP2:4951(void) fprintf(fp, "OP2 %s (%s)\n", opstr(dnp->dn_op), buf);4952dt_node_printr(dnp->dn_left, fp, depth + 1);4953dt_node_printr(dnp->dn_right, fp, depth + 1);4954if (dnp->dn_op == DT_TOK_LBRAC) {4955dt_node_t *ln = dnp->dn_right;4956while (ln->dn_list != NULL) {4957dt_node_printr(ln->dn_list, fp, depth + 1);4958ln = ln->dn_list;4959}4960}4961break;49624963case DT_NODE_OP3:4964(void) fprintf(fp, "OP3 (%s)\n", buf);4965dt_node_printr(dnp->dn_expr, fp, depth + 1);4966(void) fprintf(fp, "%*s?\n", depth * 2, "");4967dt_node_printr(dnp->dn_left, fp, depth + 1);4968(void) fprintf(fp, "%*s:\n", depth * 2, "");4969dt_node_printr(dnp->dn_right, fp, depth + 1);4970break;49714972case DT_NODE_DEXPR:4973case DT_NODE_DFUNC:4974(void) fprintf(fp, "D EXPRESSION attr=%s\n", a);4975dt_node_printr(dnp->dn_expr, fp, depth + 1);4976break;49774978case DT_NODE_AGG:4979(void) fprintf(fp, "AGGREGATE @%s attr=%s [\n",4980dnp->dn_ident->di_name, a);49814982for (arg = dnp->dn_aggtup; arg != NULL; arg = arg->dn_list) {4983dt_node_printr(arg, fp, depth + 1);4984if (arg->dn_list != NULL)4985(void) fprintf(fp, "%*s,\n", depth * 2, "");4986}49874988if (dnp->dn_aggfun) {4989(void) fprintf(fp, "%*s] = ", depth * 2, "");4990dt_node_printr(dnp->dn_aggfun, fp, depth + 1);4991} else4992(void) fprintf(fp, "%*s]\n", depth * 2, "");49934994if (dnp->dn_aggfun)4995(void) fprintf(fp, "%*s)\n", depth * 2, "");4996break;49974998case DT_NODE_PDESC:4999(void) fprintf(fp, "PDESC %s:%s:%s:%s [%u]\n",5000dnp->dn_desc->dtpd_provider, dnp->dn_desc->dtpd_mod,5001dnp->dn_desc->dtpd_func, dnp->dn_desc->dtpd_name,5002dnp->dn_desc->dtpd_id);5003break;50045005case DT_NODE_CLAUSE:5006(void) fprintf(fp, "CLAUSE attr=%s\n", a);50075008for (arg = dnp->dn_pdescs; arg != NULL; arg = arg->dn_list)5009dt_node_printr(arg, fp, depth + 1);50105011(void) fprintf(fp, "%*sCTXATTR %s\n", depth * 2, "",5012dt_attr_str(dnp->dn_ctxattr, a, sizeof (a)));50135014if (dnp->dn_pred != NULL) {5015(void) fprintf(fp, "%*sPREDICATE /\n", depth * 2, "");5016dt_node_printr(dnp->dn_pred, fp, depth + 1);5017(void) fprintf(fp, "%*s/\n", depth * 2, "");5018}50195020for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list)5021dt_node_printr(arg, fp, depth + 1);5022(void) fprintf(fp, "\n");5023break;50245025case DT_NODE_INLINE:5026inp = dnp->dn_ident->di_iarg;50275028(void) fprintf(fp, "INLINE %s (%s)\n",5029dnp->dn_ident->di_name, buf);5030dt_node_printr(inp->din_root, fp, depth + 1);5031break;50325033case DT_NODE_MEMBER:5034(void) fprintf(fp, "MEMBER %s (%s)\n", dnp->dn_membname, buf);5035if (dnp->dn_membexpr)5036dt_node_printr(dnp->dn_membexpr, fp, depth + 1);5037break;50385039case DT_NODE_XLATOR:5040(void) fprintf(fp, "XLATOR (%s)", buf);50415042if (ctf_type_name(dnp->dn_xlator->dx_src_ctfp,5043dnp->dn_xlator->dx_src_type, n, sizeof (n)) != NULL)5044(void) fprintf(fp, " from <%s>", n);50455046if (ctf_type_name(dnp->dn_xlator->dx_dst_ctfp,5047dnp->dn_xlator->dx_dst_type, n, sizeof (n)) != NULL)5048(void) fprintf(fp, " to <%s>", n);50495050(void) fprintf(fp, "\n");50515052for (arg = dnp->dn_members; arg != NULL; arg = arg->dn_list)5053dt_node_printr(arg, fp, depth + 1);5054break;50555056case DT_NODE_PROBE:5057(void) fprintf(fp, "PROBE %s\n", dnp->dn_ident->di_name);5058break;50595060case DT_NODE_PROVIDER:5061(void) fprintf(fp, "PROVIDER %s (%s)\n",5062dnp->dn_provname, dnp->dn_provred ? "redecl" : "decl");5063for (arg = dnp->dn_probes; arg != NULL; arg = arg->dn_list)5064dt_node_printr(arg, fp, depth + 1);5065break;50665067case DT_NODE_PROG:5068(void) fprintf(fp, "PROGRAM attr=%s\n", a);5069for (arg = dnp->dn_list; arg != NULL; arg = arg->dn_list)5070dt_node_printr(arg, fp, depth + 1);5071break;50725073case DT_NODE_IF:5074(void) fprintf(fp, "IF attr=%s CONDITION:\n", a);50755076dt_node_printr(dnp->dn_conditional, fp, depth + 1);50775078(void) fprintf(fp, "%*sIF BODY: \n", depth * 2, "");5079for (arg = dnp->dn_body; arg != NULL; arg = arg->dn_list)5080dt_node_printr(arg, fp, depth + 1);50815082if (dnp->dn_alternate_body != NULL) {5083(void) fprintf(fp, "%*sIF ELSE: \n", depth * 2, "");5084for (arg = dnp->dn_alternate_body; arg != NULL;5085arg = arg->dn_list)5086dt_node_printr(arg, fp, depth + 1);5087}50885089break;50905091default:5092(void) fprintf(fp, "<bad node %p, kind %d>\n",5093(void *)dnp, dnp->dn_kind);5094}5095}50965097int5098dt_node_root(dt_node_t *dnp)5099{5100yypcb->pcb_root = dnp;5101return (0);5102}51035104/*PRINTFLIKE3*/5105void5106dnerror(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...)5107{5108int oldlineno = yylineno;5109va_list ap;51105111yylineno = dnp->dn_line;51125113va_start(ap, format);5114xyvwarn(tag, format, ap);5115va_end(ap);51165117yylineno = oldlineno;5118longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);5119}51205121/*PRINTFLIKE3*/5122void5123dnwarn(const dt_node_t *dnp, dt_errtag_t tag, const char *format, ...)5124{5125int oldlineno = yylineno;5126va_list ap;51275128yylineno = dnp->dn_line;51295130va_start(ap, format);5131xyvwarn(tag, format, ap);5132va_end(ap);51335134yylineno = oldlineno;5135}51365137/*PRINTFLIKE2*/5138void5139xyerror(dt_errtag_t tag, const char *format, ...)5140{5141va_list ap;51425143va_start(ap, format);5144xyvwarn(tag, format, ap);5145va_end(ap);51465147longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);5148}51495150/*PRINTFLIKE2*/5151void5152xywarn(dt_errtag_t tag, const char *format, ...)5153{5154va_list ap;51555156va_start(ap, format);5157xyvwarn(tag, format, ap);5158va_end(ap);5159}51605161void5162xyvwarn(dt_errtag_t tag, const char *format, va_list ap)5163{5164if (yypcb == NULL)5165return; /* compiler is not currently active: act as a no-op */51665167dt_set_errmsg(yypcb->pcb_hdl, dt_errtag(tag), yypcb->pcb_region,5168yypcb->pcb_filetag, yypcb->pcb_fileptr ? yylineno : 0, format, ap);5169}51705171/*PRINTFLIKE1*/5172void5173yyerror(const char *format, ...)5174{5175va_list ap;51765177va_start(ap, format);5178yyvwarn(format, ap);5179va_end(ap);51805181longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER);5182}51835184/*PRINTFLIKE1*/5185void5186yywarn(const char *format, ...)5187{5188va_list ap;51895190va_start(ap, format);5191yyvwarn(format, ap);5192va_end(ap);5193}51945195void5196yyvwarn(const char *format, va_list ap)5197{5198if (yypcb == NULL)5199return; /* compiler is not currently active: act as a no-op */52005201dt_set_errmsg(yypcb->pcb_hdl, dt_errtag(D_SYNTAX), yypcb->pcb_region,5202yypcb->pcb_filetag, yypcb->pcb_fileptr ? yylineno : 0, format, ap);52035204if (strchr(format, '\n') == NULL) {5205dtrace_hdl_t *dtp = yypcb->pcb_hdl;5206size_t len = strlen(dtp->dt_errmsg);5207char *p, *s = dtp->dt_errmsg + len;5208size_t n = sizeof (dtp->dt_errmsg) - len;52095210if (yytext[0] == '\0')5211(void) snprintf(s, n, " near end of input");5212else if (yytext[0] == '\n')5213(void) snprintf(s, n, " near end of line");5214else {5215if ((p = strchr(yytext, '\n')) != NULL)5216*p = '\0'; /* crop at newline */5217(void) snprintf(s, n, " near \"%s\"", yytext);5218}5219}5220}52215222void5223yylabel(const char *label)5224{5225dt_dprintf("set label to <%s>\n", label ? label : "NULL");5226yypcb->pcb_region = label;5227}52285229int5230yywrap(void)5231{5232return (1); /* indicate that lex should return a zero token for EOF */5233}523452355236