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