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-2020 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(cast(uint)d.EV.Vstrlen); 675 memcpy(d.EV.Vstring,e.EV.Vstring,cast(uint)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 targ_size_t len; 1582 1583 assert(!PARSER); 1584 elem_debug(e); 1585 assert(e.Eoper == OPstring); 1586 p = e.EV.Vstring; 1587 e.EV.Vstring = null; 1588 len = e.EV.Vstrlen; 1589 1590 // Handle strings that go into the code segment 1591 if (tybasic(e.Ety) == TYcptr || 1592 (tyfv(e.Ety) && config.flags3 & CFG3strcod)) 1593 { 1594 assert(config.objfmt == OBJ_OMF); // option not done yet for others 1595 s = symbol_generate(SCstatic, type_fake(mTYcs | e.Ety)); 1596 s.Sfl = FLcsdata; 1597 s.Soffset = Offset(cseg); 1598 s.Sseg = cseg; 1599 symbol_keep(s); 1600 if (!eecontext.EEcompile || eecontext.EEin) 1601 { 1602 objmod.bytes(cseg,Offset(cseg),cast(uint)len,p); 1603 Offset(cseg) += len; 1604 } 1605 mem_free(p); 1606 goto L1; 1607 } 1608 1609 if (eecontext.EEin) // if compiling debugger expression 1610 { 1611 s = out_readonly_sym(e.Ety, p, cast(int)len); 1612 mem_free(p); 1613 goto L1; 1614 } 1615 1616 // See if e is already in the string table 1617 for (i = 0; i < stable.length; i++) 1618 { 1619 if (stable[i].str.length == len && 1620 memcmp(stable[i].str.ptr,p,cast(uint)len) == 0) 1621 { 1622 // Replace e with that symbol 1623 MEM_PH_FREE(p); 1624 s = stable[i].sym; 1625 goto L1; 1626 } 1627 } 1628 1629 // Replace string with a symbol that refers to that string 1630 // in the DATA segment 1631 1632 if (eecontext.EEcompile) 1633 { 1634 s = symboldata(Offset(DATA),e.Ety); 1635 s.Sseg = DATA; 1636 } 1637 else 1638 s = out_readonly_sym(e.Ety,p,cast(int)len); 1639 1640 // Remember the string for possible reuse later 1641 //printf("Adding %d, '%s'\n",stable_si,p); 1642 mem_free(stable[stable_si].str.ptr); 1643 stable[stable_si].str = p[0 .. cast(size_t)len]; 1644 stable[stable_si].sym = s; 1645 stable_si = (stable_si + 1) & (stable.length - 1); 1646 1647 L1: 1648 // Refer e to the symbol generated 1649 elem *ex = el_ptr(s); 1650 ex.Ety = e.Ety; 1651 if (e.EV.Voffset) 1652 { 1653 if (ex.Eoper == OPrelconst) 1654 ex.EV.Voffset += e.EV.Voffset; 1655 else 1656 ex = el_bin(OPadd, ex.Ety, ex, el_long(TYint, e.EV.Voffset)); 1657 } 1658 el_free(e); 1659 return ex; 1660 } 1661 1662 /******************************************** 1663 * If e is a long double constant, and it is perfectly representable as a 1664 * double constant, convert it to a double constant. 1665 * Note that this must NOT be done in contexts where there are no further 1666 * operations, since then it could change the type (eg, in the function call 1667 * printf("%La", 2.0L); the 2.0 must stay as a long double). 1668 */ 1669 static if (1) 1670 { 1671 void shrinkLongDoubleConstantIfPossible(elem *e) 1672 { 1673 if (e.Eoper == OPconst && e.Ety == TYldouble) 1674 { 1675 /* Check to see if it can be converted into a double (this happens 1676 * when the low bits are all zero, and the exponent is in the 1677 * double range). 1678 * Use 'volatile' to prevent optimizer from folding away the conversions, 1679 * and thereby missing the truncation in the conversion to double. 1680 */ 1681 auto v = e.EV.Vldouble; 1682 double vDouble; 1683 1684 version (CRuntime_Microsoft) 1685 { 1686 static if (is(typeof(v) == real)) 1687 *(&vDouble) = v; 1688 else 1689 *(&vDouble) = cast(double)v; 1690 } 1691 else 1692 *(&vDouble) = v; 1693 1694 if (v == vDouble) // This will fail if compiler does NaN incorrectly! 1695 { 1696 // Yes, we can do it! 1697 e.EV.Vdouble = vDouble; 1698 e.Ety = TYdouble; 1699 } 1700 } 1701 } 1702 } 1703 1704 1705 /************************* 1706 * Run through a tree converting it to CODGEN. 1707 */ 1708 1709 version (HTOD) { } else 1710 { 1711 elem *el_convert(elem *e) 1712 { 1713 //printf("el_convert(%p)\n", e); 1714 elem_debug(e); 1715 const op = e.Eoper; 1716 switch (op) 1717 { 1718 case OPvar: 1719 break; 1720 1721 case OPconst: 1722 if (tyvector(e.Ety)) 1723 e = el_convxmm(e); 1724 else if (tyfloating(e.Ety) && config.inline8087) 1725 e = el_convfloat(e); 1726 break; 1727 1728 case OPstring: 1729 go.changes++; 1730 e = el_convstring(e); 1731 break; 1732 1733 case OPnullptr: 1734 e = el_long(e.Ety, 0); 1735 break; 1736 1737 case OPmul: 1738 /* special floating-point case: allow x*2 to be x+x 1739 * in this case, we preserve the constant 2. 1740 */ 1741 if (tyreal(e.Ety) && // don't bother with imaginary or complex 1742 e.EV.E2.Eoper == OPconst && el_toldoubled(e.EV.E2) == 2.0L) 1743 { 1744 e.EV.E1 = el_convert(e.EV.E1); 1745 /* Don't call el_convert(e.EV.E2), we want it to stay as a constant 1746 * which will be detected by code gen. 1747 */ 1748 break; 1749 } 1750 goto case OPdiv; 1751 1752 case OPdiv: 1753 case OPadd: 1754 case OPmin: 1755 // For a*b,a+b,a-b,a/b, if a long double constant is involved, convert it to a double constant. 1756 if (tyreal(e.Ety)) 1757 shrinkLongDoubleConstantIfPossible(e.EV.E1); 1758 if (tyreal(e.Ety)) 1759 shrinkLongDoubleConstantIfPossible(e.EV.E2); 1760 goto default; 1761 1762 default: 1763 if (OTbinary(op)) 1764 { 1765 e.EV.E1 = el_convert(e.EV.E1); 1766 e.EV.E2 = el_convert(e.EV.E2); 1767 } 1768 else if (OTunary(op)) 1769 { 1770 e.EV.E1 = el_convert(e.EV.E1); 1771 } 1772 break; 1773 } 1774 return e; 1775 } 1776 } 1777 1778 1779 /************************ 1780 * Make a constant elem. 1781 * ty = type of elem 1782 * *pconst = union of constant data 1783 */ 1784 1785 elem * el_const(tym_t ty, eve *pconst) 1786 { 1787 elem *e; 1788 1789 version (MARS) { } 1790 else assert(!PARSER); 1791 1792 e = el_calloc(); 1793 e.Eoper = OPconst; 1794 e.Ety = ty; 1795 memcpy(&e.EV,pconst,(e.EV).sizeof); 1796 return e; 1797 } 1798 1799 1800 /************************** 1801 * Insert constructor information into tree. 1802 * A corresponding el_ddtor() must be called later. 1803 * Params: 1804 * e = code to construct the object 1805 * decl = VarDeclaration of variable being constructed 1806 */ 1807 1808 static if (0) 1809 { 1810 elem *el_dctor(elem *e,void *decl) 1811 { 1812 elem *ector = el_calloc(); 1813 ector.Eoper = OPdctor; 1814 ector.Ety = TYvoid; 1815 ector.EV.ed.Edecl = decl; 1816 if (e) 1817 e = el_bin(OPinfo,e.Ety,ector,e); 1818 else 1819 /* Remember that a "constructor" may execute no code, hence 1820 * the need for OPinfo if there is code to execute. 1821 */ 1822 e = ector; 1823 return e; 1824 } 1825 } 1826 1827 /************************** 1828 * Insert destructor information into tree. 1829 * e code to destruct the object 1830 * decl VarDeclaration of variable being destructed 1831 * (must match decl for corresponding OPctor) 1832 */ 1833 1834 static if (0) 1835 { 1836 elem *el_ddtor(elem *e,void *decl) 1837 { 1838 /* A destructor always executes code, or we wouldn't need 1839 * eh for it. 1840 * An OPddtor must match 1:1 with an OPdctor 1841 */ 1842 elem *edtor = el_calloc(); 1843 edtor.Eoper = OPddtor; 1844 edtor.Ety = TYvoid; 1845 edtor.EV.ed.Edecl = decl; 1846 edtor.EV.ed.Eleft = e; 1847 return edtor; 1848 } 1849 } 1850 1851 /********************************************* 1852 * Create constructor/destructor pair of elems. 1853 * Caution: The pattern generated here must match that detected in e2ir.c's visit(CallExp). 1854 * Params: 1855 * ec = code to construct (may be null) 1856 * ed = code to destruct 1857 * pedtor = set to destructor node 1858 * Returns: 1859 * constructor node 1860 */ 1861 1862 elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor) 1863 { 1864 elem *er; 1865 if (config.ehmethod == EHmethod.EH_DWARF) 1866 { 1867 /* Construct (note that OPinfo is evaluated RTOL): 1868 * er = (OPdctor OPinfo (__flag = 0, ec)) 1869 * edtor = __flag = 1, (OPddtor ((__exception_object = _EAX), ed, (!__flag && _Unsafe_Resume(__exception_object)))) 1870 */ 1871 1872 /* Declare __flag, __EAX, __exception_object variables. 1873 * Use volatile to prevent optimizer from messing them up, since optimizer doesn't know about 1874 * landing pads (the landing pad will be on the OPddtor's EV.ed.Eleft) 1875 */ 1876 Symbol *sflag = symbol_name("__flag", SCauto, type_fake(mTYvolatile | TYbool)); 1877 Symbol *sreg = symbol_name("__EAX", SCpseudo, type_fake(mTYvolatile | TYnptr)); 1878 sreg.Sreglsw = 0; // EAX, RAX, whatevs 1879 Symbol *seo = symbol_name("__exception_object", SCauto, tspvoid); 1880 1881 symbol_add(sflag); 1882 symbol_add(sreg); 1883 symbol_add(seo); 1884 1885 elem *ector = el_calloc(); 1886 ector.Eoper = OPdctor; 1887 ector.Ety = TYvoid; 1888 // ector.EV.ed.Edecl = decl; 1889 1890 eve c = void; 1891 memset(&c, 0, c.sizeof); 1892 elem *e_flag_0 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 0 1893 er = el_bin(OPinfo, ec ? ec.Ety : TYvoid, ector, el_combine(e_flag_0, ec)); 1894 1895 /* A destructor always executes code, or we wouldn't need 1896 * eh for it. 1897 * An OPddtor must match 1:1 with an OPdctor 1898 */ 1899 elem *edtor = el_calloc(); 1900 edtor.Eoper = OPddtor; 1901 edtor.Ety = TYvoid; 1902 // edtor.EV.Edecl = decl; 1903 // edtor.EV.E1 = e; 1904 1905 c.Vint = 1; 1906 elem *e_flag_1 = el_bin(OPeq, TYvoid, el_var(sflag), el_const(TYbool, &c)); // __flag = 1 1907 elem *e_eax = el_bin(OPeq, TYvoid, el_var(seo), el_var(sreg)); // __exception_object = __EAX 1908 elem *eu = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_UNWIND_RESUME)), el_var(seo)); 1909 eu = el_bin(OPandand, TYvoid, el_una(OPnot, TYbool, el_var(sflag)), eu); 1910 1911 edtor.EV.E1 = el_combine(el_combine(e_eax, ed), eu); 1912 1913 *pedtor = el_combine(e_flag_1, edtor); 1914 } 1915 else 1916 { 1917 /* Construct (note that OPinfo is evaluated RTOL): 1918 * er = (OPdctor OPinfo ec) 1919 * edtor = (OPddtor ed) 1920 */ 1921 elem *ector = el_calloc(); 1922 ector.Eoper = OPdctor; 1923 ector.Ety = TYvoid; 1924 // ector.EV.ed.Edecl = decl; 1925 if (ec) 1926 er = el_bin(OPinfo,ec.Ety,ector,ec); 1927 else 1928 /* Remember that a "constructor" may execute no code, hence 1929 * the need for OPinfo if there is code to execute. 1930 */ 1931 er = ector; 1932 1933 /* A destructor always executes code, or we wouldn't need 1934 * eh for it. 1935 * An OPddtor must match 1:1 with an OPdctor 1936 */ 1937 elem *edtor = el_calloc(); 1938 edtor.Eoper = OPddtor; 1939 edtor.Ety = TYvoid; 1940 // edtor.EV.Edecl = decl; 1941 edtor.EV.E1 = ed; 1942 *pedtor = edtor; 1943 } 1944 1945 return er; 1946 } 1947 1948 /************************** 1949 * Insert constructor information into tree. 1950 * ector pointer to object being constructed 1951 * e code to construct the object 1952 * sdtor function to destruct the object 1953 */ 1954 1955 version (SCPP_HTOD) 1956 { 1957 elem *el_ctor(elem *ector,elem *e,Symbol *sdtor) 1958 { 1959 //printf("el_ctor(ector = %p, e = %p, sdtor = %p)\n", ector, e, sdtor); 1960 //printf("stdor = '%s'\n", cpp_prettyident(sdtor)); 1961 //printf("e:\n"); elem_print(e); 1962 if (ector) 1963 { 1964 if (sdtor) 1965 { 1966 if (sdtor.Sfunc.Fbody) 1967 { 1968 n2_instantiate_memfunc(sdtor); 1969 } 1970 // Causes symbols to be written out prematurely when 1971 // writing precompiled headers. 1972 // Moved to outelem(). 1973 //nwc_mustwrite(sdtor); 1974 } 1975 if (!sdtor || ector.Eoper == OPcall || 1976 (ector.Eoper == OPrelconst && !(sytab[ector.EV.Vsym.Sclass] & SCSS)) 1977 // Not ambient memory model 1978 || (tyfarfunc(sdtor.ty()) ? !LARGECODE : LARGECODE) 1979 ) 1980 { 1981 el_free(ector); 1982 } 1983 else 1984 { 1985 ector = el_unat(OPctor,ector.ET,ector); 1986 ector.EV.Edtor = sdtor; 1987 symbol_debug(sdtor); 1988 if (e) 1989 e = el_bint(OPinfo,e.ET,ector,e); 1990 else 1991 e = ector; 1992 } 1993 } 1994 return e; 1995 } 1996 } 1997 1998 /************************** 1999 * Insert destructor information into tree. 2000 * edtor pointer to object being destructed 2001 * e code to do the destruction 2002 */ 2003 2004 elem *el_dtor(elem *edtor,elem *e) 2005 { 2006 if (edtor) 2007 { 2008 edtor = el_unat(OPdtor,edtor.ET,edtor); 2009 if (e) 2010 e = el_bint(OPcomma,e.ET,edtor,e); 2011 else 2012 e = edtor; 2013 } 2014 return e; 2015 } 2016 2017 /********************************** 2018 * Create an elem of the constant 0, of the type t. 2019 */ 2020 2021 elem *el_zero(type *t) 2022 { 2023 assert(PARSER); 2024 2025 elem* e = el_calloc(); 2026 e.Eoper = OPconst; 2027 e.ET = t; 2028 if (t) 2029 { 2030 type_debug(t); 2031 e.ET.Tcount++; 2032 } 2033 return(e); 2034 } 2035 2036 /******************* 2037 * Find and return pointer to parent of e starting at *pe. 2038 * Return null if can't find it. 2039 */ 2040 2041 elem ** el_parent(elem *e,elem **pe) 2042 { 2043 assert(e && pe && *pe); 2044 elem_debug(e); 2045 elem_debug(*pe); 2046 if (e == *pe) 2047 return pe; 2048 else if (OTunary((*pe).Eoper)) 2049 return el_parent(e,&((*pe).EV.E1)); 2050 else if (OTbinary((*pe).Eoper)) 2051 { 2052 elem **pe2; 2053 return ((pe2 = el_parent(e,&((*pe).EV.E1))) != null) 2054 ? pe2 2055 : el_parent(e,&((*pe).EV.E2)); 2056 } 2057 else 2058 return null; 2059 } 2060 2061 /******************************* 2062 * Returns: true if trees match. 2063 */ 2064 2065 private bool el_matchx(const(elem)* n1, const(elem)* n2, int gmatch2) 2066 { 2067 if (n1 == n2) 2068 return true; 2069 if (!n1 || !n2) 2070 return false; 2071 elem_debug(n1); 2072 elem_debug(n2); 2073 2074 L1: 2075 const op = n1.Eoper; 2076 if (op != n2.Eoper) 2077 return false; 2078 2079 auto tym = typemask(n1); 2080 auto tym2 = typemask(n2); 2081 if (tym != tym2) 2082 { 2083 if ((tym & ~mTYbasic) != (tym2 & ~mTYbasic)) 2084 { 2085 if (!(gmatch2 & 2)) 2086 return false; 2087 } 2088 tym = tybasic(tym); 2089 tym2 = tybasic(tym2); 2090 if (tyequiv[tym] != tyequiv[tym2] && 2091 !((gmatch2 & 8) && touns(tym) == touns(tym2)) 2092 ) 2093 return false; 2094 gmatch2 &= ~8; 2095 } 2096 2097 if (OTunary(op)) 2098 { 2099 L2: 2100 if (PARSER) 2101 { 2102 n1 = n1.EV.E1; 2103 n2 = n2.EV.E1; 2104 assert(n1 && n2); 2105 goto L1; 2106 } 2107 else if (OPTIMIZER) 2108 { 2109 if (op == OPstrpar || op == OPstrctor) 2110 { if (/*n1.Enumbytes != n2.Enumbytes ||*/ n1.ET != n2.ET) 2111 return false; 2112 } 2113 n1 = n1.EV.E1; 2114 n2 = n2.EV.E1; 2115 assert(n1 && n2); 2116 goto L1; 2117 } 2118 else 2119 { 2120 if (n1.EV.E1 == n2.EV.E1) 2121 goto ismatch; 2122 n1 = n1.EV.E1; 2123 n2 = n2.EV.E1; 2124 assert(n1 && n2); 2125 goto L1; 2126 } 2127 } 2128 else if (OTbinary(op)) 2129 { 2130 if (!PARSER) 2131 { 2132 if (op == OPstreq) 2133 { 2134 if (/*n1.Enumbytes != n2.Enumbytes ||*/ n1.ET != n2.ET) 2135 return false; 2136 } 2137 } 2138 if (el_matchx(n1.EV.E2, n2.EV.E2, gmatch2)) 2139 { 2140 goto L2; // check left tree 2141 } 2142 return false; 2143 } 2144 else /* leaf elem */ 2145 { 2146 switch (op) 2147 { 2148 case OPconst: 2149 if (gmatch2 & 1) 2150 break; 2151 Lagain: 2152 switch (tybasic(tym)) 2153 { 2154 case TYshort: 2155 case TYwchar_t: 2156 case TYushort: 2157 case TYchar16: 2158 case_short: 2159 if (n1.EV.Vshort != n2.EV.Vshort) 2160 return false; 2161 break; 2162 2163 case TYlong: 2164 case TYulong: 2165 case TYdchar: 2166 case_long: 2167 if (n1.EV.Vlong != n2.EV.Vlong) 2168 return false; 2169 break; 2170 2171 case TYllong: 2172 case TYullong: 2173 case_llong: 2174 if (n1.EV.Vllong != n2.EV.Vllong) 2175 return false; 2176 break; 2177 2178 case TYcent: 2179 case TYucent: 2180 if (n1.EV.Vcent.lsw != n2.EV.Vcent.lsw || 2181 n1.EV.Vcent.msw != n2.EV.Vcent.msw) 2182 return false; 2183 break; 2184 2185 case TYenum: 2186 if (PARSER) 2187 { tym = n1.ET.Tnext.Tty; 2188 goto Lagain; 2189 } 2190 goto case TYuint; 2191 2192 case TYint: 2193 case TYuint: 2194 if (_tysize[TYint] == SHORTSIZE) 2195 goto case_short; 2196 else 2197 goto case_long; 2198 2199 case TYnullptr: 2200 case TYnptr: 2201 case TYnref: 2202 case TYsptr: 2203 case TYcptr: 2204 case TYimmutPtr: 2205 case TYsharePtr: 2206 case TYrestrictPtr: 2207 case TYfgPtr: 2208 if (_tysize[TYnptr] == SHORTSIZE) 2209 goto case_short; 2210 else if (_tysize[TYnptr] == LONGSIZE) 2211 goto case_long; 2212 else 2213 { assert(_tysize[TYnptr] == LLONGSIZE); 2214 goto case_llong; 2215 } 2216 2217 case TYbool: 2218 case TYchar: 2219 case TYuchar: 2220 case TYschar: 2221 if (n1.EV.Vschar != n2.EV.Vschar) 2222 return false; 2223 break; 2224 2225 case TYfptr: 2226 case TYhptr: 2227 case TYvptr: 2228 2229 /* Far pointers on the 386 are longer than 2230 any integral type... 2231 */ 2232 if (memcmp(&n1.EV, &n2.EV, tysize(tym))) 2233 return false; 2234 break; 2235 2236 /* Compare bit patterns w/o worrying about 2237 exceptions, unordered comparisons, etc. 2238 */ 2239 case TYfloat: 2240 case TYifloat: 2241 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vfloat).sizeof)) 2242 return false; 2243 break; 2244 2245 case TYdouble: 2246 case TYdouble_alias: 2247 case TYidouble: 2248 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vdouble).sizeof)) 2249 return false; 2250 break; 2251 2252 case TYldouble: 2253 case TYildouble: 2254 static if ((n1.EV.Vldouble).sizeof > 10) 2255 { 2256 /* sizeof is 12, but actual size is 10 */ 2257 if (memcmp(&n1.EV,&n2.EV,10)) 2258 return false; 2259 } 2260 else 2261 { 2262 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vldouble).sizeof)) 2263 return false; 2264 } 2265 break; 2266 2267 case TYcfloat: 2268 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcfloat).sizeof)) 2269 return false; 2270 break; 2271 2272 case TYcdouble: 2273 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcdouble).sizeof)) 2274 return false; 2275 break; 2276 2277 case TYfloat4: 2278 case TYdouble2: 2279 case TYschar16: 2280 case TYuchar16: 2281 case TYshort8: 2282 case TYushort8: 2283 case TYlong4: 2284 case TYulong4: 2285 case TYllong2: 2286 case TYullong2: 2287 if (n1.EV.Vcent.msw != n2.EV.Vcent.msw || n1.EV.Vcent.lsw != n2.EV.Vcent.lsw) 2288 return false; 2289 break; 2290 2291 case TYcldouble: 2292 static if ((n1.EV.Vldouble).sizeof > 10) 2293 { 2294 /* sizeof is 12, but actual size of each part is 10 */ 2295 if (memcmp(&n1.EV,&n2.EV,10) || 2296 memcmp(&n1.EV.Vldouble + 1, &n2.EV.Vldouble + 1, 10)) 2297 return false; 2298 } 2299 else 2300 { 2301 if (memcmp(&n1.EV,&n2.EV,(n1.EV.Vcldouble).sizeof)) 2302 return false; 2303 } 2304 break; 2305 2306 case TYvoid: 2307 break; // voids always match 2308 2309 version (SCPP_HTOD) 2310 { 2311 case TYident: 2312 assert(errcnt); 2313 return false; 2314 } 2315 2316 default: 2317 elem_print(n1); 2318 assert(0); 2319 } 2320 break; 2321 case OPrelconst: 2322 case OPvar: 2323 version (SCPP_HTOD) 2324 case OPsizeof: 2325 2326 symbol_debug(n1.EV.Vsym); 2327 symbol_debug(n2.EV.Vsym); 2328 if (n1.EV.Voffset != n2.EV.Voffset) 2329 return false; 2330 version (SCPP_HTOD) 2331 { 2332 if (gmatch2 & 4) 2333 { 2334 static if (0) 2335 { 2336 printf("------- symbols ---------\n"); 2337 symbol_print(n1.EV.Vsym); 2338 symbol_print(n2.EV.Vsym); 2339 printf("\n"); 2340 } 2341 if (/*strcmp(n1.EV.Vsym.Sident, n2.EV.Vsym.Sident) &&*/ 2342 n1.EV.Vsym != n2.EV.Vsym && 2343 (!n1.EV.Vsym.Ssequence || n1.EV.Vsym.Ssequence != n2.EV.Vsym.Ssequence)) 2344 return false; 2345 } 2346 else if (n1.EV.Vsym != n2.EV.Vsym) 2347 return false; 2348 } 2349 else 2350 { 2351 if (n1.EV.Vsym != n2.EV.Vsym) 2352 return false; 2353 } 2354 break; 2355 2356 case OPasm: 2357 case OPstring: 2358 { 2359 const n = n2.EV.Vstrlen; 2360 if (n1.EV.Vstrlen != n || 2361 n1.EV.Voffset != n2.EV.Voffset || 2362 memcmp(n1.EV.Vstring, n2.EV.Vstring, cast(size_t)n)) 2363 return false; /* check bytes in the string */ 2364 break; 2365 } 2366 2367 case OPstrthis: 2368 case OPframeptr: 2369 case OPhalt: 2370 case OPgot: 2371 break; 2372 2373 version (SCPP_HTOD) 2374 { 2375 case OPmark: 2376 break; 2377 } 2378 default: 2379 WROP(op); 2380 assert(0); 2381 } 2382 ismatch: 2383 return true; 2384 } 2385 assert(0); 2386 } 2387 2388 /******************************* 2389 * Returns: true if trees match. 2390 */ 2391 bool el_match(const elem* n1, const elem* n2) 2392 { 2393 return el_matchx(n1, n2, 0); 2394 } 2395 2396 /********************************* 2397 * Kludge on el_match(). Same, but ignore differences in OPconst. 2398 */ 2399 2400 bool el_match2(const elem* n1, const elem* n2) 2401 { 2402 return el_matchx(n1,n2,1); 2403 } 2404 2405 /********************************* 2406 * Kludge on el_match(). Same, but ignore differences in type modifiers. 2407 */ 2408 2409 bool el_match3(const elem* n1, const elem* n2) 2410 { 2411 return el_matchx(n1,n2,2); 2412 } 2413 2414 /********************************* 2415 * Kludge on el_match(). Same, but ignore differences in spelling of var's. 2416 */ 2417 2418 bool el_match4(const elem* n1, const elem* n2) 2419 { 2420 return el_matchx(n1,n2,2|4); 2421 } 2422 2423 /********************************* 2424 * Kludge on el_match(). Same, but regard signed/unsigned as equivalent. 2425 */ 2426 2427 bool el_match5(const elem* n1, const elem* n2) 2428 { 2429 return el_matchx(n1,n2,8); 2430 } 2431 2432 2433 /****************************** 2434 * Extract long value from constant parser elem. 2435 */ 2436 2437 targ_llong el_tolongt(elem *e) 2438 { 2439 const parsersave = PARSER; 2440 PARSER = 1; 2441 const result = el_tolong(e); 2442 PARSER = parsersave; 2443 return result; 2444 } 2445 2446 /****************************** 2447 * Extract long value from constant elem. 2448 */ 2449 2450 targ_llong el_tolong(elem *e) 2451 { 2452 elem_debug(e); 2453 version (SCPP_HTOD) 2454 { 2455 if (e.Eoper == OPsizeof) 2456 { 2457 e.Eoper = OPconst; 2458 e.EV.Vllong = type_size(e.EV.Vsym.Stype); 2459 } 2460 } 2461 if (e.Eoper != OPconst) 2462 elem_print(e); 2463 assert(e.Eoper == OPconst); 2464 auto ty = tybasic(typemask(e)); 2465 L1: 2466 targ_llong result; 2467 switch (ty) 2468 { 2469 case TYchar: 2470 if (config.flags & CFGuchar) 2471 goto Uchar; 2472 goto case TYschar; 2473 2474 case TYschar: 2475 result = e.EV.Vschar; 2476 break; 2477 2478 case TYuchar: 2479 case TYbool: 2480 Uchar: 2481 result = e.EV.Vuchar; 2482 break; 2483 2484 case TYshort: 2485 Ishort: 2486 result = e.EV.Vshort; 2487 break; 2488 2489 case TYushort: 2490 case TYwchar_t: 2491 case TYchar16: 2492 Ushort: 2493 result = e.EV.Vushort; 2494 break; 2495 version (SCPP_HTOD) 2496 { 2497 case TYenum: 2498 assert(PARSER); 2499 ty = e.ET.Tnext.Tty; 2500 goto L1; 2501 } 2502 2503 case TYsptr: 2504 case TYcptr: 2505 case TYnptr: 2506 case TYnullptr: 2507 case TYnref: 2508 case TYimmutPtr: 2509 case TYsharePtr: 2510 case TYrestrictPtr: 2511 case TYfgPtr: 2512 if (_tysize[TYnptr] == SHORTSIZE) 2513 goto Ushort; 2514 if (_tysize[TYnptr] == LONGSIZE) 2515 goto Ulong; 2516 if (_tysize[TYnptr] == LLONGSIZE) 2517 goto Ullong; 2518 assert(0); 2519 2520 case TYuint: 2521 if (_tysize[TYint] == SHORTSIZE) 2522 goto Ushort; 2523 goto Ulong; 2524 2525 case TYulong: 2526 case TYdchar: 2527 case TYfptr: 2528 case TYhptr: 2529 case TYvptr: 2530 case TYvoid: /* some odd cases */ 2531 Ulong: 2532 result = e.EV.Vulong; 2533 break; 2534 2535 case TYint: 2536 if (_tysize[TYint] == SHORTSIZE) 2537 goto Ishort; 2538 goto Ilong; 2539 2540 case TYlong: 2541 Ilong: 2542 result = e.EV.Vlong; 2543 break; 2544 2545 case TYllong: 2546 case TYullong: 2547 Ullong: 2548 result = e.EV.Vullong; 2549 break; 2550 2551 case TYdouble_alias: 2552 case TYldouble: 2553 case TYdouble: 2554 case TYfloat: 2555 case TYildouble: 2556 case TYidouble: 2557 case TYifloat: 2558 case TYcldouble: 2559 case TYcdouble: 2560 case TYcfloat: 2561 result = cast(targ_llong)el_toldoubled(e); 2562 break; 2563 2564 version (SCPP_HTOD) 2565 { 2566 case TYmemptr: 2567 ty = tybasic(tym_conv(e.ET)); 2568 goto L1; 2569 } 2570 2571 case TYcent: 2572 case TYucent: 2573 goto Ullong; // should do better than this when actually doing arithmetic on cents 2574 2575 default: 2576 version (SCPP_HTOD) 2577 { 2578 // Can happen as result of syntax errors 2579 assert(errcnt); 2580 } 2581 else 2582 { 2583 elem_print(e); 2584 assert(0); 2585 } 2586 } 2587 return result; 2588 } 2589 2590 /*********************************** 2591 * Determine if constant e is all ones or all zeros. 2592 * Params: 2593 * e = elem to test 2594 * bit = 0: all zeros 2595 * 1: 1 2596 * -1: all ones 2597 * Returns: 2598 * true if it is 2599 */ 2600 2601 bool el_allbits(const elem* e,int bit) 2602 { 2603 elem_debug(e); 2604 assert(e.Eoper == OPconst); 2605 targ_llong value = e.EV.Vullong; 2606 switch (tysize(e.Ety)) 2607 { 2608 case 1: value = cast(byte) value; 2609 break; 2610 2611 case 2: value = cast(short) value; 2612 break; 2613 2614 case 4: value = cast(int) value; 2615 break; 2616 2617 case 8: break; 2618 2619 default: 2620 assert(0); 2621 } 2622 if (bit == -1) 2623 value++; 2624 else if (bit == 1) 2625 value--; 2626 return value == 0; 2627 } 2628 2629 /******************************************** 2630 * Determine if constant e is a 32 bit or less value, or is a 32 bit value sign extended to 64 bits. 2631 */ 2632 2633 bool el_signx32(const elem* e) 2634 { 2635 elem_debug(e); 2636 assert(e.Eoper == OPconst); 2637 if (tysize(e.Ety) == 8) 2638 { 2639 if (e.EV.Vullong != cast(int)e.EV.Vullong) 2640 return false; 2641 } 2642 return true; 2643 } 2644 2645 /****************************** 2646 * Extract long double value from constant elem. 2647 * Silently ignore types which are not floating point values. 2648 */ 2649 2650 version (CRuntime_Microsoft) 2651 { 2652 longdouble_soft el_toldouble(elem *e) 2653 { 2654 longdouble_soft result; 2655 elem_debug(e); 2656 assert(e.Eoper == OPconst); 2657 switch (tybasic(typemask(e))) 2658 { 2659 case TYfloat: 2660 case TYifloat: 2661 result = longdouble_soft(e.EV.Vfloat); 2662 break; 2663 2664 case TYdouble: 2665 case TYidouble: 2666 case TYdouble_alias: 2667 result = longdouble_soft(e.EV.Vdouble); 2668 break; 2669 2670 case TYldouble: 2671 case TYildouble: 2672 static if (is(typeof(e.EV.Vldouble) == real)) 2673 result = longdouble_soft(e.EV.Vldouble); 2674 else 2675 result = longdouble_soft(cast(real)e.EV.Vldouble); 2676 break; 2677 2678 default: 2679 result = longdouble_soft(0); 2680 break; 2681 } 2682 return result; 2683 } 2684 } 2685 else 2686 { 2687 targ_ldouble el_toldouble(elem *e) 2688 { 2689 targ_ldouble result; 2690 elem_debug(e); 2691 assert(e.Eoper == OPconst); 2692 switch (tybasic(typemask(e))) 2693 { 2694 case TYfloat: 2695 case TYifloat: 2696 result = e.EV.Vfloat; 2697 break; 2698 2699 case TYdouble: 2700 case TYidouble: 2701 case TYdouble_alias: 2702 result = e.EV.Vdouble; 2703 break; 2704 2705 case TYldouble: 2706 case TYildouble: 2707 result = e.EV.Vldouble; 2708 break; 2709 2710 default: 2711 result = 0; 2712 break; 2713 } 2714 return result; 2715 } 2716 } 2717 2718 /******************************** 2719 * Is elem type-dependent or value-dependent? 2720 * Returns: true if so 2721 */ 2722 2723 bool el_isdependent(elem* e) 2724 { 2725 if (type_isdependent(e.ET)) 2726 return true; 2727 while (1) 2728 { 2729 if (e.PEFflags & PEFdependent) 2730 return true; 2731 if (OTunary(e.Eoper)) 2732 e = e.EV.E1; 2733 else if (OTbinary(e.Eoper)) 2734 { 2735 if (el_isdependent(e.EV.E2)) 2736 return true; 2737 e = e.EV.E1; 2738 } 2739 else 2740 break; 2741 } 2742 return false; 2743 } 2744 2745 /**************************************** 2746 * Returns: alignment size of elem e 2747 */ 2748 2749 uint el_alignsize(elem *e) 2750 { 2751 const tym = tybasic(e.Ety); 2752 uint alignsize = tyalignsize(tym); 2753 if (alignsize == cast(uint)-1) 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 }