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