17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
22e5803b76SAdam H. Leventhal
237c478bd9Sstevel@tonic-gate /*
247c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
28e5803b76SAdam H. Leventhal /*
29e5803b76SAdam H. Leventhal * Copyright (c) 2012 by Delphix. All rights reserved.
30e5803b76SAdam H. Leventhal */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <setjmp.h>
397c478bd9Sstevel@tonic-gate #include <assert.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include <dt_impl.h>
437c478bd9Sstevel@tonic-gate #include <dt_grammar.h>
447c478bd9Sstevel@tonic-gate #include <dt_parser.h>
457c478bd9Sstevel@tonic-gate #include <dt_provider.h>
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate static void dt_cg_node(dt_node_t *, dt_irlist_t *, dt_regset_t *);
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate static dt_irnode_t *
dt_cg_node_alloc(uint_t label,dif_instr_t instr)507c478bd9Sstevel@tonic-gate dt_cg_node_alloc(uint_t label, dif_instr_t instr)
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate dt_irnode_t *dip = malloc(sizeof (dt_irnode_t));
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate if (dip == NULL)
557c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate dip->di_label = label;
587c478bd9Sstevel@tonic-gate dip->di_instr = instr;
591a7c1b72Smws dip->di_extern = NULL;
607c478bd9Sstevel@tonic-gate dip->di_next = NULL;
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate return (dip);
637c478bd9Sstevel@tonic-gate }
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate * Code generator wrapper function for ctf_member_info. If we are given a
677c478bd9Sstevel@tonic-gate * reference to a forward declaration tag, search the entire type space for
687c478bd9Sstevel@tonic-gate * the actual definition and then call ctf_member_info on the result.
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate static ctf_file_t *
dt_cg_membinfo(ctf_file_t * fp,ctf_id_t type,const char * s,ctf_membinfo_t * mp)717c478bd9Sstevel@tonic-gate dt_cg_membinfo(ctf_file_t *fp, ctf_id_t type, const char *s, ctf_membinfo_t *mp)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate while (ctf_type_kind(fp, type) == CTF_K_FORWARD) {
747c478bd9Sstevel@tonic-gate char n[DT_TYPE_NAMELEN];
757c478bd9Sstevel@tonic-gate dtrace_typeinfo_t dtt;
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate if (ctf_type_name(fp, type, n, sizeof (n)) == NULL ||
787c478bd9Sstevel@tonic-gate dt_type_lookup(n, &dtt) == -1 || (
797c478bd9Sstevel@tonic-gate dtt.dtt_ctfp == fp && dtt.dtt_type == type))
807c478bd9Sstevel@tonic-gate break; /* unable to improve our position */
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate fp = dtt.dtt_ctfp;
837c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dtt.dtt_type);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate if (ctf_member_info(fp, type, s, mp) == CTF_ERR)
877c478bd9Sstevel@tonic-gate return (NULL); /* ctf_errno is set for us */
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate return (fp);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static void
dt_cg_xsetx(dt_irlist_t * dlp,dt_ident_t * idp,uint_t lbl,int reg,uint64_t x)937c478bd9Sstevel@tonic-gate dt_cg_xsetx(dt_irlist_t *dlp, dt_ident_t *idp, uint_t lbl, int reg, uint64_t x)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate int flag = idp != NULL ? DT_INT_PRIVATE : DT_INT_SHARED;
967c478bd9Sstevel@tonic-gate int intoff = dt_inttab_insert(yypcb->pcb_inttab, x, flag);
977c478bd9Sstevel@tonic-gate dif_instr_t instr = DIF_INSTR_SETX((uint_t)intoff, reg);
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate if (intoff == -1)
1007c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate if (intoff > DIF_INTOFF_MAX)
1037c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_INT2BIG);
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl, instr));
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate if (idp != NULL)
1081a7c1b72Smws dlp->dl_last->di_extern = idp;
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate static void
dt_cg_setx(dt_irlist_t * dlp,int reg,uint64_t x)1127c478bd9Sstevel@tonic-gate dt_cg_setx(dt_irlist_t *dlp, int reg, uint64_t x)
1137c478bd9Sstevel@tonic-gate {
1147c478bd9Sstevel@tonic-gate dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, reg, x);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * When loading bit-fields, we want to convert a byte count in the range
1197c478bd9Sstevel@tonic-gate * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
1207c478bd9Sstevel@tonic-gate * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
1217c478bd9Sstevel@tonic-gate */
1227c478bd9Sstevel@tonic-gate static size_t
clp2(size_t x)1237c478bd9Sstevel@tonic-gate clp2(size_t x)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate x--;
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate x |= (x >> 1);
1287c478bd9Sstevel@tonic-gate x |= (x >> 2);
1297c478bd9Sstevel@tonic-gate x |= (x >> 4);
1307c478bd9Sstevel@tonic-gate x |= (x >> 8);
1317c478bd9Sstevel@tonic-gate x |= (x >> 16);
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate return (x + 1);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate * Lookup the correct load opcode to use for the specified node and CTF type.
1387c478bd9Sstevel@tonic-gate * We determine the size and convert it to a 3-bit index. Our lookup table
1397c478bd9Sstevel@tonic-gate * is constructed to use a 5-bit index, consisting of the 3-bit size 0-7, a
1407c478bd9Sstevel@tonic-gate * bit for the sign, and a bit for userland address. For example, a 4-byte
1417c478bd9Sstevel@tonic-gate * signed load from userland would be at the following table index:
1427c478bd9Sstevel@tonic-gate * user=1 sign=1 size=4 => binary index 11011 = decimal index 27
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate static uint_t
dt_cg_load(dt_node_t * dnp,ctf_file_t * ctfp,ctf_id_t type)1457c478bd9Sstevel@tonic-gate dt_cg_load(dt_node_t *dnp, ctf_file_t *ctfp, ctf_id_t type)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate static const uint_t ops[] = {
1487c478bd9Sstevel@tonic-gate DIF_OP_LDUB, DIF_OP_LDUH, 0, DIF_OP_LDUW,
1497c478bd9Sstevel@tonic-gate 0, 0, 0, DIF_OP_LDX,
1507c478bd9Sstevel@tonic-gate DIF_OP_LDSB, DIF_OP_LDSH, 0, DIF_OP_LDSW,
1517c478bd9Sstevel@tonic-gate 0, 0, 0, DIF_OP_LDX,
1527c478bd9Sstevel@tonic-gate DIF_OP_ULDUB, DIF_OP_ULDUH, 0, DIF_OP_ULDUW,
1537c478bd9Sstevel@tonic-gate 0, 0, 0, DIF_OP_ULDX,
1547c478bd9Sstevel@tonic-gate DIF_OP_ULDSB, DIF_OP_ULDSH, 0, DIF_OP_ULDSW,
1557c478bd9Sstevel@tonic-gate 0, 0, 0, DIF_OP_ULDX,
1567c478bd9Sstevel@tonic-gate };
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate ctf_encoding_t e;
1597c478bd9Sstevel@tonic-gate ssize_t size;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate * If we're loading a bit-field, the size of our load is found by
1637c478bd9Sstevel@tonic-gate * rounding cte_bits up to a byte boundary and then finding the
1647c478bd9Sstevel@tonic-gate * nearest power of two to this value (see clp2(), above).
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate if ((dnp->dn_flags & DT_NF_BITFIELD) &&
1677c478bd9Sstevel@tonic-gate ctf_type_encoding(ctfp, type, &e) != CTF_ERR)
1687c478bd9Sstevel@tonic-gate size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
1697c478bd9Sstevel@tonic-gate else
1707c478bd9Sstevel@tonic-gate size = ctf_type_size(ctfp, type);
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate if (size < 1 || size > 8 || (size & (size - 1)) != 0) {
1737c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "internal error -- cg cannot load "
1747c478bd9Sstevel@tonic-gate "size %ld when passed by value\n", (long)size);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate size--; /* convert size to 3-bit index */
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED)
1807c478bd9Sstevel@tonic-gate size |= 0x08;
1817c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_USERLAND)
1827c478bd9Sstevel@tonic-gate size |= 0x10;
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate return (ops[size]);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate static void
dt_cg_ptrsize(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,uint_t op,int dreg)1887c478bd9Sstevel@tonic-gate dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
1897c478bd9Sstevel@tonic-gate uint_t op, int dreg)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate ctf_file_t *ctfp = dnp->dn_ctfp;
1927c478bd9Sstevel@tonic-gate ctf_arinfo_t r;
1937c478bd9Sstevel@tonic-gate dif_instr_t instr;
1947c478bd9Sstevel@tonic-gate ctf_id_t type;
1957c478bd9Sstevel@tonic-gate uint_t kind;
1967c478bd9Sstevel@tonic-gate ssize_t size;
1977c478bd9Sstevel@tonic-gate int sreg;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, dnp->dn_type);
2007c478bd9Sstevel@tonic-gate kind = ctf_type_kind(ctfp, type);
2017c478bd9Sstevel@tonic-gate assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate if (kind == CTF_K_ARRAY) {
2047c478bd9Sstevel@tonic-gate if (ctf_array_info(ctfp, type, &r) != 0) {
2057c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr = ctf_errno(ctfp);
2067c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate type = r.ctr_contents;
2097c478bd9Sstevel@tonic-gate } else
2107c478bd9Sstevel@tonic-gate type = ctf_type_reference(ctfp, type);
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate if ((size = ctf_type_size(ctfp, type)) == 1)
2137c478bd9Sstevel@tonic-gate return; /* multiply or divide by one can be omitted */
2147c478bd9Sstevel@tonic-gate
215e5803b76SAdam H. Leventhal sreg = dt_regset_alloc(drp);
2167c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, sreg, size);
2177c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
2187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
2197c478bd9Sstevel@tonic-gate dt_regset_free(drp, sreg);
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * If the result of a "." or "->" operation is a bit-field, we use this routine
2247c478bd9Sstevel@tonic-gate * to generate an epilogue to the load instruction that extracts the value. In
2257c478bd9Sstevel@tonic-gate * the diagrams below the "ld??" is the load instruction that is generated to
2267c478bd9Sstevel@tonic-gate * load the containing word that is generating prior to calling this function.
2277c478bd9Sstevel@tonic-gate *
2287c478bd9Sstevel@tonic-gate * Epilogue for unsigned fields: Epilogue for signed fields:
2297c478bd9Sstevel@tonic-gate *
2307c478bd9Sstevel@tonic-gate * ldu? [r1], r1 lds? [r1], r1
2317c478bd9Sstevel@tonic-gate * setx USHIFT, r2 setx 64 - SSHIFT, r2
2327c478bd9Sstevel@tonic-gate * srl r1, r2, r1 sll r1, r2, r1
2337c478bd9Sstevel@tonic-gate * setx (1 << bits) - 1, r2 setx 64 - bits, r2
2347c478bd9Sstevel@tonic-gate * and r1, r2, r1 sra r1, r2, r1
2357c478bd9Sstevel@tonic-gate *
2367c478bd9Sstevel@tonic-gate * The *SHIFT constants above changes value depending on the endian-ness of our
2377c478bd9Sstevel@tonic-gate * target architecture. Refer to the comments below for more details.
2387c478bd9Sstevel@tonic-gate */
2397c478bd9Sstevel@tonic-gate static void
dt_cg_field_get(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,ctf_file_t * fp,const ctf_membinfo_t * mp)2407c478bd9Sstevel@tonic-gate dt_cg_field_get(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
2417c478bd9Sstevel@tonic-gate ctf_file_t *fp, const ctf_membinfo_t *mp)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate ctf_encoding_t e;
2447c478bd9Sstevel@tonic-gate dif_instr_t instr;
2457c478bd9Sstevel@tonic-gate uint64_t shift;
2467c478bd9Sstevel@tonic-gate int r1, r2;
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate if (ctf_type_encoding(fp, mp->ctm_type, &e) != 0 || e.cte_bits > 64) {
2497c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "cg: bad field: off %lu type <%ld> "
2507c478bd9Sstevel@tonic-gate "bits %u\n", mp->ctm_offset, mp->ctm_type, e.cte_bits);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
2547c478bd9Sstevel@tonic-gate r1 = dnp->dn_left->dn_reg;
255e5803b76SAdam H. Leventhal r2 = dt_regset_alloc(drp);
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * On little-endian architectures, ctm_offset counts from the right so
2597c478bd9Sstevel@tonic-gate * ctm_offset % NBBY itself is the amount we want to shift right to
2607c478bd9Sstevel@tonic-gate * move the value bits to the little end of the register to mask them.
2617c478bd9Sstevel@tonic-gate * On big-endian architectures, ctm_offset counts from the left so we
2627c478bd9Sstevel@tonic-gate * must subtract (ctm_offset % NBBY + cte_bits) from the size in bits
2637c478bd9Sstevel@tonic-gate * we used for the load. The size of our load in turn is found by
2647c478bd9Sstevel@tonic-gate * rounding cte_bits up to a byte boundary and then finding the
2657c478bd9Sstevel@tonic-gate * nearest power of two to this value (see clp2(), above). These
2667c478bd9Sstevel@tonic-gate * properties are used to compute shift as USHIFT or SSHIFT, below.
2677c478bd9Sstevel@tonic-gate */
2687c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_SIGNED) {
2697c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN
2707c478bd9Sstevel@tonic-gate shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
2717c478bd9Sstevel@tonic-gate mp->ctm_offset % NBBY;
2727c478bd9Sstevel@tonic-gate #else
2737c478bd9Sstevel@tonic-gate shift = mp->ctm_offset % NBBY + e.cte_bits;
2747c478bd9Sstevel@tonic-gate #endif
2757c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, 64 - shift);
2767c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SLL, r1, r2, r1);
2777c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, 64 - e.cte_bits);
2807c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SRA, r1, r2, r1);
2817c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
2827c478bd9Sstevel@tonic-gate } else {
2837c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN
2847c478bd9Sstevel@tonic-gate shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
2857c478bd9Sstevel@tonic-gate (mp->ctm_offset % NBBY + e.cte_bits);
2867c478bd9Sstevel@tonic-gate #else
2877c478bd9Sstevel@tonic-gate shift = mp->ctm_offset % NBBY;
2887c478bd9Sstevel@tonic-gate #endif
2897c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, shift);
2907c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SRL, r1, r2, r1);
2917c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, (1ULL << e.cte_bits) - 1);
2947c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_AND, r1, r2, r1);
2957c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate dt_regset_free(drp, r2);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate /*
3027c478bd9Sstevel@tonic-gate * If the destination of a store operation is a bit-field, we use this routine
3037c478bd9Sstevel@tonic-gate * to generate a prologue to the store instruction that loads the surrounding
3047c478bd9Sstevel@tonic-gate * bits, clears the destination field, and ORs in the new value of the field.
3057c478bd9Sstevel@tonic-gate * In the diagram below the "st?" is the store instruction that is generated to
3067c478bd9Sstevel@tonic-gate * store the containing word that is generating after calling this function.
3077c478bd9Sstevel@tonic-gate *
3087c478bd9Sstevel@tonic-gate * ld [dst->dn_reg], r1
3097c478bd9Sstevel@tonic-gate * setx ~(((1 << cte_bits) - 1) << (ctm_offset % NBBY)), r2
3107c478bd9Sstevel@tonic-gate * and r1, r2, r1
3117c478bd9Sstevel@tonic-gate *
3127c478bd9Sstevel@tonic-gate * setx (1 << cte_bits) - 1, r2
3137c478bd9Sstevel@tonic-gate * and src->dn_reg, r2, r2
3147c478bd9Sstevel@tonic-gate * setx ctm_offset % NBBY, r3
3157c478bd9Sstevel@tonic-gate * sll r2, r3, r2
3167c478bd9Sstevel@tonic-gate *
3177c478bd9Sstevel@tonic-gate * or r1, r2, r1
3187c478bd9Sstevel@tonic-gate * st? r1, [dst->dn_reg]
3197c478bd9Sstevel@tonic-gate *
3207c478bd9Sstevel@tonic-gate * This routine allocates a new register to hold the value to be stored and
3217c478bd9Sstevel@tonic-gate * returns it. The caller is responsible for freeing this register later.
3227c478bd9Sstevel@tonic-gate */
3237c478bd9Sstevel@tonic-gate static int
dt_cg_field_set(dt_node_t * src,dt_irlist_t * dlp,dt_regset_t * drp,dt_node_t * dst)3247c478bd9Sstevel@tonic-gate dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
3257c478bd9Sstevel@tonic-gate dt_regset_t *drp, dt_node_t *dst)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate uint64_t cmask, fmask, shift;
3287c478bd9Sstevel@tonic-gate dif_instr_t instr;
3297c478bd9Sstevel@tonic-gate int r1, r2, r3;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate ctf_membinfo_t m;
3327c478bd9Sstevel@tonic-gate ctf_encoding_t e;
3337c478bd9Sstevel@tonic-gate ctf_file_t *fp, *ofp;
3347c478bd9Sstevel@tonic-gate ctf_id_t type;
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate assert(dst->dn_op == DT_TOK_PTR || dst->dn_op == DT_TOK_DOT);
3377c478bd9Sstevel@tonic-gate assert(dst->dn_right->dn_kind == DT_NODE_IDENT);
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate fp = dst->dn_left->dn_ctfp;
3407c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, dst->dn_left->dn_type);
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate if (dst->dn_op == DT_TOK_PTR) {
3437c478bd9Sstevel@tonic-gate type = ctf_type_reference(fp, type);
3447c478bd9Sstevel@tonic-gate type = ctf_type_resolve(fp, type);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate if ((fp = dt_cg_membinfo(ofp = fp, type,
3487c478bd9Sstevel@tonic-gate dst->dn_right->dn_string, &m)) == NULL) {
3497c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr = ctf_errno(ofp);
3507c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (ctf_type_encoding(fp, m.ctm_type, &e) != 0 || e.cte_bits > 64) {
3547c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "cg: bad field: off %lu type <%ld> "
3557c478bd9Sstevel@tonic-gate "bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
358e5803b76SAdam H. Leventhal r1 = dt_regset_alloc(drp);
359e5803b76SAdam H. Leventhal r2 = dt_regset_alloc(drp);
360e5803b76SAdam H. Leventhal r3 = dt_regset_alloc(drp);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate * Compute shifts and masks. We need to compute "shift" as the amount
3647c478bd9Sstevel@tonic-gate * we need to shift left to position our field in the containing word.
3657c478bd9Sstevel@tonic-gate * Refer to the comments in dt_cg_field_get(), above, for more info.
3667c478bd9Sstevel@tonic-gate * We then compute fmask as the mask that truncates the value in the
3677c478bd9Sstevel@tonic-gate * input register to width cte_bits, and cmask as the mask used to
3687c478bd9Sstevel@tonic-gate * pass through the containing bits and zero the field bits.
3697c478bd9Sstevel@tonic-gate */
3707c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN
3717c478bd9Sstevel@tonic-gate shift = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY) * NBBY -
3727c478bd9Sstevel@tonic-gate (m.ctm_offset % NBBY + e.cte_bits);
3737c478bd9Sstevel@tonic-gate #else
3747c478bd9Sstevel@tonic-gate shift = m.ctm_offset % NBBY;
3757c478bd9Sstevel@tonic-gate #endif
3767c478bd9Sstevel@tonic-gate fmask = (1ULL << e.cte_bits) - 1;
3777c478bd9Sstevel@tonic-gate cmask = ~(fmask << shift);
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LOAD(
3807c478bd9Sstevel@tonic-gate dt_cg_load(dst, fp, m.ctm_type), dst->dn_reg, r1);
3817c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, cmask);
3847c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_AND, r1, r2, r1);
3857c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, fmask);
3887c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_AND, src->dn_reg, r2, r2);
3897c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r3, shift);
3927c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SLL, r2, r3, r2);
3937c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_OR, r1, r2, r1);
3967c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate dt_regset_free(drp, r3);
3997c478bd9Sstevel@tonic-gate dt_regset_free(drp, r2);
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate return (r1);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
4047c478bd9Sstevel@tonic-gate static void
dt_cg_store(dt_node_t * src,dt_irlist_t * dlp,dt_regset_t * drp,dt_node_t * dst)4057c478bd9Sstevel@tonic-gate dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate ctf_encoding_t e;
4087c478bd9Sstevel@tonic-gate dif_instr_t instr;
4097c478bd9Sstevel@tonic-gate size_t size;
4107c478bd9Sstevel@tonic-gate int reg;
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate * If we're loading a bit-field, the size of our store is found by
4147c478bd9Sstevel@tonic-gate * rounding dst's cte_bits up to a byte boundary and then finding the
4157c478bd9Sstevel@tonic-gate * nearest power of two to this value (see clp2(), above).
4167c478bd9Sstevel@tonic-gate */
4177c478bd9Sstevel@tonic-gate if ((dst->dn_flags & DT_NF_BITFIELD) &&
4187c478bd9Sstevel@tonic-gate ctf_type_encoding(dst->dn_ctfp, dst->dn_type, &e) != CTF_ERR)
4197c478bd9Sstevel@tonic-gate size = clp2(P2ROUNDUP(e.cte_bits, NBBY) / NBBY);
4207c478bd9Sstevel@tonic-gate else
4217c478bd9Sstevel@tonic-gate size = dt_node_type_size(src);
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate if (src->dn_flags & DT_NF_REF) {
424e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
4257c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, reg, size);
4267c478bd9Sstevel@tonic-gate instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
4277c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
4287c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
4297c478bd9Sstevel@tonic-gate } else {
4307c478bd9Sstevel@tonic-gate if (dst->dn_flags & DT_NF_BITFIELD)
4317c478bd9Sstevel@tonic-gate reg = dt_cg_field_set(src, dlp, drp, dst);
4327c478bd9Sstevel@tonic-gate else
4337c478bd9Sstevel@tonic-gate reg = src->dn_reg;
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate switch (size) {
4367c478bd9Sstevel@tonic-gate case 1:
4377c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STORE(DIF_OP_STB, reg, dst->dn_reg);
4387c478bd9Sstevel@tonic-gate break;
4397c478bd9Sstevel@tonic-gate case 2:
4407c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STORE(DIF_OP_STH, reg, dst->dn_reg);
4417c478bd9Sstevel@tonic-gate break;
4427c478bd9Sstevel@tonic-gate case 4:
4437c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STORE(DIF_OP_STW, reg, dst->dn_reg);
4447c478bd9Sstevel@tonic-gate break;
4457c478bd9Sstevel@tonic-gate case 8:
4467c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STORE(DIF_OP_STX, reg, dst->dn_reg);
4477c478bd9Sstevel@tonic-gate break;
4487c478bd9Sstevel@tonic-gate default:
4497c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "internal error -- cg cannot store "
4507c478bd9Sstevel@tonic-gate "size %lu when passed by value\n", (ulong_t)size);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate if (dst->dn_flags & DT_NF_BITFIELD)
4557c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate * Generate code for a typecast or for argument promotion from the type of the
4617c478bd9Sstevel@tonic-gate * actual to the type of the formal. We need to generate code for casts when
4627c478bd9Sstevel@tonic-gate * a scalar type is being narrowed or changing signed-ness. We first shift the
4637c478bd9Sstevel@tonic-gate * desired bits high (losing excess bits if narrowing) and then shift them down
4647c478bd9Sstevel@tonic-gate * using logical shift (unsigned result) or arithmetic shift (signed result).
4657c478bd9Sstevel@tonic-gate */
4667c478bd9Sstevel@tonic-gate static void
dt_cg_typecast(const dt_node_t * src,const dt_node_t * dst,dt_irlist_t * dlp,dt_regset_t * drp)4677c478bd9Sstevel@tonic-gate dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
4687c478bd9Sstevel@tonic-gate dt_irlist_t *dlp, dt_regset_t *drp)
4697c478bd9Sstevel@tonic-gate {
4707c478bd9Sstevel@tonic-gate size_t srcsize = dt_node_type_size(src);
4717c478bd9Sstevel@tonic-gate size_t dstsize = dt_node_type_size(dst);
4727c478bd9Sstevel@tonic-gate
4737c478bd9Sstevel@tonic-gate dif_instr_t instr;
474e5803b76SAdam H. Leventhal int rg;
4757c478bd9Sstevel@tonic-gate
476e5803b76SAdam H. Leventhal if (!dt_node_is_scalar(dst))
477e5803b76SAdam H. Leventhal return; /* not a scalar */
478e5803b76SAdam H. Leventhal if (dstsize == srcsize &&
479*9149877bSBryan Cantrill ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) == 0)
480e5803b76SAdam H. Leventhal return; /* not narrowing or changing signed-ness */
481e5803b76SAdam H. Leventhal if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0)
482e5803b76SAdam H. Leventhal return; /* nothing to do in this case */
4837c478bd9Sstevel@tonic-gate
484e5803b76SAdam H. Leventhal rg = dt_regset_alloc(drp);
4857c478bd9Sstevel@tonic-gate
486e5803b76SAdam H. Leventhal if (dstsize > srcsize) {
487e5803b76SAdam H. Leventhal int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
488e5803b76SAdam H. Leventhal int s = (dstsize - srcsize) * NBBY;
4897c478bd9Sstevel@tonic-gate
490e5803b76SAdam H. Leventhal dt_cg_setx(dlp, rg, n);
491e5803b76SAdam H. Leventhal
492e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
493e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
494e5803b76SAdam H. Leventhal
495e5803b76SAdam H. Leventhal if ((dst->dn_flags & DT_NF_SIGNED) || n == s) {
496e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_SRA,
497e5803b76SAdam H. Leventhal dst->dn_reg, rg, dst->dn_reg);
498e5803b76SAdam H. Leventhal dt_irlist_append(dlp,
499e5803b76SAdam H. Leventhal dt_cg_node_alloc(DT_LBL_NONE, instr));
500e5803b76SAdam H. Leventhal } else {
501e5803b76SAdam H. Leventhal dt_cg_setx(dlp, rg, s);
502e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_SRA,
503e5803b76SAdam H. Leventhal dst->dn_reg, rg, dst->dn_reg);
504e5803b76SAdam H. Leventhal dt_irlist_append(dlp,
505e5803b76SAdam H. Leventhal dt_cg_node_alloc(DT_LBL_NONE, instr));
506e5803b76SAdam H. Leventhal dt_cg_setx(dlp, rg, n - s);
507e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_SRL,
508e5803b76SAdam H. Leventhal dst->dn_reg, rg, dst->dn_reg);
509e5803b76SAdam H. Leventhal dt_irlist_append(dlp,
510e5803b76SAdam H. Leventhal dt_cg_node_alloc(DT_LBL_NONE, instr));
511e5803b76SAdam H. Leventhal }
512e5803b76SAdam H. Leventhal } else if (dstsize != sizeof (uint64_t)) {
513e5803b76SAdam H. Leventhal int n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
514e5803b76SAdam H. Leventhal
515e5803b76SAdam H. Leventhal dt_cg_setx(dlp, rg, n);
516e5803b76SAdam H. Leventhal
517e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
5187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
521e5803b76SAdam H. Leventhal DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, rg, dst->dn_reg);
5227c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
5237c478bd9Sstevel@tonic-gate }
524e5803b76SAdam H. Leventhal
525e5803b76SAdam H. Leventhal dt_regset_free(drp, rg);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate * Generate code to push the specified argument list on to the tuple stack.
5307c478bd9Sstevel@tonic-gate * We use this routine for handling subroutine calls and associative arrays.
5317c478bd9Sstevel@tonic-gate * We must first generate code for all subexpressions before loading the stack
5327c478bd9Sstevel@tonic-gate * because any subexpression could itself require the use of the tuple stack.
5337c478bd9Sstevel@tonic-gate * This holds a number of registers equal to the number of arguments, but this
5347c478bd9Sstevel@tonic-gate * is not a huge problem because the number of arguments can't exceed the
5357c478bd9Sstevel@tonic-gate * number of tuple register stack elements anyway. At most one extra register
5367c478bd9Sstevel@tonic-gate * is required (either by dt_cg_typecast() or for dtdt_size, below). This
5377c478bd9Sstevel@tonic-gate * implies that a DIF implementation should offer a number of general purpose
5387c478bd9Sstevel@tonic-gate * registers at least one greater than the number of tuple registers.
5397c478bd9Sstevel@tonic-gate */
5407c478bd9Sstevel@tonic-gate static void
dt_cg_arglist(dt_ident_t * idp,dt_node_t * args,dt_irlist_t * dlp,dt_regset_t * drp)5417c478bd9Sstevel@tonic-gate dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
5427c478bd9Sstevel@tonic-gate dt_irlist_t *dlp, dt_regset_t *drp)
5437c478bd9Sstevel@tonic-gate {
5447c478bd9Sstevel@tonic-gate const dt_idsig_t *isp = idp->di_data;
5457c478bd9Sstevel@tonic-gate dt_node_t *dnp;
5467c478bd9Sstevel@tonic-gate int i = 0;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
5497c478bd9Sstevel@tonic-gate dt_cg_node(dnp, dlp, drp);
5507c478bd9Sstevel@tonic-gate
551e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
5547c478bd9Sstevel@tonic-gate dtrace_diftype_t t;
5557c478bd9Sstevel@tonic-gate dif_instr_t instr;
5567c478bd9Sstevel@tonic-gate uint_t op;
5577c478bd9Sstevel@tonic-gate int reg;
5587c478bd9Sstevel@tonic-gate
5591a7c1b72Smws dt_node_diftype(yypcb->pcb_hdl, dnp, &t);
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate isp->dis_args[i].dn_reg = dnp->dn_reg; /* re-use register */
5627c478bd9Sstevel@tonic-gate dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
5637c478bd9Sstevel@tonic-gate isp->dis_args[i].dn_reg = -1;
5647c478bd9Sstevel@tonic-gate
565e5803b76SAdam H. Leventhal if (t.dtdt_flags & DIF_TF_BYREF) {
5667c478bd9Sstevel@tonic-gate op = DIF_OP_PUSHTR;
5677c478bd9Sstevel@tonic-gate if (t.dtdt_size != 0) {
568e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
5697c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, reg, t.dtdt_size);
570e5803b76SAdam H. Leventhal } else {
5717c478bd9Sstevel@tonic-gate reg = DIF_REG_R0;
572e5803b76SAdam H. Leventhal }
573e5803b76SAdam H. Leventhal } else {
574e5803b76SAdam H. Leventhal op = DIF_OP_PUSHTV;
575e5803b76SAdam H. Leventhal reg = DIF_REG_R0;
576e5803b76SAdam H. Leventhal }
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
5797c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
5807c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_reg);
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate if (reg != DIF_REG_R0)
5837c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate if (i > yypcb->pcb_hdl->dt_conf.dtc_diftupregs)
5877c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOTUPREG);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate static void
dt_cg_arithmetic_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,uint_t op)5917c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dt_node_t *dnp, dt_irlist_t *dlp,
5927c478bd9Sstevel@tonic-gate dt_regset_t *drp, uint_t op)
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate int is_ptr_op = (dnp->dn_op == DT_TOK_ADD || dnp->dn_op == DT_TOK_SUB ||
5957c478bd9Sstevel@tonic-gate dnp->dn_op == DT_TOK_ADD_EQ || dnp->dn_op == DT_TOK_SUB_EQ);
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate int lp_is_ptr = dt_node_is_pointer(dnp->dn_left);
5987c478bd9Sstevel@tonic-gate int rp_is_ptr = dt_node_is_pointer(dnp->dn_right);
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate dif_instr_t instr;
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate if (lp_is_ptr && rp_is_ptr) {
6037c478bd9Sstevel@tonic-gate assert(dnp->dn_op == DT_TOK_SUB);
6047c478bd9Sstevel@tonic-gate is_ptr_op = 0;
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
6087c478bd9Sstevel@tonic-gate if (is_ptr_op && rp_is_ptr)
6097c478bd9Sstevel@tonic-gate dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_left->dn_reg);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
6127c478bd9Sstevel@tonic-gate if (is_ptr_op && lp_is_ptr)
6137c478bd9Sstevel@tonic-gate dt_cg_ptrsize(dnp, dlp, drp, DIF_OP_MUL, dnp->dn_right->dn_reg);
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(op, dnp->dn_left->dn_reg,
6167c478bd9Sstevel@tonic-gate dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
6197c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_right->dn_reg);
6207c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_left->dn_reg;
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate if (lp_is_ptr && rp_is_ptr)
6237c478bd9Sstevel@tonic-gate dt_cg_ptrsize(dnp->dn_right,
6247c478bd9Sstevel@tonic-gate dlp, drp, DIF_OP_UDIV, dnp->dn_reg);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate static uint_t
dt_cg_stvar(const dt_ident_t * idp)6287c478bd9Sstevel@tonic-gate dt_cg_stvar(const dt_ident_t *idp)
6297c478bd9Sstevel@tonic-gate {
6307c478bd9Sstevel@tonic-gate static const uint_t aops[] = { DIF_OP_STGAA, DIF_OP_STTAA, DIF_OP_NOP };
6317c478bd9Sstevel@tonic-gate static const uint_t sops[] = { DIF_OP_STGS, DIF_OP_STTS, DIF_OP_STLS };
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate uint_t i = (((idp->di_flags & DT_IDFLG_LOCAL) != 0) << 1) |
6347c478bd9Sstevel@tonic-gate ((idp->di_flags & DT_IDFLG_TLS) != 0);
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate return (idp->di_kind == DT_IDENT_ARRAY ? aops[i] : sops[i]);
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate
6397c478bd9Sstevel@tonic-gate static void
dt_cg_prearith_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,uint_t op)6407c478bd9Sstevel@tonic-gate dt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
6417c478bd9Sstevel@tonic-gate {
6427c478bd9Sstevel@tonic-gate ctf_file_t *ctfp = dnp->dn_ctfp;
6437c478bd9Sstevel@tonic-gate dif_instr_t instr;
6447c478bd9Sstevel@tonic-gate ctf_id_t type;
6457c478bd9Sstevel@tonic-gate ssize_t size = 1;
6467c478bd9Sstevel@tonic-gate int reg;
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate if (dt_node_is_pointer(dnp)) {
6497c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, dnp->dn_type);
6507c478bd9Sstevel@tonic-gate assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
6517c478bd9Sstevel@tonic-gate size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
6557c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
6567c478bd9Sstevel@tonic-gate
657e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
6587c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, reg, size);
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
6617c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
6627c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate /*
6657c478bd9Sstevel@tonic-gate * If we are modifying a variable, generate an stv instruction from
6667c478bd9Sstevel@tonic-gate * the variable specified by the identifier. If we are storing to a
6677c478bd9Sstevel@tonic-gate * memory address, generate code again for the left-hand side using
6687c478bd9Sstevel@tonic-gate * DT_NF_REF to get the address, and then generate a store to it.
6697c478bd9Sstevel@tonic-gate * In both paths, we store the value in dnp->dn_reg (the new value).
6707c478bd9Sstevel@tonic-gate */
6717c478bd9Sstevel@tonic-gate if (dnp->dn_child->dn_kind == DT_NODE_VAR) {
6727c478bd9Sstevel@tonic-gate dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate idp->di_flags |= DT_IDFLG_DIFW;
6757c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STV(dt_cg_stvar(idp),
6767c478bd9Sstevel@tonic-gate idp->di_id, dnp->dn_reg);
6777c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
6787c478bd9Sstevel@tonic-gate } else {
6797c478bd9Sstevel@tonic-gate uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);
6827c478bd9Sstevel@tonic-gate assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);
6837c478bd9Sstevel@tonic-gate
6847c478bd9Sstevel@tonic-gate dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
6857c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate dt_cg_store(dnp, dlp, drp, dnp->dn_child);
6887c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_child->dn_reg);
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags &= ~DT_NF_REF;
6917c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags |= rbit;
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate static void
dt_cg_postarith_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,uint_t op)6967c478bd9Sstevel@tonic-gate dt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,
6977c478bd9Sstevel@tonic-gate dt_regset_t *drp, uint_t op)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate ctf_file_t *ctfp = dnp->dn_ctfp;
7007c478bd9Sstevel@tonic-gate dif_instr_t instr;
7017c478bd9Sstevel@tonic-gate ctf_id_t type;
7027c478bd9Sstevel@tonic-gate ssize_t size = 1;
7037c478bd9Sstevel@tonic-gate int nreg;
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate if (dt_node_is_pointer(dnp)) {
7067c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, dnp->dn_type);
7077c478bd9Sstevel@tonic-gate assert(ctf_type_kind(ctfp, type) == CTF_K_POINTER);
7087c478bd9Sstevel@tonic-gate size = ctf_type_size(ctfp, ctf_type_reference(ctfp, type));
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
7127c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
7137c478bd9Sstevel@tonic-gate
714e5803b76SAdam H. Leventhal nreg = dt_regset_alloc(drp);
7157c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, nreg, size);
7167c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
7177c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate /*
7207c478bd9Sstevel@tonic-gate * If we are modifying a variable, generate an stv instruction from
7217c478bd9Sstevel@tonic-gate * the variable specified by the identifier. If we are storing to a
7227c478bd9Sstevel@tonic-gate * memory address, generate code again for the left-hand side using
7237c478bd9Sstevel@tonic-gate * DT_NF_REF to get the address, and then generate a store to it.
7247c478bd9Sstevel@tonic-gate * In both paths, we store the value from 'nreg' (the new value).
7257c478bd9Sstevel@tonic-gate */
7267c478bd9Sstevel@tonic-gate if (dnp->dn_child->dn_kind == DT_NODE_VAR) {
7277c478bd9Sstevel@tonic-gate dt_ident_t *idp = dt_ident_resolve(dnp->dn_child->dn_ident);
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate idp->di_flags |= DT_IDFLG_DIFW;
7307c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STV(dt_cg_stvar(idp), idp->di_id, nreg);
7317c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
7327c478bd9Sstevel@tonic-gate } else {
7337c478bd9Sstevel@tonic-gate uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
7347c478bd9Sstevel@tonic-gate int oreg = dnp->dn_reg;
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate assert(dnp->dn_child->dn_flags & DT_NF_WRITABLE);
7377c478bd9Sstevel@tonic-gate assert(dnp->dn_child->dn_flags & DT_NF_LVALUE);
7387c478bd9Sstevel@tonic-gate
7397c478bd9Sstevel@tonic-gate dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
7407c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate dnp->dn_reg = nreg;
7437c478bd9Sstevel@tonic-gate dt_cg_store(dnp, dlp, drp, dnp->dn_child);
7447c478bd9Sstevel@tonic-gate dnp->dn_reg = oreg;
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_child->dn_reg);
7477c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags &= ~DT_NF_REF;
7487c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags |= rbit;
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate dt_regset_free(drp, nreg);
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * Determine if we should perform signed or unsigned comparison for an OP2.
7567c478bd9Sstevel@tonic-gate * If both operands are of arithmetic type, perform the usual arithmetic
7577c478bd9Sstevel@tonic-gate * conversions to determine the common real type for comparison [ISOC 6.5.8.3].
7587c478bd9Sstevel@tonic-gate */
7597c478bd9Sstevel@tonic-gate static int
dt_cg_compare_signed(dt_node_t * dnp)7607c478bd9Sstevel@tonic-gate dt_cg_compare_signed(dt_node_t *dnp)
7617c478bd9Sstevel@tonic-gate {
7627c478bd9Sstevel@tonic-gate dt_node_t dn;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate if (dt_node_is_string(dnp->dn_left) ||
7657c478bd9Sstevel@tonic-gate dt_node_is_string(dnp->dn_right))
7667c478bd9Sstevel@tonic-gate return (1); /* strings always compare signed */
7677c478bd9Sstevel@tonic-gate else if (!dt_node_is_arith(dnp->dn_left) ||
7687c478bd9Sstevel@tonic-gate !dt_node_is_arith(dnp->dn_right))
7697c478bd9Sstevel@tonic-gate return (0); /* non-arithmetic types always compare unsigned */
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate bzero(&dn, sizeof (dn));
7727c478bd9Sstevel@tonic-gate dt_node_promote(dnp->dn_left, dnp->dn_right, &dn);
7737c478bd9Sstevel@tonic-gate return (dn.dn_flags & DT_NF_SIGNED);
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate static void
dt_cg_compare_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp,uint_t op)7777c478bd9Sstevel@tonic-gate dt_cg_compare_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate uint_t lbl_true = dt_irlist_label(dlp);
7807c478bd9Sstevel@tonic-gate uint_t lbl_post = dt_irlist_label(dlp);
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate dif_instr_t instr;
7837c478bd9Sstevel@tonic-gate uint_t opc;
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
7867c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate if (dt_node_is_string(dnp->dn_left) || dt_node_is_string(dnp->dn_right))
7897c478bd9Sstevel@tonic-gate opc = DIF_OP_SCMP;
7907c478bd9Sstevel@tonic-gate else
7917c478bd9Sstevel@tonic-gate opc = DIF_OP_CMP;
7927c478bd9Sstevel@tonic-gate
7937c478bd9Sstevel@tonic-gate instr = DIF_INSTR_CMP(opc, dnp->dn_left->dn_reg, dnp->dn_right->dn_reg);
7947c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
7957c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_right->dn_reg);
7967c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_left->dn_reg;
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(op, lbl_true);
7997c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8007c478bd9Sstevel@tonic-gate
8017c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
8027c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
8057c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);
8087c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate * Code generation for the ternary op requires some trickery with the assembler
8137c478bd9Sstevel@tonic-gate * in order to conserve registers. We generate code for dn_expr and dn_left
8147c478bd9Sstevel@tonic-gate * and free their registers so they do not have be consumed across codegen for
8157c478bd9Sstevel@tonic-gate * dn_right. We insert a dummy MOV at the end of dn_left into the destination
8167c478bd9Sstevel@tonic-gate * register, which is not yet known because we haven't done dn_right yet, and
8177c478bd9Sstevel@tonic-gate * save the pointer to this instruction node. We then generate code for
8187c478bd9Sstevel@tonic-gate * dn_right and use its register as our output. Finally, we reach back and
8197c478bd9Sstevel@tonic-gate * patch the instruction for dn_left to move its output into this register.
8207c478bd9Sstevel@tonic-gate */
8217c478bd9Sstevel@tonic-gate static void
dt_cg_ternary_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)8227c478bd9Sstevel@tonic-gate dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
8237c478bd9Sstevel@tonic-gate {
8247c478bd9Sstevel@tonic-gate uint_t lbl_false = dt_irlist_label(dlp);
8257c478bd9Sstevel@tonic-gate uint_t lbl_post = dt_irlist_label(dlp);
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate dif_instr_t instr;
8287c478bd9Sstevel@tonic-gate dt_irnode_t *dip;
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_expr, dlp, drp);
8317c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_expr->dn_reg);
8327c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8337c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_expr->dn_reg);
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
8367c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
8397c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, DIF_REG_R0);
8407c478bd9Sstevel@tonic-gate dip = dt_cg_node_alloc(DT_LBL_NONE, instr); /* save dip for below */
8417c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dip);
8427c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
8437c478bd9Sstevel@tonic-gate
8447c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
8457c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8467c478bd9Sstevel@tonic-gate
8477c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, DIF_INSTR_NOP));
8487c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
8497c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate /*
8527c478bd9Sstevel@tonic-gate * Now that dn_reg is assigned, reach back and patch the correct MOV
8537c478bd9Sstevel@tonic-gate * instruction into the tail of dn_left. We know dn_reg was unused
8547c478bd9Sstevel@tonic-gate * at that point because otherwise dn_right couldn't have allocated it.
8557c478bd9Sstevel@tonic-gate */
8567c478bd9Sstevel@tonic-gate dip->di_instr = DIF_INSTR_MOV(dnp->dn_left->dn_reg, dnp->dn_reg);
8577c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate static void
dt_cg_logical_and(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)8617c478bd9Sstevel@tonic-gate dt_cg_logical_and(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
8627c478bd9Sstevel@tonic-gate {
8637c478bd9Sstevel@tonic-gate uint_t lbl_false = dt_irlist_label(dlp);
8647c478bd9Sstevel@tonic-gate uint_t lbl_post = dt_irlist_label(dlp);
8657c478bd9Sstevel@tonic-gate
8667c478bd9Sstevel@tonic-gate dif_instr_t instr;
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
8697c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
8707c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8717c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
8747c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
8777c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
8787c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8797c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
8827c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_reg, 1);
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
8877c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
8907c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate static void
dt_cg_logical_xor(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)8967c478bd9Sstevel@tonic-gate dt_cg_logical_xor(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
8977c478bd9Sstevel@tonic-gate {
8987c478bd9Sstevel@tonic-gate uint_t lbl_next = dt_irlist_label(dlp);
8997c478bd9Sstevel@tonic-gate uint_t lbl_tail = dt_irlist_label(dlp);
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate dif_instr_t instr;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
9047c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
9057c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_next);
9087c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9097c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_left->dn_reg, 1);
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_next, DIF_INSTR_NOP));
9127c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
9157c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9167c478bd9Sstevel@tonic-gate
9177c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_tail);
9187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9197c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_right->dn_reg, 1);
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_XOR, dnp->dn_left->dn_reg,
9227c478bd9Sstevel@tonic-gate dnp->dn_right->dn_reg, dnp->dn_left->dn_reg);
9237c478bd9Sstevel@tonic-gate
9247c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_tail, instr));
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_right->dn_reg);
9277c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_left->dn_reg;
9287c478bd9Sstevel@tonic-gate }
9297c478bd9Sstevel@tonic-gate
9307c478bd9Sstevel@tonic-gate static void
dt_cg_logical_or(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)9317c478bd9Sstevel@tonic-gate dt_cg_logical_or(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
9327c478bd9Sstevel@tonic-gate {
9337c478bd9Sstevel@tonic-gate uint_t lbl_true = dt_irlist_label(dlp);
9347c478bd9Sstevel@tonic-gate uint_t lbl_false = dt_irlist_label(dlp);
9357c478bd9Sstevel@tonic-gate uint_t lbl_post = dt_irlist_label(dlp);
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate dif_instr_t instr;
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
9407c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_left->dn_reg);
9417c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9427c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BNE, lbl_true);
9457c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
9487c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_right->dn_reg);
9497c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9507c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_false);
9537c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate dt_cg_xsetx(dlp, NULL, lbl_true, dnp->dn_reg, 1);
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
9587c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9597c478bd9Sstevel@tonic-gate
9607c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
9617c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_false, instr));
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate
9667c478bd9Sstevel@tonic-gate static void
dt_cg_logical_neg(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)9677c478bd9Sstevel@tonic-gate dt_cg_logical_neg(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate uint_t lbl_zero = dt_irlist_label(dlp);
9707c478bd9Sstevel@tonic-gate uint_t lbl_post = dt_irlist_label(dlp);
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate dif_instr_t instr;
9737c478bd9Sstevel@tonic-gate
9747c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
9757c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_reg);
9787c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BE, lbl_zero);
9817c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(DIF_REG_R0, dnp->dn_reg);
9847c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9857c478bd9Sstevel@tonic-gate
9867c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BA, lbl_post);
9877c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
9887c478bd9Sstevel@tonic-gate
9897c478bd9Sstevel@tonic-gate dt_cg_xsetx(dlp, NULL, lbl_zero, dnp->dn_reg, 1);
9907c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(lbl_post, DIF_INSTR_NOP));
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate static void
dt_cg_asgn_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)9947c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
9957c478bd9Sstevel@tonic-gate {
9967c478bd9Sstevel@tonic-gate dif_instr_t instr;
9977c478bd9Sstevel@tonic-gate dt_ident_t *idp;
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate /*
10007c478bd9Sstevel@tonic-gate * If we are performing a structure assignment of a translated type,
10017c478bd9Sstevel@tonic-gate * we must instantiate all members and create a snapshot of the object
10027c478bd9Sstevel@tonic-gate * in scratch space. We allocs a chunk of memory, generate code for
10037c478bd9Sstevel@tonic-gate * each member, and then set dnp->dn_reg to the scratch object address.
10047c478bd9Sstevel@tonic-gate */
10057c478bd9Sstevel@tonic-gate if ((idp = dt_node_resolve(dnp->dn_right, DT_IDENT_XLSOU)) != NULL) {
10067c478bd9Sstevel@tonic-gate ctf_membinfo_t ctm;
10077c478bd9Sstevel@tonic-gate dt_xlator_t *dxp = idp->di_data;
10087c478bd9Sstevel@tonic-gate dt_node_t *mnp, dn, mn;
10097c478bd9Sstevel@tonic-gate int r1, r2;
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate /*
10127c478bd9Sstevel@tonic-gate * Create two fake dt_node_t's representing operator "." and a
10137c478bd9Sstevel@tonic-gate * right-hand identifier child node. These will be repeatedly
10147c478bd9Sstevel@tonic-gate * modified according to each instantiated member so that we
10157c478bd9Sstevel@tonic-gate * can pass them to dt_cg_store() and effect a member store.
10167c478bd9Sstevel@tonic-gate */
10177c478bd9Sstevel@tonic-gate bzero(&dn, sizeof (dt_node_t));
10187c478bd9Sstevel@tonic-gate dn.dn_kind = DT_NODE_OP2;
10197c478bd9Sstevel@tonic-gate dn.dn_op = DT_TOK_DOT;
10207c478bd9Sstevel@tonic-gate dn.dn_left = dnp;
10217c478bd9Sstevel@tonic-gate dn.dn_right = &mn;
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate bzero(&mn, sizeof (dt_node_t));
10247c478bd9Sstevel@tonic-gate mn.dn_kind = DT_NODE_IDENT;
10257c478bd9Sstevel@tonic-gate mn.dn_op = DT_TOK_IDENT;
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate /*
10287c478bd9Sstevel@tonic-gate * Allocate a register for our scratch data pointer. First we
10297c478bd9Sstevel@tonic-gate * set it to the size of our data structure, and then replace
10307c478bd9Sstevel@tonic-gate * it with the result of an allocs of the specified size.
10317c478bd9Sstevel@tonic-gate */
1032e5803b76SAdam H. Leventhal r1 = dt_regset_alloc(drp);
10337c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r1,
10347c478bd9Sstevel@tonic-gate ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate instr = DIF_INSTR_ALLOCS(r1, r1);
10377c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate /*
10407c478bd9Sstevel@tonic-gate * When dt_cg_asgn_op() is called, we have already generated
10417c478bd9Sstevel@tonic-gate * code for dnp->dn_right, which is the translator input. We
10427c478bd9Sstevel@tonic-gate * now associate this register with the translator's input
10437c478bd9Sstevel@tonic-gate * identifier so it can be referenced during our member loop.
10447c478bd9Sstevel@tonic-gate */
10457c478bd9Sstevel@tonic-gate dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
10467c478bd9Sstevel@tonic-gate dxp->dx_ident->di_id = dnp->dn_right->dn_reg;
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate for (mnp = dxp->dx_members; mnp != NULL; mnp = mnp->dn_list) {
10497c478bd9Sstevel@tonic-gate /*
10507c478bd9Sstevel@tonic-gate * Generate code for the translator member expression,
10517c478bd9Sstevel@tonic-gate * and then cast the result to the member type.
10527c478bd9Sstevel@tonic-gate */
10537c478bd9Sstevel@tonic-gate dt_cg_node(mnp->dn_membexpr, dlp, drp);
10547c478bd9Sstevel@tonic-gate mnp->dn_reg = mnp->dn_membexpr->dn_reg;
10557c478bd9Sstevel@tonic-gate dt_cg_typecast(mnp->dn_membexpr, mnp, dlp, drp);
10567c478bd9Sstevel@tonic-gate
10577c478bd9Sstevel@tonic-gate /*
10587c478bd9Sstevel@tonic-gate * Ask CTF for the offset of the member so we can store
10597c478bd9Sstevel@tonic-gate * to the appropriate offset. This call has already
10607c478bd9Sstevel@tonic-gate * been done once by the parser, so it should succeed.
10617c478bd9Sstevel@tonic-gate */
10627c478bd9Sstevel@tonic-gate if (ctf_member_info(dxp->dx_dst_ctfp, dxp->dx_dst_base,
10637c478bd9Sstevel@tonic-gate mnp->dn_membname, &ctm) == CTF_ERR) {
10647c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr =
10657c478bd9Sstevel@tonic-gate ctf_errno(dxp->dx_dst_ctfp);
10667c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /*
10707c478bd9Sstevel@tonic-gate * If the destination member is at offset 0, store the
10717c478bd9Sstevel@tonic-gate * result directly to r1 (the scratch buffer address).
10727c478bd9Sstevel@tonic-gate * Otherwise allocate another temporary for the offset
10737c478bd9Sstevel@tonic-gate * and add r1 to it before storing the result.
10747c478bd9Sstevel@tonic-gate */
10757c478bd9Sstevel@tonic-gate if (ctm.ctm_offset != 0) {
1076e5803b76SAdam H. Leventhal r2 = dt_regset_alloc(drp);
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate /*
10797c478bd9Sstevel@tonic-gate * Add the member offset rounded down to the
10807c478bd9Sstevel@tonic-gate * nearest byte. If the offset was not aligned
10817c478bd9Sstevel@tonic-gate * on a byte boundary, this member is a bit-
10827c478bd9Sstevel@tonic-gate * field and dt_cg_store() will handle masking.
10837c478bd9Sstevel@tonic-gate */
10847c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, r2, ctm.ctm_offset / NBBY);
10857c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_ADD, r1, r2, r2);
10867c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
10877c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
10887c478bd9Sstevel@tonic-gate
10897c478bd9Sstevel@tonic-gate dt_node_type_propagate(mnp, &dn);
10907c478bd9Sstevel@tonic-gate dn.dn_right->dn_string = mnp->dn_membname;
10917c478bd9Sstevel@tonic-gate dn.dn_reg = r2;
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate dt_cg_store(mnp, dlp, drp, &dn);
10947c478bd9Sstevel@tonic-gate dt_regset_free(drp, r2);
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate } else {
10977c478bd9Sstevel@tonic-gate dt_node_type_propagate(mnp, &dn);
10987c478bd9Sstevel@tonic-gate dn.dn_right->dn_string = mnp->dn_membname;
10997c478bd9Sstevel@tonic-gate dn.dn_reg = r1;
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate dt_cg_store(mnp, dlp, drp, &dn);
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate dt_regset_free(drp, mnp->dn_reg);
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
11087c478bd9Sstevel@tonic-gate dxp->dx_ident->di_id = 0;
11097c478bd9Sstevel@tonic-gate
11101a7c1b72Smws if (dnp->dn_right->dn_reg != -1)
11117c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_right->dn_reg);
11121a7c1b72Smws
11131a7c1b72Smws assert(dnp->dn_reg == dnp->dn_right->dn_reg);
11147c478bd9Sstevel@tonic-gate dnp->dn_reg = r1;
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /*
11187c478bd9Sstevel@tonic-gate * If we are storing to a variable, generate an stv instruction from
11197c478bd9Sstevel@tonic-gate * the variable specified by the identifier. If we are storing to a
11207c478bd9Sstevel@tonic-gate * memory address, generate code again for the left-hand side using
11217c478bd9Sstevel@tonic-gate * DT_NF_REF to get the address, and then generate a store to it.
11227c478bd9Sstevel@tonic-gate * In both paths, we assume dnp->dn_reg already has the new value.
11237c478bd9Sstevel@tonic-gate */
11247c478bd9Sstevel@tonic-gate if (dnp->dn_left->dn_kind == DT_NODE_VAR) {
11257c478bd9Sstevel@tonic-gate idp = dt_ident_resolve(dnp->dn_left->dn_ident);
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate if (idp->di_kind == DT_IDENT_ARRAY)
11287c478bd9Sstevel@tonic-gate dt_cg_arglist(idp, dnp->dn_left->dn_args, dlp, drp);
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate idp->di_flags |= DT_IDFLG_DIFW;
11317c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STV(dt_cg_stvar(idp),
11327c478bd9Sstevel@tonic-gate idp->di_id, dnp->dn_reg);
11337c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
11347c478bd9Sstevel@tonic-gate } else {
11357c478bd9Sstevel@tonic-gate uint_t rbit = dnp->dn_left->dn_flags & DT_NF_REF;
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate assert(dnp->dn_left->dn_flags & DT_NF_WRITABLE);
11387c478bd9Sstevel@tonic-gate assert(dnp->dn_left->dn_flags & DT_NF_LVALUE);
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags |= DT_NF_REF; /* force pass-by-ref */
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
11437c478bd9Sstevel@tonic-gate dt_cg_store(dnp, dlp, drp, dnp->dn_left);
11447c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags &= ~DT_NF_REF;
11477c478bd9Sstevel@tonic-gate dnp->dn_left->dn_flags |= rbit;
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate static void
dt_cg_assoc_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)11527c478bd9Sstevel@tonic-gate dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
11537c478bd9Sstevel@tonic-gate {
11547c478bd9Sstevel@tonic-gate dif_instr_t instr;
11557c478bd9Sstevel@tonic-gate uint_t op;
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate assert(dnp->dn_kind == DT_NODE_VAR);
11587c478bd9Sstevel@tonic-gate assert(!(dnp->dn_ident->di_flags & DT_IDFLG_LOCAL));
11597c478bd9Sstevel@tonic-gate assert(dnp->dn_args != NULL);
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
11627c478bd9Sstevel@tonic-gate
1163e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
11667c478bd9Sstevel@tonic-gate op = DIF_OP_LDTAA;
11677c478bd9Sstevel@tonic-gate else
11687c478bd9Sstevel@tonic-gate op = DIF_OP_LDGAA;
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
11717c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LDV(op, dnp->dn_ident->di_id, dnp->dn_reg);
11727c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate /*
11757c478bd9Sstevel@tonic-gate * If the associative array is a pass-by-reference type, then we are
11767c478bd9Sstevel@tonic-gate * loading its value as a pointer to either load or store through it.
11777c478bd9Sstevel@tonic-gate * The array element in question may not have been faulted in yet, in
11787c478bd9Sstevel@tonic-gate * which case DIF_OP_LD*AA will return zero. We append an epilogue
11797c478bd9Sstevel@tonic-gate * of instructions similar to the following:
11807c478bd9Sstevel@tonic-gate *
11817c478bd9Sstevel@tonic-gate * ld?aa id, %r1 ! base ld?aa instruction above
11827c478bd9Sstevel@tonic-gate * tst %r1 ! start of epilogue
11837c478bd9Sstevel@tonic-gate * +--- bne label
11847c478bd9Sstevel@tonic-gate * | setx size, %r1
11857c478bd9Sstevel@tonic-gate * | allocs %r1, %r1
11867c478bd9Sstevel@tonic-gate * | st?aa id, %r1
11877c478bd9Sstevel@tonic-gate * | ld?aa id, %r1
11887c478bd9Sstevel@tonic-gate * v
11897c478bd9Sstevel@tonic-gate * label: < rest of code >
11907c478bd9Sstevel@tonic-gate *
11917c478bd9Sstevel@tonic-gate * The idea is that we allocs a zero-filled chunk of scratch space and
11927c478bd9Sstevel@tonic-gate * do a DIF_OP_ST*AA to fault in and initialize the array element, and
11937c478bd9Sstevel@tonic-gate * then reload it to get the faulted-in address of the new variable
11947c478bd9Sstevel@tonic-gate * storage. This isn't cheap, but pass-by-ref associative array values
11957c478bd9Sstevel@tonic-gate * are (thus far) uncommon and the allocs cost only occurs once. If
11967c478bd9Sstevel@tonic-gate * this path becomes important to DTrace users, we can improve things
11977c478bd9Sstevel@tonic-gate * by adding a new DIF opcode to fault in associative array elements.
11987c478bd9Sstevel@tonic-gate */
11997c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_REF) {
12007c478bd9Sstevel@tonic-gate uint_t stvop = op == DIF_OP_LDTAA ? DIF_OP_STTAA : DIF_OP_STGAA;
12017c478bd9Sstevel@tonic-gate uint_t label = dt_irlist_label(dlp);
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate instr = DIF_INSTR_TST(dnp->dn_reg);
12047c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12057c478bd9Sstevel@tonic-gate
12067c478bd9Sstevel@tonic-gate instr = DIF_INSTR_BRANCH(DIF_OP_BNE, label);
12077c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_reg, dt_node_type_size(dnp));
12107c478bd9Sstevel@tonic-gate instr = DIF_INSTR_ALLOCS(dnp->dn_reg, dnp->dn_reg);
12117c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12127c478bd9Sstevel@tonic-gate
12137c478bd9Sstevel@tonic-gate dnp->dn_ident->di_flags |= DT_IDFLG_DIFW;
12147c478bd9Sstevel@tonic-gate instr = DIF_INSTR_STV(stvop, dnp->dn_ident->di_id, dnp->dn_reg);
12157c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LDV(op, dnp->dn_ident->di_id, dnp->dn_reg);
12187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12197c478bd9Sstevel@tonic-gate
12207c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(label, DIF_INSTR_NOP));
12217c478bd9Sstevel@tonic-gate }
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate static void
dt_cg_array_op(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)12257c478bd9Sstevel@tonic-gate dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
12267c478bd9Sstevel@tonic-gate {
12277c478bd9Sstevel@tonic-gate dt_probe_t *prp = yypcb->pcb_probe;
12287c478bd9Sstevel@tonic-gate uintmax_t saved = dnp->dn_args->dn_value;
12291a7c1b72Smws dt_ident_t *idp = dnp->dn_ident;
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate dif_instr_t instr;
12327c478bd9Sstevel@tonic-gate uint_t op;
12337c478bd9Sstevel@tonic-gate size_t size;
12347c478bd9Sstevel@tonic-gate int reg, n;
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate assert(dnp->dn_kind == DT_NODE_VAR);
12371a7c1b72Smws assert(!(idp->di_flags & DT_IDFLG_LOCAL));
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate assert(dnp->dn_args->dn_kind == DT_NODE_INT);
12407c478bd9Sstevel@tonic-gate assert(dnp->dn_args->dn_list == NULL);
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate /*
12437c478bd9Sstevel@tonic-gate * If this is a reference in the args[] array, temporarily modify the
12441a7c1b72Smws * array index according to the static argument mapping (if any),
12451a7c1b72Smws * unless the argument reference is provided by a dynamic translator.
12461a7c1b72Smws * If we're using a dynamic translator for args[], then just set dn_reg
12471a7c1b72Smws * to an invalid reg and return: DIF_OP_XLARG will fetch the arg later.
12487c478bd9Sstevel@tonic-gate */
12491a7c1b72Smws if (idp->di_id == DIF_VAR_ARGS) {
12501a7c1b72Smws if ((idp->di_kind == DT_IDENT_XLPTR ||
12511a7c1b72Smws idp->di_kind == DT_IDENT_XLSOU) &&
12521a7c1b72Smws dt_xlator_dynamic(idp->di_data)) {
12531a7c1b72Smws dnp->dn_reg = -1;
12541a7c1b72Smws return;
12551a7c1b72Smws }
12567c478bd9Sstevel@tonic-gate dnp->dn_args->dn_value = prp->pr_mapping[saved];
12571a7c1b72Smws }
12587c478bd9Sstevel@tonic-gate
12597c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_args, dlp, drp);
12607c478bd9Sstevel@tonic-gate dnp->dn_args->dn_value = saved;
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_args->dn_reg;
12637c478bd9Sstevel@tonic-gate
12641a7c1b72Smws if (idp->di_flags & DT_IDFLG_TLS)
12657c478bd9Sstevel@tonic-gate op = DIF_OP_LDTA;
12667c478bd9Sstevel@tonic-gate else
12677c478bd9Sstevel@tonic-gate op = DIF_OP_LDGA;
12687c478bd9Sstevel@tonic-gate
12691a7c1b72Smws idp->di_flags |= DT_IDFLG_DIFR;
12707c478bd9Sstevel@tonic-gate
12711a7c1b72Smws instr = DIF_INSTR_LDA(op, idp->di_id,
12727c478bd9Sstevel@tonic-gate dnp->dn_args->dn_reg, dnp->dn_reg);
12737c478bd9Sstevel@tonic-gate
12747c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate /*
12777c478bd9Sstevel@tonic-gate * If this is a reference to the args[] array, we need to take the
12787c478bd9Sstevel@tonic-gate * additional step of explicitly eliminating any bits larger than the
12797c478bd9Sstevel@tonic-gate * type size: the DIF interpreter in the kernel will always give us
12807c478bd9Sstevel@tonic-gate * the raw (64-bit) argument value, and any bits larger than the type
12817c478bd9Sstevel@tonic-gate * size may be junk. As a practical matter, this arises only on 64-bit
12827c478bd9Sstevel@tonic-gate * architectures and only when the argument index is larger than the
12837c478bd9Sstevel@tonic-gate * number of arguments passed directly to DTrace: if a 8-, 16- or
12847c478bd9Sstevel@tonic-gate * 32-bit argument must be retrieved from the stack, it is possible
12857c478bd9Sstevel@tonic-gate * (and it some cases, likely) that the upper bits will be garbage.
12867c478bd9Sstevel@tonic-gate */
12871a7c1b72Smws if (idp->di_id != DIF_VAR_ARGS || !dt_node_is_scalar(dnp))
12887c478bd9Sstevel@tonic-gate return;
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
12917c478bd9Sstevel@tonic-gate return;
12927c478bd9Sstevel@tonic-gate
1293e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
12947c478bd9Sstevel@tonic-gate assert(size < sizeof (uint64_t));
12957c478bd9Sstevel@tonic-gate n = sizeof (uint64_t) * NBBY - size * NBBY;
12967c478bd9Sstevel@tonic-gate
12977c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, reg, n);
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SLL, dnp->dn_reg, reg, dnp->dn_reg);
13007c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT((dnp->dn_flags & DT_NF_SIGNED) ?
13037c478bd9Sstevel@tonic-gate DIF_OP_SRA : DIF_OP_SRL, dnp->dn_reg, reg, dnp->dn_reg);
13047c478bd9Sstevel@tonic-gate
13057c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
13067c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
13077c478bd9Sstevel@tonic-gate }
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate /*
13107c478bd9Sstevel@tonic-gate * Generate code for an inlined variable reference. Inlines can be used to
13117c478bd9Sstevel@tonic-gate * define either scalar or associative array substitutions. For scalars, we
13127c478bd9Sstevel@tonic-gate * simply generate code for the parse tree saved in the identifier's din_root,
13137c478bd9Sstevel@tonic-gate * and then cast the resulting expression to the inline's declaration type.
13147c478bd9Sstevel@tonic-gate * For arrays, we take the input parameter subtrees from dnp->dn_args and
13157c478bd9Sstevel@tonic-gate * temporarily store them in the din_root of each din_argv[i] identifier,
13167c478bd9Sstevel@tonic-gate * which are themselves inlines and were set up for us by the parser. The
13177c478bd9Sstevel@tonic-gate * result is that any reference to the inlined parameter inside the top-level
13187c478bd9Sstevel@tonic-gate * din_root will turn into a recursive call to dt_cg_inline() for a scalar
13197c478bd9Sstevel@tonic-gate * inline whose din_root will refer to the subtree pointed to by the argument.
13207c478bd9Sstevel@tonic-gate */
13217c478bd9Sstevel@tonic-gate static void
dt_cg_inline(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)13227c478bd9Sstevel@tonic-gate dt_cg_inline(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
13237c478bd9Sstevel@tonic-gate {
13247c478bd9Sstevel@tonic-gate dt_ident_t *idp = dnp->dn_ident;
13257c478bd9Sstevel@tonic-gate dt_idnode_t *inp = idp->di_iarg;
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate dt_idnode_t *pinp;
13287c478bd9Sstevel@tonic-gate dt_node_t *pnp;
13297c478bd9Sstevel@tonic-gate int i;
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate assert(idp->di_flags & DT_IDFLG_INLINE);
13327c478bd9Sstevel@tonic-gate assert(idp->di_ops == &dt_idops_inline);
13337c478bd9Sstevel@tonic-gate
13347c478bd9Sstevel@tonic-gate if (idp->di_kind == DT_IDENT_ARRAY) {
13357c478bd9Sstevel@tonic-gate for (i = 0, pnp = dnp->dn_args;
13367c478bd9Sstevel@tonic-gate pnp != NULL; pnp = pnp->dn_list, i++) {
13377c478bd9Sstevel@tonic-gate if (inp->din_argv[i] != NULL) {
13387c478bd9Sstevel@tonic-gate pinp = inp->din_argv[i]->di_iarg;
13397c478bd9Sstevel@tonic-gate pinp->din_root = pnp;
13407c478bd9Sstevel@tonic-gate }
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate }
13437c478bd9Sstevel@tonic-gate
13447c478bd9Sstevel@tonic-gate dt_cg_node(inp->din_root, dlp, drp);
13457c478bd9Sstevel@tonic-gate dnp->dn_reg = inp->din_root->dn_reg;
13467c478bd9Sstevel@tonic-gate dt_cg_typecast(inp->din_root, dnp, dlp, drp);
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate if (idp->di_kind == DT_IDENT_ARRAY) {
13497c478bd9Sstevel@tonic-gate for (i = 0; i < inp->din_argc; i++) {
13507c478bd9Sstevel@tonic-gate pinp = inp->din_argv[i]->di_iarg;
13517c478bd9Sstevel@tonic-gate pinp->din_root = NULL;
13527c478bd9Sstevel@tonic-gate }
13537c478bd9Sstevel@tonic-gate }
13547c478bd9Sstevel@tonic-gate }
13557c478bd9Sstevel@tonic-gate
1356e5803b76SAdam H. Leventhal typedef struct dt_xlmemb {
1357e5803b76SAdam H. Leventhal dt_ident_t *dtxl_idp; /* translated ident */
1358e5803b76SAdam H. Leventhal dt_irlist_t *dtxl_dlp; /* instruction list */
1359e5803b76SAdam H. Leventhal dt_regset_t *dtxl_drp; /* register set */
1360e5803b76SAdam H. Leventhal int dtxl_sreg; /* location of the translation input */
1361e5803b76SAdam H. Leventhal int dtxl_dreg; /* location of our allocated buffer */
1362e5803b76SAdam H. Leventhal } dt_xlmemb_t;
1363e5803b76SAdam H. Leventhal
1364e5803b76SAdam H. Leventhal /*ARGSUSED*/
1365e5803b76SAdam H. Leventhal static int
dt_cg_xlate_member(const char * name,ctf_id_t type,ulong_t off,void * arg)1366e5803b76SAdam H. Leventhal dt_cg_xlate_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
1367e5803b76SAdam H. Leventhal {
1368e5803b76SAdam H. Leventhal dt_xlmemb_t *dx = arg;
1369e5803b76SAdam H. Leventhal dt_ident_t *idp = dx->dtxl_idp;
1370e5803b76SAdam H. Leventhal dt_irlist_t *dlp = dx->dtxl_dlp;
1371e5803b76SAdam H. Leventhal dt_regset_t *drp = dx->dtxl_drp;
1372e5803b76SAdam H. Leventhal
1373e5803b76SAdam H. Leventhal dt_node_t *mnp;
1374e5803b76SAdam H. Leventhal dt_xlator_t *dxp;
1375e5803b76SAdam H. Leventhal
1376e5803b76SAdam H. Leventhal int reg, treg;
1377e5803b76SAdam H. Leventhal uint32_t instr;
1378e5803b76SAdam H. Leventhal size_t size;
1379e5803b76SAdam H. Leventhal
1380e5803b76SAdam H. Leventhal /* Generate code for the translation. */
1381e5803b76SAdam H. Leventhal dxp = idp->di_data;
1382e5803b76SAdam H. Leventhal mnp = dt_xlator_member(dxp, name);
1383e5803b76SAdam H. Leventhal
1384e5803b76SAdam H. Leventhal /* If there's no translator for the given member, skip it. */
1385e5803b76SAdam H. Leventhal if (mnp == NULL)
1386e5803b76SAdam H. Leventhal return (0);
1387e5803b76SAdam H. Leventhal
1388e5803b76SAdam H. Leventhal dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
1389e5803b76SAdam H. Leventhal dxp->dx_ident->di_id = dx->dtxl_sreg;
1390e5803b76SAdam H. Leventhal
1391e5803b76SAdam H. Leventhal dt_cg_node(mnp->dn_membexpr, dlp, drp);
1392e5803b76SAdam H. Leventhal
1393e5803b76SAdam H. Leventhal dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
1394e5803b76SAdam H. Leventhal dxp->dx_ident->di_id = 0;
1395e5803b76SAdam H. Leventhal
1396e5803b76SAdam H. Leventhal treg = mnp->dn_membexpr->dn_reg;
1397e5803b76SAdam H. Leventhal
1398e5803b76SAdam H. Leventhal /* Compute the offset into our buffer and store the result there. */
1399e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
1400e5803b76SAdam H. Leventhal
1401e5803b76SAdam H. Leventhal dt_cg_setx(dlp, reg, off / NBBY);
1402e5803b76SAdam H. Leventhal instr = DIF_INSTR_FMT(DIF_OP_ADD, dx->dtxl_dreg, reg, reg);
1403e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1404e5803b76SAdam H. Leventhal
1405e5803b76SAdam H. Leventhal size = ctf_type_size(mnp->dn_membexpr->dn_ctfp,
1406e5803b76SAdam H. Leventhal mnp->dn_membexpr->dn_type);
1407e5803b76SAdam H. Leventhal if (dt_node_is_scalar(mnp->dn_membexpr)) {
1408e5803b76SAdam H. Leventhal /*
1409e5803b76SAdam H. Leventhal * Copying scalars is simple.
1410e5803b76SAdam H. Leventhal */
1411e5803b76SAdam H. Leventhal switch (size) {
1412e5803b76SAdam H. Leventhal case 1:
1413e5803b76SAdam H. Leventhal instr = DIF_INSTR_STORE(DIF_OP_STB, treg, reg);
1414e5803b76SAdam H. Leventhal break;
1415e5803b76SAdam H. Leventhal case 2:
1416e5803b76SAdam H. Leventhal instr = DIF_INSTR_STORE(DIF_OP_STH, treg, reg);
1417e5803b76SAdam H. Leventhal break;
1418e5803b76SAdam H. Leventhal case 4:
1419e5803b76SAdam H. Leventhal instr = DIF_INSTR_STORE(DIF_OP_STW, treg, reg);
1420e5803b76SAdam H. Leventhal break;
1421e5803b76SAdam H. Leventhal case 8:
1422e5803b76SAdam H. Leventhal instr = DIF_INSTR_STORE(DIF_OP_STX, treg, reg);
1423e5803b76SAdam H. Leventhal break;
1424e5803b76SAdam H. Leventhal default:
1425e5803b76SAdam H. Leventhal xyerror(D_UNKNOWN, "internal error -- unexpected "
1426e5803b76SAdam H. Leventhal "size: %lu\n", (ulong_t)size);
1427e5803b76SAdam H. Leventhal }
1428e5803b76SAdam H. Leventhal
1429e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1430e5803b76SAdam H. Leventhal
1431e5803b76SAdam H. Leventhal } else if (dt_node_is_string(mnp->dn_membexpr)) {
1432e5803b76SAdam H. Leventhal int szreg;
1433e5803b76SAdam H. Leventhal
1434e5803b76SAdam H. Leventhal /*
1435e5803b76SAdam H. Leventhal * Use the copys instruction for strings.
1436e5803b76SAdam H. Leventhal */
1437e5803b76SAdam H. Leventhal szreg = dt_regset_alloc(drp);
1438e5803b76SAdam H. Leventhal dt_cg_setx(dlp, szreg, size);
1439e5803b76SAdam H. Leventhal instr = DIF_INSTR_COPYS(treg, szreg, reg);
1440e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1441e5803b76SAdam H. Leventhal dt_regset_free(drp, szreg);
1442e5803b76SAdam H. Leventhal } else {
1443e5803b76SAdam H. Leventhal int szreg;
1444e5803b76SAdam H. Leventhal
1445e5803b76SAdam H. Leventhal /*
1446e5803b76SAdam H. Leventhal * If it's anything else then we'll just bcopy it.
1447e5803b76SAdam H. Leventhal */
1448e5803b76SAdam H. Leventhal szreg = dt_regset_alloc(drp);
1449e5803b76SAdam H. Leventhal dt_cg_setx(dlp, szreg, size);
1450e5803b76SAdam H. Leventhal dt_irlist_append(dlp,
1451e5803b76SAdam H. Leventhal dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
1452e5803b76SAdam H. Leventhal instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
1453e5803b76SAdam H. Leventhal DIF_REG_R0, treg);
1454e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1455e5803b76SAdam H. Leventhal instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
1456e5803b76SAdam H. Leventhal DIF_REG_R0, reg);
1457e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1458e5803b76SAdam H. Leventhal instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
1459e5803b76SAdam H. Leventhal DIF_REG_R0, szreg);
1460e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1461e5803b76SAdam H. Leventhal instr = DIF_INSTR_CALL(DIF_SUBR_BCOPY, szreg);
1462e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1463e5803b76SAdam H. Leventhal dt_regset_free(drp, szreg);
1464e5803b76SAdam H. Leventhal }
1465e5803b76SAdam H. Leventhal
1466e5803b76SAdam H. Leventhal dt_regset_free(drp, reg);
1467e5803b76SAdam H. Leventhal dt_regset_free(drp, treg);
1468e5803b76SAdam H. Leventhal
1469e5803b76SAdam H. Leventhal return (0);
1470e5803b76SAdam H. Leventhal }
1471e5803b76SAdam H. Leventhal
1472e5803b76SAdam H. Leventhal /*
1473e5803b76SAdam H. Leventhal * If we're expanding a translated type, we create an appropriately sized
1474e5803b76SAdam H. Leventhal * buffer with alloca() and then translate each member into it.
1475e5803b76SAdam H. Leventhal */
1476e5803b76SAdam H. Leventhal static int
dt_cg_xlate_expand(dt_node_t * dnp,dt_ident_t * idp,dt_irlist_t * dlp,dt_regset_t * drp)1477e5803b76SAdam H. Leventhal dt_cg_xlate_expand(dt_node_t *dnp, dt_ident_t *idp, dt_irlist_t *dlp,
1478e5803b76SAdam H. Leventhal dt_regset_t *drp)
1479e5803b76SAdam H. Leventhal {
1480e5803b76SAdam H. Leventhal dt_xlmemb_t dlm;
1481e5803b76SAdam H. Leventhal uint32_t instr;
1482e5803b76SAdam H. Leventhal int dreg;
1483e5803b76SAdam H. Leventhal size_t size;
1484e5803b76SAdam H. Leventhal
1485e5803b76SAdam H. Leventhal dreg = dt_regset_alloc(drp);
1486e5803b76SAdam H. Leventhal size = ctf_type_size(dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
1487e5803b76SAdam H. Leventhal
1488e5803b76SAdam H. Leventhal /* Call alloca() to create the buffer. */
1489e5803b76SAdam H. Leventhal dt_cg_setx(dlp, dreg, size);
1490e5803b76SAdam H. Leventhal
1491e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
1492e5803b76SAdam H. Leventhal
1493e5803b76SAdam H. Leventhal instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF, DIF_REG_R0, dreg);
1494e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1495e5803b76SAdam H. Leventhal
1496e5803b76SAdam H. Leventhal instr = DIF_INSTR_CALL(DIF_SUBR_ALLOCA, dreg);
1497e5803b76SAdam H. Leventhal dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
1498e5803b76SAdam H. Leventhal
1499e5803b76SAdam H. Leventhal /* Generate the translation for each member. */
1500e5803b76SAdam H. Leventhal dlm.dtxl_idp = idp;
1501e5803b76SAdam H. Leventhal dlm.dtxl_dlp = dlp;
1502e5803b76SAdam H. Leventhal dlm.dtxl_drp = drp;
1503e5803b76SAdam H. Leventhal dlm.dtxl_sreg = dnp->dn_reg;
1504e5803b76SAdam H. Leventhal dlm.dtxl_dreg = dreg;
1505e5803b76SAdam H. Leventhal (void) ctf_member_iter(dnp->dn_ident->di_ctfp,
1506e5803b76SAdam H. Leventhal dnp->dn_ident->di_type, dt_cg_xlate_member,
1507e5803b76SAdam H. Leventhal &dlm);
1508e5803b76SAdam H. Leventhal
1509e5803b76SAdam H. Leventhal return (dreg);
1510e5803b76SAdam H. Leventhal }
1511e5803b76SAdam H. Leventhal
15127c478bd9Sstevel@tonic-gate static void
dt_cg_node(dt_node_t * dnp,dt_irlist_t * dlp,dt_regset_t * drp)15137c478bd9Sstevel@tonic-gate dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
15147c478bd9Sstevel@tonic-gate {
15157c478bd9Sstevel@tonic-gate ctf_file_t *ctfp = dnp->dn_ctfp;
15167c478bd9Sstevel@tonic-gate ctf_file_t *octfp;
15177c478bd9Sstevel@tonic-gate ctf_membinfo_t m;
15187c478bd9Sstevel@tonic-gate ctf_id_t type;
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate dif_instr_t instr;
15217c478bd9Sstevel@tonic-gate dt_ident_t *idp;
15227c478bd9Sstevel@tonic-gate ssize_t stroff;
15237c478bd9Sstevel@tonic-gate uint_t op;
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate switch (dnp->dn_op) {
15267c478bd9Sstevel@tonic-gate case DT_TOK_COMMA:
15277c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
15287c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
15297c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
15307c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
15317c478bd9Sstevel@tonic-gate break;
15327c478bd9Sstevel@tonic-gate
15337c478bd9Sstevel@tonic-gate case DT_TOK_ASGN:
15347c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
15357c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
15367c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15377c478bd9Sstevel@tonic-gate break;
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate case DT_TOK_ADD_EQ:
15407c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD);
15417c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15427c478bd9Sstevel@tonic-gate break;
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate case DT_TOK_SUB_EQ:
15457c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB);
15467c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15477c478bd9Sstevel@tonic-gate break;
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate case DT_TOK_MUL_EQ:
15507c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL);
15517c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15527c478bd9Sstevel@tonic-gate break;
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate case DT_TOK_DIV_EQ:
15557c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
15567c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV);
15577c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15587c478bd9Sstevel@tonic-gate break;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate case DT_TOK_MOD_EQ:
15617c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
15627c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM);
15637c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15647c478bd9Sstevel@tonic-gate break;
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate case DT_TOK_AND_EQ:
15677c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);
15687c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15697c478bd9Sstevel@tonic-gate break;
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate case DT_TOK_XOR_EQ:
15727c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);
15737c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15747c478bd9Sstevel@tonic-gate break;
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate case DT_TOK_OR_EQ:
15777c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);
15787c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15797c478bd9Sstevel@tonic-gate break;
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate case DT_TOK_LSH_EQ:
15827c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL);
15837c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15847c478bd9Sstevel@tonic-gate break;
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate case DT_TOK_RSH_EQ:
15877c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
15887c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL);
15897c478bd9Sstevel@tonic-gate dt_cg_asgn_op(dnp, dlp, drp);
15907c478bd9Sstevel@tonic-gate break;
15917c478bd9Sstevel@tonic-gate
15927c478bd9Sstevel@tonic-gate case DT_TOK_QUESTION:
15937c478bd9Sstevel@tonic-gate dt_cg_ternary_op(dnp, dlp, drp);
15947c478bd9Sstevel@tonic-gate break;
15957c478bd9Sstevel@tonic-gate
15967c478bd9Sstevel@tonic-gate case DT_TOK_LOR:
15977c478bd9Sstevel@tonic-gate dt_cg_logical_or(dnp, dlp, drp);
15987c478bd9Sstevel@tonic-gate break;
15997c478bd9Sstevel@tonic-gate
16007c478bd9Sstevel@tonic-gate case DT_TOK_LXOR:
16017c478bd9Sstevel@tonic-gate dt_cg_logical_xor(dnp, dlp, drp);
16027c478bd9Sstevel@tonic-gate break;
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate case DT_TOK_LAND:
16057c478bd9Sstevel@tonic-gate dt_cg_logical_and(dnp, dlp, drp);
16067c478bd9Sstevel@tonic-gate break;
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate case DT_TOK_BOR:
16097c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_OR);
16107c478bd9Sstevel@tonic-gate break;
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate case DT_TOK_XOR:
16137c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_XOR);
16147c478bd9Sstevel@tonic-gate break;
16157c478bd9Sstevel@tonic-gate
16167c478bd9Sstevel@tonic-gate case DT_TOK_BAND:
16177c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_AND);
16187c478bd9Sstevel@tonic-gate break;
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate case DT_TOK_EQU:
16217c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BE);
16227c478bd9Sstevel@tonic-gate break;
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate case DT_TOK_NEQ:
16257c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp, DIF_OP_BNE);
16267c478bd9Sstevel@tonic-gate break;
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate case DT_TOK_LT:
16297c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp,
16307c478bd9Sstevel@tonic-gate dt_cg_compare_signed(dnp) ? DIF_OP_BL : DIF_OP_BLU);
16317c478bd9Sstevel@tonic-gate break;
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate case DT_TOK_LE:
16347c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp,
16357c478bd9Sstevel@tonic-gate dt_cg_compare_signed(dnp) ? DIF_OP_BLE : DIF_OP_BLEU);
16367c478bd9Sstevel@tonic-gate break;
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate case DT_TOK_GT:
16397c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp,
16407c478bd9Sstevel@tonic-gate dt_cg_compare_signed(dnp) ? DIF_OP_BG : DIF_OP_BGU);
16417c478bd9Sstevel@tonic-gate break;
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate case DT_TOK_GE:
16447c478bd9Sstevel@tonic-gate dt_cg_compare_op(dnp, dlp, drp,
16457c478bd9Sstevel@tonic-gate dt_cg_compare_signed(dnp) ? DIF_OP_BGE : DIF_OP_BGEU);
16467c478bd9Sstevel@tonic-gate break;
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate case DT_TOK_LSH:
16497c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SLL);
16507c478bd9Sstevel@tonic-gate break;
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate case DT_TOK_RSH:
16537c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
16547c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SRA : DIF_OP_SRL);
16557c478bd9Sstevel@tonic-gate break;
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate case DT_TOK_ADD:
16587c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_ADD);
16597c478bd9Sstevel@tonic-gate break;
16607c478bd9Sstevel@tonic-gate
16617c478bd9Sstevel@tonic-gate case DT_TOK_SUB:
16627c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_SUB);
16637c478bd9Sstevel@tonic-gate break;
16647c478bd9Sstevel@tonic-gate
16657c478bd9Sstevel@tonic-gate case DT_TOK_MUL:
16667c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp, DIF_OP_MUL);
16677c478bd9Sstevel@tonic-gate break;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate case DT_TOK_DIV:
16707c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
16717c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SDIV : DIF_OP_UDIV);
16727c478bd9Sstevel@tonic-gate break;
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate case DT_TOK_MOD:
16757c478bd9Sstevel@tonic-gate dt_cg_arithmetic_op(dnp, dlp, drp,
16767c478bd9Sstevel@tonic-gate (dnp->dn_flags & DT_NF_SIGNED) ? DIF_OP_SREM : DIF_OP_UREM);
16777c478bd9Sstevel@tonic-gate break;
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate case DT_TOK_LNEG:
16807c478bd9Sstevel@tonic-gate dt_cg_logical_neg(dnp, dlp, drp);
16817c478bd9Sstevel@tonic-gate break;
16827c478bd9Sstevel@tonic-gate
16837c478bd9Sstevel@tonic-gate case DT_TOK_BNEG:
16847c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
16857c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
16867c478bd9Sstevel@tonic-gate instr = DIF_INSTR_NOT(dnp->dn_reg, dnp->dn_reg);
16877c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
16887c478bd9Sstevel@tonic-gate break;
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate case DT_TOK_PREINC:
16917c478bd9Sstevel@tonic-gate dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_ADD);
16927c478bd9Sstevel@tonic-gate break;
16937c478bd9Sstevel@tonic-gate
16947c478bd9Sstevel@tonic-gate case DT_TOK_POSTINC:
16957c478bd9Sstevel@tonic-gate dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_ADD);
16967c478bd9Sstevel@tonic-gate break;
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate case DT_TOK_PREDEC:
16997c478bd9Sstevel@tonic-gate dt_cg_prearith_op(dnp, dlp, drp, DIF_OP_SUB);
17007c478bd9Sstevel@tonic-gate break;
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate case DT_TOK_POSTDEC:
17037c478bd9Sstevel@tonic-gate dt_cg_postarith_op(dnp, dlp, drp, DIF_OP_SUB);
17047c478bd9Sstevel@tonic-gate break;
17057c478bd9Sstevel@tonic-gate
17067c478bd9Sstevel@tonic-gate case DT_TOK_IPOS:
17077c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
17087c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
17097c478bd9Sstevel@tonic-gate break;
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate case DT_TOK_INEG:
17127c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
17137c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
17147c478bd9Sstevel@tonic-gate
17157c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_SUB, DIF_REG_R0,
17167c478bd9Sstevel@tonic-gate dnp->dn_reg, dnp->dn_reg);
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
17197c478bd9Sstevel@tonic-gate break;
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate case DT_TOK_DEREF:
17227c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
17237c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
17247c478bd9Sstevel@tonic-gate
1725e5803b76SAdam H. Leventhal if (dt_node_is_dynamic(dnp->dn_child)) {
1726e5803b76SAdam H. Leventhal int reg;
1727e5803b76SAdam H. Leventhal idp = dt_node_resolve(dnp->dn_child, DT_IDENT_XLPTR);
1728e5803b76SAdam H. Leventhal assert(idp != NULL);
1729e5803b76SAdam H. Leventhal reg = dt_cg_xlate_expand(dnp, idp, dlp, drp);
1730e5803b76SAdam H. Leventhal
1731e5803b76SAdam H. Leventhal dt_regset_free(drp, dnp->dn_child->dn_reg);
1732e5803b76SAdam H. Leventhal dnp->dn_reg = reg;
1733e5803b76SAdam H. Leventhal
1734e5803b76SAdam H. Leventhal } else if (!(dnp->dn_flags & DT_NF_REF)) {
17357c478bd9Sstevel@tonic-gate uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
17367c478bd9Sstevel@tonic-gate
17377c478bd9Sstevel@tonic-gate /*
17387c478bd9Sstevel@tonic-gate * Save and restore DT_NF_USERLAND across dt_cg_load():
17397c478bd9Sstevel@tonic-gate * we need the sign bit from dnp and the user bit from
17407c478bd9Sstevel@tonic-gate * dnp->dn_child in order to get the proper opcode.
17417c478bd9Sstevel@tonic-gate */
17427c478bd9Sstevel@tonic-gate dnp->dn_flags |=
17437c478bd9Sstevel@tonic-gate (dnp->dn_child->dn_flags & DT_NF_USERLAND);
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp,
17467c478bd9Sstevel@tonic-gate dnp->dn_type), dnp->dn_reg, dnp->dn_reg);
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate dnp->dn_flags &= ~DT_NF_USERLAND;
17497c478bd9Sstevel@tonic-gate dnp->dn_flags |= ubit;
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
17527c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
17537c478bd9Sstevel@tonic-gate }
17547c478bd9Sstevel@tonic-gate break;
17557c478bd9Sstevel@tonic-gate
17567c478bd9Sstevel@tonic-gate case DT_TOK_ADDROF: {
17577c478bd9Sstevel@tonic-gate uint_t rbit = dnp->dn_child->dn_flags & DT_NF_REF;
17587c478bd9Sstevel@tonic-gate
17597c478bd9Sstevel@tonic-gate dnp->dn_child->dn_flags |= DT_NF_REF; /* force pass-by-ref */
17607c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
17617c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
17627c478bd9Sstevel@tonic-gate
17637c478bd9Sstevel@tonic-gate dnp->dn_child->dn_flags &= ~DT_NF_REF;
17647c478bd9Sstevel@tonic-gate dnp->dn_child->dn_flags |= rbit;
17657c478bd9Sstevel@tonic-gate break;
17667c478bd9Sstevel@tonic-gate }
17677c478bd9Sstevel@tonic-gate
17687c478bd9Sstevel@tonic-gate case DT_TOK_SIZEOF: {
17697c478bd9Sstevel@tonic-gate size_t size = dt_node_sizeof(dnp->dn_child);
1770e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
17717c478bd9Sstevel@tonic-gate assert(size != 0);
17727c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_reg, size);
17737c478bd9Sstevel@tonic-gate break;
17747c478bd9Sstevel@tonic-gate }
17757c478bd9Sstevel@tonic-gate
17767c478bd9Sstevel@tonic-gate case DT_TOK_STRINGOF:
17777c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_child, dlp, drp);
17787c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_child->dn_reg;
17797c478bd9Sstevel@tonic-gate break;
17807c478bd9Sstevel@tonic-gate
17817c478bd9Sstevel@tonic-gate case DT_TOK_XLATE:
17821a7c1b72Smws /*
17831a7c1b72Smws * An xlate operator appears in either an XLATOR, indicating a
17841a7c1b72Smws * reference to a dynamic translator, or an OP2, indicating
17851a7c1b72Smws * use of the xlate operator in the user's program. For the
17861a7c1b72Smws * dynamic case, generate an xlate opcode with a reference to
17871a7c1b72Smws * the corresponding member, pre-computed for us in dn_members.
17881a7c1b72Smws */
17891a7c1b72Smws if (dnp->dn_kind == DT_NODE_XLATOR) {
17901a7c1b72Smws dt_xlator_t *dxp = dnp->dn_xlator;
17911a7c1b72Smws
17921a7c1b72Smws assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
17931a7c1b72Smws assert(dxp->dx_ident->di_id != 0);
17941a7c1b72Smws
1795e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
17961a7c1b72Smws
17971a7c1b72Smws if (dxp->dx_arg == -1) {
17981a7c1b72Smws instr = DIF_INSTR_MOV(
17991a7c1b72Smws dxp->dx_ident->di_id, dnp->dn_reg);
18001a7c1b72Smws dt_irlist_append(dlp,
18011a7c1b72Smws dt_cg_node_alloc(DT_LBL_NONE, instr));
18021a7c1b72Smws op = DIF_OP_XLATE;
18031a7c1b72Smws } else
18041a7c1b72Smws op = DIF_OP_XLARG;
18051a7c1b72Smws
18061a7c1b72Smws instr = DIF_INSTR_XLATE(op, 0, dnp->dn_reg);
18071a7c1b72Smws dt_irlist_append(dlp,
18081a7c1b72Smws dt_cg_node_alloc(DT_LBL_NONE, instr));
18091a7c1b72Smws
18101a7c1b72Smws dlp->dl_last->di_extern = dnp->dn_xmember;
18111a7c1b72Smws break;
18121a7c1b72Smws }
18131a7c1b72Smws
18141a7c1b72Smws assert(dnp->dn_kind == DT_NODE_OP2);
18157c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
18167c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
18177c478bd9Sstevel@tonic-gate break;
18187c478bd9Sstevel@tonic-gate
18197c478bd9Sstevel@tonic-gate case DT_TOK_LPAR:
18207c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_right, dlp, drp);
18217c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_right->dn_reg;
18227c478bd9Sstevel@tonic-gate dt_cg_typecast(dnp->dn_right, dnp, dlp, drp);
18237c478bd9Sstevel@tonic-gate break;
18247c478bd9Sstevel@tonic-gate
18257c478bd9Sstevel@tonic-gate case DT_TOK_PTR:
18267c478bd9Sstevel@tonic-gate case DT_TOK_DOT:
18277c478bd9Sstevel@tonic-gate assert(dnp->dn_right->dn_kind == DT_NODE_IDENT);
18287c478bd9Sstevel@tonic-gate dt_cg_node(dnp->dn_left, dlp, drp);
18297c478bd9Sstevel@tonic-gate
18307c478bd9Sstevel@tonic-gate /*
18317c478bd9Sstevel@tonic-gate * If the left-hand side of PTR or DOT is a dynamic variable,
18327c478bd9Sstevel@tonic-gate * we expect it to be the output of a D translator. In this
18337c478bd9Sstevel@tonic-gate * case, we look up the parse tree corresponding to the member
18347c478bd9Sstevel@tonic-gate * that is being accessed and run the code generator over it.
18357c478bd9Sstevel@tonic-gate * We then cast the result as if by the assignment operator.
18367c478bd9Sstevel@tonic-gate */
18377c478bd9Sstevel@tonic-gate if ((idp = dt_node_resolve(
18387c478bd9Sstevel@tonic-gate dnp->dn_left, DT_IDENT_XLSOU)) != NULL ||
18397c478bd9Sstevel@tonic-gate (idp = dt_node_resolve(
18407c478bd9Sstevel@tonic-gate dnp->dn_left, DT_IDENT_XLPTR)) != NULL) {
18417c478bd9Sstevel@tonic-gate
18427c478bd9Sstevel@tonic-gate dt_xlator_t *dxp;
18437c478bd9Sstevel@tonic-gate dt_node_t *mnp;
18447c478bd9Sstevel@tonic-gate
18457c478bd9Sstevel@tonic-gate dxp = idp->di_data;
18467c478bd9Sstevel@tonic-gate mnp = dt_xlator_member(dxp, dnp->dn_right->dn_string);
18477c478bd9Sstevel@tonic-gate assert(mnp != NULL);
18487c478bd9Sstevel@tonic-gate
18497c478bd9Sstevel@tonic-gate dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
18507c478bd9Sstevel@tonic-gate dxp->dx_ident->di_id = dnp->dn_left->dn_reg;
18517c478bd9Sstevel@tonic-gate
18527c478bd9Sstevel@tonic-gate dt_cg_node(mnp->dn_membexpr, dlp, drp);
18537c478bd9Sstevel@tonic-gate dnp->dn_reg = mnp->dn_membexpr->dn_reg;
18547c478bd9Sstevel@tonic-gate dt_cg_typecast(mnp->dn_membexpr, dnp, dlp, drp);
18557c478bd9Sstevel@tonic-gate
18567c478bd9Sstevel@tonic-gate dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
18577c478bd9Sstevel@tonic-gate dxp->dx_ident->di_id = 0;
18587c478bd9Sstevel@tonic-gate
18591a7c1b72Smws if (dnp->dn_left->dn_reg != -1)
18607c478bd9Sstevel@tonic-gate dt_regset_free(drp, dnp->dn_left->dn_reg);
18617c478bd9Sstevel@tonic-gate break;
18627c478bd9Sstevel@tonic-gate }
18637c478bd9Sstevel@tonic-gate
18647c478bd9Sstevel@tonic-gate ctfp = dnp->dn_left->dn_ctfp;
18657c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, dnp->dn_left->dn_type);
18667c478bd9Sstevel@tonic-gate
18677c478bd9Sstevel@tonic-gate if (dnp->dn_op == DT_TOK_PTR) {
18687c478bd9Sstevel@tonic-gate type = ctf_type_reference(ctfp, type);
18697c478bd9Sstevel@tonic-gate type = ctf_type_resolve(ctfp, type);
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate if ((ctfp = dt_cg_membinfo(octfp = ctfp, type,
18737c478bd9Sstevel@tonic-gate dnp->dn_right->dn_string, &m)) == NULL) {
18747c478bd9Sstevel@tonic-gate yypcb->pcb_hdl->dt_ctferr = ctf_errno(octfp);
18757c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_CTF);
18767c478bd9Sstevel@tonic-gate }
18777c478bd9Sstevel@tonic-gate
18787c478bd9Sstevel@tonic-gate if (m.ctm_offset != 0) {
1879e5803b76SAdam H. Leventhal int reg;
1880e5803b76SAdam H. Leventhal
1881e5803b76SAdam H. Leventhal reg = dt_regset_alloc(drp);
18827c478bd9Sstevel@tonic-gate
18837c478bd9Sstevel@tonic-gate /*
18847c478bd9Sstevel@tonic-gate * If the offset is not aligned on a byte boundary, it
18857c478bd9Sstevel@tonic-gate * is a bit-field member and we will extract the value
18867c478bd9Sstevel@tonic-gate * bits below after we generate the appropriate load.
18877c478bd9Sstevel@tonic-gate */
18887c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, reg, m.ctm_offset / NBBY);
18897c478bd9Sstevel@tonic-gate
18907c478bd9Sstevel@tonic-gate instr = DIF_INSTR_FMT(DIF_OP_ADD,
18917c478bd9Sstevel@tonic-gate dnp->dn_left->dn_reg, reg, dnp->dn_left->dn_reg);
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
18947c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
18957c478bd9Sstevel@tonic-gate dt_regset_free(drp, reg);
18967c478bd9Sstevel@tonic-gate }
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate if (!(dnp->dn_flags & DT_NF_REF)) {
18997c478bd9Sstevel@tonic-gate uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
19007c478bd9Sstevel@tonic-gate
19017c478bd9Sstevel@tonic-gate /*
19027c478bd9Sstevel@tonic-gate * Save and restore DT_NF_USERLAND across dt_cg_load():
19037c478bd9Sstevel@tonic-gate * we need the sign bit from dnp and the user bit from
19047c478bd9Sstevel@tonic-gate * dnp->dn_left in order to get the proper opcode.
19057c478bd9Sstevel@tonic-gate */
19067c478bd9Sstevel@tonic-gate dnp->dn_flags |=
19077c478bd9Sstevel@tonic-gate (dnp->dn_left->dn_flags & DT_NF_USERLAND);
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LOAD(dt_cg_load(dnp,
19107c478bd9Sstevel@tonic-gate ctfp, m.ctm_type), dnp->dn_left->dn_reg,
19117c478bd9Sstevel@tonic-gate dnp->dn_left->dn_reg);
19127c478bd9Sstevel@tonic-gate
19137c478bd9Sstevel@tonic-gate dnp->dn_flags &= ~DT_NF_USERLAND;
19147c478bd9Sstevel@tonic-gate dnp->dn_flags |= ubit;
19157c478bd9Sstevel@tonic-gate
19167c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
19177c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
19187c478bd9Sstevel@tonic-gate
19197c478bd9Sstevel@tonic-gate if (dnp->dn_flags & DT_NF_BITFIELD)
19207c478bd9Sstevel@tonic-gate dt_cg_field_get(dnp, dlp, drp, ctfp, &m);
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate
19237c478bd9Sstevel@tonic-gate dnp->dn_reg = dnp->dn_left->dn_reg;
19247c478bd9Sstevel@tonic-gate break;
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate case DT_TOK_STRING:
1927e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate assert(dnp->dn_kind == DT_NODE_STRING);
19307c478bd9Sstevel@tonic-gate stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
19317c478bd9Sstevel@tonic-gate
19327c478bd9Sstevel@tonic-gate if (stroff == -1L)
19337c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
19347c478bd9Sstevel@tonic-gate if (stroff > DIF_STROFF_MAX)
19357c478bd9Sstevel@tonic-gate longjmp(yypcb->pcb_jmpbuf, EDT_STR2BIG);
19367c478bd9Sstevel@tonic-gate
19377c478bd9Sstevel@tonic-gate instr = DIF_INSTR_SETS((ulong_t)stroff, dnp->dn_reg);
19387c478bd9Sstevel@tonic-gate dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
19397c478bd9Sstevel@tonic-gate break;
19407c478bd9Sstevel@tonic-gate
19417c478bd9Sstevel@tonic-gate case DT_TOK_IDENT:
19427c478bd9Sstevel@tonic-gate /*
19437c478bd9Sstevel@tonic-gate * If the specified identifier is a variable on which we have
19447c478bd9Sstevel@tonic-gate * set the code generator register flag, then this variable
19457c478bd9Sstevel@tonic-gate * has already had code generated for it and saved in di_id.
19467c478bd9Sstevel@tonic-gate * Allocate a new register and copy the existing value to it.
19477c478bd9Sstevel@tonic-gate */
19487c478bd9Sstevel@tonic-gate if (dnp->dn_kind == DT_NODE_VAR &&
19497c478bd9Sstevel@tonic-gate (dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
1950e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
19517c478bd9Sstevel@tonic-gate instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
19527c478bd9Sstevel@tonic-gate dnp->dn_reg);
19537c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
19547c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
19557c478bd9Sstevel@tonic-gate break;
19567c478bd9Sstevel@tonic-gate }
19577c478bd9Sstevel@tonic-gate
19587c478bd9Sstevel@tonic-gate /*
19597c478bd9Sstevel@tonic-gate * Identifiers can represent function calls, variable refs, or
19607c478bd9Sstevel@tonic-gate * symbols. First we check for inlined variables, and handle
19617c478bd9Sstevel@tonic-gate * them by generating code for the inline parse tree.
19627c478bd9Sstevel@tonic-gate */
19637c478bd9Sstevel@tonic-gate if (dnp->dn_kind == DT_NODE_VAR &&
19647c478bd9Sstevel@tonic-gate (dnp->dn_ident->di_flags & DT_IDFLG_INLINE)) {
19657c478bd9Sstevel@tonic-gate dt_cg_inline(dnp, dlp, drp);
19667c478bd9Sstevel@tonic-gate break;
19677c478bd9Sstevel@tonic-gate }
19687c478bd9Sstevel@tonic-gate
19697c478bd9Sstevel@tonic-gate switch (dnp->dn_kind) {
19707c478bd9Sstevel@tonic-gate case DT_NODE_FUNC:
19717c478bd9Sstevel@tonic-gate if ((idp = dnp->dn_ident)->di_kind != DT_IDENT_FUNC) {
19727c478bd9Sstevel@tonic-gate dnerror(dnp, D_CG_EXPR, "%s %s( ) may not be "
19737c478bd9Sstevel@tonic-gate "called from a D expression (D program "
19747c478bd9Sstevel@tonic-gate "context required)\n",
19757c478bd9Sstevel@tonic-gate dt_idkind_name(idp->di_kind), idp->di_name);
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
19797c478bd9Sstevel@tonic-gate
1980e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
1981e5803b76SAdam H. Leventhal instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
1982e5803b76SAdam H. Leventhal dnp->dn_reg);
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
19857c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
19867c478bd9Sstevel@tonic-gate
19877c478bd9Sstevel@tonic-gate break;
19887c478bd9Sstevel@tonic-gate
19897c478bd9Sstevel@tonic-gate case DT_NODE_VAR:
19907c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_kind == DT_IDENT_XLSOU ||
19917c478bd9Sstevel@tonic-gate dnp->dn_ident->di_kind == DT_IDENT_XLPTR) {
19927c478bd9Sstevel@tonic-gate /*
19937c478bd9Sstevel@tonic-gate * This can only happen if we have translated
19947c478bd9Sstevel@tonic-gate * args[]. See dt_idcook_args() for details.
19957c478bd9Sstevel@tonic-gate */
19967c478bd9Sstevel@tonic-gate assert(dnp->dn_ident->di_id == DIF_VAR_ARGS);
19977c478bd9Sstevel@tonic-gate dt_cg_array_op(dnp, dlp, drp);
19987c478bd9Sstevel@tonic-gate break;
19997c478bd9Sstevel@tonic-gate }
20007c478bd9Sstevel@tonic-gate
20017c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_kind == DT_IDENT_ARRAY) {
20027c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_id > DIF_VAR_ARRAY_MAX)
20037c478bd9Sstevel@tonic-gate dt_cg_assoc_op(dnp, dlp, drp);
20047c478bd9Sstevel@tonic-gate else
20057c478bd9Sstevel@tonic-gate dt_cg_array_op(dnp, dlp, drp);
20067c478bd9Sstevel@tonic-gate break;
20077c478bd9Sstevel@tonic-gate }
20087c478bd9Sstevel@tonic-gate
2009e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
20107c478bd9Sstevel@tonic-gate
20117c478bd9Sstevel@tonic-gate if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
20127c478bd9Sstevel@tonic-gate op = DIF_OP_LDLS;
20137c478bd9Sstevel@tonic-gate else if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
20147c478bd9Sstevel@tonic-gate op = DIF_OP_LDTS;
20157c478bd9Sstevel@tonic-gate else
20167c478bd9Sstevel@tonic-gate op = DIF_OP_LDGS;
20177c478bd9Sstevel@tonic-gate
20187c478bd9Sstevel@tonic-gate dnp->dn_ident->di_flags |= DT_IDFLG_DIFR;
20197c478bd9Sstevel@tonic-gate
20207c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LDV(op,
20217c478bd9Sstevel@tonic-gate dnp->dn_ident->di_id, dnp->dn_reg);
20227c478bd9Sstevel@tonic-gate
20237c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
20247c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
20257c478bd9Sstevel@tonic-gate break;
20267c478bd9Sstevel@tonic-gate
20277c478bd9Sstevel@tonic-gate case DT_NODE_SYM: {
20287c478bd9Sstevel@tonic-gate dtrace_hdl_t *dtp = yypcb->pcb_hdl;
20297c478bd9Sstevel@tonic-gate dtrace_syminfo_t *sip = dnp->dn_ident->di_data;
20307c478bd9Sstevel@tonic-gate GElf_Sym sym;
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate if (dtrace_lookup_by_name(dtp,
20337c478bd9Sstevel@tonic-gate sip->dts_object, sip->dts_name, &sym, NULL) == -1) {
20347c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "cg failed for symbol %s`%s:"
20357c478bd9Sstevel@tonic-gate " %s\n", sip->dts_object, sip->dts_name,
20367c478bd9Sstevel@tonic-gate dtrace_errmsg(dtp, dtrace_errno(dtp)));
20377c478bd9Sstevel@tonic-gate }
20387c478bd9Sstevel@tonic-gate
2039e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
20407c478bd9Sstevel@tonic-gate dt_cg_xsetx(dlp, dnp->dn_ident,
20417c478bd9Sstevel@tonic-gate DT_LBL_NONE, dnp->dn_reg, sym.st_value);
20427c478bd9Sstevel@tonic-gate
20437c478bd9Sstevel@tonic-gate if (!(dnp->dn_flags & DT_NF_REF)) {
20447c478bd9Sstevel@tonic-gate instr = DIF_INSTR_LOAD(dt_cg_load(dnp, ctfp,
20457c478bd9Sstevel@tonic-gate dnp->dn_type), dnp->dn_reg, dnp->dn_reg);
20467c478bd9Sstevel@tonic-gate dt_irlist_append(dlp,
20477c478bd9Sstevel@tonic-gate dt_cg_node_alloc(DT_LBL_NONE, instr));
20487c478bd9Sstevel@tonic-gate }
20497c478bd9Sstevel@tonic-gate break;
20507c478bd9Sstevel@tonic-gate }
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gate default:
20537c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "internal error -- node type %u is "
20547c478bd9Sstevel@tonic-gate "not valid for an identifier\n", dnp->dn_kind);
20557c478bd9Sstevel@tonic-gate }
20567c478bd9Sstevel@tonic-gate break;
20577c478bd9Sstevel@tonic-gate
20587c478bd9Sstevel@tonic-gate case DT_TOK_INT:
2059e5803b76SAdam H. Leventhal dnp->dn_reg = dt_regset_alloc(drp);
20607c478bd9Sstevel@tonic-gate dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
20617c478bd9Sstevel@tonic-gate break;
20627c478bd9Sstevel@tonic-gate
20637c478bd9Sstevel@tonic-gate default:
20647c478bd9Sstevel@tonic-gate xyerror(D_UNKNOWN, "internal error -- token type %u is not a "
20657c478bd9Sstevel@tonic-gate "valid D compilation token\n", dnp->dn_op);
20667c478bd9Sstevel@tonic-gate }
20677c478bd9Sstevel@tonic-gate }
20687c478bd9Sstevel@tonic-gate
20697c478bd9Sstevel@tonic-gate void
dt_cg(dt_pcb_t * pcb,dt_node_t * dnp)20707c478bd9Sstevel@tonic-gate dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
20717c478bd9Sstevel@tonic-gate {
20727c478bd9Sstevel@tonic-gate dif_instr_t instr;
20731a7c1b72Smws dt_xlator_t *dxp;
2074e5803b76SAdam H. Leventhal dt_ident_t *idp;
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
20777c478bd9Sstevel@tonic-gate dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
20787c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
20797c478bd9Sstevel@tonic-gate
20807c478bd9Sstevel@tonic-gate dt_regset_reset(pcb->pcb_regs);
20817c478bd9Sstevel@tonic-gate (void) dt_regset_alloc(pcb->pcb_regs); /* allocate %r0 */
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate if (pcb->pcb_inttab != NULL)
20847c478bd9Sstevel@tonic-gate dt_inttab_destroy(pcb->pcb_inttab);
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate if ((pcb->pcb_inttab = dt_inttab_create(yypcb->pcb_hdl)) == NULL)
20877c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
20887c478bd9Sstevel@tonic-gate
20897c478bd9Sstevel@tonic-gate if (pcb->pcb_strtab != NULL)
20907c478bd9Sstevel@tonic-gate dt_strtab_destroy(pcb->pcb_strtab);
20917c478bd9Sstevel@tonic-gate
20927c478bd9Sstevel@tonic-gate if ((pcb->pcb_strtab = dt_strtab_create(BUFSIZ)) == NULL)
20937c478bd9Sstevel@tonic-gate longjmp(pcb->pcb_jmpbuf, EDT_NOMEM);
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate dt_irlist_destroy(&pcb->pcb_ir);
20967c478bd9Sstevel@tonic-gate dt_irlist_create(&pcb->pcb_ir);
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate assert(pcb->pcb_dret == NULL);
20997c478bd9Sstevel@tonic-gate pcb->pcb_dret = dnp;
21007c478bd9Sstevel@tonic-gate
2101e5803b76SAdam H. Leventhal if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
21027c478bd9Sstevel@tonic-gate dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
2103e5803b76SAdam H. Leventhal "of a translated pointer\n");
21047c478bd9Sstevel@tonic-gate }
21057c478bd9Sstevel@tonic-gate
21061a7c1b72Smws /*
21071a7c1b72Smws * If we're generating code for a translator body, assign the input
21081a7c1b72Smws * parameter to the first available register (i.e. caller passes %r1).
21091a7c1b72Smws */
21101a7c1b72Smws if (dnp->dn_kind == DT_NODE_MEMBER) {
21111a7c1b72Smws dxp = dnp->dn_membxlator;
21121a7c1b72Smws dnp = dnp->dn_membexpr;
21131a7c1b72Smws
21141a7c1b72Smws dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
21151a7c1b72Smws dxp->dx_ident->di_id = dt_regset_alloc(pcb->pcb_regs);
21161a7c1b72Smws }
21171a7c1b72Smws
21187c478bd9Sstevel@tonic-gate dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
2119e5803b76SAdam H. Leventhal
2120e5803b76SAdam H. Leventhal if ((idp = dt_node_resolve(dnp, DT_IDENT_XLSOU)) != NULL) {
2121e5803b76SAdam H. Leventhal int reg = dt_cg_xlate_expand(dnp, idp,
2122e5803b76SAdam H. Leventhal &pcb->pcb_ir, pcb->pcb_regs);
2123e5803b76SAdam H. Leventhal dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
2124e5803b76SAdam H. Leventhal dnp->dn_reg = reg;
2125e5803b76SAdam H. Leventhal }
2126e5803b76SAdam H. Leventhal
21277c478bd9Sstevel@tonic-gate instr = DIF_INSTR_RET(dnp->dn_reg);
21287c478bd9Sstevel@tonic-gate dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
21297c478bd9Sstevel@tonic-gate dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
21301a7c1b72Smws
21311a7c1b72Smws if (dnp->dn_kind == DT_NODE_MEMBER) {
21321a7c1b72Smws dt_regset_free(pcb->pcb_regs, dxp->dx_ident->di_id);
21331a7c1b72Smws dxp->dx_ident->di_id = 0;
21341a7c1b72Smws dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
21351a7c1b72Smws }
2136e5803b76SAdam H. Leventhal
2137e5803b76SAdam H. Leventhal dt_regset_free(pcb->pcb_regs, 0);
2138e5803b76SAdam H. Leventhal dt_regset_assert_free(pcb->pcb_regs);
21397c478bd9Sstevel@tonic-gate }
2140