📄 dt_parser.c
字号:
bzero(&idn, sizeof (dt_node_t)); idp = dt_idhash_lookup(dhp, dsp->ds_ident); if (idp != NULL) (void) dt_ident_cook(&idn, idp, NULL); /* * Cache some attributes of the decl to make the rest of this * code simpler: if the decl is an array which is subscripted * by a type rather than an integer, then it's an associative * array (assc). We then expect to match either DT_IDENT_ARRAY * for associative arrays or DT_IDENT_SCALAR for anything else. */ assc = ddp->dd_kind == CTF_K_ARRAY && ddp->dd_node->dn_kind == DT_NODE_TYPE; idkind = assc ? DT_IDENT_ARRAY : DT_IDENT_SCALAR; if (assc) { if (class == DT_DC_THIS) { xyerror(D_DECL_LOCASSC, "associative arrays " "may not be declared as local variables:" " %s\n", dsp->ds_ident); } if (dt_decl_type(ddp->dd_next, &dtt) != 0) longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); } if (idp != NULL && (idp->di_kind != idkind || ctf_type_cmp(dtt.dtt_ctfp, dtt.dtt_type, idn.dn_ctfp, idn.dn_type) != 0)) { xyerror(D_DECL_IDRED, "identifier redeclared: %s\n" "\t current: %s %s\n\tprevious: %s %s\n", dsp->ds_ident, dt_idkind_name(idkind), dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, n1, sizeof (n1)), dt_idkind_name(idp->di_kind), dt_node_type_name(&idn, n2, sizeof (n2))); } else if (idp != NULL && assc) { const dt_idsig_t *isp = idp->di_data; dt_node_t *dnp = ddp->dd_node; int argc = 0; for (; dnp != NULL; dnp = dnp->dn_list, argc++) { const dt_node_t *pnp = &isp->dis_args[argc]; if (ctf_type_cmp(dnp->dn_ctfp, dnp->dn_type, pnp->dn_ctfp, pnp->dn_type) == 0) continue; xyerror(D_DECL_IDRED, "identifier redeclared: %s\n" "\t current: %s, key #%d of type %s\n" "\tprevious: %s, key #%d of type %s\n", dsp->ds_ident, dt_idkind_name(idkind), argc + 1, dt_node_type_name(dnp, n1, sizeof (n1)), dt_idkind_name(idp->di_kind), argc + 1, dt_node_type_name(pnp, n2, sizeof (n2))); } if (isp->dis_argc != argc) { xyerror(D_DECL_IDRED, "identifier redeclared: %s\n" "\t current: %s of %s, tuple length %d\n" "\tprevious: %s of %s, tuple length %d\n", dsp->ds_ident, dt_idkind_name(idkind), dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, n1, sizeof (n1)), argc, dt_idkind_name(idp->di_kind), dt_node_type_name(&idn, n2, sizeof (n2)), isp->dis_argc); } } else if (idp == NULL) { type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type); kind = ctf_type_kind(dtt.dtt_ctfp, type); switch (kind) { case CTF_K_INTEGER: if (ctf_type_encoding(dtt.dtt_ctfp, type, &cte) == 0 && IS_VOID(cte)) { xyerror(D_DECL_VOIDOBJ, "cannot have " "void object: %s\n", dsp->ds_ident); } break; case CTF_K_STRUCT: case CTF_K_UNION: if (ctf_type_size(dtt.dtt_ctfp, type) != 0) break; /* proceed to declaring */ /*FALLTHRU*/ case CTF_K_FORWARD: xyerror(D_DECL_INCOMPLETE, "incomplete struct/union/enum %s: %s\n", dt_type_name(dtt.dtt_ctfp, dtt.dtt_type, n1, sizeof (n1)), dsp->ds_ident); /*NOTREACHED*/ } if ((kind == CTF_K_STRUCT || kind == CTF_K_UNION || kind == CTF_K_ARRAY) && class == DT_DC_THIS) { xyerror(D_VAR_UNSUP, "clause-local variable" " cannot be used with struct/union/array" " type: %s\n", dsp->ds_ident); } if (dt_idhash_nextid(dhp, &id) == -1) { xyerror(D_ID_OFLOW, "cannot create %s: limit " "on number of %s variables exceeded\n", dsp->ds_ident, dt_idhash_name(dhp)); } dt_dprintf("declare %s %s variable %s, id=%u\n", dt_idhash_name(dhp), dt_idkind_name(idkind), dsp->ds_ident, id); idp = dt_idhash_insert(dhp, dsp->ds_ident, idkind, idflags | DT_IDFLG_WRITE | DT_IDFLG_DECL, id, _dtrace_defattr, 0, assc ? &dt_idops_assc : &dt_idops_thaw, NULL, dtp->dt_gen); if (idp == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); dt_ident_type_assign(idp, dtt.dtt_ctfp, dtt.dtt_type); /* * If we are declaring an associative array, use our * fake parse node to cook the new assoc identifier. * This will force the ident code to instantiate the * array type signature corresponding to the list of * types pointed to by ddp->dd_node. We also reset * the identifier's attributes based upon the result. */ if (assc) { idp->di_attr = dt_ident_cook(&idn, idp, &ddp->dd_node); } } } } /* end of switch */ free(dsp->ds_ident); dsp->ds_ident = NULL; return (NULL);}dt_node_t *dt_node_func(dt_node_t *dnp, dt_node_t *args){ dt_ident_t *idp; if (dnp->dn_kind != DT_NODE_IDENT) { xyerror(D_FUNC_IDENT, "function designator is not of function type\n"); } idp = dt_idhash_lookup(yypcb->pcb_hdl->dt_globals, dnp->dn_string); if (idp == NULL) { xyerror(D_FUNC_UNDEF, "undefined function name: %s\n", dnp->dn_string); } if (idp->di_kind != DT_IDENT_FUNC && idp->di_kind != DT_IDENT_AGGFUNC && idp->di_kind != DT_IDENT_ACTFUNC) { xyerror(D_FUNC_IDKIND, "%s '%s' may not be referenced as a " "function\n", dt_idkind_name(idp->di_kind), idp->di_name); } free(dnp->dn_string); dnp->dn_string = NULL; dnp->dn_kind = DT_NODE_FUNC; dnp->dn_flags &= ~DT_NF_COOKED; dnp->dn_ident = idp; dnp->dn_args = args; dnp->dn_list = NULL; return (dnp);}/* * The offsetof() function is special because it takes a type name as an * argument. It does not actually construct its own node; after looking up the * structure or union offset, we just return an integer node with the offset. */dt_node_t *dt_node_offsetof(dt_decl_t *ddp, char *s){ dtrace_typeinfo_t dtt; dt_node_t dn; char *name; int err; ctf_membinfo_t ctm; ctf_id_t type; uint_t kind; name = alloca(strlen(s) + 1); (void) strcpy(name, s); free(s); err = dt_decl_type(ddp, &dtt); dt_decl_free(ddp); if (err != 0) longjmp(yypcb->pcb_jmpbuf, EDT_COMPILER); type = ctf_type_resolve(dtt.dtt_ctfp, dtt.dtt_type); kind = ctf_type_kind(dtt.dtt_ctfp, type); if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) { xyerror(D_OFFSETOF_TYPE, "offsetof operand must be a struct or union type\n"); } if (ctf_member_info(dtt.dtt_ctfp, type, name, &ctm) == CTF_ERR) { xyerror(D_UNKNOWN, "failed to determine offset of %s: %s\n", name, ctf_errmsg(ctf_errno(dtt.dtt_ctfp))); } bzero(&dn, sizeof (dn)); dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type); if (dn.dn_flags & DT_NF_BITFIELD) { xyerror(D_OFFSETOF_BITFIELD, "cannot take offset of a bit-field: %s\n", name); } return (dt_node_int(ctm.ctm_offset / NBBY));}dt_node_t *dt_node_op1(int op, dt_node_t *cp){ dt_node_t *dnp; if (cp->dn_kind == DT_NODE_INT) { switch (op) { case DT_TOK_INEG: /* * If we're negating an unsigned integer, zero out any * extra top bits to truncate the value to the size of * the effective type determined by dt_node_int(). */ cp->dn_value = -cp->dn_value; if (!(cp->dn_flags & DT_NF_SIGNED)) { cp->dn_value &= ~0ULL >> (64 - dt_node_type_size(cp) * NBBY); } /*FALLTHRU*/ case DT_TOK_IPOS: return (cp); case DT_TOK_BNEG: cp->dn_value = ~cp->dn_value; return (cp); case DT_TOK_LNEG: cp->dn_value = !cp->dn_value; return (cp); } } /* * If sizeof is applied to a type_name or string constant, we can * transform 'cp' into an integer constant in the node construction * pass so that it can then be used for arithmetic in this pass. */ if (op == DT_TOK_SIZEOF && (cp->dn_kind == DT_NODE_STRING || cp->dn_kind == DT_NODE_TYPE)) { dtrace_hdl_t *dtp = yypcb->pcb_hdl; size_t size = dt_node_type_size(cp); if (size == 0) { xyerror(D_SIZEOF_TYPE, "cannot apply sizeof to an " "operand of unknown size\n"); } dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp, ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t")); cp->dn_kind = DT_NODE_INT; cp->dn_op = DT_TOK_INT; cp->dn_value = size; return (cp); } dnp = dt_node_alloc(DT_NODE_OP1); assert(op <= USHRT_MAX); dnp->dn_op = (ushort_t)op; dnp->dn_child = cp; return (dnp);}dt_node_t *dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp){ dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_node_t *dnp; /* * First we check for operations that are illegal -- namely those that * might result in integer division by zero, and abort if one is found. */ if (rp->dn_kind == DT_NODE_INT && rp->dn_value == 0 && (op == DT_TOK_MOD || op == DT_TOK_DIV || op == DT_TOK_MOD_EQ || op == DT_TOK_DIV_EQ)) xyerror(D_DIV_ZERO, "expression contains division by zero\n"); /* * If both children are immediate values, we can just perform inline * calculation and return a new immediate node with the result. */ if (lp->dn_kind == DT_NODE_INT && rp->dn_kind == DT_NODE_INT) { uintmax_t l = lp->dn_value; uintmax_t r = rp->dn_value; dnp = dt_node_int(0); /* allocate new integer node for result */ switch (op) { case DT_TOK_LOR: dnp->dn_value = l || r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_LXOR: dnp->dn_value = (l != 0) ^ (r != 0); dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_LAND: dnp->dn_value = l && r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_BOR: dnp->dn_value = l | r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_XOR: dnp->dn_value = l ^ r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_BAND: dnp->dn_value = l & r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_EQU: dnp->dn_value = l == r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_NEQ: dnp->dn_value = l != r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_LT: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l < (intmax_t)r; else dnp->dn_value = l < r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_LE: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l <= (intmax_t)r; else dnp->dn_value = l <= r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_GT: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l > (intmax_t)r; else dnp->dn_value = l > r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_GE: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l >= (intmax_t)r; else dnp->dn_value = l >= r; dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp)); break; case DT_TOK_LSH: dnp->dn_value = l << r; dt_node_type_propagate(lp, dnp); dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr)); break; case DT_TOK_RSH: dnp->dn_value = l >> r; dt_node_type_propagate(lp, dnp); dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr)); break; case DT_TOK_ADD: dnp->dn_value = l + r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_SUB: dnp->dn_value = l - r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_MUL: dnp->dn_value = l * r; dt_node_promote(lp, rp, dnp); break; case DT_TOK_DIV: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l / (intmax_t)r; else dnp->dn_value = l / r; break; case DT_TOK_MOD: dt_node_promote(lp, rp, dnp); if (dnp->dn_flags & DT_NF_SIGNED) dnp->dn_value = (intmax_t)l % (intmax_t)r; else dnp->dn_value = l % r; break; default: dt_node_free(dnp); dnp = NULL; } if (dnp != NULL) { dt_node_free(lp); dt_node_free(rp); return (dnp); } } /* * If an integer constant is being cast to another integer type, we can * perform the cast as part of integer constant folding in this pass. * We must take action when the integer is being cast to a smaller type * or if it is changing signed-ness. If so, we first shift rp's bits * bits high (losing excess bits if narrowing) and then shift them down * with either a logical shift (unsigned) or arithmetic shift (signed). */ if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT && dt_node_is_integer(lp)) { size_t srcsize = dt_node_type_size(rp); size_t dstsize = dt_node_type_size(lp); if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^ (rp->dn_flags & DT_NF_SIGNED))) { int n = dstsize < srcsize ? (sizeof (uint64_t) * NBBY - dstsize * NBBY) : (sizeof (uint64_t) * NBBY - srcsize * NBBY); rp->dn_value <<= n; if (lp->dn_flags & DT_NF_SIGNED) rp->dn_value = (intmax_t)rp->dn_value >> n; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -