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