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