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