Home | History | Annotate | Line # | Download | only in common
dt_cg.c revision 1.3
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/sysmacros.h>
     31 #include <sys/isa_defs.h>
     32 
     33 #include <strings.h>
     34 #include <stdlib.h>
     35 #include <setjmp.h>
     36 #include <assert.h>
     37 #include <errno.h>
     38 
     39 #include <dt_impl.h>
     40 #include <dt_grammar.h>
     41 #include <dt_parser.h>
     42 #include <dt_provider.h>
     43 
     44 static void dt_cg_node(dt_node_t *, dt_irlist_t *, dt_regset_t *);
     45 
     46 static dt_irnode_t *
     47 dt_cg_node_alloc(uint_t label, dif_instr_t instr)
     48 {
     49 	dt_irnode_t *dip = malloc(sizeof (dt_irnode_t));
     50 
     51 	if (dip == NULL)
     52 		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
     53 
     54 	dip->di_label = label;
     55 	dip->di_instr = instr;
     56 	dip->di_extern = NULL;
     57 	dip->di_next = NULL;
     58 
     59 	return (dip);
     60 }
     61 
     62 /*
     63  * Code generator wrapper function for ctf_member_info.  If we are given a
     64  * reference to a forward declaration tag, search the entire type space for
     65  * the actual definition and then call ctf_member_info on the result.
     66  */
     67 static ctf_file_t *
     68 dt_cg_membinfo(ctf_file_t *fp, ctf_id_t type, const char *s, ctf_membinfo_t *mp)
     69 {
     70 	while (ctf_type_kind(fp, type) == CTF_K_FORWARD) {
     71 		char n[DT_TYPE_NAMELEN];
     72 		dtrace_typeinfo_t dtt;
     73 
     74 		if (ctf_type_name(fp, type, n, sizeof (n)) == NULL ||
     75 		    dt_type_lookup(n, &dtt) == -1 || (
     76 		    dtt.dtt_ctfp == fp && dtt.dtt_type == type))
     77 			break; /* unable to improve our position */
     78 
     79 		fp = dtt.dtt_ctfp;
     80 		type = ctf_type_resolve(fp, dtt.dtt_type);
     81 	}
     82 
     83 	if (ctf_member_info(fp, type, s, mp) == CTF_ERR)
     84 		return (NULL); /* ctf_errno is set for us */
     85 
     86 	return (fp);
     87 }
     88 
     89 static void
     90 dt_cg_xsetx(dt_irlist_t *dlp, dt_ident_t *idp, uint_t lbl, int reg, uint64_t x)
     91 {
     92 	int flag = idp != NULL ? DT_INT_PRIVATE : DT_INT_SHARED;
     93 	int intoff = dt_inttab_insert(yypcb->pcb_inttab, x, flag);
     94 	dif_instr_t instr = DIF_INSTR_SETX((uint_t)intoff, reg);
     95 
     96 	if (intoff == -1)
     97 		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
     98 
     99 	if (intoff > DIF_INTOFF_MAX)
    100 		longjmp(yypcb->pcb_jmpbuf, EDT_INT2BIG);
    101 
    102 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl, instr));
    103 
    104 	if (idp != NULL)
    105 		dlp->dl_last->di_extern = idp;
    106 }
    107 
    108 static void
    109 dt_cg_setx(dt_irlist_t *dlp, int reg, uint64_t x)
    110 {
    111 	dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, reg, x);
    112 }
    113 
    114 /*
    115  * When loading bit-fields, we want to convert a byte count in the range
    116  * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
    117  * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
    118  */
    119 static size_t
    120 clp2(size_t x)
    121 {
    122 	x--;
    123 
    124 	x |= (x >> 1);
    125 	x |= (x >> 2);
    126 	x |= (x >> 4);
    127 	x |= (x >> 8);
    128 	x |= (x >> 16);
    129 
    130 	return (x + 1);
    131 }
    132 
    133 /*
    134  * Lookup the correct load opcode to use for the specified node and CTF type.
    135  * We determine the size and convert it to a 3-bit index.  Our lookup table
    136  * is constructed to use a 5-bit index, consisting of the 3-bit size 0-7, a
    137  * bit for the sign, and a bit for userland address.  For example, a 4-byte
    138  * signed load from userland would be at the following table index:
    139  * user=1 sign=1 size=4 => binary index 11011 = decimal index 27
    140  */
    141 static uint_t
    142 dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
    143 {
    144 	static const uint_t ops[] = {
    145 		DIF_OP_LDUB,	DIF_OP_LDUH,	0,	DIF_OP_LDUW,
    146 		0,		0,		0,	DIF_OP_LDX,
    147 		DIF_OP_LDSB,	DIF_OP_LDSH,	0,	DIF_OP_LDSW,
    148 		0,		0,		0,	DIF_OP_LDX,
    149 		DIF_OP_ULDUB,	DIF_OP_ULDUH,	0,	DIF_OP_ULDUW,
    150 		0,		0,		0,	DIF_OP_ULDX,
    151 		DIF_OP_ULDSB,	DIF_OP_ULDSH,	0,	DIF_OP_ULDSW,
    152 		0,		0,		0,	DIF_OP_ULDX,
    153 	};
    154 
    155 	ctf_encoding_t e;
    156 	ssize_t size;
    157 
    158 	/*
    159 	 * If we're loading a bit-field, the size of our load is found by
    160 	 * rounding cte_bits up to a byte boundary and then finding the
    161 	 * nearest power of two to this value (see clp2(), above).
    162 	 */
    163 	if ((dnp->dn_flags & DT_NF_BITFIELD) &&
    164 	    ctf_type_encoding(ctfp, type, &e) != CTF_ERR)
    165 		size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
    166 	else
    167 		size = ctf_type_size(ctfp, type);
    168 
    169 	if (size < 1 || size > 8 || (size & (size - 1)) != 0) {
    170 		xyerror(D_UNKNOWN, "internal error -- cg cannot load "
    171 		    "size %ld when passed by value\n", (long)size);
    172 	}
    173 
    174 	size--; /* convert size to 3-bit index */
    175 
    176 	if (dnp->dn_flags & DT_NF_SIGNED)
    177 		size |= 0x08;
    178 	if (dnp->dn_flags & DT_NF_USERLAND)
    179 		size |= 0x10;
    180 
    181 	return (ops[size]);
    182 }
    183 
    184 static void
    185 dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
    186     uint_t op, int dreg)
    187 {
    188 	ctf_file_t *ctfp = dnp->dn_ctfp;
    189 	ctf_arinfo_t r;
    190 	dif_instr_t instr;
    191 	ctf_id_t type;
    192 	uint_t kind;
    193 	ssize_t size;
    194 	int sreg;
    195 
    196 	if ((sreg = dt_regset_alloc(drp)) == -1)
    197 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    198 
    199 	type = ctf_type_resolve(ctfp, dnp->dn_type);
    200 	kind = ctf_type_kind(ctfp, type);
    201 	assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
    202 
    203 	if (kind == CTF_K_ARRAY) {
    204 		if (ctf_array_info(ctfp, type, &r) != 0) {
    205 			yypcb->pcb_hdl->dt_ctferr = ctf_errno(ctfp);
    206 			longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
    207 		}
    208 		type = r.ctr_contents;
    209 	} else
    210 		type = ctf_type_reference(ctfp, type);
    211 
    212 	if ((size = ctf_type_size(ctfp, type)) == 1)
    213 		return; /* multiply or divide by one can be omitted */
    214 
    215 	dt_cg_setx(dlp, sreg, size);
    216 	instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
    217 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    218 	dt_regset_free(drp, sreg);
    219 }
    220 
    221 /*
    222  * If the result of a "." or "->" operation is a bit-field, we use this routine
    223  * to generate an epilogue to the load instruction that extracts the value.  In
    224  * the diagrams below the "ld??" is the load instruction that is generated to
    225  * load the containing word that is generating prior to calling this function.
    226  *
    227  * Epilogue for unsigned fields:	Epilogue for signed fields:
    228  *
    229  * ldu?	[r1], r1			lds? [r1], r1
    230  * setx	USHIFT, r2			setx 64 - SSHIFT, r2
    231  * srl	r1, r2, r1			sll  r1, r2, r1
    232  * setx	(1 << bits) - 1, r2		setx 64 - bits, r2
    233  * and	r1, r2, r1			sra  r1, r2, r1
    234  *
    235  * The *SHIFT constants above changes value depending on the endian-ness of our
    236  * target architecture.  Refer to the comments below for more details.
    237  */
    238 static void
    239 dt_cg_field_get(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
    240     ctf_file_t *fp, const ctf_membinfo_t *mp)
    241 {
    242 	ctf_encoding_t e;
    243 	dif_instr_t instr;
    244 	uint64_t shift;
    245 	int r1, r2;
    246 
    247 	if (ctf_type_encoding(fp, mp->ctm_type, &e) != 0 || e.cte_bits > 64) {
    248 		xyerror(D_UNKNOWN, "cg: bad field: off %lu type <%ld> "
    249 		    "bits %u\n", mp->ctm_offset, mp->ctm_type, e.cte_bits);
    250 	}
    251 
    252 	assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
    253 	r1 = dnp->dn_left->dn_reg;
    254 
    255 	if ((r2 = dt_regset_alloc(drp)) == -1)
    256 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    257 
    258 	/*
    259 	 * On little-endian architectures, ctm_offset counts from the right so
    260 	 * ctm_offset % NBBY itself is the amount we want to shift right to
    261 	 * move the value bits to the little end of the register to mask them.
    262 	 * On big-endian architectures, ctm_offset counts from the left so we
    263 	 * must subtract (ctm_offset % NBBY + cte_bits) from the size in bits
    264 	 * we used for the load.  The size of our load in turn is found by
    265 	 * rounding cte_bits up to a byte boundary and then finding the
    266 	 * nearest power of two to this value (see clp2(), above).  These
    267 	 * properties are used to compute shift as USHIFT or SSHIFT, below.
    268 	 */
    269 	if (dnp->dn_flags & DT_NF_SIGNED) {
    270 #if BYTE_ORDER == _BIG_ENDIAN
    271 		shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
    272 		    mp->ctm_offset % NBBY;
    273 #else
    274 		shift = mp->ctm_offset % NBBY + e.cte_bits;
    275 #endif
    276 		dt_cg_setx(dlp, r2, 64 - shift);
    277 		instr = DIF_INSTR_FMT(DIF_OP_SLL, r1, r2, r1);
    278 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    279 
    280 		dt_cg_setx(dlp, r2, 64 - e.cte_bits);
    281 		instr = DIF_INSTR_FMT(DIF_OP_SRA, r1, r2, r1);
    282 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    283 	} else {
    284 #if BYTE_ORDER == _BIG_ENDIAN
    285 		shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
    286 		    (mp->ctm_offset % NBBY + e.cte_bits);
    287 #else
    288 		shift = mp->ctm_offset % NBBY;
    289 #endif
    290 		dt_cg_setx(dlp, r2, shift);
    291 		instr = DIF_INSTR_FMT(DIF_OP_SRL, r1, r2, r1);
    292 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    293 
    294 		dt_cg_setx(dlp, r2, (1ULL << e.cte_bits) - 1);
    295 		instr = DIF_INSTR_FMT(DIF_OP_AND, r1, r2, r1);
    296 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    297 	}
    298 
    299 	dt_regset_free(drp, r2);
    300 }
    301 
    302 /*
    303  * If the destination of a store operation is a bit-field, we use this routine
    304  * to generate a prologue to the store instruction that loads the surrounding
    305  * bits, clears the destination field, and ORs in the new value of the field.
    306  * In the diagram below the "st?" is the store instruction that is generated to
    307  * store the containing word that is generating after calling this function.
    308  *
    309  * ld	[dst->dn_reg], r1
    310  * setx	~(((1 << cte_bits) - 1) << (ctm_offset % NBBY)), r2
    311  * and	r1, r2, r1
    312  *
    313  * setx	(1 << cte_bits) - 1, r2
    314  * and	src->dn_reg, r2, r2
    315  * setx ctm_offset % NBBY, r3
    316  * sll	r2, r3, r2
    317  *
    318  * or	r1, r2, r1
    319  * st?	r1, [dst->dn_reg]
    320  *
    321  * This routine allocates a new register to hold the value to be stored and
    322  * returns it.  The caller is responsible for freeing this register later.
    323  */
    324 static int
    325 dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
    326     dt_regset_t *drp, dt_node_t *dst)
    327 {
    328 	uint64_t cmask, fmask, shift;
    329 	dif_instr_t instr;
    330 	int r1, r2, r3;
    331 
    332 	ctf_membinfo_t m;
    333 	ctf_encoding_t e;
    334 	ctf_file_t *fp, *ofp;
    335 	ctf_id_t type;
    336 
    337 	assert(dst->dn_op == DT_TOK_PTR || dst->dn_op == DT_TOK_DOT);
    338 	assert(dst->dn_right->dn_kind == DT_NODE_IDENT);
    339 
    340 	fp = dst->dn_left->dn_ctfp;
    341 	type = ctf_type_resolve(fp, dst->dn_left->dn_type);
    342 
    343 	if (dst->dn_op == DT_TOK_PTR) {
    344 		type = ctf_type_reference(fp, type);
    345 		type = ctf_type_resolve(fp, type);
    346 	}
    347 
    348 	if ((fp = dt_cg_membinfo(ofp = fp, type,
    349 	    dst->dn_right->dn_string, &m)) == NULL) {
    350 		yypcb->pcb_hdl->dt_ctferr = ctf_errno(ofp);
    351 		longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
    352 	}
    353 
    354 	if (ctf_type_encoding(fp, m.ctm_type, &e) != 0 || e.cte_bits > 64) {
    355 		xyerror(D_UNKNOWN, "cg: bad field: off %lu type <%ld> "
    356 		    "bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
    357 	}
    358 
    359 	if ((r1 = dt_regset_alloc(drp)) == -1 ||
    360 	    (r2 = dt_regset_alloc(drp)) == -1 ||
    361 	    (r3 = dt_regset_alloc(drp)) == -1)
    362 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    363 
    364 	/*
    365 	 * Compute shifts and masks.  We need to compute "shift" as the amount
    366 	 * we need to shift left to position our field in the containing word.
    367 	 * Refer to the comments in dt_cg_field_get(), above, for more info.
    368 	 * We then compute fmask as the mask that truncates the value in the
    369 	 * input register to width cte_bits, and cmask as the mask used to
    370 	 * pass through the containing bits and zero the field bits.
    371 	 */
    372 #if BYTE_ORDER == _BIG_ENDIAN
    373 	shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
    374 	    (m.ctm_offset % NBBY + e.cte_bits);
    375 #else
    376 	shift = m.ctm_offset % NBBY;
    377 #endif
    378 	fmask = (1ULL << e.cte_bits) - 1;
    379 	cmask = ~(fmask << shift);
    380 
    381 	instr = DIF_INSTR_LOAD(
    382 	    dt_cg_load(dst, fp, m.ctm_type), dst->dn_reg, r1);
    383 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    384 
    385 	dt_cg_setx(dlp, r2, cmask);
    386 	instr = DIF_INSTR_FMT(DIF_OP_AND, r1, r2, r1);
    387 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    388 
    389 	dt_cg_setx(dlp, r2, fmask);
    390 	instr = DIF_INSTR_FMT(DIF_OP_AND, src->dn_reg, r2, r2);
    391 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    392 
    393 	dt_cg_setx(dlp, r3, shift);
    394 	instr = DIF_INSTR_FMT(DIF_OP_SLL, r2, r3, r2);
    395 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    396 
    397 	instr = DIF_INSTR_FMT(DIF_OP_OR, r1, r2, r1);
    398 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    399 
    400 	dt_regset_free(drp, r3);
    401 	dt_regset_free(drp, r2);
    402 
    403 	return (r1);
    404 }
    405 
    406 static void
    407 dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
    408 {
    409 	ctf_encoding_t e;
    410 	dif_instr_t instr = NULL;
    411 	size_t size;
    412 	int reg;
    413 
    414 	/*
    415 	 * If we're loading a bit-field, the size of our store is found by
    416 	 * rounding dst's cte_bits up to a byte boundary and then finding the
    417 	 * nearest power of two to this value (see clp2(), above).
    418 	 */
    419 	if ((dst->dn_flags & DT_NF_BITFIELD) &&
    420 	    ctf_type_encoding(dst->dn_ctfp, dst->dn_type, &e) != CTF_ERR)
    421 		size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
    422 	else
    423 		size = dt_node_type_size(src);
    424 
    425 	if (src->dn_flags & DT_NF_REF) {
    426 		if ((reg = dt_regset_alloc(drp)) == -1)
    427 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    428 		dt_cg_setx(dlp, reg, size);
    429 		instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
    430 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    431 		dt_regset_free(drp, reg);
    432 	} else {
    433 		if (dst->dn_flags & DT_NF_BITFIELD)
    434 			reg = dt_cg_field_set(src, dlp, drp, dst);
    435 		else
    436 			reg = src->dn_reg;
    437 
    438 		switch (size) {
    439 		case 1:
    440 			instr = DIF_INSTR_STORE(DIF_OP_STB, reg, dst->dn_reg);
    441 			break;
    442 		case 2:
    443 			instr = DIF_INSTR_STORE(DIF_OP_STH, reg, dst->dn_reg);
    444 			break;
    445 		case 4:
    446 			instr = DIF_INSTR_STORE(DIF_OP_STW, reg, dst->dn_reg);
    447 			break;
    448 		case 8:
    449 			instr = DIF_INSTR_STORE(DIF_OP_STX, reg, dst->dn_reg);
    450 			break;
    451 		default:
    452 			xyerror(D_UNKNOWN, "internal error -- cg cannot store "
    453 			    "size %lu when passed by value\n", (ulong_t)size);
    454 		}
    455 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    456 
    457 		if (dst->dn_flags & DT_NF_BITFIELD)
    458 			dt_regset_free(drp, reg);
    459 	}
    460 }
    461 
    462 /*
    463  * Generate code for a typecast or for argument promotion from the type of the
    464  * actual to the type of the formal.  We need to generate code for casts when
    465  * a scalar type is being narrowed or changing signed-ness.  We first shift the
    466  * desired bits high (losing excess bits if narrowing) and then shift them down
    467  * using logical shift (unsigned result) or arithmetic shift (signed result).
    468  */
    469 static void
    470 dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
    471     dt_irlist_t *dlp, dt_regset_t *drp)
    472 {
    473 	size_t srcsize = dt_node_type_size(src);
    474 	size_t dstsize = dt_node_type_size(dst);
    475 
    476 	dif_instr_t instr;
    477 	int reg, n;
    478 
    479 	if (dt_node_is_scalar(dst) && (dstsize < srcsize ||
    480 	    (src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
    481 		if ((reg = dt_regset_alloc(drp)) == -1)
    482 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    483 
    484 		if (dstsize < srcsize)
    485 			n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
    486 		else
    487 			n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
    488 
    489 		dt_cg_setx(dlp, reg, n);
    490 
    491 		instr = DIF_INSTR_FMT(DIF_OP_SLL,
    492 		    src->dn_reg, reg, dst->dn_reg);
    493 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    494 
    495 		instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
    496 		    DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
    497 
    498 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    499 		dt_regset_free(drp, reg);
    500 	}
    501 }
    502 
    503 /*
    504  * Generate code to push the specified argument list on to the tuple stack.
    505  * We use this routine for handling subroutine calls and associative arrays.
    506  * We must first generate code for all subexpressions before loading the stack
    507  * because any subexpression could itself require the use of the tuple stack.
    508  * This holds a number of registers equal to the number of arguments, but this
    509  * is not a huge problem because the number of arguments can't exceed the
    510  * number of tuple register stack elements anyway.  At most one extra register
    511  * is required (either by dt_cg_typecast() or for dtdt_size, below).  This
    512  * implies that a DIF implementation should offer a number of general purpose
    513  * registers at least one greater than the number of tuple registers.
    514  */
    515 static void
    516 dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
    517     dt_irlist_t *dlp, dt_regset_t *drp)
    518 {
    519 	const dt_idsig_t *isp = idp->di_data;
    520 	dt_node_t *dnp;
    521 	int i = 0;
    522 
    523 	for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
    524 		dt_cg_node(dnp, dlp, drp);
    525 
    526 	dt_irlist_append(dlp,
    527 	    dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
    528 
    529 	for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
    530 		dtrace_diftype_t t;
    531 		dif_instr_t instr;
    532 		uint_t op;
    533 		int reg;
    534 
    535 		dt_node_diftype(yypcb->pcb_hdl, dnp, &t);
    536 
    537 		isp->dis_args[i].dn_reg = dnp->dn_reg; /* re-use register */
    538 		dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
    539 		isp->dis_args[i].dn_reg = -1;
    540 
    541 		if (t.dtdt_flags & DIF_TF_BYREF)
    542 			op = DIF_OP_PUSHTR;
    543 		else
    544 			op = DIF_OP_PUSHTV;
    545 
    546 		if (t.dtdt_size != 0) {
    547 			if ((reg = dt_regset_alloc(drp)) == -1)
    548 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    549 			dt_cg_setx(dlp, reg, t.dtdt_size);
    550 		} else
    551 			reg = DIF_REG_R0;
    552 
    553 		instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
    554 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    555 		dt_regset_free(drp, dnp->dn_reg);
    556 
    557 		if (reg != DIF_REG_R0)
    558 			dt_regset_free(drp, reg);
    559 	}
    560 
    561 	if (i > yypcb->pcb_hdl->dt_conf.dtc_diftupregs)
    562 		longjmp(yypcb->pcb_jmpbuf, EDT_NOTUPREG);
    563 }
    564 
    565 static void
    566 dt_cg_arithmetic_op(dt_node_t *dnp, dt_irlist_t *dlp,
    567     dt_regset_t *drp, uint_t op)
    568 {
    569 	int is_ptr_op = (dnp->dn_op == DT_TOK_ADD || dnp->dn_op == DT_TOK_SUB ||
    570 	    dnp->dn_op == DT_TOK_ADD_EQ || dnp->dn_op == DT_TOK_SUB_EQ);
    571 
    572 	int lp_is_ptr = dt_node_is_pointer(dnp->dn_left);
    573 	int rp_is_ptr = dt_node_is_pointer(dnp->dn_right);
    574 
    575 	dif_instr_t instr;
    576 
    577 	if (lp_is_ptr && rp_is_ptr) {
    578 		assert(dnp->dn_op == DT_TOK_SUB);
    579 		is_ptr_op = 0;
    580 	}
    581 
    582 	dt_cg_node(dnp->dn_left, dlp, drp);
    583 	if (is_ptr_op && rp_is_ptr)
    584 		dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_left->dn_reg);
    585 
    586 	dt_cg_node(dnp->dn_right, dlp, drp);
    587 	if (is_ptr_op && lp_is_ptr)
    588 		dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_right->dn_reg);
    589 
    590 	instr = DIF_INSTR_FMT(op, dnp->dn_left->dn_reg,
    591 	    dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);
    592 
    593 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    594 	dt_regset_free(drp, dnp->dn_right->dn_reg);
    595 	dnp->dn_reg = dnp->dn_left->dn_reg;
    596 
    597 	if (lp_is_ptr && rp_is_ptr)
    598 		dt_cg_ptrsize(dnp->dn_right,
    599 		    dlp, drp, DIF_OP_UDIV, dnp->dn_reg);
    600 }
    601 
    602 static uint_t
    603 dt_cg_stvar(const dt_ident_t *idp)
    604 {
    605 	static const uint_t aops[] = { DIF_OP_STGAA, DIF_OP_STTAA, DIF_OP_NOP };
    606 	static const uint_t sops[] = { DIF_OP_STGS, DIF_OP_STTS, DIF_OP_STLS };
    607 
    608 	uint_t i = (((idp->di_flags & DT_IDFLG_LOCAL) != 0) << 1) |
    609 	    ((idp->di_flags & DT_IDFLG_TLS) != 0);
    610 
    611 	return (idp->di_kind == DT_IDENT_ARRAY ? aops[i] : sops[i]);
    612 }
    613 
    614 static void
    615 dt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
    616 {
    617 	ctf_file_t *ctfp = dnp->dn_ctfp;
    618 	dif_instr_t instr;
    619 	ctf_id_t type;
    620 	ssize_t size = 1;
    621 	int reg;
    622 
    623 	if (dt_node_is_pointer(dnp)) {
    624 		type = ctf_type_resolve(ctfp, dnp->dn_type);
    625 		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
    626 		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
    627 	}
    628 
    629 	dt_cg_node(dnp->dn_child, dlp, drp);
    630 	dnp->dn_reg = dnp->dn_child->dn_reg;
    631 
    632 	if ((reg = dt_regset_alloc(drp)) == -1)
    633 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    634 
    635 	dt_cg_setx(dlp, reg, size);
    636 
    637 	instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
    638 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    639 	dt_regset_free(drp, reg);
    640 
    641 	/*
    642 	 * If we are modifying a variable, generate an stv instruction from
    643 	 * the variable specified by the identifier.  If we are storing to a
    644 	 * memory address, generate code again for the left-hand side using
    645 	 * DT_NF_REF to get the address, and then generate a store to it.
    646 	 * In both paths, we store the value in dnp->dn_reg (the new value).
    647 	 */
    648 	if (dnp->dn_child->dn_kind == DT_NODE_VAR) {
    649 		dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);
    650 
    651 		idp->di_flags |= DT_IDFLG_DIFW;
    652 		instr = DIF_INSTR_STV(dt_cg_stvar(idp),
    653 		    idp->di_id, dnp->dn_reg);
    654 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    655 	} else {
    656 		uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
    657 
    658 		assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);
    659 		assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);
    660 
    661 		dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
    662 		dt_cg_node(dnp->dn_child, dlp, drp);
    663 
    664 		dt_cg_store(dnp, dlp, drp, dnp->dn_child);
    665 		dt_regset_free(drp, dnp->dn_child->dn_reg);
    666 
    667 		dnp->dn_left->dn_flags &= ~DT_NF_REF;
    668 		dnp->dn_left->dn_flags |= rbit;
    669 	}
    670 }
    671 
    672 static void
    673 dt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,
    674     dt_regset_t *drp, uint_t op)
    675 {
    676 	ctf_file_t *ctfp = dnp->dn_ctfp;
    677 	dif_instr_t instr;
    678 	ctf_id_t type;
    679 	ssize_t size = 1;
    680 	int nreg;
    681 
    682 	if (dt_node_is_pointer(dnp)) {
    683 		type = ctf_type_resolve(ctfp, dnp->dn_type);
    684 		assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
    685 		size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
    686 	}
    687 
    688 	dt_cg_node(dnp->dn_child, dlp, drp);
    689 	dnp->dn_reg = dnp->dn_child->dn_reg;
    690 
    691 	if ((nreg = dt_regset_alloc(drp)) == -1)
    692 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
    693 
    694 	dt_cg_setx(dlp, nreg, size);
    695 	instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
    696 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    697 
    698 	/*
    699 	 * If we are modifying a variable, generate an stv instruction from
    700 	 * the variable specified by the identifier.  If we are storing to a
    701 	 * memory address, generate code again for the left-hand side using
    702 	 * DT_NF_REF to get the address, and then generate a store to it.
    703 	 * In both paths, we store the value from 'nreg' (the new value).
    704 	 */
    705 	if (dnp->dn_child->dn_kind == DT_NODE_VAR) {
    706 		dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);
    707 
    708 		idp->di_flags |= DT_IDFLG_DIFW;
    709 		instr = DIF_INSTR_STV(dt_cg_stvar(idp), idp->di_id, nreg);
    710 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    711 	} else {
    712 		uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
    713 		int oreg = dnp->dn_reg;
    714 
    715 		assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);
    716 		assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);
    717 
    718 		dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
    719 		dt_cg_node(dnp->dn_child, dlp, drp);
    720 
    721 		dnp->dn_reg = nreg;
    722 		dt_cg_store(dnp, dlp, drp, dnp->dn_child);
    723 		dnp->dn_reg = oreg;
    724 
    725 		dt_regset_free(drp, dnp->dn_child->dn_reg);
    726 		dnp->dn_left->dn_flags &= ~DT_NF_REF;
    727 		dnp->dn_left->dn_flags |= rbit;
    728 	}
    729 
    730 	dt_regset_free(drp, nreg);
    731 }
    732 
    733 /*
    734  * Determine if we should perform signed or unsigned comparison for an OP2.
    735  * If both operands are of arithmetic type, perform the usual arithmetic
    736  * conversions to determine the common real type for comparison [ISOC 6.5.8.3].
    737  */
    738 static int
    739 dt_cg_compare_signed(dt_node_t *dnp)
    740 {
    741 	dt_node_t dn;
    742 
    743 	if (dt_node_is_string(dnp->dn_left) ||
    744 	    dt_node_is_string(dnp->dn_right))
    745 		return (1); /* strings always compare signed */
    746 	else if (!dt_node_is_arith(dnp->dn_left) ||
    747 	    !dt_node_is_arith(dnp->dn_right))
    748 		return (0); /* non-arithmetic types always compare unsigned */
    749 
    750 	bzero(&dn, sizeof (dn));
    751 	dt_node_promote(dnp->dn_left, dnp->dn_right, &dn);
    752 	return (dn.dn_flags & DT_NF_SIGNED);
    753 }
    754 
    755 static void
    756 dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
    757 {
    758 	uint_t lbl_true = dt_irlist_label(dlp);
    759 	uint_t lbl_post = dt_irlist_label(dlp);
    760 
    761 	dif_instr_t instr;
    762 	uint_t opc;
    763 
    764 	dt_cg_node(dnp->dn_left, dlp, drp);
    765 	dt_cg_node(dnp->dn_right, dlp, drp);
    766 
    767 	if (dt_node_is_string(dnp->dn_left) || dt_node_is_string(dnp->dn_right))
    768 		opc = DIF_OP_SCMP;
    769 	else
    770 		opc = DIF_OP_CMP;
    771 
    772 	instr = DIF_INSTR_CMP(opc, dnp->dn_left->dn_reg, dnp->dn_right->dn_reg);
    773 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    774 	dt_regset_free(drp, dnp->dn_right->dn_reg);
    775 	dnp->dn_reg = dnp->dn_left->dn_reg;
    776 
    777 	instr = DIF_INSTR_BRANCH(op, lbl_true);
    778 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    779 
    780 	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
    781 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    782 
    783 	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
    784 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    785 
    786 	dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);
    787 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
    788 }
    789 
    790 /*
    791  * Code generation for the ternary op requires some trickery with the assembler
    792  * in order to conserve registers.  We generate code for dn_expr and dn_left
    793  * and free their registers so they do not have be consumed across codegen for
    794  * dn_right.  We insert a dummy MOV at the end of dn_left into the destination
    795  * register, which is not yet known because we haven't done dn_right yet, and
    796  * save the pointer to this instruction node.  We then generate code for
    797  * dn_right and use its register as our output.  Finally, we reach back and
    798  * patch the instruction for dn_left to move its output into this register.
    799  */
    800 static void
    801 dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    802 {
    803 	uint_t lbl_false = dt_irlist_label(dlp);
    804 	uint_t lbl_post = dt_irlist_label(dlp);
    805 
    806 	dif_instr_t instr;
    807 	dt_irnode_t *dip;
    808 
    809 	dt_cg_node(dnp->dn_expr, dlp, drp);
    810 	instr = DIF_INSTR_TST(dnp->dn_expr->dn_reg);
    811 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    812 	dt_regset_free(drp, dnp->dn_expr->dn_reg);
    813 
    814 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
    815 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    816 
    817 	dt_cg_node(dnp->dn_left, dlp, drp);
    818 	instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, DIF_REG_R0);
    819 	dip = dt_cg_node_alloc(DT_LBL_NONE, instr); /* save dip for below */
    820 	dt_irlist_append(dlp, dip);
    821 	dt_regset_free(drp, dnp->dn_left->dn_reg);
    822 
    823 	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
    824 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    825 
    826 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, DIF_INSTR_NOP));
    827 	dt_cg_node(dnp->dn_right, dlp, drp);
    828 	dnp->dn_reg = dnp->dn_right->dn_reg;
    829 
    830 	/*
    831 	 * Now that dn_reg is assigned, reach back and patch the correct MOV
    832 	 * instruction into the tail of dn_left.  We know dn_reg was unused
    833 	 * at that point because otherwise dn_right couldn't have allocated it.
    834 	 */
    835 	dip->di_instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, dnp->dn_reg);
    836 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
    837 }
    838 
    839 static void
    840 dt_cg_logical_and(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    841 {
    842 	uint_t lbl_false = dt_irlist_label(dlp);
    843 	uint_t lbl_post = dt_irlist_label(dlp);
    844 
    845 	dif_instr_t instr;
    846 
    847 	dt_cg_node(dnp->dn_left, dlp, drp);
    848 	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
    849 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    850 	dt_regset_free(drp, dnp->dn_left->dn_reg);
    851 
    852 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
    853 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    854 
    855 	dt_cg_node(dnp->dn_right, dlp, drp);
    856 	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
    857 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    858 	dnp->dn_reg = dnp->dn_right->dn_reg;
    859 
    860 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
    861 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    862 
    863 	dt_cg_setx(dlp, dnp->dn_reg, 1);
    864 
    865 	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
    866 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    867 
    868 	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
    869 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));
    870 
    871 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
    872 }
    873 
    874 static void
    875 dt_cg_logical_xor(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    876 {
    877 	uint_t lbl_next = dt_irlist_label(dlp);
    878 	uint_t lbl_tail = dt_irlist_label(dlp);
    879 
    880 	dif_instr_t instr;
    881 
    882 	dt_cg_node(dnp->dn_left, dlp, drp);
    883 	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
    884 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    885 
    886 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_next);
    887 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    888 	dt_cg_setx(dlp, dnp->dn_left->dn_reg, 1);
    889 
    890 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_next, DIF_INSTR_NOP));
    891 	dt_cg_node(dnp->dn_right, dlp, drp);
    892 
    893 	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
    894 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    895 
    896 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_tail);
    897 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    898 	dt_cg_setx(dlp, dnp->dn_right->dn_reg, 1);
    899 
    900 	instr = DIF_INSTR_FMT(DIF_OP_XOR, dnp->dn_left->dn_reg,
    901 	    dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);
    902 
    903 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_tail, instr));
    904 
    905 	dt_regset_free(drp, dnp->dn_right->dn_reg);
    906 	dnp->dn_reg = dnp->dn_left->dn_reg;
    907 }
    908 
    909 static void
    910 dt_cg_logical_or(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    911 {
    912 	uint_t lbl_true = dt_irlist_label(dlp);
    913 	uint_t lbl_false = dt_irlist_label(dlp);
    914 	uint_t lbl_post = dt_irlist_label(dlp);
    915 
    916 	dif_instr_t instr;
    917 
    918 	dt_cg_node(dnp->dn_left, dlp, drp);
    919 	instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
    920 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    921 	dt_regset_free(drp, dnp->dn_left->dn_reg);
    922 
    923 	instr = DIF_INSTR_BRANCH(DIF_OP_BNE, lbl_true);
    924 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    925 
    926 	dt_cg_node(dnp->dn_right, dlp, drp);
    927 	instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
    928 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    929 	dnp->dn_reg = dnp->dn_right->dn_reg;
    930 
    931 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
    932 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    933 
    934 	dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);
    935 
    936 	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
    937 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    938 
    939 	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
    940 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));
    941 
    942 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
    943 }
    944 
    945 static void
    946 dt_cg_logical_neg(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    947 {
    948 	uint_t lbl_zero = dt_irlist_label(dlp);
    949 	uint_t lbl_post = dt_irlist_label(dlp);
    950 
    951 	dif_instr_t instr;
    952 
    953 	dt_cg_node(dnp->dn_child, dlp, drp);
    954 	dnp->dn_reg = dnp->dn_child->dn_reg;
    955 
    956 	instr = DIF_INSTR_TST(dnp->dn_reg);
    957 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    958 
    959 	instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_zero);
    960 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    961 
    962 	instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
    963 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    964 
    965 	instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
    966 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
    967 
    968 	dt_cg_xsetx(dlp, NULL, lbl_zero, dnp->dn_reg, 1);
    969 	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
    970 }
    971 
    972 static void
    973 dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
    974 {
    975 	dif_instr_t instr;
    976 	dt_ident_t *idp;
    977 
    978 	/*
    979 	 * If we are performing a structure assignment of a translated type,
    980 	 * we must instantiate all members and create a snapshot of the object
    981 	 * in scratch space.  We allocs a chunk of memory, generate code for
    982 	 * each member, and then set dnp->dn_reg to the scratch object address.
    983 	 */
    984 	if ((idp = dt_node_resolve(dnp->dn_right, DT_IDENT_XLSOU)) != NULL) {
    985 		ctf_membinfo_t ctm;
    986 		dt_xlator_t *dxp = idp->di_data;
    987 		dt_node_t *mnp, dn, mn;
    988 		int r1, r2;
    989 
    990 		/*
    991 		 * Create two fake dt_node_t's representing operator "." and a
    992 		 * right-hand identifier child node.  These will be repeatedly
    993 		 * modified according to each instantiated member so that we
    994 		 * can pass them to dt_cg_store() and effect a member store.
    995 		 */
    996 		bzero(&dn, sizeof (dt_node_t));
    997 		dn.dn_kind = DT_NODE_OP2;
    998 		dn.dn_op = DT_TOK_DOT;
    999 		dn.dn_left = dnp;
   1000 		dn.dn_right = &mn;
   1001 
   1002 		bzero(&mn, sizeof (dt_node_t));
   1003 		mn.dn_kind = DT_NODE_IDENT;
   1004 		mn.dn_op = DT_TOK_IDENT;
   1005 
   1006 		/*
   1007 		 * Allocate a register for our scratch data pointer.  First we
   1008 		 * set it to the size of our data structure, and then replace
   1009 		 * it with the result of an allocs of the specified size.
   1010 		 */
   1011 		if ((r1 = dt_regset_alloc(drp)) == -1)
   1012 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1013 
   1014 		dt_cg_setx(dlp, r1,
   1015 		    ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
   1016 
   1017 		instr = DIF_INSTR_ALLOCS(r1, r1);
   1018 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1019 
   1020 		/*
   1021 		 * When dt_cg_asgn_op() is called, we have already generated
   1022 		 * code for dnp->dn_right, which is the translator input.  We
   1023 		 * now associate this register with the translator's input
   1024 		 * identifier so it can be referenced during our member loop.
   1025 		 */
   1026 		dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
   1027 		dxp->dx_ident->di_id = dnp->dn_right->dn_reg;
   1028 
   1029 		for (mnp = dxp->dx_members; mnp != NULL; mnp = mnp->dn_list) {
   1030 			/*
   1031 			 * Generate code for the translator member expression,
   1032 			 * and then cast the result to the member type.
   1033 			 */
   1034 			dt_cg_node(mnp->dn_membexpr, dlp, drp);
   1035 			mnp->dn_reg = mnp->dn_membexpr->dn_reg;
   1036 			dt_cg_typecast(mnp->dn_membexpr, mnp, dlp, drp);
   1037 
   1038 			/*
   1039 			 * Ask CTF for the offset of the member so we can store
   1040 			 * to the appropriate offset.  This call has already
   1041 			 * been done once by the parser, so it should succeed.
   1042 			 */
   1043 			if (ctf_member_info(dxp->dx_dst_ctfp, dxp->dx_dst_base,
   1044 			    mnp->dn_membname, &ctm) == CTF_ERR) {
   1045 				yypcb->pcb_hdl->dt_ctferr =
   1046 				    ctf_errno(dxp->dx_dst_ctfp);
   1047 				longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
   1048 			}
   1049 
   1050 			/*
   1051 			 * If the destination member is at offset 0, store the
   1052 			 * result directly to r1 (the scratch buffer address).
   1053 			 * Otherwise allocate another temporary for the offset
   1054 			 * and add r1 to it before storing the result.
   1055 			 */
   1056 			if (ctm.ctm_offset != 0) {
   1057 				if ((r2 = dt_regset_alloc(drp)) == -1)
   1058 					longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1059 
   1060 				/*
   1061 				 * Add the member offset rounded down to the
   1062 				 * nearest byte.  If the offset was not aligned
   1063 				 * on a byte boundary, this member is a bit-
   1064 				 * field and dt_cg_store() will handle masking.
   1065 				 */
   1066 				dt_cg_setx(dlp, r2, ctm.ctm_offset / NBBY);
   1067 				instr = DIF_INSTR_FMT(DIF_OP_ADD, r1, r2, r2);
   1068 				dt_irlist_append(dlp,
   1069 				    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1070 
   1071 				dt_node_type_propagate(mnp, &dn);
   1072 				dn.dn_right->dn_string = mnp->dn_membname;
   1073 				dn.dn_reg = r2;
   1074 
   1075 				dt_cg_store(mnp, dlp, drp, &dn);
   1076 				dt_regset_free(drp, r2);
   1077 
   1078 			} else {
   1079 				dt_node_type_propagate(mnp, &dn);
   1080 				dn.dn_right->dn_string = mnp->dn_membname;
   1081 				dn.dn_reg = r1;
   1082 
   1083 				dt_cg_store(mnp, dlp, drp, &dn);
   1084 			}
   1085 
   1086 			dt_regset_free(drp, mnp->dn_reg);
   1087 		}
   1088 
   1089 		dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
   1090 		dxp->dx_ident->di_id = 0;
   1091 
   1092 		if (dnp->dn_right->dn_reg != -1)
   1093 			dt_regset_free(drp, dnp->dn_right->dn_reg);
   1094 
   1095 		assert(dnp->dn_reg == dnp->dn_right->dn_reg);
   1096 		dnp->dn_reg = r1;
   1097 	}
   1098 
   1099 	/*
   1100 	 * If we are storing to a variable, generate an stv instruction from
   1101 	 * the variable specified by the identifier.  If we are storing to a
   1102 	 * memory address, generate code again for the left-hand side using
   1103 	 * DT_NF_REF to get the address, and then generate a store to it.
   1104 	 * In both paths, we assume dnp->dn_reg already has the new value.
   1105 	 */
   1106 	if (dnp->dn_left->dn_kind == DT_NODE_VAR) {
   1107 		idp = dt_ident_resolve(dnp->dn_left->dn_ident);
   1108 
   1109 		if (idp->di_kind == DT_IDENT_ARRAY)
   1110 			dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);
   1111 
   1112 		idp->di_flags |= DT_IDFLG_DIFW;
   1113 		instr = DIF_INSTR_STV(dt_cg_stvar(idp),
   1114 		    idp->di_id, dnp->dn_reg);
   1115 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1116 	} else {
   1117 		uint_t rbit = dnp->dn_left->dn_flags & DT_NF_REF;
   1118 
   1119 		assert(dnp->dn_left->dn_flags & DT_NF_WRITABLE);
   1120 		assert(dnp->dn_left->dn_flags & DT_NF_LVALUE);
   1121 
   1122 		dnp->dn_left->dn_flags |= DT_NF_REF; /* force pass-by-ref */
   1123 
   1124 		dt_cg_node(dnp->dn_left, dlp, drp);
   1125 		dt_cg_store(dnp, dlp, drp, dnp->dn_left);
   1126 		dt_regset_free(drp, dnp->dn_left->dn_reg);
   1127 
   1128 		dnp->dn_left->dn_flags &= ~DT_NF_REF;
   1129 		dnp->dn_left->dn_flags |= rbit;
   1130 	}
   1131 }
   1132 
   1133 static void
   1134 dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
   1135 {
   1136 	dif_instr_t instr;
   1137 	uint_t op;
   1138 
   1139 	assert(dnp->dn_kind == DT_NODE_VAR);
   1140 	assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));
   1141 	assert(dnp->dn_args != NULL);
   1142 
   1143 	dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
   1144 
   1145 	if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1146 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1147 
   1148 	if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
   1149 		op = DIF_OP_LDTAA;
   1150 	else
   1151 		op = DIF_OP_LDGAA;
   1152 
   1153 	dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
   1154 	instr = DIF_INSTR_LDV(op, dnp->dn_ident->di_id, dnp->dn_reg);
   1155 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1156 
   1157 	/*
   1158 	 * If the associative array is a pass-by-reference type, then we are
   1159 	 * loading its value as a pointer to either load or store through it.
   1160 	 * The array element in question may not have been faulted in yet, in
   1161 	 * which case DIF_OP_LD*AA will return zero.  We append an epilogue
   1162 	 * of instructions similar to the following:
   1163 	 *
   1164 	 *	  ld?aa	 id, %r1	! base ld?aa instruction above
   1165 	 *	  tst	 %r1		! start of epilogue
   1166 	 *   +--- bne	 label
   1167 	 *   |    setx	 size, %r1
   1168 	 *   |    allocs %r1, %r1
   1169 	 *   |    st?aa	 id, %r1
   1170 	 *   |    ld?aa	 id, %r1
   1171 	 *   v
   1172 	 * label: < rest of code >
   1173 	 *
   1174 	 * The idea is that we allocs a zero-filled chunk of scratch space and
   1175 	 * do a DIF_OP_ST*AA to fault in and initialize the array element, and
   1176 	 * then reload it to get the faulted-in address of the new variable
   1177 	 * storage.  This isn't cheap, but pass-by-ref associative array values
   1178 	 * are (thus far) uncommon and the allocs cost only occurs once.  If
   1179 	 * this path becomes important to DTrace users, we can improve things
   1180 	 * by adding a new DIF opcode to fault in associative array elements.
   1181 	 */
   1182 	if (dnp->dn_flags & DT_NF_REF) {
   1183 		uint_t stvop = op == DIF_OP_LDTAA ? DIF_OP_STTAA : DIF_OP_STGAA;
   1184 		uint_t label = dt_irlist_label(dlp);
   1185 
   1186 		instr = DIF_INSTR_TST(dnp->dn_reg);
   1187 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1188 
   1189 		instr = DIF_INSTR_BRANCH(DIF_OP_BNE, label);
   1190 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1191 
   1192 		dt_cg_setx(dlp, dnp->dn_reg, dt_node_type_size(dnp));
   1193 		instr = DIF_INSTR_ALLOCS(dnp->dn_reg, dnp->dn_reg);
   1194 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1195 
   1196 		dnp->dn_ident->di_flags |= DT_IDFLG_DIFW;
   1197 		instr = DIF_INSTR_STV(stvop, dnp->dn_ident->di_id, dnp->dn_reg);
   1198 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1199 
   1200 		instr = DIF_INSTR_LDV(op, dnp->dn_ident->di_id, dnp->dn_reg);
   1201 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1202 
   1203 		dt_irlist_append(dlp, dt_cg_node_alloc(label, DIF_INSTR_NOP));
   1204 	}
   1205 }
   1206 
   1207 static void
   1208 dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
   1209 {
   1210 	dt_probe_t *prp = yypcb->pcb_probe;
   1211 	uintmax_t saved = dnp->dn_args->dn_value;
   1212 	dt_ident_t *idp = dnp->dn_ident;
   1213 
   1214 	dif_instr_t instr;
   1215 	uint_t op;
   1216 	size_t size;
   1217 	int reg, n;
   1218 
   1219 	assert(dnp->dn_kind == DT_NODE_VAR);
   1220 	assert(!(idp->di_flags & DT_IDFLG_LOCAL));
   1221 
   1222 	assert(dnp->dn_args->dn_kind == DT_NODE_INT);
   1223 	assert(dnp->dn_args->dn_list == NULL);
   1224 
   1225 	/*
   1226 	 * If this is a reference in the args[] array, temporarily modify the
   1227 	 * array index according to the static argument mapping (if any),
   1228 	 * unless the argument reference is provided by a dynamic translator.
   1229 	 * If we're using a dynamic translator for args[], then just set dn_reg
   1230 	 * to an invalid reg and return: DIF_OP_XLARG will fetch the arg later.
   1231 	 */
   1232 	if (idp->di_id == DIF_VAR_ARGS) {
   1233 		if ((idp->di_kind == DT_IDENT_XLPTR ||
   1234 		    idp->di_kind == DT_IDENT_XLSOU) &&
   1235 		    dt_xlator_dynamic(idp->di_data)) {
   1236 			dnp->dn_reg = -1;
   1237 			return;
   1238 		}
   1239 		dnp->dn_args->dn_value = prp->pr_mapping[saved];
   1240 	}
   1241 
   1242 	dt_cg_node(dnp->dn_args, dlp, drp);
   1243 	dnp->dn_args->dn_value = saved;
   1244 
   1245 	dnp->dn_reg = dnp->dn_args->dn_reg;
   1246 
   1247 	if (idp->di_flags & DT_IDFLG_TLS)
   1248 		op = DIF_OP_LDTA;
   1249 	else
   1250 		op = DIF_OP_LDGA;
   1251 
   1252 	idp->di_flags |= DT_IDFLG_DIFR;
   1253 
   1254 	instr = DIF_INSTR_LDA(op, idp->di_id,
   1255 	    dnp->dn_args->dn_reg, dnp->dn_reg);
   1256 
   1257 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1258 
   1259 	/*
   1260 	 * If this is a reference to the args[] array, we need to take the
   1261 	 * additional step of explicitly eliminating any bits larger than the
   1262 	 * type size: the DIF interpreter in the kernel will always give us
   1263 	 * the raw (64-bit) argument value, and any bits larger than the type
   1264 	 * size may be junk.  As a practical matter, this arises only on 64-bit
   1265 	 * architectures and only when the argument index is larger than the
   1266 	 * number of arguments passed directly to DTrace: if a 8-, 16- or
   1267 	 * 32-bit argument must be retrieved from the stack, it is possible
   1268 	 * (and it some cases, likely) that the upper bits will be garbage.
   1269 	 */
   1270 	if (idp->di_id != DIF_VAR_ARGS || !dt_node_is_scalar(dnp))
   1271 		return;
   1272 
   1273 	if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
   1274 		return;
   1275 
   1276 	if ((reg = dt_regset_alloc(drp)) == -1)
   1277 		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1278 
   1279 	assert(size < sizeof (uint64_t));
   1280 	n = sizeof (uint64_t) * NBBY - size * NBBY;
   1281 
   1282 	dt_cg_setx(dlp, reg, n);
   1283 
   1284 	instr = DIF_INSTR_FMT(DIF_OP_SLL, dnp->dn_reg, reg, dnp->dn_reg);
   1285 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1286 
   1287 	instr = DIF_INSTR_FMT((dnp->dn_flags & DT_NF_SIGNED) ?
   1288 	    DIF_OP_SRA : DIF_OP_SRL, dnp->dn_reg, reg, dnp->dn_reg);
   1289 
   1290 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1291 	dt_regset_free(drp, reg);
   1292 }
   1293 
   1294 /*
   1295  * Generate code for an inlined variable reference.  Inlines can be used to
   1296  * define either scalar or associative array substitutions.  For scalars, we
   1297  * simply generate code for the parse tree saved in the identifier's din_root,
   1298  * and then cast the resulting expression to the inline's declaration type.
   1299  * For arrays, we take the input parameter subtrees from dnp->dn_args and
   1300  * temporarily store them in the din_root of each din_argv[i] identifier,
   1301  * which are themselves inlines and were set up for us by the parser.  The
   1302  * result is that any reference to the inlined parameter inside the top-level
   1303  * din_root will turn into a recursive call to dt_cg_inline() for a scalar
   1304  * inline whose din_root will refer to the subtree pointed to by the argument.
   1305  */
   1306 static void
   1307 dt_cg_inline(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
   1308 {
   1309 	dt_ident_t *idp = dnp->dn_ident;
   1310 	dt_idnode_t *inp = idp->di_iarg;
   1311 
   1312 	dt_idnode_t *pinp;
   1313 	dt_node_t *pnp;
   1314 	int i;
   1315 
   1316 	assert(idp->di_flags & DT_IDFLG_INLINE);
   1317 	assert(idp->di_ops == &dt_idops_inline);
   1318 
   1319 	if (idp->di_kind == DT_IDENT_ARRAY) {
   1320 		for (i = 0, pnp = dnp->dn_args;
   1321 		    pnp != NULL; pnp = pnp->dn_list, i++) {
   1322 			if (inp->din_argv[i] != NULL) {
   1323 				pinp = inp->din_argv[i]->di_iarg;
   1324 				pinp->din_root = pnp;
   1325 			}
   1326 		}
   1327 	}
   1328 
   1329 	dt_cg_node(inp->din_root, dlp, drp);
   1330 	dnp->dn_reg = inp->din_root->dn_reg;
   1331 	dt_cg_typecast(inp->din_root, dnp, dlp, drp);
   1332 
   1333 	if (idp->di_kind == DT_IDENT_ARRAY) {
   1334 		for (i = 0; i < inp->din_argc; i++) {
   1335 			pinp = inp->din_argv[i]->di_iarg;
   1336 			pinp->din_root = NULL;
   1337 		}
   1338 	}
   1339 }
   1340 
   1341 static void
   1342 dt_cg_func_typeref(dtrace_hdl_t *dtp, dt_node_t *dnp)
   1343 {
   1344 	dtrace_typeinfo_t dtt;
   1345 	dt_node_t *addr = dnp->dn_args;
   1346 	dt_node_t *nelm = addr->dn_list;
   1347 	dt_node_t *strp = nelm->dn_list;
   1348 	dt_node_t *typs = strp->dn_list;
   1349 	char buf[DT_TYPE_NAMELEN];
   1350 	char *p;
   1351 
   1352 	ctf_type_name(addr->dn_ctfp, addr->dn_type, buf, sizeof (buf));
   1353 
   1354 	/*
   1355 	 * XXX Hack alert! XXX
   1356 	 * The prototype has two dummy args that we munge to represent
   1357 	 * the type string and the type size.
   1358 	 *
   1359 	 * Yes, I hear your grumble, but it works for now. We'll come
   1360 	 * up with a more elegant implementation later. :-)
   1361 	 */
   1362 	free(strp->dn_string);
   1363 
   1364 	if ((p = strchr(buf, '*')) != NULL)
   1365 		*p = '\0';
   1366 
   1367 	strp->dn_string = strdup(buf);
   1368 
   1369 	if (dtrace_lookup_by_type(dtp,  DTRACE_OBJ_EVERY, buf, &dtt) < 0)
   1370 		return;
   1371 
   1372 	typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
   1373 }
   1374 
   1375 static void
   1376 dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
   1377 {
   1378 	ctf_file_t *ctfp = dnp->dn_ctfp;
   1379 	ctf_file_t *octfp;
   1380 	ctf_membinfo_t m;
   1381 	ctf_id_t type;
   1382 
   1383 	dif_instr_t instr;
   1384 	dt_ident_t *idp;
   1385 	ssize_t stroff;
   1386 	uint_t op;
   1387 	int reg;
   1388 
   1389 	switch (dnp->dn_op) {
   1390 	case DT_TOK_COMMA:
   1391 		dt_cg_node(dnp->dn_left, dlp, drp);
   1392 		dt_regset_free(drp, dnp->dn_left->dn_reg);
   1393 		dt_cg_node(dnp->dn_right, dlp, drp);
   1394 		dnp->dn_reg = dnp->dn_right->dn_reg;
   1395 		break;
   1396 
   1397 	case DT_TOK_ASGN:
   1398 		dt_cg_node(dnp->dn_right, dlp, drp);
   1399 		dnp->dn_reg = dnp->dn_right->dn_reg;
   1400 		dt_cg_asgn_op(dnp, dlp, drp);
   1401 		break;
   1402 
   1403 	case DT_TOK_ADD_EQ:
   1404 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD);
   1405 		dt_cg_asgn_op(dnp, dlp, drp);
   1406 		break;
   1407 
   1408 	case DT_TOK_SUB_EQ:
   1409 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB);
   1410 		dt_cg_asgn_op(dnp, dlp, drp);
   1411 		break;
   1412 
   1413 	case DT_TOK_MUL_EQ:
   1414 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL);
   1415 		dt_cg_asgn_op(dnp, dlp, drp);
   1416 		break;
   1417 
   1418 	case DT_TOK_DIV_EQ:
   1419 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1420 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV);
   1421 		dt_cg_asgn_op(dnp, dlp, drp);
   1422 		break;
   1423 
   1424 	case DT_TOK_MOD_EQ:
   1425 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1426 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM);
   1427 		dt_cg_asgn_op(dnp, dlp, drp);
   1428 		break;
   1429 
   1430 	case DT_TOK_AND_EQ:
   1431 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);
   1432 		dt_cg_asgn_op(dnp, dlp, drp);
   1433 		break;
   1434 
   1435 	case DT_TOK_XOR_EQ:
   1436 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);
   1437 		dt_cg_asgn_op(dnp, dlp, drp);
   1438 		break;
   1439 
   1440 	case DT_TOK_OR_EQ:
   1441 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);
   1442 		dt_cg_asgn_op(dnp, dlp, drp);
   1443 		break;
   1444 
   1445 	case DT_TOK_LSH_EQ:
   1446 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL);
   1447 		dt_cg_asgn_op(dnp, dlp, drp);
   1448 		break;
   1449 
   1450 	case DT_TOK_RSH_EQ:
   1451 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1452 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL);
   1453 		dt_cg_asgn_op(dnp, dlp, drp);
   1454 		break;
   1455 
   1456 	case DT_TOK_QUESTION:
   1457 		dt_cg_ternary_op(dnp, dlp, drp);
   1458 		break;
   1459 
   1460 	case DT_TOK_LOR:
   1461 		dt_cg_logical_or(dnp, dlp, drp);
   1462 		break;
   1463 
   1464 	case DT_TOK_LXOR:
   1465 		dt_cg_logical_xor(dnp, dlp, drp);
   1466 		break;
   1467 
   1468 	case DT_TOK_LAND:
   1469 		dt_cg_logical_and(dnp, dlp, drp);
   1470 		break;
   1471 
   1472 	case DT_TOK_BOR:
   1473 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);
   1474 		break;
   1475 
   1476 	case DT_TOK_XOR:
   1477 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);
   1478 		break;
   1479 
   1480 	case DT_TOK_BAND:
   1481 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);
   1482 		break;
   1483 
   1484 	case DT_TOK_EQU:
   1485 		dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BE);
   1486 		break;
   1487 
   1488 	case DT_TOK_NEQ:
   1489 		dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BNE);
   1490 		break;
   1491 
   1492 	case DT_TOK_LT:
   1493 		dt_cg_compare_op(dnp, dlp, drp,
   1494 		    dt_cg_compare_signed(dnp) ? DIF_OP_BL : DIF_OP_BLU);
   1495 		break;
   1496 
   1497 	case DT_TOK_LE:
   1498 		dt_cg_compare_op(dnp, dlp, drp,
   1499 		    dt_cg_compare_signed(dnp) ? DIF_OP_BLE : DIF_OP_BLEU);
   1500 		break;
   1501 
   1502 	case DT_TOK_GT:
   1503 		dt_cg_compare_op(dnp, dlp, drp,
   1504 		    dt_cg_compare_signed(dnp) ? DIF_OP_BG : DIF_OP_BGU);
   1505 		break;
   1506 
   1507 	case DT_TOK_GE:
   1508 		dt_cg_compare_op(dnp, dlp, drp,
   1509 		    dt_cg_compare_signed(dnp) ? DIF_OP_BGE : DIF_OP_BGEU);
   1510 		break;
   1511 
   1512 	case DT_TOK_LSH:
   1513 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL);
   1514 		break;
   1515 
   1516 	case DT_TOK_RSH:
   1517 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1518 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL);
   1519 		break;
   1520 
   1521 	case DT_TOK_ADD:
   1522 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD);
   1523 		break;
   1524 
   1525 	case DT_TOK_SUB:
   1526 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB);
   1527 		break;
   1528 
   1529 	case DT_TOK_MUL:
   1530 		dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL);
   1531 		break;
   1532 
   1533 	case DT_TOK_DIV:
   1534 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1535 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV);
   1536 		break;
   1537 
   1538 	case DT_TOK_MOD:
   1539 		dt_cg_arithmetic_op(dnp, dlp, drp,
   1540 		    (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM);
   1541 		break;
   1542 
   1543 	case DT_TOK_LNEG:
   1544 		dt_cg_logical_neg(dnp, dlp, drp);
   1545 		break;
   1546 
   1547 	case DT_TOK_BNEG:
   1548 		dt_cg_node(dnp->dn_child, dlp, drp);
   1549 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1550 		instr = DIF_INSTR_NOT(dnp->dn_reg, dnp->dn_reg);
   1551 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1552 		break;
   1553 
   1554 	case DT_TOK_PREINC:
   1555 		dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_ADD);
   1556 		break;
   1557 
   1558 	case DT_TOK_POSTINC:
   1559 		dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_ADD);
   1560 		break;
   1561 
   1562 	case DT_TOK_PREDEC:
   1563 		dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_SUB);
   1564 		break;
   1565 
   1566 	case DT_TOK_POSTDEC:
   1567 		dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_SUB);
   1568 		break;
   1569 
   1570 	case DT_TOK_IPOS:
   1571 		dt_cg_node(dnp->dn_child, dlp, drp);
   1572 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1573 		break;
   1574 
   1575 	case DT_TOK_INEG:
   1576 		dt_cg_node(dnp->dn_child, dlp, drp);
   1577 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1578 
   1579 		instr = DIF_INSTR_FMT(DIF_OP_SUB, DIF_REG_R0,
   1580 		    dnp->dn_reg, dnp->dn_reg);
   1581 
   1582 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1583 		break;
   1584 
   1585 	case DT_TOK_DEREF:
   1586 		dt_cg_node(dnp->dn_child, dlp, drp);
   1587 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1588 
   1589 		if (!(dnp->dn_flags & DT_NF_REF)) {
   1590 			uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
   1591 
   1592 			/*
   1593 			 * Save and restore DT_NF_USERLAND across dt_cg_load():
   1594 			 * we need the sign bit from dnp and the user bit from
   1595 			 * dnp->dn_child in order to get the proper opcode.
   1596 			 */
   1597 			dnp->dn_flags |=
   1598 			    (dnp->dn_child->dn_flags & DT_NF_USERLAND);
   1599 
   1600 			instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp,
   1601 			    dnp->dn_type), dnp->dn_reg, dnp->dn_reg);
   1602 
   1603 			dnp->dn_flags &= ~DT_NF_USERLAND;
   1604 			dnp->dn_flags |= ubit;
   1605 
   1606 			dt_irlist_append(dlp,
   1607 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1608 		}
   1609 		break;
   1610 
   1611 	case DT_TOK_ADDROF: {
   1612 		uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
   1613 
   1614 		dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
   1615 		dt_cg_node(dnp->dn_child, dlp, drp);
   1616 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1617 
   1618 		dnp->dn_child->dn_flags &= ~DT_NF_REF;
   1619 		dnp->dn_child->dn_flags |= rbit;
   1620 		break;
   1621 	}
   1622 
   1623 	case DT_TOK_SIZEOF: {
   1624 		size_t size = dt_node_sizeof(dnp->dn_child);
   1625 
   1626 		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1627 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1628 
   1629 		assert(size != 0);
   1630 		dt_cg_setx(dlp, dnp->dn_reg, size);
   1631 		break;
   1632 	}
   1633 
   1634 	case DT_TOK_STRINGOF:
   1635 		dt_cg_node(dnp->dn_child, dlp, drp);
   1636 		dnp->dn_reg = dnp->dn_child->dn_reg;
   1637 		break;
   1638 
   1639 	case DT_TOK_XLATE:
   1640 		/*
   1641 		 * An xlate operator appears in either an XLATOR, indicating a
   1642 		 * reference to a dynamic translator, or an OP2, indicating
   1643 		 * use of the xlate operator in the user's program.  For the
   1644 		 * dynamic case, generate an xlate opcode with a reference to
   1645 		 * the corresponding member, pre-computed for us in dn_members.
   1646 		 */
   1647 		if (dnp->dn_kind == DT_NODE_XLATOR) {
   1648 			dt_xlator_t *dxp = dnp->dn_xlator;
   1649 
   1650 			assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
   1651 			assert(dxp->dx_ident->di_id != 0);
   1652 
   1653 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1654 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1655 
   1656 			if (dxp->dx_arg == -1) {
   1657 				instr = DIF_INSTR_MOV(
   1658 				    dxp->dx_ident->di_id, dnp->dn_reg);
   1659 				dt_irlist_append(dlp,
   1660 				    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1661 				op = DIF_OP_XLATE;
   1662 			} else
   1663 				op = DIF_OP_XLARG;
   1664 
   1665 			instr = DIF_INSTR_XLATE(op, 0, dnp->dn_reg);
   1666 			dt_irlist_append(dlp,
   1667 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1668 
   1669 			dlp->dl_last->di_extern = dnp->dn_xmember;
   1670 			break;
   1671 		}
   1672 
   1673 		assert(dnp->dn_kind == DT_NODE_OP2);
   1674 		dt_cg_node(dnp->dn_right, dlp, drp);
   1675 		dnp->dn_reg = dnp->dn_right->dn_reg;
   1676 		break;
   1677 
   1678 	case DT_TOK_LPAR:
   1679 		dt_cg_node(dnp->dn_right, dlp, drp);
   1680 		dnp->dn_reg = dnp->dn_right->dn_reg;
   1681 		dt_cg_typecast(dnp->dn_right, dnp, dlp, drp);
   1682 		break;
   1683 
   1684 	case DT_TOK_PTR:
   1685 	case DT_TOK_DOT:
   1686 		assert(dnp->dn_right->dn_kind == DT_NODE_IDENT);
   1687 		dt_cg_node(dnp->dn_left, dlp, drp);
   1688 
   1689 		/*
   1690 		 * If the left-hand side of PTR or DOT is a dynamic variable,
   1691 		 * we expect it to be the output of a D translator.   In this
   1692 		 * case, we look up the parse tree corresponding to the member
   1693 		 * that is being accessed and run the code generator over it.
   1694 		 * We then cast the result as if by the assignment operator.
   1695 		 */
   1696 		if ((idp = dt_node_resolve(
   1697 		    dnp->dn_left, DT_IDENT_XLSOU)) != NULL ||
   1698 		    (idp = dt_node_resolve(
   1699 		    dnp->dn_left, DT_IDENT_XLPTR)) != NULL) {
   1700 
   1701 			dt_xlator_t *dxp;
   1702 			dt_node_t *mnp;
   1703 
   1704 			dxp = idp->di_data;
   1705 			mnp = dt_xlator_member(dxp, dnp->dn_right->dn_string);
   1706 			assert(mnp != NULL);
   1707 
   1708 			dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
   1709 			dxp->dx_ident->di_id = dnp->dn_left->dn_reg;
   1710 
   1711 			dt_cg_node(mnp->dn_membexpr, dlp, drp);
   1712 			dnp->dn_reg = mnp->dn_membexpr->dn_reg;
   1713 			dt_cg_typecast(mnp->dn_membexpr, dnp, dlp, drp);
   1714 
   1715 			dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
   1716 			dxp->dx_ident->di_id = 0;
   1717 
   1718 			if (dnp->dn_left->dn_reg != -1)
   1719 				dt_regset_free(drp, dnp->dn_left->dn_reg);
   1720 			break;
   1721 		}
   1722 
   1723 		ctfp = dnp->dn_left->dn_ctfp;
   1724 		type = ctf_type_resolve(ctfp, dnp->dn_left->dn_type);
   1725 
   1726 		if (dnp->dn_op == DT_TOK_PTR) {
   1727 			type = ctf_type_reference(ctfp, type);
   1728 			type = ctf_type_resolve(ctfp, type);
   1729 		}
   1730 
   1731 		if ((ctfp = dt_cg_membinfo(octfp = ctfp, type,
   1732 		    dnp->dn_right->dn_string, &m)) == NULL) {
   1733 			yypcb->pcb_hdl->dt_ctferr = ctf_errno(octfp);
   1734 			longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
   1735 		}
   1736 
   1737 		if (m.ctm_offset != 0) {
   1738 			if ((reg = dt_regset_alloc(drp)) == -1)
   1739 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1740 
   1741 			/*
   1742 			 * If the offset is not aligned on a byte boundary, it
   1743 			 * is a bit-field member and we will extract the value
   1744 			 * bits below after we generate the appropriate load.
   1745 			 */
   1746 			dt_cg_setx(dlp, reg, m.ctm_offset / NBBY);
   1747 
   1748 			instr = DIF_INSTR_FMT(DIF_OP_ADD,
   1749 			    dnp->dn_left->dn_reg, reg, dnp->dn_left->dn_reg);
   1750 
   1751 			dt_irlist_append(dlp,
   1752 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1753 			dt_regset_free(drp, reg);
   1754 		}
   1755 
   1756 		if (!(dnp->dn_flags & DT_NF_REF)) {
   1757 			uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
   1758 
   1759 			/*
   1760 			 * Save and restore DT_NF_USERLAND across dt_cg_load():
   1761 			 * we need the sign bit from dnp and the user bit from
   1762 			 * dnp->dn_left in order to get the proper opcode.
   1763 			 */
   1764 			dnp->dn_flags |=
   1765 			    (dnp->dn_left->dn_flags & DT_NF_USERLAND);
   1766 
   1767 			instr = DIF_INSTR_LOAD(dt_cg_load(dnp,
   1768 			    ctfp, m.ctm_type), dnp->dn_left->dn_reg,
   1769 			    dnp->dn_left->dn_reg);
   1770 
   1771 			dnp->dn_flags &= ~DT_NF_USERLAND;
   1772 			dnp->dn_flags |= ubit;
   1773 
   1774 			dt_irlist_append(dlp,
   1775 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1776 
   1777 			if (dnp->dn_flags & DT_NF_BITFIELD)
   1778 				dt_cg_field_get(dnp, dlp, drp, ctfp, &m);
   1779 		}
   1780 
   1781 		dnp->dn_reg = dnp->dn_left->dn_reg;
   1782 		break;
   1783 
   1784 	case DT_TOK_STRING:
   1785 		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1786 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1787 
   1788 		assert(dnp->dn_kind == DT_NODE_STRING);
   1789 		stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
   1790 
   1791 		if (stroff == -1L)
   1792 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
   1793 		if (stroff > DIF_STROFF_MAX)
   1794 			longjmp(yypcb->pcb_jmpbuf, EDT_STR2BIG);
   1795 
   1796 		instr = DIF_INSTR_SETS((ulong_t)stroff, dnp->dn_reg);
   1797 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
   1798 		break;
   1799 
   1800 	case DT_TOK_IDENT:
   1801 		/*
   1802 		 * If the specified identifier is a variable on which we have
   1803 		 * set the code generator register flag, then this variable
   1804 		 * has already had code generated for it and saved in di_id.
   1805 		 * Allocate a new register and copy the existing value to it.
   1806 		 */
   1807 		if (dnp->dn_kind == DT_NODE_VAR &&
   1808 		    (dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
   1809 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1810 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1811 			instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
   1812 			    dnp->dn_reg);
   1813 			dt_irlist_append(dlp,
   1814 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1815 			break;
   1816 		}
   1817 
   1818 		/*
   1819 		 * Identifiers can represent function calls, variable refs, or
   1820 		 * symbols.  First we check for inlined variables, and handle
   1821 		 * them by generating code for the inline parse tree.
   1822 		 */
   1823 		if (dnp->dn_kind == DT_NODE_VAR &&
   1824 		    (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {
   1825 			dt_cg_inline(dnp, dlp, drp);
   1826 			break;
   1827 		}
   1828 
   1829 		switch (dnp->dn_kind) {
   1830 		case DT_NODE_FUNC: {
   1831 			dtrace_hdl_t *dtp = yypcb->pcb_hdl;
   1832 
   1833 			if ((idp = dnp->dn_ident)->di_kind != DT_IDENT_FUNC) {
   1834 				dnerror(dnp, D_CG_EXPR, "%s %s( ) may not be "
   1835 				    "called from a D expression (D program "
   1836 				    "context required)\n",
   1837 				    dt_idkind_name(idp->di_kind), idp->di_name);
   1838 			}
   1839 
   1840 			switch (idp->di_id) {
   1841 			case DIF_SUBR_TYPEREF:
   1842 				dt_cg_func_typeref(dtp, dnp);
   1843 				break;
   1844 
   1845 			default:
   1846 				break;
   1847 			}
   1848 
   1849 			dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
   1850 
   1851 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1852 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1853 
   1854 			instr = DIF_INSTR_CALL(
   1855 			    dnp->dn_ident->di_id, dnp->dn_reg);
   1856 
   1857 			dt_irlist_append(dlp,
   1858 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1859 
   1860 			break;
   1861 		}
   1862 
   1863 		case DT_NODE_VAR:
   1864 			if (dnp->dn_ident->di_kind == DT_IDENT_XLSOU ||
   1865 			    dnp->dn_ident->di_kind == DT_IDENT_XLPTR) {
   1866 				/*
   1867 				 * This can only happen if we have translated
   1868 				 * args[].  See dt_idcook_args() for details.
   1869 				 */
   1870 				assert(dnp->dn_ident->di_id == DIF_VAR_ARGS);
   1871 				dt_cg_array_op(dnp, dlp, drp);
   1872 				break;
   1873 			}
   1874 
   1875 			if (dnp->dn_ident->di_kind == DT_IDENT_ARRAY) {
   1876 				if (dnp->dn_ident->di_id > DIF_VAR_ARRAY_MAX)
   1877 					dt_cg_assoc_op(dnp, dlp, drp);
   1878 				else
   1879 					dt_cg_array_op(dnp, dlp, drp);
   1880 				break;
   1881 			}
   1882 
   1883 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1884 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1885 
   1886 			if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
   1887 				op = DIF_OP_LDLS;
   1888 			else if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
   1889 				op = DIF_OP_LDTS;
   1890 			else
   1891 				op = DIF_OP_LDGS;
   1892 
   1893 			dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
   1894 
   1895 			instr = DIF_INSTR_LDV(op,
   1896 			    dnp->dn_ident->di_id, dnp->dn_reg);
   1897 
   1898 			dt_irlist_append(dlp,
   1899 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1900 			break;
   1901 
   1902 		case DT_NODE_SYM: {
   1903 			dtrace_hdl_t *dtp = yypcb->pcb_hdl;
   1904 			dtrace_syminfo_t *sip = dnp->dn_ident->di_data;
   1905 			GElf_Sym sym;
   1906 
   1907 			if (dtrace_lookup_by_name(dtp,
   1908 			    sip->dts_object, sip->dts_name, &sym, NULL) == -1) {
   1909 				xyerror(D_UNKNOWN, "cg failed for symbol %s`%s:"
   1910 				    " %s\n", sip->dts_object, sip->dts_name,
   1911 				    dtrace_errmsg(dtp, dtrace_errno(dtp)));
   1912 			}
   1913 
   1914 			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1915 				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1916 
   1917 			dt_cg_xsetx(dlp, dnp->dn_ident,
   1918 			    DT_LBL_NONE, dnp->dn_reg, sym.st_value);
   1919 
   1920 			if (!(dnp->dn_flags & DT_NF_REF)) {
   1921 				instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp,
   1922 				    dnp->dn_type), dnp->dn_reg, dnp->dn_reg);
   1923 				dt_irlist_append(dlp,
   1924 				    dt_cg_node_alloc(DT_LBL_NONE, instr));
   1925 			}
   1926 			break;
   1927 		}
   1928 
   1929 		default:
   1930 			xyerror(D_UNKNOWN, "internal error -- node type %u is "
   1931 			    "not valid for an identifier\n", dnp->dn_kind);
   1932 		}
   1933 		break;
   1934 
   1935 	case DT_TOK_INT:
   1936 		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
   1937 			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
   1938 
   1939 		dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
   1940 		break;
   1941 
   1942 	default:
   1943 		xyerror(D_UNKNOWN, "internal error -- token type %u is not a "
   1944 		    "valid D compilation token\n", dnp->dn_op);
   1945 	}
   1946 }
   1947 
   1948 void
   1949 dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
   1950 {
   1951 	dif_instr_t instr;
   1952 	dt_xlator_t *dxp = NULL;
   1953 
   1954 	if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
   1955 	    dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
   1956 		longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
   1957 
   1958 	dt_regset_reset(pcb->pcb_regs);
   1959 	(void) dt_regset_alloc(pcb->pcb_regs); /* allocate %r0 */
   1960 
   1961 	if (pcb->pcb_inttab != NULL)
   1962 		dt_inttab_destroy(pcb->pcb_inttab);
   1963 
   1964 	if ((pcb->pcb_inttab = dt_inttab_create(yypcb->pcb_hdl)) == NULL)
   1965 		longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
   1966 
   1967 	if (pcb->pcb_strtab != NULL)
   1968 		dt_strtab_destroy(pcb->pcb_strtab);
   1969 
   1970 	if ((pcb->pcb_strtab = dt_strtab_create(BUFSIZ)) == NULL)
   1971 		longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
   1972 
   1973 	dt_irlist_destroy(&pcb->pcb_ir);
   1974 	dt_irlist_create(&pcb->pcb_ir);
   1975 
   1976 	assert(pcb->pcb_dret == NULL);
   1977 	pcb->pcb_dret = dnp;
   1978 
   1979 	if (dt_node_is_dynamic(dnp)) {
   1980 		dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
   1981 		    "of dynamic type\n");
   1982 	}
   1983 
   1984 	/*
   1985 	 * If we're generating code for a translator body, assign the input
   1986 	 * parameter to the first available register (i.e. caller passes %r1).
   1987 	 */
   1988 	if (dnp->dn_kind == DT_NODE_MEMBER) {
   1989 		dxp = dnp->dn_membxlator;
   1990 		dnp = dnp->dn_membexpr;
   1991 
   1992 		dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
   1993 		dxp->dx_ident->di_id = dt_regset_alloc(pcb->pcb_regs);
   1994 	}
   1995 
   1996 	dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
   1997 	instr = DIF_INSTR_RET(dnp->dn_reg);
   1998 	dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
   1999 	dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
   2000 
   2001 	if (dnp->dn_kind == DT_NODE_MEMBER) {
   2002 		dt_regset_free(pcb->pcb_regs, dxp->dx_ident->di_id);
   2003 		dxp->dx_ident->di_id = 0;
   2004 		dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
   2005 	}
   2006 }
   2007