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