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