1 /** 2 * Routines to handle elems. 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1985-1998 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/elem.d, backend/elem.d) 12 */ 13 14 module dmd.backend.elem; 15 16 enum HYDRATE = false; 17 enum DEHYDRATE = false; 18 19 import core.stdc.stdarg; 20 import core.stdc.stdio; 21 import core.stdc.stdlib; 22 import core.stdc.string; 23 24 import dmd.backend.cdef; 25 import dmd.backend.cc; 26 import dmd.backend.cgcv; 27 import dmd.backend.code; 28 import dmd.backend.code_x86; 29 import dmd.backend.dlist; 30 import dmd.backend.dt; 31 import dmd.backend.dvec; 32 import dmd.backend.el; 33 import dmd.backend.evalu8 : el_toldoubled; 34 import dmd.backend.global; 35 import dmd.backend.goh; 36 import dmd.backend.mem; 37 import dmd.backend.obj; 38 import dmd.backend.oper; 39 import dmd.backend.rtlsym; 40 import dmd.backend.ty; 41 import dmd.backend.type; 42 43 version (CRuntime_Microsoft) 44 { 45 import dmd.root.longdouble; 46 } 47 48 /+ 49 version (CRuntime_Microsoft) extern (C++) 50 { 51 alias real_t = real; 52 private struct longdouble_soft { real_t r; } 53 size_t ld_sprint(char* str, size_t size, int fmt, longdouble_soft x); 54 } 55 +/ 56 57 58 nothrow: 59 @safe: 60 61 version (STATS) 62 { 63 private __gshared 64 { 65 int elfreed = 0; /* number of freed elems */ 66 int eprm_cnt; /* max # of allocs at any point */ 67 } 68 } 69 70 /******************************* 71 * Do our own storage allocation of elems. 72 */ 73 74 private __gshared 75 { 76 elem *nextfree = null; /* pointer to next free elem */ 77 78 int elcount = 0; /* number of allocated elems */ 79 int elem_size = elem.sizeof; 80 81 debug 82 int elmax; /* max # of allocs at any point */ 83 } 84 85 ///////////////////////////// 86 // Table to gather redundant strings in. 87 88 struct STAB 89 { 90 Symbol *sym; // symbol that refers to the string 91 char[] str; // the string 92 } 93 94 private __gshared 95 { 96 STAB[16] stable; 97 int stable_si; 98 } 99 100 /************************ 101 * Initialize el package. 102 */ 103 104 @trusted 105 void el_init() 106 { 107 if (!configv.addlinenumbers) 108 elem_size = elem.sizeof - Srcpos.sizeof; 109 } 110 111 /******************************* 112 * Initialize for another run through. 113 */ 114 115 @trusted 116 void el_reset() 117 { 118 stable_si = 0; 119 for (int i = 0; i < stable.length; i++) 120 mem_free(stable[i].str.ptr); 121 memset(stable.ptr,0,stable.sizeof); 122 } 123 124 /************************ 125 * Terminate el package. 126 */ 127 128 @trusted 129 void el_term() 130 { 131 static if (TERMCODE) 132 { 133 for (int i = 0; i < stable.length; i++) 134 mem_free(stable[i].str.ptr); 135 136 debug printf("Max # of elems = %d\n",elmax); 137 138 if (elcount != 0) 139 printf("unfreed elems = %d\n",elcount); 140 while (nextfree) 141 { 142 elem *e; 143 e = nextfree.EV.E1; 144 mem_ffree(nextfree); 145 nextfree = e; 146 } 147 } 148 else 149 { 150 assert(elcount == 0); 151 } 152 } 153 154 /*********************** 155 * Allocate an element. 156 */ 157 158 @trusted 159 elem *el_calloc() 160 { 161 elem *e; 162 163 elcount++; 164 if (nextfree) 165 { 166 e = nextfree; 167 nextfree = e.EV.E1; 168 } 169 else 170 e = cast(elem *) mem_fmalloc(elem.sizeof); 171 172 version (STATS) 173 eprm_cnt++; 174 175 //MEMCLEAR(e, (*e).sizeof); 176 memset(e, 0, (*e).sizeof); 177 178 debug 179 { 180 e.id = elem.IDelem; 181 if (elcount > elmax) 182 elmax = elcount; 183 } 184 /*printf("el_calloc() = %p\n",e);*/ 185 return e; 186 } 187 188 189 /*************** 190 * Free element 191 */ 192 @trusted 193 void el_free(elem *e) 194 { 195 L1: 196 if (!e) return; 197 elem_debug(e); 198 //printf("el_free(%p)\n",e); 199 //elem_print(e); 200 if (e.Ecount--) 201 return; // usage count 202 elcount--; 203 const op = e.Eoper; 204 switch (op) 205 { 206 case OPconst: 207 break; 208 209 case OPvar: 210 break; 211 212 case OPrelconst: 213 break; 214 215 case OPstring: 216 case OPasm: 217 mem_free(e.EV.Vstring); 218 break; 219 220 default: 221 debug assert(op < OPMAX); 222 if (!OTleaf(op)) 223 { 224 if (OTbinary(op)) 225 el_free(e.EV.E2); 226 elem* en = e.EV.E1; 227 debug memset(e,0xFF,elem_size); 228 e.EV.E1 = nextfree; 229 nextfree = e; 230 231 version (STATS) 232 elfreed++; 233 234 e = en; 235 goto L1; 236 } 237 break; 238 } 239 debug memset(e,0xFF,elem_size); 240 e.EV.E1 = nextfree; 241 nextfree = e; 242 243 version (STATS) 244 elfreed++; 245 } 246 247 version (STATS) 248 { 249 /* count number of elems available on free list */ 250 void el_count_free() 251 { 252 elem *e; 253 int count; 254 255 for(e=nextfree;e;e=e.EV.E1) 256 count++; 257 printf("Requests for elems %d\n",elcount); 258 printf("Requests to free elems %d\n",elfreed); 259 printf("Number of elems %d\n",eprm_cnt); 260 printf("Number of elems currently on free list %d\n",count); 261 } 262 } 263 264 /********************* 265 * Combine e1 and e2 with a comma-expression. 266 * Be careful about either or both being null. 267 */ 268 269 elem * el_combine(elem *e1,elem *e2) 270 { 271 if (e1) 272 { 273 if (e2) 274 { 275 e1 = el_bin(OPcomma,e2.Ety,e1,e2); 276 } 277 } 278 else 279 e1 = e2; 280 return e1; 281 } 282 283 /********************* 284 * Combine e1 and e2 as parameters to a function. 285 * Be careful about either or both being null. 286 */ 287 288 elem * el_param(elem *e1,elem *e2) 289 { 290 //printf("el_param(%p, %p)\n", e1, e2); 291 if (e1) 292 { 293 if (e2) 294 { 295 e1 = el_bin(OPparam,TYvoid,e1,e2); 296 } 297 } 298 else 299 e1 = e2; 300 return e1; 301 } 302 303 /********************************* 304 * Create parameter list, terminated by a null. 305 */ 306 307 @trusted 308 elem *el_params(elem *e1, ...) 309 { 310 elem *e; 311 va_list ap; 312 313 e = null; 314 va_start(ap, e1); 315 for (; e1; e1 = va_arg!(elem *)(ap)) 316 { 317 e = el_param(e, e1); 318 } 319 va_end(ap); 320 return e; 321 } 322 323 /***************************************** 324 * Do an array of parameters as a balanced 325 * binary tree. 326 */ 327 328 @trusted 329 elem *el_params(void **args, int length) 330 { 331 if (length == 0) 332 return null; 333 if (length == 1) 334 return cast(elem *)args[0]; 335 int mid = length >> 1; 336 return el_param(el_params(args, mid), 337 el_params(args + mid, length - mid)); 338 } 339 340 /***************************************** 341 * Do an array of parameters as a balanced 342 * binary tree. 343 */ 344 345 @trusted 346 elem *el_combines(void **args, int length) 347 { 348 if (length == 0) 349 return null; 350 if (length == 1) 351 return cast(elem *)args[0]; 352 int mid = length >> 1; 353 return el_combine(el_combines(args, mid), 354 el_combines(args + mid, length - mid)); 355 } 356 357 /************************************** 358 * Return number of op nodes 359 */ 360 361 @trusted 362 size_t el_opN(const elem *e, OPER op) 363 { 364 if (e.Eoper == op) 365 return el_opN(e.EV.E1, op) + el_opN(e.EV.E2, op); 366 else 367 return 1; 368 } 369 370 /****************************************** 371 * Fill an array with the ops. 372 */ 373 374 @trusted 375 void el_opArray(elem ***parray, elem *e, OPER op) 376 { 377 if (e.Eoper == op) 378 { 379 el_opArray(parray, e.EV.E1, op); 380 el_opArray(parray, e.EV.E2, op); 381 } 382 else 383 { 384 **parray = e; 385 ++(*parray); 386 } 387 } 388 389 @trusted 390 void el_opFree(elem *e, OPER op) 391 { 392 if (e.Eoper == op) 393 { 394 el_opFree(e.EV.E1, op); 395 el_opFree(e.EV.E2, op); 396 e.EV.E1 = null; 397 e.EV.E2 = null; 398 el_free(e); 399 } 400 } 401 402 /***************************************** 403 * Do an array of parameters as a tree 404 */ 405 406 @trusted 407 extern (C) elem *el_opCombine(elem **args, size_t length, OPER op, tym_t ty) 408 { 409 if (length == 0) 410 return null; 411 if (length == 1) 412 return args[0]; 413 return el_bin(op, ty, el_opCombine(args, length - 1, op, ty), args[length - 1]); 414 } 415 416 /*************************************** 417 * Return a list of the parameters. 418 */ 419 420 int el_nparams(const elem *e) 421 { 422 return cast(int)el_opN(e, OPparam); 423 } 424 425 /****************************************** 426 * Fill an array with the parameters. 427 */ 428 429 @trusted 430 void el_paramArray(elem ***parray, elem *e) 431 { 432 if (e.Eoper == OPparam) 433 { 434 el_paramArray(parray, e.EV.E1); 435 el_paramArray(parray, e.EV.E2); 436 freenode(e); 437 } 438 else 439 { 440 **parray = e; 441 ++(*parray); 442 } 443 } 444 445 /************************************* 446 * Create a quad word out of two dwords. 447 */ 448 449 elem *el_pair(tym_t tym, elem *lo, elem *hi) 450 { 451 static if (0) 452 { 453 lo = el_una(OPu32_64, TYullong, lo); 454 hi = el_una(OPu32_64, TYullong, hi); 455 hi = el_bin(OPshl, TYullong, hi, el_long(TYint, 32)); 456 return el_bin(OPor, tym, lo, hi); 457 } 458 else 459 { 460 return el_bin(OPpair, tym, lo, hi); 461 } 462 } 463 464 465 /************************* 466 * Copy an element (not the tree!). 467 */ 468 469 @trusted 470 void el_copy(elem *to, const elem *from) 471 { 472 assert(to && from); 473 elem_debug(from); 474 elem_debug(to); 475 memcpy(to,from,elem_size); 476 elem_debug(to); 477 } 478 479 /*********************************** 480 * Allocate a temporary, and return temporary elem. 481 */ 482 483 @trusted 484 elem * el_alloctmp(tym_t ty) 485 { 486 Symbol *s; 487 s = symbol_generate(SC.auto_,type_fake(ty)); 488 symbol_add(s); 489 s.Sfl = FLauto; 490 s.Sflags = SFLfree | SFLunambig | GTregcand; 491 return el_var(s); 492 } 493 494 /******************************** 495 * Select the e1 child of e. 496 */ 497 498 @trusted 499 elem * el_selecte1(elem *e) 500 { 501 elem *e1; 502 assert(!PARSER); 503 elem_debug(e); 504 assert(!OTleaf(e.Eoper)); 505 e1 = e.EV.E1; 506 elem_debug(e1); 507 if (e.EV.E2) elem_debug(e.EV.E2); 508 e.EV.E1 = null; // so e1 won't be freed 509 if (configv.addlinenumbers) 510 { 511 if (e.Esrcpos.Slinnum) 512 e1.Esrcpos = e.Esrcpos; 513 } 514 e1.Ety = e.Ety; 515 //if (tyaggregate(e1.Ety)) 516 // e1.Enumbytes = e.Enumbytes; 517 if (!e1.Ejty) 518 e1.Ejty = e.Ejty; 519 el_free(e); 520 return e1; 521 } 522 523 /******************************** 524 * Select the e2 child of e. 525 */ 526 527 @trusted 528 elem * el_selecte2(elem *e) 529 { 530 elem *e2; 531 //printf("el_selecte2(%p)\n",e); 532 elem_debug(e); 533 assert(OTbinary(e.Eoper)); 534 if (e.EV.E1) 535 elem_debug(e.EV.E1); 536 e2 = e.EV.E2; 537 elem_debug(e2); 538 e.EV.E2 = null; // so e2 won't be freed 539 if (configv.addlinenumbers) 540 { 541 if (e.Esrcpos.Slinnum) 542 e2.Esrcpos = e.Esrcpos; 543 } 544 if (PARSER) 545 el_settype(e2,e.ET); 546 else 547 { 548 e2.Ety = e.Ety; 549 //if (tyaggregate(e.Ety)) 550 // e2.Enumbytes = e.Enumbytes; 551 } 552 el_free(e); 553 return e2; 554 } 555 556 /************************* 557 * Create and return a duplicate of e, including its leaves. 558 * No CSEs. 559 */ 560 561 @trusted 562 elem * el_copytree(elem *e) 563 { 564 elem *d; 565 if (!e) 566 return e; 567 elem_debug(e); 568 d = el_calloc(); 569 el_copy(d,e); 570 d.Ecount = 0; 571 if (!OTleaf(e.Eoper)) 572 { 573 d.EV.E1 = el_copytree(e.EV.E1); 574 if (OTbinary(e.Eoper)) 575 d.EV.E2 = el_copytree(e.EV.E2); 576 } 577 else 578 { 579 switch (e.Eoper) 580 { 581 case OPstring: 582 static if (0) 583 { 584 if (OPTIMIZER) 585 { 586 /* Convert the string to a static symbol and 587 then just refer to it, because two OPstrings can't 588 refer to the same string. 589 */ 590 591 el_convstring(e); // convert string to symbol 592 d.Eoper = OPrelconst; 593 d.EV.Vsym = e.EV.Vsym; 594 break; 595 } 596 } 597 static if (0) 598 { 599 case OPrelconst: 600 e.EV.sm.ethis = null; 601 break; 602 } 603 case OPasm: 604 d.EV.Vstring = cast(char *) mem_malloc(d.EV.Vstrlen); 605 memcpy(d.EV.Vstring,e.EV.Vstring,e.EV.Vstrlen); 606 break; 607 608 default: 609 break; 610 } 611 } 612 return d; 613 } 614 615 /******************************* 616 * Replace (e) with ((stmp = e),stmp) 617 */ 618 @trusted 619 elem *exp2_copytotemp(elem *e) 620 { 621 //printf("exp2_copytotemp()\n"); 622 elem_debug(e); 623 tym_t ty = tybasic(e.Ety); 624 type *t; 625 if ((ty == TYstruct || ty == TYarray) && e.ET) 626 t = e.ET; 627 else 628 t = type_fake(ty); 629 630 Symbol *stmp = symbol_genauto(t); 631 elem *eeq = el_bin(OPeq,e.Ety,el_var(stmp),e); 632 elem *er = el_bin(OPcomma,e.Ety,eeq,el_var(stmp)); 633 if (ty == TYstruct || ty == TYarray) 634 { 635 eeq.Eoper = OPstreq; 636 eeq.ET = e.ET; 637 eeq.EV.E1.ET = e.ET; 638 er.ET = e.ET; 639 er.EV.E2.ET = e.ET; 640 } 641 return er; 642 } 643 644 /************************* 645 * Similar to el_copytree(e). But if e has any side effects, it's replaced 646 * with (tmp = e) and tmp is returned. 647 */ 648 649 @trusted 650 elem * el_same(elem **pe) 651 { 652 elem *e = *pe; 653 if (e && el_sideeffect(e)) 654 { 655 *pe = exp2_copytotemp(e); /* convert to ((tmp=e),tmp) */ 656 e = (*pe).EV.E2; /* point at tmp */ 657 } 658 return el_copytree(e); 659 } 660 661 /************************* 662 * Thin wrapper of exp2_copytotemp. Different from el_same, 663 * always makes a temporary. 664 */ 665 @trusted 666 elem *el_copytotmp(elem **pe) 667 { 668 //printf("copytotemp()\n"); 669 elem *e = *pe; 670 if (e) 671 { 672 *pe = exp2_copytotemp(e); 673 e = (*pe).EV.E2; 674 } 675 return el_copytree(e); 676 } 677 678 /************************************* 679 * Does symbol s appear in tree e? 680 * Returns: 681 * 1 yes 682 * 0 no 683 */ 684 685 @trusted 686 int el_appears(const(elem)* e, const Symbol *s) 687 { 688 symbol_debug(s); 689 while (1) 690 { 691 elem_debug(e); 692 if (!OTleaf(e.Eoper)) 693 { 694 if (OTbinary(e.Eoper) && el_appears(e.EV.E2,s)) 695 return 1; 696 e = e.EV.E1; 697 } 698 else 699 { 700 switch (e.Eoper) 701 { 702 case OPvar: 703 case OPrelconst: 704 if (e.EV.Vsym == s) 705 return 1; 706 break; 707 708 default: 709 break; 710 } 711 break; 712 } 713 } 714 return 0; 715 } 716 717 /***************************************** 718 * Look for symbol that is a base of addressing mode e. 719 * Returns: 720 * s symbol used as base 721 * null couldn't find a base symbol 722 */ 723 724 static if (0) 725 { 726 Symbol *el_basesym(elem *e) 727 { 728 Symbol *s; 729 s = null; 730 while (1) 731 { 732 elem_debug(e); 733 switch (e.Eoper) 734 { 735 case OPvar: 736 s = e.EV.Vsym; 737 break; 738 739 case OPcomma: 740 e = e.EV.E2; 741 continue; 742 743 case OPind: 744 s = el_basesym(e.EV.E1); 745 break; 746 747 case OPadd: 748 s = el_basesym(e.EV.E1); 749 if (!s) 750 s = el_basesym(e.EV.E2); 751 break; 752 } 753 break; 754 } 755 return s; 756 } 757 } 758 759 /**************************************** 760 * Does any definition of lvalue ed appear in e? 761 * Returns: 762 * true if there is one 763 */ 764 765 @trusted 766 bool el_anydef(const elem *ed, const(elem)* e) 767 { 768 const edop = ed.Eoper; 769 const s = (edop == OPvar) ? ed.EV.Vsym : null; 770 while (1) 771 { 772 const op = e.Eoper; 773 if (!OTleaf(op)) 774 { 775 auto e1 = e.EV.E1; 776 if (OTdef(op)) 777 { 778 if (e1.Eoper == OPvar && e1.EV.Vsym == s) 779 return true; 780 781 // This doesn't cover all the cases 782 if (e1.Eoper == edop && el_match(e1,ed)) 783 return true; 784 } 785 if (OTbinary(op) && el_anydef(ed,e.EV.E2)) 786 return true; 787 e = e1; 788 } 789 else 790 break; 791 } 792 return false; 793 } 794 795 /************************ 796 * Make a binary operator node. 797 */ 798 799 @trusted 800 elem* el_bint(OPER op,type *t,elem *e1,elem *e2) 801 { 802 elem *e; 803 /* e2 is null when OPpostinc is built */ 804 assert(op < OPMAX && OTbinary(op) && e1); 805 assert(PARSER); 806 e = el_calloc(); 807 if (t) 808 { 809 e.ET = t; 810 type_debug(t); 811 e.ET.Tcount++; 812 } 813 e.Eoper = cast(ubyte)op; 814 elem_debug(e1); 815 if (e2) 816 elem_debug(e2); 817 e.EV.E1 = e1; 818 e.EV.E2 = e2; 819 return e; 820 } 821 822 @trusted 823 elem* el_bin(OPER op,tym_t ty,elem *e1,elem *e2) 824 { 825 static if (0) 826 { 827 if (!(op < OPMAX && OTbinary(op) && e1 && e2)) 828 *cast(char *)0=0; 829 } 830 assert(op < OPMAX && OTbinary(op) && e1 && e2); 831 elem_debug(e1); 832 elem_debug(e2); 833 elem* e = el_calloc(); 834 e.Ety = ty; 835 e.Eoper = cast(ubyte)op; 836 e.EV.E1 = e1; 837 e.EV.E2 = e2; 838 if (op == OPcomma && tyaggregate(ty)) 839 e.ET = e2.ET; 840 return e; 841 } 842 843 /************************ 844 * Make a unary operator node. 845 */ 846 847 @trusted 848 elem* el_unat(OPER op,type *t,elem *e1) 849 { 850 debug if (!(op < OPMAX && OTunary(op) && e1)) 851 printf("op = x%x, e1 = %p\n",op,e1); 852 853 assert(op < OPMAX && OTunary(op) && e1); 854 assert(PARSER); 855 elem_debug(e1); 856 elem* e = el_calloc(); 857 e.Eoper = cast(ubyte)op; 858 e.EV.E1 = e1; 859 if (t) 860 { 861 type_debug(t); 862 t.Tcount++; 863 e.ET = t; 864 } 865 return e; 866 } 867 868 @trusted 869 elem* el_una(OPER op,tym_t ty,elem *e1) 870 { 871 debug if (!(op < OPMAX && OTunary(op) && e1)) 872 printf("op = x%x, e1 = %p\n",op,e1); 873 874 assert(op < OPMAX && OTunary(op) && e1); 875 elem_debug(e1); 876 elem* e = el_calloc(); 877 e.Ety = ty; 878 e.Eoper = cast(ubyte)op; 879 e.EV.E1 = e1; 880 return e; 881 } 882 883 /******************* 884 * Make a constant node out of integral type. 885 */ 886 887 @trusted 888 extern (C) elem * el_longt(type *t,targ_llong val) 889 { 890 assert(PARSER); 891 elem* e = el_calloc(); 892 e.Eoper = OPconst; 893 e.ET = t; 894 if (e.ET) 895 { 896 type_debug(t); 897 e.ET.Tcount++; 898 } 899 e.EV.Vllong = val; 900 return e; 901 } 902 903 extern (C) // necessary because D <=> C++ mangling of "long long" is not consistent across memory models 904 { 905 elem * el_long(tym_t t,targ_llong val) 906 { 907 elem* e = el_calloc(); 908 e.Eoper = OPconst; 909 e.Ety = t; 910 switch (tybasic(t)) 911 { 912 case TYfloat: 913 case TYifloat: 914 e.EV.Vfloat = val; 915 break; 916 917 case TYdouble: 918 case TYidouble: 919 e.EV.Vdouble = val; 920 break; 921 922 case TYldouble: 923 case TYildouble: 924 e.EV.Vldouble = val; 925 break; 926 927 case TYcfloat: 928 case TYcdouble: 929 case TYcldouble: 930 assert(0); 931 932 default: 933 e.EV.Vllong = val; 934 break; 935 } 936 return e; 937 } 938 939 /****************************** 940 * Create a const integer vector elem 941 * Params: 942 * ty = type of the vector 943 * val = value to broadcast to the vector elements 944 * Returns: 945 * created OPconst elem 946 */ 947 @trusted 948 elem* el_vectorConst(tym_t ty, ulong val) 949 { 950 elem* e = el_calloc(); 951 e.Eoper = OPconst; 952 e.Ety = ty; 953 const sz = tysize(ty); 954 955 if (val == 0 || !((val & 0xFF) + 1)) 956 { 957 memset(&e.EV, cast(ubyte)val, sz); 958 return e; 959 } 960 961 switch (tybasic(ty)) 962 { 963 case TYschar16: 964 case TYuchar16: 965 case TYschar32: 966 case TYuchar32: 967 foreach (i; 0 .. sz) 968 { 969 e.EV.Vuchar32[i] = cast(ubyte)val; 970 } 971 break; 972 973 case TYshort8: 974 case TYushort8: 975 case TYshort16: 976 case TYushort16: 977 foreach (i; 0 .. sz / 2) 978 { 979 e.EV.Vushort16[i] = cast(ushort)val; 980 } 981 break; 982 983 case TYlong4: 984 case TYulong4: 985 case TYlong8: 986 case TYulong8: 987 foreach (i; 0 .. sz / 4) 988 { 989 e.EV.Vulong8[i] = cast(uint)val; 990 } 991 break; 992 993 case TYllong2: 994 case TYullong2: 995 case TYllong4: 996 case TYullong4: 997 foreach (i; 0 .. sz / 8) 998 { 999 e.EV.Vullong4[i] = val; 1000 } 1001 break; 1002 1003 default: 1004 assert(0); 1005 } 1006 return e; 1007 } 1008 } 1009 1010 /******************************* 1011 * Set new type for elem. 1012 */ 1013 1014 elem * el_settype(elem *e,type *t) 1015 { 1016 assert(0); 1017 } 1018 1019 /******************************* 1020 * Create elem that is the size of a type. 1021 */ 1022 1023 elem * el_typesize(type *t) 1024 { 1025 assert(0); 1026 } 1027 1028 /************************************ 1029 * Returns: true if function has any side effects. 1030 */ 1031 1032 @trusted 1033 bool el_funcsideeff(const elem *e) 1034 { 1035 const(Symbol)* s; 1036 if (e.Eoper == OPvar && 1037 tyfunc((s = e.EV.Vsym).Stype.Tty) && 1038 ((s.Sfunc && s.Sfunc.Fflags3 & Fnosideeff) || s == funcsym_p) 1039 ) 1040 return false; 1041 return true; // assume it does have side effects 1042 } 1043 1044 /**************************** 1045 * Returns: true if elem has any side effects. 1046 */ 1047 1048 @trusted 1049 bool el_sideeffect(const elem *e) 1050 { 1051 assert(e); 1052 const op = e.Eoper; 1053 assert(op < OPMAX); 1054 elem_debug(e); 1055 return typemask(e) & (mTYvolatile | mTYshared) || 1056 OTsideff(op) || 1057 (OTunary(op) && el_sideeffect(e.EV.E1)) || 1058 (OTbinary(op) && (el_sideeffect(e.EV.E1) || 1059 el_sideeffect(e.EV.E2))); 1060 } 1061 1062 /****************************** 1063 * Input: 1064 * ea lvalue (might be an OPbit) 1065 * Returns: 1066 * 0 eb has no dependency on ea 1067 * 1 eb might have a dependency on ea 1068 * 2 eb definitely depends on ea 1069 */ 1070 1071 @trusted 1072 int el_depends(const(elem)* ea, const elem *eb) 1073 { 1074 L1: 1075 elem_debug(ea); 1076 elem_debug(eb); 1077 switch (ea.Eoper) 1078 { 1079 case OPbit: 1080 ea = ea.EV.E1; 1081 goto L1; 1082 1083 case OPvar: 1084 case OPind: 1085 break; 1086 1087 default: 1088 assert(0); 1089 } 1090 switch (eb.Eoper) 1091 { 1092 case OPconst: 1093 case OPrelconst: 1094 case OPstring: 1095 goto Lnodep; 1096 1097 case OPvar: 1098 if (ea.Eoper == OPvar && ea.EV.Vsym != eb.EV.Vsym) 1099 goto Lnodep; 1100 break; 1101 1102 default: 1103 break; // this could use improvement 1104 } 1105 return 1; 1106 1107 Lnodep: 1108 return 0; 1109 } 1110 1111 1112 /************************* 1113 * Returns: 1114 * true elem evaluates right-to-left 1115 * false elem evaluates left-to-right 1116 */ 1117 1118 @trusted 1119 bool ERTOL(const elem *e) 1120 { 1121 elem_debug(e); 1122 assert(!PARSER); 1123 return OTrtol(e.Eoper) && 1124 (!OTopeq(e.Eoper) || config.inline8087 || !tyfloating(e.Ety)); 1125 } 1126 1127 /******************************** 1128 * Determine if expression may return. 1129 * Does not detect all cases, errs on the side of saying it returns. 1130 * Params: 1131 * e = tree 1132 * Returns: 1133 * false if expression never returns. 1134 */ 1135 1136 @trusted 1137 bool el_returns(const(elem)* e) 1138 { 1139 while (1) 1140 { 1141 elem_debug(e); 1142 switch (e.Eoper) 1143 { 1144 case OPcall: 1145 case OPucall: 1146 e = e.EV.E1; 1147 if (e.Eoper == OPvar && e.EV.Vsym.Sflags & SFLexit) 1148 return false; 1149 break; 1150 1151 case OPhalt: 1152 return false; 1153 1154 case OPandand: 1155 case OPoror: 1156 e = e.EV.E1; 1157 continue; 1158 1159 case OPcolon: 1160 case OPcolon2: 1161 return el_returns(e.EV.E1) || el_returns(e.EV.E2); 1162 1163 default: 1164 if (OTbinary(e.Eoper)) 1165 { 1166 if (!el_returns(e.EV.E2)) 1167 return false; 1168 e = e.EV.E1; 1169 continue; 1170 } 1171 if (OTunary(e.Eoper)) 1172 { 1173 e = e.EV.E1; 1174 continue; 1175 } 1176 break; 1177 } 1178 break; 1179 } 1180 return true; 1181 } 1182 1183 /******************************** 1184 * Scan down commas and return the controlling elem. 1185 */ 1186 1187 @trusted 1188 elem *el_scancommas(elem *e) 1189 { 1190 while (e.Eoper == OPcomma) 1191 e = e.EV.E2; 1192 return e; 1193 } 1194 1195 /*************************** 1196 * Count number of commas in the expression. 1197 */ 1198 1199 @trusted 1200 int el_countCommas(const(elem)* e) 1201 { 1202 int ncommas = 0; 1203 while (1) 1204 { 1205 if (OTbinary(e.Eoper)) 1206 { 1207 ncommas += (e.Eoper == OPcomma) + el_countCommas(e.EV.E2); 1208 } 1209 else if (OTunary(e.Eoper)) 1210 { 1211 } 1212 else 1213 break; 1214 e = e.EV.E1; 1215 } 1216 return ncommas; 1217 } 1218 1219 /************************************ 1220 * Convert floating point constant to a read-only symbol. 1221 * Needed iff floating point code can't load immediate constants. 1222 */ 1223 @trusted 1224 elem *el_convfloat(elem *e) 1225 { 1226 ubyte[32] buffer = void; 1227 1228 assert(config.inline8087); 1229 1230 // Do not convert if the constants can be loaded with the special FPU instructions 1231 if (tycomplex(e.Ety)) 1232 { 1233 if (loadconst(e, 0) && loadconst(e, 1)) 1234 return e; 1235 } 1236 else if (loadconst(e, 0)) 1237 return e; 1238 1239 go.changes++; 1240 tym_t ty = e.Ety; 1241 int sz = tysize(ty); 1242 assert(sz <= buffer.length); 1243 void *p; 1244 switch (tybasic(ty)) 1245 { 1246 case TYfloat: 1247 case TYifloat: 1248 p = &e.EV.Vfloat; 1249 assert(sz == (e.EV.Vfloat).sizeof); 1250 break; 1251 1252 case TYdouble: 1253 case TYidouble: 1254 case TYdouble_alias: 1255 p = &e.EV.Vdouble; 1256 assert(sz == (e.EV.Vdouble).sizeof); 1257 break; 1258 1259 case TYldouble: 1260 case TYildouble: 1261 /* The size, alignment, and padding of long doubles may be different 1262 * from host to target 1263 */ 1264 p = buffer.ptr; 1265 memset(buffer.ptr, 0, sz); // ensure padding is 0 1266 memcpy(buffer.ptr, &e.EV.Vldouble, 10); 1267 break; 1268 1269 case TYcfloat: 1270 p = &e.EV.Vcfloat; 1271 assert(sz == (e.EV.Vcfloat).sizeof); 1272 break; 1273 1274 case TYcdouble: 1275 p = &e.EV.Vcdouble; 1276 assert(sz == (e.EV.Vcdouble).sizeof); 1277 break; 1278 1279 case TYcldouble: 1280 p = buffer.ptr; 1281 memset(buffer.ptr, 0, sz); 1282 memcpy(buffer.ptr, &e.EV.Vcldouble.re, 10); 1283 memcpy(buffer.ptr + tysize(TYldouble), &e.EV.Vcldouble.im, 10); 1284 break; 1285 1286 default: 1287 assert(0); 1288 } 1289 1290 static if (0) 1291 { 1292 printf("%gL+%gLi\n", cast(double)e.EV.Vcldouble.re, cast(double)e.EV.Vcldouble.im); 1293 printf("el_convfloat() %g %g sz=%d\n", e.EV.Vcdouble.re, e.EV.Vcdouble.im, sz); 1294 printf("el_convfloat(): sz = %d\n", sz); 1295 ushort *p = cast(ushort *)&e.EV.Vcldouble; 1296 for (int i = 0; i < sz/2; i++) printf("%04x ", p[i]); 1297 printf("\n"); 1298 } 1299 1300 Symbol *s = out_readonly_sym(ty, p, sz); 1301 el_free(e); 1302 e = el_var(s); 1303 e.Ety = ty; 1304 if (e.Eoper == OPvar) 1305 e.Ety |= mTYconst; 1306 //printf("s: %s %d:x%x\n", s.Sident, s.Sseg, s.Soffset); 1307 return e; 1308 } 1309 1310 /************************************ 1311 * Convert vector constant to a read-only symbol. 1312 * Needed iff vector code can't load immediate constants. 1313 */ 1314 1315 @trusted 1316 elem *el_convxmm(elem *e) 1317 { 1318 ubyte[eve.sizeof] buffer = void; 1319 1320 // Do not convert if the constants can be loaded with the special XMM instructions 1321 if (loadxmmconst(e)) 1322 return e; 1323 1324 go.changes++; 1325 tym_t ty = e.Ety; 1326 int sz = tysize(ty); 1327 assert(sz <= buffer.length); 1328 void *p = &e.EV; 1329 1330 static if (0) 1331 { 1332 printf("el_convxmm(): sz = %d\n", sz); 1333 for (size i = 0; i < sz; i++) printf("%02x ", (cast(ubyte *)p)[i]); 1334 printf("\n"); 1335 } 1336 1337 Symbol *s = out_readonly_sym(ty, p, sz); 1338 el_free(e); 1339 e = el_var(s); 1340 e.Ety = ty; 1341 if (e.Eoper == OPvar) 1342 e.Ety |= mTYconst; 1343 //printf("s: %s %d:x%x\n", s.Sident, s.Sseg, s.Soffset); 1344 return e; 1345 } 1346 1347 /******************************** 1348 * Convert reference to a string to reference to a symbol 1349 * stored in the static data segment. 1350 */ 1351 1352 @trusted 1353 elem *el_convstring(elem *e) 1354 { 1355 //printf("el_convstring()\n"); 1356 int i; 1357 Symbol *s; 1358 char *p; 1359 1360 assert(!PARSER); 1361 elem_debug(e); 1362 assert(e.Eoper == OPstring); 1363 p = e.EV.Vstring; 1364 e.EV.Vstring = null; 1365 size_t len = e.EV.Vstrlen; 1366 1367 // Handle strings that go into the code segment 1368 if (tybasic(e.Ety) == TYcptr || 1369 (tyfv(e.Ety) && config.flags3 & CFG3strcod)) 1370 { 1371 assert(config.objfmt == OBJ_OMF); // option not done yet for others 1372 s = symbol_generate(SC.static_, type_fake(mTYcs | e.Ety)); 1373 s.Sfl = FLcsdata; 1374 s.Soffset = Offset(cseg); 1375 s.Sseg = cseg; 1376 symbol_keep(s); 1377 if (!eecontext.EEcompile || eecontext.EEin) 1378 { 1379 objmod.bytes(cseg,Offset(cseg),cast(uint)len,p); 1380 Offset(cseg) += len; 1381 } 1382 mem_free(p); 1383 goto L1; 1384 } 1385 1386 if (eecontext.EEin) // if compiling debugger expression 1387 { 1388 s = out_readonly_sym(e.Ety, p, cast(int)len); 1389 mem_free(p); 1390 goto L1; 1391 } 1392 1393 // See if e is already in the string table 1394 for (i = 0; i < stable.length; i++) 1395 { 1396 if (stable[i].str.length == len && 1397 memcmp(stable[i].str.ptr,p,len) == 0) 1398 { 1399 // Replace e with that symbol 1400 mem_free(p); 1401 s = stable[i].sym; 1402 goto L1; 1403 } 1404 } 1405 1406 // Replace string with a symbol that refers to that string 1407 // in the DATA segment 1408 1409 if (eecontext.EEcompile) 1410 { 1411 s = symboldata(Offset(DATA),e.Ety); 1412 s.Sseg = DATA; 1413 } 1414 else 1415 s = out_readonly_sym(e.Ety,p,cast(int)len); 1416 1417 // Remember the string for possible reuse later 1418 //printf("Adding %d, '%s'\n",stable_si,p); 1419 mem_free(stable[stable_si].str.ptr); 1420 stable[stable_si].str = p[0 .. cast(size_t)len]; 1421 stable[stable_si].sym = s; 1422 stable_si = (stable_si + 1) & (stable.length - 1); 1423 1424 L1: 1425 // Refer e to the symbol generated 1426 elem *ex = el_ptr(s); 1427 ex.Ety = e.Ety; 1428 if (e.EV.Voffset) 1429 { 1430 if (ex.Eoper == OPrelconst) 1431 ex.EV.Voffset += e.EV.Voffset; 1432 else 1433 ex = el_bin(OPadd, ex.Ety, ex, el_long(TYint, e.EV.Voffset)); 1434 } 1435 el_free(e); 1436 return ex; 1437 } 1438 1439 /******************************************** 1440 * If e is a long double constant, and it is perfectly representable as a 1441 * double constant, convert it to a double constant. 1442 * Note that this must NOT be done in contexts where there are no further 1443 * operations, since then it could change the type (eg, in the function call 1444 * printf("%La", 2.0L); the 2.0 must stay as a long double). 1445 */ 1446 static if (1) 1447 { 1448 @trusted 1449 void shrinkLongDoubleConstantIfPossible(elem *e) 1450 { 1451 if (e.Eoper == OPconst && e.Ety == TYldouble) 1452 { 1453 /* Check to see if it can be converted into a double (this happens 1454 * when the low bits are all zero, and the exponent is in the 1455 * double range). 1456 * Use 'volatile' to prevent optimizer from folding away the conversions, 1457 * and thereby missing the truncation in the conversion to double. 1458 */ 1459 auto v = e.EV.Vldouble; 1460 double vDouble; 1461 1462 version (CRuntime_Microsoft) 1463 { 1464 static if (is(typeof(v) == real)) 1465 *(&vDouble) = v; 1466 else 1467 *(&vDouble) = cast(double)v; 1468 } 1469 else 1470 *(&vDouble) = v; 1471 1472 if (v == vDouble) // This will fail if compiler does NaN incorrectly! 1473 { 1474 // Yes, we can do it! 1475 e.EV.Vdouble = vDouble; 1476 e.Ety = TYdouble; 1477 } 1478 } 1479 } 1480 } 1481 1482 1483 /************************* 1484 * Run through a tree converting it to CODGEN. 1485 */ 1486 @trusted 1487 elem *el_convert(elem *e) 1488 { 1489 //printf("el_convert(%p)\n", e); 1490 elem_debug(e); 1491 const op = e.Eoper; 1492 switch (op) 1493 { 1494 case OPvar: 1495 break; 1496 1497 case OPconst: 1498 if (tyvector(e.Ety)) 1499 e = el_convxmm(e); 1500 else if (tyfloating(e.Ety) && config.inline8087) 1501 e = el_convfloat(e); 1502 break; 1503 1504 case OPstring: 1505 go.changes++; 1506 e = el_convstring(e); 1507 break; 1508 1509 case OPnullptr: 1510 e = el_long(e.Ety, 0); 1511 break; 1512 1513 case OPmul: 1514 /* special floating-point case: allow x*2 to be x+x 1515 * in this case, we preserve the constant 2. 1516 */ 1517 if (tyreal(e.Ety) && // don't bother with imaginary or complex 1518 e.EV.E2.Eoper == OPconst && el_toldoubled(e.EV.E2) == 2.0L) 1519 { 1520 e.EV.E1 = el_convert(e.EV.E1); 1521 /* Don't call el_convert(e.EV.E2), we want it to stay as a constant 1522 * which will be detected by code gen. 1523 */ 1524 break; 1525 } 1526 goto case OPdiv; 1527 1528 case OPdiv: 1529 case OPadd: 1530 case OPmin: 1531 // For a*b,a+b,a-b,a/b, if a long double constant is involved, convert it to a double constant. 1532 if (tyreal(e.Ety)) 1533 shrinkLongDoubleConstantIfPossible(e.EV.E1); 1534 if (tyreal(e.Ety)) 1535 shrinkLongDoubleConstantIfPossible(e.EV.E2); 1536 goto default; 1537 1538 default: 1539 if (OTbinary(op)) 1540 { 1541 e.EV.E1 = el_convert(e.EV.E1); 1542 e.EV.E2 = el_convert(e.EV.E2); 1543 } 1544 else if (OTunary(op)) 1545 { 1546 e.EV.E1 = el_convert(e.EV.E1); 1547 } 1548 break; 1549 } 1550 return e; 1551 } 1552 1553 1554 /************************ 1555 * Make a constant elem. 1556 * ty = type of elem 1557 * *pconst = union of constant data 1558 */ 1559 1560 @trusted 1561 elem * el_const(tym_t ty, eve *pconst) 1562 { 1563 elem *e; 1564 1565 e = el_calloc(); 1566 e.Eoper = OPconst; 1567 e.Ety = ty; 1568 memcpy(&e.EV,pconst,(e.EV).sizeof); 1569 return e; 1570 } 1571 1572 1573 /************************** 1574 * Insert constructor information into tree. 1575 * A corresponding el_ddtor() must be called later. 1576 * Params: 1577 * e = code to construct the object 1578 * decl = VarDeclaration of variable being constructed 1579 */ 1580 1581 static if (0) 1582 { 1583 elem *el_dctor(elem *e,void *decl) 1584 { 1585 elem *ector = el_calloc(); 1586 ector.Eoper = OPdctor; 1587 ector.Ety = TYvoid; 1588 ector.EV.ed.Edecl = decl; 1589 if (e) 1590 e = el_bin(OPinfo,e.Ety,ector,e); 1591 else 1592 /* Remember that a "constructor" may execute no code, hence 1593 * the need for OPinfo if there is code to execute. 1594 */ 1595 e = ector; 1596 return e; 1597 } 1598 } 1599 1600 /************************** 1601 * Insert destructor information into tree. 1602 * e code to destruct the object 1603 * decl VarDeclaration of variable being destructed 1604 * (must match decl for corresponding OPctor) 1605 */ 1606 1607 static if (0) 1608 { 1609 elem *el_ddtor(elem *e,void *decl) 1610 { 1611 /* A destructor always executes code, or we wouldn't need 1612 * eh for it. 1613 * An OPddtor must match 1:1 with an OPdctor 1614 */ 1615 elem *edtor = el_calloc(); 1616 edtor.Eoper = OPddtor; 1617 edtor.Ety = TYvoid; 1618 edtor.EV.ed.Edecl = decl; 1619 edtor.EV.ed.Eleft = e; 1620 return edtor; 1621 } 1622 } 1623 1624 /********************************************* 1625 * Create constructor/destructor pair of elems. 1626 * Caution: The pattern generated here must match that detected in e2ir.c's visit(CallExp). 1627 * Params: 1628 * ec = code to construct (may be null) 1629 * ed = code to destruct 1630 * pedtor = set to destructor node 1631 * Returns: 1632 * constructor node 1633 */ 1634 1635 @trusted 1636 elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor) 1637 { 1638 elem *er; 1639 if (config.ehmethod == EHmethod.EH_DWARF) 1640 { 1641 /* Construct (note that OPinfo is evaluated RTOL): 1642 * er = (OPdctor OPinfo (__flag = 0, ec)) 1643 * edtor = __flag = 1, (OPddtor ((__exception_object = _EAX), ed, (!__flag && _Unsafe_Resume(__exception_object)))) 1644 */ 1645 1646 /* Declare __flag, __EAX, __exception_object variables. 1647 * Use volatile to prevent optimizer from messing them up, since optimizer doesn't know about 1648 * landing pads (the landing pad will be on the OPddtor's EV.ed.Eleft) 1649 */ 1650 Symbol *sflag = symbol_name("__flag", SC.auto_, type_fake(mTYvolatile | TYbool)); 1651 Symbol *sreg = symbol_name("__EAX", SC.pseudo, type_fake(mTYvolatile | TYnptr)); 1652 sreg.Sreglsw = 0; // EAX, RAX, whatevs 1653 Symbol *seo = symbol_name("__exception_object", SC.auto_, tspvoid); 1654 1655 symbol_add(sflag); 1656 symbol_add(sreg); 1657 symbol_add(seo); 1658 1659 elem *ector = el_calloc(); 1660 ector.Eoper = OPdctor; 1661 ector.Ety = TYvoid; 1662 // ector.EV.ed.Edecl = decl; 1663 1664 eve c = void; 1665 memset(&c, 0, c.sizeof); 1666 elem *e_flag_0 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 0 1667 er = el_bin(OPinfo, ec ? ec.Ety : TYvoid, ector, el_combine(e_flag_0, ec)); 1668 1669 /* A destructor always executes code, or we wouldn't need 1670 * eh for it. 1671 * An OPddtor must match 1:1 with an OPdctor 1672 */ 1673 elem *edtor = el_calloc(); 1674 edtor.Eoper = OPddtor; 1675 edtor.Ety = TYvoid; 1676 // edtor.EV.Edecl = decl; 1677 // edtor.EV.E1 = e; 1678 1679 c.Vint = 1; 1680 elem *e_flag_1 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 1 1681 elem *e_eax = el_bin(OPeq, TYvoid, el_var(seo), el_var(sreg)); // __exception_object = __EAX 1682 elem *eu = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM.UNWIND_RESUME)), el_var(seo)); 1683 eu = el_bin(OPandand, TYvoid, el_una(OPnot, TYbool, el_var(sflag)), eu); 1684 1685 edtor.EV.E1 = el_combine(el_combine(e_eax, ed), eu); 1686 1687 *pedtor = el_combine(e_flag_1, edtor); 1688 } 1689 else 1690 { 1691 /* Construct (note that OPinfo is evaluated RTOL): 1692 * er = (OPdctor OPinfo ec) 1693 * edtor = (OPddtor ed) 1694 */ 1695 elem *ector = el_calloc(); 1696 ector.Eoper = OPdctor; 1697 ector.Ety = TYvoid; 1698 // ector.EV.ed.Edecl = decl; 1699 if (ec) 1700 er = el_bin(OPinfo,ec.Ety,ector,ec); 1701 else 1702 /* Remember that a "constructor" may execute no code, hence 1703 * the need for OPinfo if there is code to execute. 1704 */ 1705 er = ector; 1706 1707 /* A destructor always executes code, or we wouldn't need 1708 * eh for it. 1709 * An OPddtor must match 1:1 with an OPdctor 1710 */ 1711 elem *edtor = el_calloc(); 1712 edtor.Eoper = OPddtor; 1713 edtor.Ety = TYvoid; 1714 // edtor.EV.Edecl = decl; 1715 edtor.EV.E1 = ed; 1716 *pedtor = edtor; 1717 } 1718 1719 return er; 1720 } 1721 1722 /************************** 1723 * Insert destructor information into tree. 1724 * edtor pointer to object being destructed 1725 * e code to do the destruction 1726 */ 1727 1728 elem *el_dtor(elem *edtor,elem *e) 1729 { 1730 if (edtor) 1731 { 1732 edtor = el_unat(OPdtor,edtor.ET,edtor); 1733 if (e) 1734 e = el_bint(OPcomma,e.ET,edtor,e); 1735 else 1736 e = edtor; 1737 } 1738 return e; 1739 } 1740 1741 /********************************** 1742 * Create an elem of the constant 0, of the type t. 1743 */ 1744 1745 @trusted 1746 elem *el_zero(type *t) 1747 { 1748 assert(PARSER); 1749 1750 elem* e = el_calloc(); 1751 e.Eoper = OPconst; 1752 e.ET = t; 1753 if (t) 1754 { 1755 type_debug(t); 1756 e.ET.Tcount++; 1757 } 1758 return(e); 1759 } 1760 1761 /******************* 1762 * Find and return pointer to parent of e starting at *pe. 1763 * Return null if can't find it. 1764 */ 1765 1766 @trusted 1767 elem ** el_parent(elem *e,elem **pe) 1768 { 1769 assert(e && pe && *pe); 1770 elem_debug(e); 1771 elem_debug(*pe); 1772 if (e == *pe) 1773 return pe; 1774 else if (OTunary((*pe).Eoper)) 1775 return el_parent(e,&((*pe).EV.E1)); 1776 else if (OTbinary((*pe).Eoper)) 1777 { 1778 elem **pe2; 1779 return ((pe2 = el_parent(e,&((*pe).EV.E1))) != null) 1780 ? pe2 1781 : el_parent(e,&((*pe).EV.E2)); 1782 } 1783 else 1784 return null; 1785 } 1786 1787 /******************************* 1788 * Returns: true if trees match. 1789 */ 1790 1791 @trusted 1792 private bool el_matchx(const(elem)* n1, const(elem)* n2, int gmatch2) 1793 { 1794 if (n1 == n2) 1795 return true; 1796 if (!n1 || !n2) 1797 return false; 1798 elem_debug(n1); 1799 elem_debug(n2); 1800 1801 L1: 1802 const op = n1.Eoper; 1803 if (op != n2.Eoper) 1804 return false; 1805 1806 auto tym = typemask(n1); 1807 auto tym2 = typemask(n2); 1808 if (tym != tym2) 1809 { 1810 if ((tym & ~mTYbasic) != (tym2 & ~mTYbasic)) 1811 { 1812 if (!(gmatch2 & 2)) 1813 return false; 1814 } 1815 tym = tybasic(tym); 1816 tym2 = tybasic(tym2); 1817 if (tyequiv[tym] != tyequiv[tym2] && 1818 !((gmatch2 & 8) && touns(tym) == touns(tym2)) 1819 ) 1820 return false; 1821 gmatch2 &= ~8; 1822 } 1823 1824 if (OTunary(op)) 1825 { 1826 L2: 1827 if (PARSER) 1828 { 1829 n1 = n1.EV.E1; 1830 n2 = n2.EV.E1; 1831 assert(n1 && n2); 1832 goto L1; 1833 } 1834 else if (OPTIMIZER) 1835 { 1836 if (op == OPstrpar || op == OPstrctor) 1837 { if (/*n1.Enumbytes != n2.Enumbytes ||*/ n1.ET != n2.ET) 1838 return false; 1839 } 1840 n1 = n1.EV.E1; 1841 n2 = n2.EV.E1; 1842 assert(n1 && n2); 1843 goto L1; 1844 } 1845 else 1846 { 1847 if (n1.EV.E1 == n2.EV.E1) 1848 goto ismatch; 1849 n1 = n1.EV.E1; 1850 n2 = n2.EV.E1; 1851 assert(n1 && n2); 1852 goto L1; 1853 } 1854 } 1855 else if (OTbinary(op)) 1856 { 1857 if (!PARSER) 1858 { 1859 if (op == OPstreq) 1860 { 1861 if (/*n1.Enumbytes != n2.Enumbytes ||*/ n1.ET != n2.ET) 1862 return false; 1863 } 1864 } 1865 if (el_matchx(n1.EV.E2, n2.EV.E2, gmatch2)) 1866 { 1867 goto L2; // check left tree 1868 } 1869 return false; 1870 } 1871 else /* leaf elem */ 1872 { 1873 switch (op) 1874 { 1875 case OPconst: 1876 if (gmatch2 & 1) 1877 break; 1878 Lagain: 1879 switch (tybasic(tym)) 1880 { 1881 case TYshort: 1882 case TYwchar_t: 1883 case TYushort: 1884 case TYchar16: 1885 case_short: 1886 if (n1.EV.Vshort != n2.EV.Vshort) 1887 return false; 1888 break; 1889 1890 case TYlong: 1891 case TYulong: 1892 case TYdchar: 1893 case_long: 1894 if (n1.EV.Vlong != n2.EV.Vlong) 1895 return false; 1896 break; 1897 1898 case TYllong: 1899 case TYullong: 1900 case_llong: 1901 if (n1.EV.Vllong != n2.EV.Vllong) 1902 return false; 1903 break; 1904 1905 case TYcent: 1906 case TYucent: 1907 if (n1.EV.Vcent != n2.EV.Vcent) 1908 return false; 1909 break; 1910 1911 case TYenum: 1912 if (PARSER) 1913 { tym = n1.ET.Tnext.Tty; 1914 goto Lagain; 1915 } 1916 goto case TYuint; 1917 1918 case TYint: 1919 case TYuint: 1920 if (_tysize[TYint] == SHORTSIZE) 1921 goto case_short; 1922 else 1923 goto case_long; 1924 1925 case TYnullptr: 1926 case TYnptr: 1927 case TYnref: 1928 case TYsptr: 1929 case TYcptr: 1930 case TYimmutPtr: 1931 case TYsharePtr: 1932 case TYrestrictPtr: 1933 case TYfgPtr: 1934 if (_tysize[TYnptr] == SHORTSIZE) 1935 goto case_short; 1936 else if (_tysize[TYnptr] == LONGSIZE) 1937 goto case_long; 1938 else 1939 { assert(_tysize[TYnptr] == LLONGSIZE); 1940 goto case_llong; 1941 } 1942 1943 case TYbool: 1944 case TYchar: 1945 case TYuchar: 1946 case TYschar: 1947 if (n1.EV.Vschar != n2.EV.Vschar) 1948 return false; 1949 break; 1950 1951 case TYfptr: 1952 case TYhptr: 1953 case TYvptr: 1954 1955 /* Far pointers on the 386 are longer than 1956 any integral type... 1957 */ 1958 if (memcmp(&n1.EV, &n2.EV, tysize(tym))) 1959 return false; 1960 break; 1961 1962 /* Compare bit patterns w/o worrying about 1963 exceptions, unordered comparisons, etc. 1964 */ 1965 case TYfloat: 1966 case TYifloat: 1967 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vfloat).sizeof)) 1968 return false; 1969 break; 1970 1971 case TYdouble: 1972 case TYdouble_alias: 1973 case TYidouble: 1974 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vdouble).sizeof)) 1975 return false; 1976 break; 1977 1978 case TYldouble: 1979 case TYildouble: 1980 static if ((n1.EV.Vldouble).sizeof > 10) 1981 { 1982 /* sizeof is 12, but actual size is 10 */ 1983 if (memcmp(&n1.EV,&n2.EV,10)) 1984 return false; 1985 } 1986 else 1987 { 1988 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vldouble).sizeof)) 1989 return false; 1990 } 1991 break; 1992 1993 case TYcfloat: 1994 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcfloat).sizeof)) 1995 return false; 1996 break; 1997 1998 case TYcdouble: 1999 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcdouble).sizeof)) 2000 return false; 2001 break; 2002 2003 case TYfloat4: 2004 case TYdouble2: 2005 case TYschar16: 2006 case TYuchar16: 2007 case TYshort8: 2008 case TYushort8: 2009 case TYlong4: 2010 case TYulong4: 2011 case TYllong2: 2012 case TYullong2: 2013 if (n1.EV.Vcent != n2.EV.Vcent) 2014 return false; 2015 break; 2016 2017 case TYfloat8: 2018 case TYdouble4: 2019 case TYschar32: 2020 case TYuchar32: 2021 case TYshort16: 2022 case TYushort16: 2023 case TYlong8: 2024 case TYulong8: 2025 case TYllong4: 2026 case TYullong4: 2027 if (memcmp(&n1.EV,&n2.EV,32)) // 32 byte vector types (256 bit) 2028 return false; 2029 break; 2030 2031 case TYcldouble: 2032 static if ((n1.EV.Vldouble).sizeof > 10) 2033 { 2034 /* sizeof is 12, but actual size of each part is 10 */ 2035 if (memcmp(&n1.EV,&n2.EV,10) || 2036 memcmp(&n1.EV.Vldouble + 1, &n2.EV.Vldouble + 1, 10)) 2037 return false; 2038 } 2039 else 2040 { 2041 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcldouble).sizeof)) 2042 return false; 2043 } 2044 break; 2045 2046 case TYvoid: 2047 break; // voids always match 2048 2049 default: 2050 elem_print(n1); 2051 assert(0); 2052 } 2053 break; 2054 case OPrelconst: 2055 case OPvar: 2056 symbol_debug(n1.EV.Vsym); 2057 symbol_debug(n2.EV.Vsym); 2058 if (n1.EV.Voffset != n2.EV.Voffset) 2059 return false; 2060 if (n1.EV.Vsym != n2.EV.Vsym) 2061 return false; 2062 break; 2063 2064 case OPasm: 2065 case OPstring: 2066 { 2067 const n = n2.EV.Vstrlen; 2068 if (n1.EV.Vstrlen != n || 2069 n1.EV.Voffset != n2.EV.Voffset || 2070 memcmp(n1.EV.Vstring, n2.EV.Vstring, n)) 2071 return false; /* check bytes in the string */ 2072 break; 2073 } 2074 2075 case OPstrthis: 2076 case OPframeptr: 2077 case OPhalt: 2078 case OPgot: 2079 break; 2080 2081 default: 2082 printf("op: %s\n", oper_str(op)); 2083 assert(0); 2084 } 2085 ismatch: 2086 return true; 2087 } 2088 assert(0); 2089 } 2090 2091 /******************************* 2092 * Returns: true if trees match. 2093 */ 2094 bool el_match(const elem* n1, const elem* n2) 2095 { 2096 return el_matchx(n1, n2, 0); 2097 } 2098 2099 /********************************* 2100 * Kludge on el_match(). Same, but ignore differences in OPconst. 2101 */ 2102 2103 bool el_match2(const elem* n1, const elem* n2) 2104 { 2105 return el_matchx(n1,n2,1); 2106 } 2107 2108 /********************************* 2109 * Kludge on el_match(). Same, but ignore differences in type modifiers. 2110 */ 2111 2112 bool el_match3(const elem* n1, const elem* n2) 2113 { 2114 return el_matchx(n1,n2,2); 2115 } 2116 2117 /********************************* 2118 * Kludge on el_match(). Same, but ignore differences in spelling of var's. 2119 */ 2120 2121 bool el_match4(const elem* n1, const elem* n2) 2122 { 2123 return el_matchx(n1,n2,2|4); 2124 } 2125 2126 /********************************* 2127 * Kludge on el_match(). Same, but regard signed/unsigned as equivalent. 2128 */ 2129 2130 bool el_match5(const elem* n1, const elem* n2) 2131 { 2132 return el_matchx(n1,n2,8); 2133 } 2134 2135 2136 /****************************** 2137 * Extract long value from constant parser elem. 2138 */ 2139 2140 @trusted 2141 targ_llong el_tolongt(elem *e) 2142 { 2143 const parsersave = PARSER; 2144 PARSER = 1; 2145 const result = el_tolong(e); 2146 PARSER = parsersave; 2147 return result; 2148 } 2149 2150 /****************************** 2151 * Extract long value from constant elem. 2152 */ 2153 2154 @trusted 2155 targ_llong el_tolong(elem *e) 2156 { 2157 elem_debug(e); 2158 if (e.Eoper != OPconst) 2159 elem_print(e); 2160 assert(e.Eoper == OPconst); 2161 auto ty = tybasic(typemask(e)); 2162 2163 targ_llong result; 2164 switch (ty) 2165 { 2166 case TYchar: 2167 if (config.flags & CFGuchar) 2168 goto Uchar; 2169 goto case TYschar; 2170 2171 case TYschar: 2172 result = e.EV.Vschar; 2173 break; 2174 2175 case TYuchar: 2176 case TYbool: 2177 Uchar: 2178 result = e.EV.Vuchar; 2179 break; 2180 2181 case TYshort: 2182 Ishort: 2183 result = e.EV.Vshort; 2184 break; 2185 2186 case TYushort: 2187 case TYwchar_t: 2188 case TYchar16: 2189 Ushort: 2190 result = e.EV.Vushort; 2191 break; 2192 2193 case TYsptr: 2194 case TYcptr: 2195 case TYnptr: 2196 case TYnullptr: 2197 case TYnref: 2198 case TYimmutPtr: 2199 case TYsharePtr: 2200 case TYrestrictPtr: 2201 case TYfgPtr: 2202 if (_tysize[TYnptr] == SHORTSIZE) 2203 goto Ushort; 2204 if (_tysize[TYnptr] == LONGSIZE) 2205 goto Ulong; 2206 if (_tysize[TYnptr] == LLONGSIZE) 2207 goto Ullong; 2208 assert(0); 2209 2210 case TYuint: 2211 if (_tysize[TYint] == SHORTSIZE) 2212 goto Ushort; 2213 goto Ulong; 2214 2215 case TYulong: 2216 case TYdchar: 2217 case TYfptr: 2218 case TYhptr: 2219 case TYvptr: 2220 case TYvoid: /* some odd cases */ 2221 Ulong: 2222 result = e.EV.Vulong; 2223 break; 2224 2225 case TYint: 2226 if (_tysize[TYint] == SHORTSIZE) 2227 goto Ishort; 2228 goto Ilong; 2229 2230 case TYlong: 2231 Ilong: 2232 result = e.EV.Vlong; 2233 break; 2234 2235 case TYllong: 2236 case TYullong: 2237 Ullong: 2238 result = e.EV.Vullong; 2239 break; 2240 2241 case TYdouble_alias: 2242 case TYldouble: 2243 case TYdouble: 2244 case TYfloat: 2245 case TYildouble: 2246 case TYidouble: 2247 case TYifloat: 2248 case TYcldouble: 2249 case TYcdouble: 2250 case TYcfloat: 2251 result = cast(targ_llong)el_toldoubled(e); 2252 break; 2253 2254 case TYcent: 2255 case TYucent: 2256 goto Ullong; // should do better than this when actually doing arithmetic on cents 2257 2258 default: 2259 elem_print(e); 2260 assert(0); 2261 } 2262 return result; 2263 } 2264 2265 /*********************************** 2266 * Determine if constant e is all ones or all zeros. 2267 * Params: 2268 * e = elem to test 2269 * bit = 0: all zeros 2270 * 1: 1 2271 * -1: all ones 2272 * Returns: 2273 * true if it is 2274 */ 2275 2276 bool el_allbits(const elem* e,int bit) 2277 { 2278 elem_debug(e); 2279 assert(e.Eoper == OPconst); 2280 targ_llong value = e.EV.Vullong; 2281 switch (tysize(e.Ety)) 2282 { 2283 case 1: value = cast(byte) value; 2284 break; 2285 2286 case 2: value = cast(short) value; 2287 break; 2288 2289 case 4: value = cast(int) value; 2290 break; 2291 2292 case 8: break; 2293 2294 default: 2295 assert(0); 2296 } 2297 if (bit == -1) 2298 value++; 2299 else if (bit == 1) 2300 value--; 2301 return value == 0; 2302 } 2303 2304 /******************************************** 2305 * Determine if constant e is a 32 bit or less value, or is a 32 bit value sign extended to 64 bits. 2306 */ 2307 2308 bool el_signx32(const elem* e) 2309 { 2310 elem_debug(e); 2311 assert(e.Eoper == OPconst); 2312 if (tysize(e.Ety) == 8) 2313 { 2314 if (e.EV.Vullong != cast(int)e.EV.Vullong) 2315 return false; 2316 } 2317 return true; 2318 } 2319 2320 /****************************** 2321 * Extract long double value from constant elem. 2322 * Silently ignore types which are not floating point values. 2323 */ 2324 2325 version (CRuntime_Microsoft) 2326 { 2327 longdouble_soft el_toldouble(elem *e) 2328 { 2329 longdouble_soft result; 2330 elem_debug(e); 2331 assert(e.Eoper == OPconst); 2332 switch (tybasic(typemask(e))) 2333 { 2334 case TYfloat: 2335 case TYifloat: 2336 result = longdouble_soft(e.EV.Vfloat); 2337 break; 2338 2339 case TYdouble: 2340 case TYidouble: 2341 case TYdouble_alias: 2342 result = longdouble_soft(e.EV.Vdouble); 2343 break; 2344 2345 case TYldouble: 2346 case TYildouble: 2347 static if (is(typeof(e.EV.Vldouble) == real)) 2348 result = longdouble_soft(e.EV.Vldouble); 2349 else 2350 result = longdouble_soft(cast(real)e.EV.Vldouble); 2351 break; 2352 2353 default: 2354 result = longdouble_soft(0); 2355 break; 2356 } 2357 return result; 2358 } 2359 } 2360 else 2361 { 2362 targ_ldouble el_toldouble(elem *e) 2363 { 2364 targ_ldouble result; 2365 elem_debug(e); 2366 assert(e.Eoper == OPconst); 2367 switch (tybasic(typemask(e))) 2368 { 2369 case TYfloat: 2370 case TYifloat: 2371 result = e.EV.Vfloat; 2372 break; 2373 2374 case TYdouble: 2375 case TYidouble: 2376 case TYdouble_alias: 2377 result = e.EV.Vdouble; 2378 break; 2379 2380 case TYldouble: 2381 case TYildouble: 2382 result = e.EV.Vldouble; 2383 break; 2384 2385 default: 2386 result = 0; 2387 break; 2388 } 2389 return result; 2390 } 2391 } 2392 2393 /******************************** 2394 * Is elem type-dependent or value-dependent? 2395 * Returns: true if so 2396 */ 2397 2398 @trusted 2399 bool el_isdependent(elem* e) 2400 { 2401 if (type_isdependent(e.ET)) 2402 return true; 2403 while (1) 2404 { 2405 if (e.PEFflags & PEFdependent) 2406 return true; 2407 if (OTunary(e.Eoper)) 2408 e = e.EV.E1; 2409 else if (OTbinary(e.Eoper)) 2410 { 2411 if (el_isdependent(e.EV.E2)) 2412 return true; 2413 e = e.EV.E1; 2414 } 2415 else 2416 break; 2417 } 2418 return false; 2419 } 2420 2421 /**************************************** 2422 * Returns: alignment size of elem e 2423 */ 2424 2425 @trusted 2426 uint el_alignsize(elem *e) 2427 { 2428 const tym = tybasic(e.Ety); 2429 uint alignsize = tyalignsize(tym); 2430 if (alignsize == cast(uint)-1 || 2431 (e.Ety & (mTYxmmgpr | mTYgprxmm))) 2432 { 2433 assert(e.ET); 2434 alignsize = type_alignsize(e.ET); 2435 } 2436 return alignsize; 2437 } 2438 2439 /******************************* 2440 * Check for errors in a tree. 2441 */ 2442 2443 debug 2444 { 2445 2446 @trusted 2447 void el_check(const(elem)* e) 2448 { 2449 elem_debug(e); 2450 while (1) 2451 { 2452 if (OTunary(e.Eoper)) 2453 e = e.EV.E1; 2454 else if (OTbinary(e.Eoper)) 2455 { 2456 el_check(e.EV.E2); 2457 e = e.EV.E1; 2458 } 2459 else 2460 break; 2461 } 2462 } 2463 2464 } 2465 2466 /******************************* 2467 * Write out expression elem. 2468 */ 2469 2470 @trusted 2471 void elem_print(const elem* e, int nestlevel = 0) 2472 { 2473 foreach (i; 0 .. nestlevel) 2474 printf(" "); 2475 printf("el:%p ",e); 2476 if (!e) 2477 { 2478 printf("\n"); 2479 return; 2480 } 2481 elem_debug(e); 2482 if (configv.addlinenumbers) 2483 { 2484 if (e.Esrcpos.Sfilename) 2485 printf("%s(%u) ", e.Esrcpos.Sfilename, e.Esrcpos.Slinnum); 2486 } 2487 if (!PARSER) 2488 { 2489 printf("cnt=%d ",e.Ecount); 2490 if (!OPTIMIZER) 2491 printf("cs=%d ",e.Ecomsub); 2492 } 2493 printf("%s ", oper_str(e.Eoper)); 2494 enum scpp = false; 2495 if (scpp && PARSER) 2496 { 2497 if (e.ET) 2498 { 2499 type_debug(e.ET); 2500 if (tybasic(e.ET.Tty) == TYstruct) 2501 printf("%d ", cast(int)type_size(e.ET)); 2502 printf("%s\n", tym_str(e.ET.Tty)); 2503 } 2504 } 2505 else 2506 { 2507 if ((e.Eoper == OPstrpar || e.Eoper == OPstrctor || e.Eoper == OPstreq) || 2508 e.Ety == TYstruct || e.Ety == TYarray) 2509 if (e.ET) 2510 printf("%d ", cast(int)type_size(e.ET)); 2511 printf("%s ", tym_str(e.Ety)); 2512 } 2513 if (OTunary(e.Eoper)) 2514 { 2515 if (e.EV.E2) 2516 printf("%p %p\n",e.EV.E1,e.EV.E2); 2517 else 2518 printf("%p\n",e.EV.E1); 2519 elem_print(e.EV.E1, nestlevel + 1); 2520 } 2521 else if (OTbinary(e.Eoper)) 2522 { 2523 if (!PARSER && e.Eoper == OPstreq && e.ET) 2524 printf("bytes=%d ", cast(int)type_size(e.ET)); 2525 printf("%p %p\n",e.EV.E1,e.EV.E2); 2526 elem_print(e.EV.E1, nestlevel + 1); 2527 elem_print(e.EV.E2, nestlevel + 1); 2528 } 2529 else 2530 { 2531 switch (e.Eoper) 2532 { 2533 case OPrelconst: 2534 printf(" %lld+&",cast(ulong)e.EV.Voffset); 2535 printf(" %s",e.EV.Vsym.Sident.ptr); 2536 break; 2537 2538 case OPvar: 2539 if (e.EV.Voffset) 2540 printf(" %lld+",cast(ulong)e.EV.Voffset); 2541 printf(" %s",e.EV.Vsym.Sident.ptr); 2542 break; 2543 2544 case OPasm: 2545 case OPstring: 2546 printf(" '%s',%lld",e.EV.Vstring,cast(ulong)e.EV.Voffset); 2547 break; 2548 2549 case OPconst: 2550 elem_print_const(e); 2551 break; 2552 2553 default: 2554 break; 2555 } 2556 printf("\n"); 2557 } 2558 } 2559 2560 @trusted 2561 void elem_print_const(const elem* e) 2562 { 2563 assert(e.Eoper == OPconst); 2564 tym_t tym = tybasic(typemask(e)); 2565 case_tym: 2566 switch (tym) 2567 { case TYbool: 2568 case TYchar: 2569 case TYschar: 2570 case TYuchar: 2571 printf("%d ",e.EV.Vuchar); 2572 break; 2573 2574 case TYsptr: 2575 case TYcptr: 2576 case TYnullptr: 2577 case TYnptr: 2578 case TYnref: 2579 case TYimmutPtr: 2580 case TYsharePtr: 2581 case TYrestrictPtr: 2582 case TYfgPtr: 2583 if (_tysize[TYnptr] == LONGSIZE) 2584 goto L1; 2585 if (_tysize[TYnptr] == SHORTSIZE) 2586 goto L3; 2587 if (_tysize[TYnptr] == LLONGSIZE) 2588 goto L2; 2589 assert(0); 2590 2591 case TYenum: 2592 if (PARSER) 2593 { tym = e.ET.Tnext.Tty; 2594 goto case_tym; 2595 } 2596 goto case TYint; 2597 2598 case TYint: 2599 case TYuint: 2600 case TYvoid: /* in case (void)(1) */ 2601 if (tysize(TYint) == LONGSIZE) 2602 goto L1; 2603 goto case TYshort; 2604 2605 case TYshort: 2606 case TYwchar_t: 2607 case TYushort: 2608 case TYchar16: 2609 L3: 2610 printf("%d ",e.EV.Vint); 2611 break; 2612 2613 case TYlong: 2614 case TYulong: 2615 case TYdchar: 2616 case TYfptr: 2617 case TYvptr: 2618 case TYhptr: 2619 L1: 2620 printf("%dL ",e.EV.Vlong); 2621 break; 2622 2623 case TYllong: 2624 L2: 2625 printf("%lldLL ",cast(ulong)e.EV.Vllong); 2626 break; 2627 2628 case TYullong: 2629 printf("%lluLL ",cast(ulong)e.EV.Vullong); 2630 break; 2631 2632 case TYcent: 2633 case TYucent: 2634 printf("%lluLL+%lluLL ", cast(ulong)e.EV.Vcent.hi, cast(ulong)e.EV.Vcent.lo); 2635 break; 2636 2637 case TYfloat: 2638 printf("%gf ",cast(double)e.EV.Vfloat); 2639 break; 2640 2641 case TYdouble: 2642 case TYdouble_alias: 2643 printf("%g ",cast(double)e.EV.Vdouble); 2644 break; 2645 2646 case TYldouble: 2647 { 2648 version (CRuntime_Microsoft) 2649 { 2650 const buffer_len = 3 + 3 * (targ_ldouble).sizeof + 1; 2651 char[buffer_len] buffer = void; 2652 static if (is(typeof(e.EV.Vldouble) == real)) 2653 ld_sprint(buffer.ptr, buffer_len, 'g', longdouble_soft(e.EV.Vldouble)); 2654 else 2655 ld_sprint(buffer.ptr, buffer_len, 'g', longdouble_soft(cast(real)e.EV.Vldouble)); 2656 printf("%s ", buffer.ptr); 2657 } 2658 else 2659 printf("%Lg ", e.EV.Vldouble); 2660 break; 2661 } 2662 2663 case TYifloat: 2664 printf("%gfi ", cast(double)e.EV.Vfloat); 2665 break; 2666 2667 case TYidouble: 2668 printf("%gi ", cast(double)e.EV.Vdouble); 2669 break; 2670 2671 case TYildouble: 2672 printf("%gLi ", cast(double)e.EV.Vldouble); 2673 break; 2674 2675 case TYcfloat: 2676 printf("%gf+%gfi ", cast(double)e.EV.Vcfloat.re, cast(double)e.EV.Vcfloat.im); 2677 break; 2678 2679 case TYcdouble: 2680 printf("%g+%gi ", cast(double)e.EV.Vcdouble.re, cast(double)e.EV.Vcdouble.im); 2681 break; 2682 2683 case TYcldouble: 2684 printf("%gL+%gLi ", cast(double)e.EV.Vcldouble.re, cast(double)e.EV.Vcldouble.im); 2685 break; 2686 2687 // SIMD 16 byte vector types // D type 2688 case TYfloat4: 2689 case TYdouble2: 2690 case TYschar16: 2691 case TYuchar16: 2692 case TYshort8: 2693 case TYushort8: 2694 case TYlong4: 2695 case TYulong4: 2696 case TYllong2: 2697 case TYullong2: 2698 printf("%llxLL+%llxLL ", cast(long)e.EV.Vcent.hi, cast(long)e.EV.Vcent.lo); 2699 break; 2700 2701 // SIMD 32 byte (256 bit) vector types 2702 case TYfloat8: // float[8] 2703 case TYdouble4: // double[4] 2704 case TYschar32: // byte[32] 2705 case TYuchar32: // ubyte[32] 2706 case TYshort16: // short[16] 2707 case TYushort16: // ushort[16] 2708 case TYlong8: // int[8] 2709 case TYulong8: // uint[8] 2710 case TYllong4: // long[4] 2711 case TYullong4: // ulong[4] 2712 printf("x%llx,x%llx,x%llx,x%llx ", 2713 e.EV.Vullong4[3],e.EV.Vullong4[2],e.EV.Vullong4[1],e.EV.Vullong4[0]); 2714 break; 2715 2716 // SIMD 64 byte (512 bit) vector types 2717 case TYfloat16: // float[16] 2718 case TYdouble8: // double[8] 2719 case TYschar64: // byte[64] 2720 case TYuchar64: // ubyte[64] 2721 case TYshort32: // short[32] 2722 case TYushort32: // ushort[32] 2723 case TYlong16: // int[16] 2724 case TYulong16: // uint[16] 2725 case TYllong8: // long[8] 2726 case TYullong8: // ulong[8] 2727 printf("512 bit vector "); // not supported yet with union eve 2728 break; 2729 2730 default: 2731 printf("Invalid type "); 2732 printf("%s\n", tym_str(typemask(e))); 2733 /*assert(0);*/ 2734 } 2735 } 2736 2737 /********************************** 2738 * Hydrate an elem. 2739 */ 2740 2741 static if (HYDRATE) 2742 { 2743 void el_hydrate(elem **pe) 2744 { 2745 if (!isdehydrated(*pe)) 2746 return; 2747 2748 assert(PARSER); 2749 elem* e = cast(elem *) ph_hydrate(cast(void**)pe); 2750 elem_debug(e); 2751 2752 debug if (!(e.Eoper < OPMAX)) 2753 printf("e = x%lx, e.Eoper = %d\n",e,e.Eoper); 2754 2755 debug assert(e.Eoper < OPMAX); 2756 type_hydrate(&e.ET); 2757 if (configv.addlinenumbers) 2758 { 2759 filename_translate(&e.Esrcpos); 2760 srcpos_hydrate(&e.Esrcpos); 2761 } 2762 if (!OTleaf(e.Eoper)) 2763 { 2764 el_hydrate(&e.EV.E1); 2765 if (OTbinary(e.Eoper)) 2766 el_hydrate(&e.EV.E2); 2767 else if (e.Eoper == OPctor) 2768 { 2769 } 2770 } 2771 else 2772 { 2773 switch (e.Eoper) 2774 { 2775 case OPstring: 2776 case OPasm: 2777 ph_hydrate(cast(void**)&e.EV.Vstring); 2778 break; 2779 2780 case OPrelconst: 2781 //if (tybasic(e.ET.Tty) == TYmemptr) 2782 //el_hydrate(&e.EV.sm.ethis); 2783 case OPvar: 2784 symbol_hydrate(&e.EV.Vsym); 2785 symbol_debug(e.EV.Vsym); 2786 break; 2787 2788 default: 2789 break; 2790 } 2791 } 2792 } 2793 } 2794 2795 /********************************** 2796 * Dehydrate an elem. 2797 */ 2798 2799 static if (DEHYDRATE) 2800 { 2801 void el_dehydrate(elem **pe) 2802 { 2803 elem* e = *pe; 2804 if (e == null || isdehydrated(e)) 2805 return; 2806 2807 assert(PARSER); 2808 elem_debug(e); 2809 2810 debug if (!(e.Eoper < OPMAX)) 2811 printf("e = x%lx, e.Eoper = %d\n",e,e.Eoper); 2812 2813 debug_assert(e.Eoper < OPMAX); 2814 ph_dehydrate(pe); 2815 2816 version (DEBUG_XSYMGEN) 2817 { 2818 if (xsym_gen && ph_in_head(e)) 2819 return; 2820 } 2821 2822 type_dehydrate(&e.ET); 2823 if (configv.addlinenumbers) 2824 srcpos_dehydrate(&e.Esrcpos); 2825 if (!OTleaf(e.Eoper)) 2826 { 2827 el_dehydrate(&e.EV.E1); 2828 if (OTbinary(e.Eoper)) 2829 el_dehydrate(&e.EV.E2); 2830 } 2831 else 2832 { 2833 switch (e.Eoper) 2834 { 2835 case OPstring: 2836 case OPasm: 2837 ph_dehydrate(&e.EV.Vstring); 2838 break; 2839 2840 case OPrelconst: 2841 //if (tybasic(e.ET.Tty) == TYmemptr) 2842 //el_dehydrate(&e.EV.sm.ethis); 2843 case OPvar: 2844 symbol_dehydrate(&e.EV.Vsym); 2845 break; 2846 2847 default: 2848 break; 2849 } 2850 } 2851 } 2852 }