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