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