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