Whitespace changes --flo
[libfirm] / ir / tv / tv.c
1 /* TV --- Target Values, aka Constant Table.
2    Copyright (C) 1995, 1996 Christian von Roques */
3
4 /* $Id$ */
5
6 /* This implementation assumes:
7    * target characters/strings can be represented as type `char'/`char *',
8    * host's type `long'/`unsigned long' can hold values of mode `l'/`L',
9    * both host and target have two's complement integral arithmetic,
10      host's C operators `/' and `%' match target's div and mod.
11      target_max_<mode> == (1<<k)-1 for some k>0
12      target_min_<mode> == -target_max_<mode>-1
13      target_max_<Mode> == target_max_<mode>-target_min_<mode>
14    * both host and target have IEEE-754 floating-point arithmetic.  */
15
16 /* !!! float and double divides MUST NOT SIGNAL !!! */
17 /* @@@ query the floating-point expception status flags */
18
19 /* @@@ ToDo: tarval_convert_to is not fully implemented! */
20 /* @@@ Problem: All Values are stored twice, once as Univ_*s and a 2nd
21    time in their real target mode. :-( */
22 /* @@@ Perhaps use a set instead of a pset: new tarvals allocated on
23    stack, copied into set by tarval_identify() if really new.  If
24    tarval_identify() discards often enough, the extra copy for kept
25    values is cheaper than the extra obstack_alloc()/free() for
26    discarded ones.  */
27
28 /* Defining this causes inclusions of functions renamed with new gmp.h */
29 #define _TARVAL_GMP_ 0
30
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 # include "xprintf.h"
36 #include <assert.h>
37 #include <limits.h>
38 #include <errno.h>
39 #include <math.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <ctype.h>
43
44 #include "pset.h"
45 #define TOBSTACK_ID "tv"
46 #include "obst.h"
47 #include "ieee754.h"
48 #include "tune.h"
49 #include "ident_t.h"
50 #include "tv_t.h"
51 #include "entity_t.h"
52 #include "irmode.h"
53
54 static struct obstack tv_obst;  /* obstack for all the target values */
55 static pset *tarvals;           /* pset containing pointers to _all_ tarvals */
56
57 /* currently building an object with tarval_start() & friends ? */
58 #define BUILDING obstack_object_size (&tv_obst)
59
60 /* special tarvals: */
61 tarval *tarval_bad;
62 tarval *tarval_b_false;
63 tarval *tarval_b_true;
64 tarval *tarval_d_NaN;
65 tarval *tarval_d_Inf;
66 tarval *tarval_p_void;
67 tarval *tarval_mode_null[irm_max];
68
69 # if 0
70 /* @@@ depends on order of ir_mode */
71 static tarval_chil min_chil[8] = {
72   TARGET_SIMIN (c), 0,
73   TARGET_SIMIN (h), 0,
74   TARGET_SIMIN (i), 0,
75   TARGET_SIMIN (l), 0
76 };
77 static tarval_chil max_chil[8] = {
78   TARGET_SIMAX (c), TARGET_UIMAX (C),
79   TARGET_SIMAX (h), TARGET_UIMAX (H),
80   TARGET_SIMAX (i), TARGET_UIMAX (I),
81   TARGET_SIMAX (l), TARGET_UIMAX (L)
82 };
83 # endif
84
85 /* return a mode-specific value */
86
87 tarval_f
88 tv_val_f (tarval *tv)
89 {
90   return tv->u.f;
91 }
92
93 tarval_d
94 tv_val_d (tarval *tv)
95 {
96   return tv->u.d;
97 }
98
99 tarval_chil
100 tv_val_chil (tarval *tv)
101 {
102   return tv->u.chil;
103 }
104
105 tarval_CHIL
106 tv_val_CHIL (tarval *tv)
107 {
108   return tv->u.CHIL;
109 }
110
111 tarval_Z
112 tv_val_Z (tarval *tv)
113 {
114   return tv->u.Z;
115 }
116
117 tarval_p
118 tv_val_p (tarval *tv)
119 {
120   return tv->u.p;
121 }
122
123 bool
124 tv_val_b (tarval *tv)
125 {
126   return tv->u.b;
127 }
128
129 tarval_B
130 tv_val_B (tarval *tv)
131 {
132   return tv->u.B;
133 }
134
135 tarval_s
136 tv_val_s (tarval *tv)
137 {
138   return tv->u.s;
139 }
140
141
142 /* Overflows `chil' signed integral `mode'?  */
143 static inline bool
144 chil_overflow (tarval_chil chil, ir_mode *mode)
145 {
146   assert (is_chilCHIL(get_mode_modecode(mode)));
147   return (get_mode_min(mode) && get_mode_max(mode)  /* only valid after firm initialization */
148           && (chil < tv_val_chil (get_mode_min(mode))
149               || tv_val_chil (get_mode_max(mode)) < chil));
150 }
151
152
153 /* Overflows `CHIL' unsigned integral `mode'?  */
154 static inline bool
155 CHIL_overflow (tarval_CHIL CHIL, ir_mode *mode)
156 {
157   assert (is_chilCHIL(get_mode_modecode(mode)));
158   return (get_mode_max(mode)   /* only valid after firm initialization */
159           && tv_val_CHIL (get_mode_max(mode)) < CHIL);
160 }
161
162
163 #ifndef NDEBUG
164 void
165 _tarval_vrfy (const tarval *val)
166 {
167   assert (val);
168   switch (get_mode_modecode(val->mode)) {
169     /* floating */
170   case irm_f:
171   case irm_d:
172     break;
173     /* integral */
174   case irm_C: case irm_H: case irm_I: case irm_L:
175     assert (!CHIL_overflow (val->u.CHIL, val->mode)); break;
176   case irm_c: case irm_h: case irm_i: case irm_l:
177     assert (!chil_overflow (val->u.chil, val->mode)); break;
178   case irm_Z:
179     break;
180     /* strange */
181   case irm_p:
182     if (val->u.p.ent)
183       assert (val->u.p.ent->kind == k_entity);
184     assert (   val->u.p.xname || val->u.p.ent
185             || !tarval_p_void || (val == tarval_p_void));
186     break;
187   case irm_s:
188   case irm_S:
189     assert (val->u.s.p); break;
190   case irm_B:
191     assert (val->u.B.p); break;
192   case irm_b:
193     assert ((unsigned)val->u.b <= 1); break;
194   default:
195     assert (val->mode == mode_T);
196   }
197 }
198 #endif
199
200
201 #ifdef STATS
202
203 void
204 tarval_stats (void)
205 {
206   pset_stats (tarvals);
207 }
208
209 #endif
210
211
212 /* Return the canonical tarval * for tv.
213    May destroy everything allocated on tv_obst after tv!  */
214 static tarval *
215 tarval_identify (tarval *tv)
216 {
217   tarval *o;
218
219   o = pset_insert (tarvals, tv, tarval_hash (tv));
220
221   if (o != tv) {
222     obstack_free (&tv_obst, (void *)tv);
223   }
224
225   TARVAL_VRFY (o);
226   return o;
227 }
228
229
230 /* Return 0 iff a equals b.  Bitwise identical NaNs compare equal.  */
231 static int
232 tarval_cmp (const void *p, const void *q)
233 {
234   const tarval *a = p;
235   const tarval *b = q;
236
237   TARVAL_VRFY (a);
238   TARVAL_VRFY (b);
239
240   if (a == b) return 0;
241   if ((void *)a->mode - (void *)b->mode)
242     return (void *)a->mode - (void *)b->mode;
243
244   switch (get_mode_modecode(a->mode)) {
245     /* floating */
246   case irm_f:
247     return memcmp (&a->u.f, &b->u.f, sizeof (a->u.f));
248   case irm_d:
249     return memcmp (&a->u.d, &b->u.d, sizeof (a->u.d));
250     /* unsigned */
251   case irm_C: case irm_H: case irm_I: case irm_L:
252     if (sizeof (int) == sizeof (tarval_CHIL)) {
253       return a->u.CHIL - b->u.CHIL;
254     }
255     return a->u.CHIL != b->u.CHIL;
256     /* signed */
257   case irm_c: case irm_h: case irm_i: case irm_l:
258     if (sizeof (int) == sizeof (tarval_chil)) {
259       return a->u.chil - b->u.chil;
260     }
261     return a->u.chil != b->u.chil;
262   case irm_Z:
263 #if _TARVAL_GMP_
264     return mpz_cmp (&a->u.Z, &b->u.Z);
265 #else
266     return 99; /* ?? */
267 #endif
268     /* strange */
269   case irm_p:
270     if (a->u.p.ent || b->u.p.ent)
271       return (char *)a->u.p.ent - (char *)b->u.p.ent;
272     if (a->u.p.xname && b->u.p.xname)
273       return strcmp (a->u.p.xname, b->u.p.xname);
274     return a->u.p.xname - b->u.p.xname;
275   case irm_b:
276     return a->u.b - b->u.b;
277   case irm_B:
278     return (  a->u.B.n - b->u.B.n
279             ? memcmp (a->u.B.p, b->u.B.p, a->u.B.n)
280             : a->u.B.n - b->u.B.n);
281   case irm_s: case irm_S:
282     return (  a->u.s.n == b->u.s.n
283             ? memcmp (a->u.s.p, b->u.s.p, a->u.s.n)
284             : a->u.s.n - b->u.s.n);
285   default: assert (0);
286   }
287 }
288
289
290 unsigned
291 tarval_hash (tarval *tv)
292 {
293   unsigned h;
294
295   h = get_mode_modecode(tv->mode) * 0x421u;
296   switch (get_mode_modecode(tv->mode)) {
297   case irm_T:
298     h = 0x94b527ce; break;
299   case irm_f:
300     /* quick & dirty */
301     { union { float f; unsigned u; } u;
302       assert (sizeof (float) <= sizeof (unsigned));
303       u.u = 0; u.f = tv->u.f;
304       h ^= u.u;
305       break;
306     }
307   case irm_d:
308     /* quick & dirty */
309     { union { double d; unsigned u[2]; } u;
310       assert (sizeof (double) <= 2*sizeof (unsigned));
311       u.u[0] = u.u[1] = 0; u.d = tv->u.d;
312       h ^= u.u[0] ^ u.u[1];
313       break;
314     }
315   case irm_C: case irm_H: case irm_I: case irm_L:
316     h ^= tv->u.CHIL; break;
317   case irm_c: case irm_h: case irm_i: case irm_l:
318     h ^= tv->u.chil; break;
319   case irm_Z:
320 #if _TARVAL_GMP_
321     h ^= mpz_get_ui (&tv->u.Z); break;
322 #else
323     h ^= (unsigned int) tv; break; /* tut das? */
324 #endif
325   case irm_p:
326     if (tv->u.p.ent) {
327       /* @@@ lower bits not random, watch for collisions; perhaps
328          replace by tv->u.p.ent - (entity *)0 */
329       h ^= ((char *)tv->u.p.ent - (char *)0) / 64;
330     } else if (tv->u.p.xname) {
331       /* Of course, strlen() in a hash function is a mistake, but this
332          case should be really rare.  */
333       h ^= ID_HASH (tv->u.p.xname, strlen (tv->u.p.xname));
334     } else {                    /* void */
335       h^= 0x2b592b88;
336     }
337     break;
338   case irm_b:
339     h ^= tv->u.b; break;
340   case irm_B:
341     h ^= tv->u.B.n; break; /* @@@ not really good */
342   case irm_s:
343     h ^= tv->u.s.p[0]<<12 ^ tv->u.s.p[tv->u.s.n]<<4 ^ tv->u.s.n; break;
344   case irm_S:
345     h ^= tv->u.s.p[0]<<4 ^ tv->u.s.p[tv->u.s.n]<<12 ^ tv->u.s.n; break;
346   default:
347     assert(0);
348   }
349   return h;
350 }
351
352
353 \f
354 /*** ***************** Initialization ************************************* ***/
355
356 void
357 tarval_init_1 (void)
358 {
359   obstack_init (&tv_obst);
360   obstack_alignment_mask (&tv_obst) = ALIGNOF (tarval) - 1;
361   assert (IS_POW2 (ALIGNOF (tarval)));
362
363   /* initialize the target value table */
364   tarvals = new_pset (tarval_cmp, TUNE_NCONSTANTS);
365 }
366
367 void
368 tarval_init_2 (void)
369 {
370   tarval *tv;
371   union ieee754_double x;
372
373   /* assumed by tarval_hash(): */
374   assert (sizeof (float) * CHAR_BIT == 32);
375   assert (sizeof (double) * CHAR_BIT == 64);
376
377 # if 0
378   /* assumed by tarval_chil & friends: */
379   assert (   (irm_C == irm_c+1) && (irm_h == irm_C+1)
380           && (irm_H == irm_h+1) && (irm_i == irm_H+1)
381           && (irm_I == irm_i+1) && (irm_l == irm_I+1)
382           && (irm_L == irm_l+1));
383
384   /* assumed everywhere: */
385   for (i = 0;  i <= irm_L-irm_c;  i += 2) {
386     assert (   IS_POW2 (max_chil[i+1]+1)
387             && (min_chil[i] == -max_chil[i]-1)
388             && ((tarval_CHIL)max_chil[i+1] == (tarval_CHIL)max_chil[i]-min_chil[i]));
389   }
390 # endif
391
392
393   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
394   tv->mode = mode_T;
395   tarval_bad = tarval_identify (tv);
396
397   tarval_b_false = tarval_from_long (mode_b, 0);
398   tarval_b_true = tarval_from_long (mode_b, 1);
399
400   /* IsInf <-> exponent == 0x7ff && ! (bits | fraction_low) */
401   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
402   tv->mode = mode_d;
403   x.ieee.negative = 0;
404   x.ieee.exponent = 0x7ff;
405   x.ieee.mantissa0 = 0;
406   x.ieee.mantissa1 = 0;
407   tv->u.d = x.d;
408   tarval_d_Inf = tarval_identify (tv);
409
410   /* IsNaN <-> exponent==0x7ff  && (qnan_bit | bits | fraction_low) */
411   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
412   tv->mode = mode_d;
413   x.ieee_nan.negative = 0;
414   x.ieee_nan.exponent = 0x7ff;
415   x.ieee_nan.quiet_nan = 1;     /* @@@ quiet or signalling? */
416   x.ieee_nan.mantissa0 = 42;
417   x.ieee_nan.mantissa1 = 0;
418   assert(x.d != x.d /* x.d is NaN */);
419   tv->u.d = x.d;
420   tarval_d_NaN = tarval_identify (tv);
421
422   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
423   tv->mode = mode_p;
424   tv->u.p.xname = NULL;
425   tv->u.p.ent = NULL;
426   tv->u.p.tv = NULL;
427   tarval_p_void = tarval_identify (tv);
428
429   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
430
431
432   tarval_mode_null [irm_f] = tarval_from_long (mode_f, 0);
433   tarval_mode_null [irm_d] = tarval_from_long (mode_d, 0);
434   tarval_mode_null [irm_c] = tarval_from_long (mode_c, 0);
435   tarval_mode_null [irm_C] = tarval_from_long (mode_C, 0);
436   tarval_mode_null [irm_h] = tarval_from_long (mode_h, 0);
437   tarval_mode_null [irm_H] = tarval_from_long (mode_H, 0);
438   tarval_mode_null [irm_i] = tarval_from_long (mode_i, 0);
439   tarval_mode_null [irm_I] = tarval_from_long (mode_I, 0);
440   tarval_mode_null [irm_l] = tarval_from_long (mode_l, 0);
441   tarval_mode_null [irm_L] = tarval_from_long (mode_L, 0);
442   tarval_mode_null [irm_b] = tarval_b_false;
443   tarval_mode_null [irm_p] = tarval_p_void;
444 }
445
446
447 \f
448 /*** ********************** Constructors for tarvals ********************** ***/
449
450 /* copy from src to dst len chars omitting '_'. */
451 static char *
452 stripcpy (char *dst, const char *src, size_t len)
453 {
454   char *d = dst;
455
456   while (len--) {
457     if (*src == '_') src++;
458     else *d++ = *src++;
459   }
460   *d = 0;                       /* make it 0-terminated. */
461
462   return dst;
463 }
464
465
466 tarval *
467 tarval_Z_from_str (const char *s, size_t len, int base)
468 {
469   tarval *tv;
470   char *buf;
471
472   assert (!BUILDING);
473
474   buf = alloca (len+1);
475   stripcpy (buf, s, len);
476
477   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
478   tv->mode = mode_Z;
479 #if _TARVAL_GMP_
480   if (mpz_init_set_str (&tv->u.Z, buf, base)) assert (0);
481 #else
482   assert(0 && "no support for Z in tv!");
483 #endif
484
485   return tarval_identify (tv);
486 }
487
488
489 tarval *
490 tarval_B_from_str (const char *s, size_t len)
491 {
492   tarval *tv;
493   size_t n;                     /* size of B */
494   const char *r;                /* read ptr */
495   unsigned x;                   /* bit store */
496   int b;                        /* bits in x */
497   int shift;                    /* base shift */
498
499   assert (!BUILDING);
500   assert (len >= 3);
501
502   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
503   tv->mode = mode_B;
504
505   assert (s[0] == '0');
506   switch (s[1]) {
507   case 'o':
508   case 'O': shift = 3; break;
509   case 'x':
510   case 'X': shift = 4; break;
511   default: assert(0);
512   }
513
514   r = s+len;                    /* set r past input */
515   s += 2;                       /* skip header */
516   x = 0; b = 0; n = 0;
517   while (--r >= s) {
518     int d;                      /* digit */
519
520     if (*r == '_') continue;    /* skip _ styropor */
521     if (('0' <= *r) && (*r <= '9')) {
522       d = *r - '0';
523     } else if (('a' <= *r) && (*r <= 'f')) {
524       d = *r - 'a' + 10;
525     } else { assert (('A' <= *r) && (*r <= 'F'));
526       d = *r - 'A' + 10;
527     }
528
529     x |= d << b;                /* insert d into x above the b present bits */
530     b += shift;                 /* x now contains shift more bits */
531
532     if (b >= 8) {               /* we've accumulated at least a byte */
533       char c = x & 0xFF;        /* extract the lower 8 bits from x */
534       obstack_grow (&tv_obst, &c, 1); /* and stuff them into B */
535       x >>= 8;                  /* remove the lower 8 bits from x */
536       b -= 8;                   /* x now contains 8 bits fewer */
537       ++n;                      /* B grew a byte */
538     }
539   }
540
541   if (b >= 0) {                 /* flush the rest of the bits */
542     char c = x;                 /* extract them */
543     obstack_grow (&tv_obst, &c, 1); /* and stuff them into B */
544     ++n;                        /* B grew a byte */
545   }
546
547   { unsigned char *p = obstack_finish (&tv_obst);
548     unsigned char *q = p + n;
549
550     tv->u.B.p = p;
551     tv->u.B.n = n;
552     /* reverse p in place */
553     while (p < q) { char c = *p; *p++ = *q; *q-- = c; }
554   }
555
556   return tarval_identify (tv);
557 }
558
559
560 tarval *
561 tarval_f_from_str (const char *s, size_t len)
562 {
563   tarval *tv;
564   char *buf;
565   char *eptr;
566
567   assert (!BUILDING);
568
569   buf = alloca (len+1);
570   stripcpy (buf, s, len);
571
572   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
573   tv->mode = mode_f;
574   tv->u.f = (float)strtod (buf, &eptr);
575   assert (eptr == buf+strlen(buf));
576
577   return tarval_identify (tv);
578 }
579
580
581 tarval *
582 tarval_d_from_str (const char *s, size_t len)
583 {
584   tarval *tv;
585   char *buf;
586   char *eptr;
587
588   assert (!BUILDING);
589
590   buf = alloca (len+1);
591   stripcpy (buf, s, len);
592
593   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
594   tv->mode = mode_d;
595   tv->u.d = strtod (buf, &eptr);
596   assert (eptr == buf+strlen(buf));
597
598   return tarval_identify (tv);
599 }
600
601
602 tarval *
603 tarval_s_from_str (const char *s, size_t len)
604 {
605   tarval *tv;
606
607   assert (!BUILDING);
608
609   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
610
611   tv->mode = mode_s;
612   tv->u.s.n = len;
613   tv->u.s.p = obstack_copy (&tv_obst, s, len);
614
615   return tarval_identify (tv);
616 }
617
618 tarval *
619 tarval_S_from_str (const char *s, size_t len)
620 {
621   tarval *tv;
622
623   assert (!BUILDING);
624
625   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
626
627   tv->mode = mode_S;
628   tv->u.s.n = len;
629   tv->u.s.p = obstack_copy (&tv_obst, s, len);
630
631   return tarval_identify (tv);
632 }
633
634 tarval *tarval_int_from_str (const char *s, size_t len, int base, ir_mode *m) {
635   long val;
636   char *eptr;
637   char *buf;
638
639   assert (mode_is_int(m));
640   assert (!BUILDING);
641
642   buf = alloca (len+1);
643   stripcpy (buf, s, len);
644
645   errno = 0;
646   val = strtol(buf, &eptr, base);    /* strtoll */
647   assert (eptr == buf+strlen(buf));
648   if ((errno == ERANGE)               &&
649       ((m == mode_l) || (m == mode_L))  ) {
650     printf("WARNING: Constant %s not representable. Continuing with %ld.\n",
651            s, val);
652   }
653
654   return tarval_from_long(m, val);
655 }
656
657 /* Create a tarval with mode `m' and value `i' casted to the type that
658    represents such tarvals on host.  The resulting value must be legal
659    for mode `m'.  */
660 tarval *
661 tarval_from_long (ir_mode *m, long val)
662 {
663   tarval *tv;
664
665   assert (!BUILDING);
666
667   if (m == mode_T) return tarval_bad;
668
669   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
670
671   tv->mode = m;
672   switch (get_mode_modecode(m)) {
673     /* floating */
674   case irm_f:
675     tv->u.f = val; break;
676   case irm_d:
677     tv->u.d = val; break;
678     /* unsigned */
679   case irm_C: case irm_H: case irm_I: case irm_L:
680     tv->u.CHIL = val; break;
681     /* signed */
682   case irm_c: case irm_h: case irm_i: case irm_l:
683     tv->u.chil = val; break;
684   case irm_Z:
685 #if _TARVAL_GMP_
686     mpz_init_set_si (&tv->u.Z, val);
687 #else
688     assert(0 && "no support for Z in tv!");
689 #endif
690     break;
691     /* strange */
692   case irm_p:
693     assert(!val);
694     obstack_free (&tv_obst, tv);
695     return tarval_p_void;
696   case irm_b:
697     tv->u.b = !!val;            /* u.b must be 0 or 1 */
698     break;
699   default:
700     assert(0);
701   }
702
703   return tarval_identify (tv);
704 }
705
706
707 tarval *
708 tarval_p_from_str (const char *xname)
709 {
710   tarval *tv;
711
712   assert (!BUILDING);
713
714   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
715
716   tv->mode = mode_p;
717   tv->u.p.xname = obstack_copy0 (&tv_obst, xname, strlen (xname));
718   tv->u.p.ent = NULL;
719   tv->u.p.tv = NULL;
720   return tarval_identify (tv);
721 }
722
723
724 tarval *
725 tarval_p_from_entity (entity *ent)
726 {
727   tarval *tv;
728
729   assert (!BUILDING);
730
731   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
732
733   tv->mode = mode_p;
734   tv->u.p.xname = NULL;
735   tv->u.p.ent = ent;
736   tv->u.p.tv = NULL;
737   return tarval_identify (tv);
738 }
739
740
741 /* Routines for building a tarval step by step follow.
742    Legal calling sequences:
743      tarval_start()
744      No contructors except tarval_append() and tarval_append1 ()
745      tarval_finish_as() or tarval_cancel() */
746
747 /* Begin building a tarval.  */
748 void
749 tarval_start (void)
750 {
751   assert (!BUILDING);
752   obstack_blank (&tv_obst, sizeof (tarval));
753 }
754
755
756 /* Append `n' chars from `p' to the tarval currently under construction.  */
757 void
758 tarval_append (const char *p, size_t n)
759 {
760   assert (BUILDING);
761   obstack_grow (&tv_obst, p, n);
762 }
763
764
765 /* Append `ch' to the tarval currently under construction.  */
766 void
767 tarval_append1 (char ch)
768 {
769   assert (BUILDING);
770   obstack_1grow (&tv_obst, ch);
771 }
772
773
774 /* Finish the tarval currently under construction and give id mode `m'.
775    `m' must be irm_C, irm_B, irm_s or irm_S.
776    Return NULL if the value does not make sense for this mode, this
777    can only happen in mode C.  */
778 tarval *
779 tarval_finish_as (ir_mode *m)
780 {
781   int size = obstack_object_size (&tv_obst) - sizeof (tarval);
782   tarval *tv;
783   unsigned char *p;
784   char ch = 0;                  /* initialized to shut up gcc */
785
786   assert (BUILDING && (size >= 0));
787   if (m == mode_C) {
788     if (size != 1) return tarval_cancel();
789     p = (unsigned char *)obstack_base (&tv_obst) + sizeof (tarval);
790     ch = *p;
791     obstack_blank (&tv_obst, -size);
792   }
793   tv = obstack_finish (&tv_obst);
794   p = (unsigned char *)tv + sizeof (tarval);
795   tv->mode = m;
796
797   switch (get_mode_modecode(m)) {
798   case irm_C:
799     tv->u.CHIL = ch;
800     break;
801   case irm_B:
802     tv->u.B.n = size;
803     tv->u.B.p = p;
804     break;
805   case irm_s:
806   case irm_S:
807     tv->u.s.n = size;
808     tv->u.s.p = p;
809     break;
810   case irm_p:
811     tv->u.p.tv = NULL;
812     break;
813   default:
814     assert (0);
815   }
816
817   return tarval_identify (tv);
818 }
819
820
821 /* Cancel tarval building and return tarval_bad.  */
822 tarval *
823 tarval_cancel (void)
824 {
825   assert (BUILDING);
826   obstack_free (&tv_obst, obstack_finish (&tv_obst));
827   return tarval_bad;
828 }
829
830
831 \f
832 /*** ****************** Arithmethic operations on tarvals ***************** ***/
833
834 /* Return `src' converted to mode `m' if representable, else NULL.
835    @@@ lots of conversions missing */
836 tarval *
837 tarval_convert_to (tarval *src, ir_mode *m)
838 {
839   tarval *tv;
840
841   if (m == src->mode) return src;
842
843   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
844   tv->mode = m;
845
846   switch (get_mode_modecode(src->mode)) {
847
848   case irm_d:
849     if (m != mode_f) goto fail;
850     tv->u.f = src->u.d;
851     break;
852
853   case irm_Z:
854 #if _TARVAL_GMP_
855     switch (get_mode_modecode(m)) {
856
857     case irm_C: case irm_H: case irm_I: case irm_L:
858       if (mpz_cmp_si (&src->u.Z, 0) < 0) goto fail;
859       if (mpz_size (&src->u.Z) > 1) goto fail;
860       tv->u.CHIL = mpz_get_ui (&src->u.Z);
861       if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
862       break;
863
864     case irm_c: case irm_h: case irm_i: case irm_l:
865       tv->u.chil = mpz_get_si (&src->u.Z);
866       if (chil_overflow (tv->u.chil, m)) goto fail;
867       break;
868
869     case irm_b:
870       tv ->u.b = !mpz_cmp_ui (&src->u.Z, 0);
871       break;
872
873     case irm_p:
874       if (mpz_cmp_ui (&src->u.Z, 0)) goto fail;
875       obstack_free (&tv_obst, tv);
876       return tarval_p_void;
877
878     default: goto fail;
879     }
880 #else
881     goto fail;
882 #endif
883     break;
884
885   case irm_c: case irm_h: case irm_i: case irm_l:
886     switch (get_mode_modecode(m)) {
887     case irm_c: case irm_h: case irm_i: case irm_l:
888       tv->u.chil = src->u.chil;
889       if (chil_overflow (tv->u.chil, m)) goto fail;
890       break;
891
892     case irm_C: case irm_H: case irm_I: case irm_L:
893       tv->u.CHIL = src->u.chil;
894       if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
895       break;
896
897     case irm_Z:
898 #if _TARVAL_GMP_
899       mpz_init_set_si (&tv->u.Z, src->u.chil);
900 #else
901       goto fail;
902 #endif
903       break;
904
905     case irm_b:
906       tv->u.b = !!src->u.chil;
907       break;
908
909     default: goto fail;
910     }
911
912   case irm_C: case irm_H: case irm_I: case irm_L:
913     switch (get_mode_modecode(m)) {
914     case irm_c: case irm_h: case irm_i: case irm_l:
915       tv->u.chil = src->u.CHIL;
916       if (chil_overflow (tv->u.chil, m)) goto fail;
917       break;
918
919     case irm_C: case irm_H: case irm_I: case irm_L:
920       tv->u.CHIL = src->u.CHIL;
921       if (CHIL_overflow (tv->u.CHIL, m)) goto fail;
922       break;
923
924     case irm_Z:
925 #if _TARVAL_GMP_
926       mpz_init_set_ui (&tv->u.Z, src->u.CHIL);
927 #else
928       goto fail;
929 #endif
930       break;
931
932     case irm_b:
933       tv->u.b = !!src->u.CHIL;
934       break;
935
936     default: goto fail;
937     }
938     break;
939
940   case irm_b:
941     switch (get_mode_modecode(m)) {
942     case irm_c: case irm_h: case irm_i: case irm_l:
943       tv->u.chil = src->u.b;
944       break;
945
946     case irm_C: case irm_H: case irm_I: case irm_L:
947       tv->u.CHIL = src->u.b;
948
949     default: goto fail;
950     }
951     break;
952
953   default:
954   fail:
955     obstack_free (&tv_obst, tv);
956     return NULL;
957   }
958
959   return tarval_identify (tv);
960 }
961
962
963 /* GL Why are there no ArmRoq comments, why is this not used? */
964 tarval *
965 tarval_neg (tarval *a)
966 {
967   tarval *tv;
968
969   TARVAL_VRFY (a);
970
971   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
972
973   tv->mode = a->mode;
974
975   switch (get_mode_modecode(a->mode)) {
976     /* floating */
977   case irm_f: tv->u.f = -a->u.f; break;
978   case irm_d: tv->u.d = -a->u.d; break;
979     /* unsigned */
980   case irm_C: case irm_H: case irm_I: case irm_L:
981     tv->u.CHIL = -a->u.CHIL & tv_val_CHIL (get_mode_max(a->mode));
982     break;
983     /* signed */
984   case irm_c: case irm_h: case irm_i: case irm_l:
985     tv->u.chil = -a->u.chil;
986     if (   chil_overflow (tv->u.chil, a->mode)
987         || ((tv->u.chil >= 0) == (a->u.chil >= 0))) {
988       obstack_free (&tv_obst, tv);
989       return NULL;
990     }
991     break;
992   case irm_Z:
993 #if _TARVAL_GMP_
994     mpz_init (&tv->u.Z);
995     mpz_neg (&tv->u.Z, &a->u.Z);
996 #else
997     obstack_free (&tv_obst, tv);
998     tv = a;
999     printf("\nWrong negation\n\n");
1000 #endif
1001     break;
1002     /* strange */
1003   case irm_b: tv->u.b = !a->u.b; break;
1004   default: assert(0);
1005   }
1006
1007   return tarval_identify (tv);
1008 }
1009
1010
1011 /* Compare `a' with `b'.
1012    Return one of irpn_Lt, irpn_Eq, irpn_Gt, irpn_Uo, or irpn_False if
1013    result is unknown.  */
1014 ir_pncmp
1015 tarval_comp (tarval *a, tarval *b)
1016 {
1017
1018   TARVAL_VRFY (a);
1019   TARVAL_VRFY (b);
1020
1021   assert (a->mode == b->mode);
1022
1023   switch (get_mode_modecode(a->mode)) {
1024     /* floating */
1025   case irm_f: return (  a->u.f == b->u.f ? irpn_Eq
1026                       : a->u.f > b->u.f ? irpn_Gt
1027                       : a->u.f < b->u.f ? irpn_Lt
1028                       : irpn_Uo);
1029   case irm_d: return (  a->u.d == b->u.d ? irpn_Eq
1030                       : a->u.d > b->u.d ? irpn_Gt
1031                       : a->u.d < b->u.d ? irpn_Lt
1032                       : irpn_Uo);
1033     /* unsigned */
1034   case irm_C: case irm_H: case irm_I: case irm_L:
1035     return (  a->u.CHIL == b->u.CHIL ? irpn_Eq
1036             : a->u.CHIL > b->u.CHIL ? irpn_Gt
1037             : irpn_Lt);
1038     /* signed */
1039   case irm_c: case irm_h: case irm_i: case irm_l:
1040     return (  a->u.chil == b->u.chil ? irpn_Eq
1041             : a->u.chil > b->u.chil ? irpn_Gt
1042             : irpn_Lt);
1043   case irm_Z:
1044     {
1045 #if _TARVAL_GMP_
1046       int cmp = mpz_cmp (&a->u.Z, &b->u.Z);
1047       return (  cmp == 0 ? irpn_Eq
1048               : cmp > 0 ? irpn_Gt
1049               : irpn_Lt);
1050 #else
1051       return irpn_False;
1052 #endif
1053     }
1054     /* strange */
1055   case irm_b: return (  a->u.b == b->u.b ? irpn_Eq
1056                       : a->u.b > b->u.b ? irpn_Gt
1057                       : irpn_Lt);
1058   /* The following assumes that pointers are unsigned, which is valid
1059      for all sane CPUs (transputers are insane). */
1060   case irm_p: return (  a == b ? irpn_Eq
1061                       : a == tarval_p_void ? irpn_Lt
1062                       : b == tarval_p_void ? irpn_Gt
1063                       : irpn_False); /* unknown */
1064   default: assert (0);
1065   }
1066 }
1067
1068
1069 /* Return `a+b' if computable, else NULL.  Modes must be equal.  */
1070 tarval *
1071 tarval_add (tarval *a, tarval *b)
1072 {
1073   tarval *tv;
1074
1075   TARVAL_VRFY (a); TARVAL_VRFY (b);
1076   assert (a->mode == b->mode);
1077
1078   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1079
1080   tv->mode = a->mode;
1081
1082   switch (get_mode_modecode(a->mode)) {
1083     /* floating */
1084   case irm_f: tv->u.f = a->u.f + b->u.f; break; /* @@@ overflow etc */
1085   case irm_d: tv->u.d = a->u.d + b->u.d; break; /* @@@ dto. */
1086     /* unsigned */
1087   case irm_C: case irm_H: case irm_I: case irm_L:
1088     tv->u.CHIL = (a->u.CHIL + b->u.CHIL) & tv_val_CHIL (get_mode_max(a->mode));
1089     break;
1090     /* signed */
1091   case irm_c: case irm_h: case irm_i: case irm_l:
1092     tv->u.chil = a->u.chil + b->u.chil;
1093     if (   chil_overflow (tv->u.chil, a->mode)
1094         || ((tv->u.chil > a->u.chil) ^ (b->u.chil > 0))) {
1095       obstack_free (&tv_obst, tv);
1096       return NULL;
1097     }
1098     break;
1099   case irm_Z:
1100 #if _TARVAL_GMP_
1101     mpz_init (&tv->u.Z);
1102     mpz_add (&tv->u.Z, &a->u.Z, &b->u.Z);
1103 #else
1104     obstack_free (&tv_obst, tv);
1105     return NULL;
1106 #endif
1107     break;
1108     /* strange */
1109   case irm_b: tv->u.b = a->u.b | b->u.b; break; /* u.b is in canonical form */
1110   default: assert(0);
1111   }
1112
1113   return tarval_identify (tv);
1114 }
1115
1116
1117 /* Return `a-b' if computable, else NULL.  Modes must be equal.  */
1118 tarval *
1119 tarval_sub (tarval *a, tarval *b)
1120 {
1121   tarval *tv;
1122
1123   TARVAL_VRFY (a); TARVAL_VRFY (b);
1124   assert (a->mode == b->mode);
1125
1126   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1127
1128   tv->mode = a->mode;
1129
1130   switch (get_mode_modecode(a->mode)) {
1131     /* floating */
1132   case irm_f: tv->u.f = a->u.f - b->u.f; break; /* @@@ overflow etc */
1133   case irm_d: tv->u.d = a->u.d - b->u.d; break; /* @@@ dto. */
1134     /* unsigned */
1135   case irm_C: case irm_H: case irm_I: case irm_L:
1136     tv->u.CHIL = (a->u.CHIL - b->u.CHIL) & tv_val_CHIL (get_mode_max(a->mode));
1137     break;
1138     /* signed */
1139   case irm_c: case irm_h: case irm_i: case irm_l:
1140     tv->u.chil = a->u.chil - b->u.chil;
1141     if (   chil_overflow (tv->u.chil, a->mode)
1142         || ((tv->u.chil > a->u.chil) ^ (b->u.chil < 0))) {
1143       obstack_free (&tv_obst, tv);
1144       return NULL;
1145     }
1146     break;
1147   case irm_Z:
1148 #if _TARVAL_GMP_
1149     mpz_init (&tv->u.Z);
1150     mpz_sub (&tv->u.Z, &a->u.Z, &b->u.Z);
1151 #else
1152     obstack_free (&tv_obst, tv);
1153     return NULL;
1154 #endif
1155     break;
1156     /* strange */
1157   case irm_b: tv->u.b = a->u.b & ~b->u.b; break; /* u.b is in canonical form */
1158   default: assert(0);
1159   }
1160
1161   return tarval_identify (tv);
1162 }
1163
1164 /* Return `a*b' if computable, else NULL.  Modes must be equal.  */
1165 tarval *
1166 tarval_mul (tarval *a, tarval *b)
1167 {
1168   tarval *tv;
1169
1170   TARVAL_VRFY (a); TARVAL_VRFY (b);
1171   assert (a->mode == b->mode);
1172
1173   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1174
1175   tv->mode = a->mode;
1176
1177   switch (get_mode_modecode(a->mode)) {
1178     /* floating */
1179   case irm_f: tv->u.f = a->u.f * b->u.f; break; /* @@@ overflow etc */
1180   case irm_d: tv->u.d = a->u.d * b->u.d; break; /* @@@ dto. */
1181     /* unsigned */
1182   case irm_C: case irm_H: case irm_I: case irm_L:
1183     tv->u.CHIL = (a->u.CHIL * b->u.CHIL) & tv_val_CHIL (get_mode_max(a->mode));
1184     break;
1185     /* signed */
1186   case irm_c: case irm_h: case irm_i: case irm_l:
1187     tv->u.chil = a->u.chil * b->u.chil;
1188     if (   chil_overflow (tv->u.chil, a->mode)
1189         || (b->u.chil && (tv->u.chil / b->u.chil != a->u.chil))) {
1190       obstack_free (&tv_obst, tv);
1191       return NULL;
1192     }
1193     break;
1194   case irm_Z:
1195 #if _TARVAL_GMP_
1196     mpz_init (&tv->u.Z);
1197     mpz_mul (&tv->u.Z, &a->u.Z, &b->u.Z);
1198 #else
1199     obstack_free (&tv_obst, tv);
1200     return NULL;
1201 #endif
1202     break;
1203     /* strange */
1204   case irm_b: tv->u.b = a->u.b & b->u.b; break; /* u.b is in canonical form */
1205   default: assert(0);
1206   }
1207
1208   return tarval_identify (tv);
1209 }
1210
1211
1212 /* Return floating-point `a/b' if computable, else NULL.
1213    Modes must be equal, non-floating-point operands are converted to irm_d.  */
1214 tarval *
1215 tarval_quo (tarval *a, tarval *b)
1216 {
1217   tarval *tv;
1218
1219   TARVAL_VRFY (a); TARVAL_VRFY (b);
1220   assert (a->mode == b->mode);
1221
1222   switch (get_mode_modecode(a->mode)) {
1223     /* floating */
1224   case irm_f:
1225     tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1226     tv->mode = mode_f;
1227     tv->u.f = a->u.f / b->u.f;  /* @@@ overflow etc */
1228     break;
1229   case irm_d:
1230     tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1231     tv->mode = mode_d;
1232     tv->u.d = a->u.d / b->u.d;  /* @@@ overflow etc */
1233     break;
1234   default:
1235     a = tarval_convert_to (a, mode_d);
1236     b = tarval_convert_to (b, mode_d);
1237     return a && b ? tarval_quo (a, b) : NULL;
1238   }
1239
1240   return tarval_identify (tv);
1241 }
1242
1243
1244 /* Return `a/b' if computable, else NULL.  Modes must be equal.  */
1245 tarval *
1246 tarval_div (tarval *a, tarval *b)
1247 {
1248   tarval *tv;
1249
1250   TARVAL_VRFY (a); TARVAL_VRFY (b);
1251   assert (a->mode == b->mode);
1252
1253   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1254
1255   tv->mode = a->mode;
1256
1257   switch (get_mode_modecode(a->mode)) {
1258     /* floating */
1259   case irm_f: tv->u.f = floor (a->u.f / b->u.f); break; /* @@@ overflow etc */
1260   case irm_d: tv->u.d = floor (a->u.d / b->u.d); break; /* @@@ dto. */
1261     /* unsigned */
1262   case irm_C: case irm_H: case irm_I: case irm_L:
1263     if (!b->u.CHIL) goto fail;
1264     tv->u.CHIL = a->u.CHIL / b->u.CHIL;
1265     break;
1266     /* signed */
1267   case irm_c: case irm_h: case irm_i: case irm_l:
1268     if (   !b->u.chil
1269         || ((b->u.chil == -1) && (a->u.chil == tv_val_chil (get_mode_max(a->mode)) ))) {
1270     fail:
1271       obstack_free (&tv_obst, tv);
1272       return NULL;
1273     }
1274     tv->u.chil = a->u.chil / b->u.chil;
1275     break;
1276   case irm_Z:
1277 #if _TARVAL_GMP_
1278     if (!mpz_cmp_ui (&b->u.Z, 0)) goto fail;
1279     mpz_init (&tv->u.Z);
1280     mpz_div (&tv->u.Z, &a->u.Z, &b->u.Z);
1281 #else
1282     goto fail;
1283 #endif
1284     break;
1285     /* strange */
1286   case irm_b: tv->u.b = a->u.b ^ b->u.b; break; /* u.b is in canonical form */
1287   default: assert(0);
1288   }
1289
1290   return tarval_identify (tv);
1291 }
1292
1293
1294 /* Return `a%b' if computable, else NULL.  Modes must be equal.  */
1295 tarval *
1296 tarval_mod (tarval *a, tarval *b)
1297 {
1298   tarval *tv;
1299
1300   TARVAL_VRFY (a); TARVAL_VRFY (b);
1301   assert (a->mode == b->mode);
1302
1303   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1304
1305   tv->mode = a->mode;
1306
1307   switch (get_mode_modecode(a->mode)) {
1308     /* floating */
1309   case irm_f: tv->u.f = fmod (a->u.f, b->u.f); break; /* @@@ overflow etc */
1310   case irm_d: tv->u.d = fmod (a->u.d, b->u.d); break; /* @@@ dto */
1311     /* unsigned */
1312   case irm_C: case irm_H: case irm_I: case irm_L:
1313     if (!b->u.CHIL) goto fail;
1314     tv->u.CHIL = a->u.CHIL % b->u.CHIL;
1315     break;
1316     /* signed */
1317   case irm_c: case irm_h: case irm_i: case irm_l:
1318     if (!b->u.chil) {
1319     fail:
1320       obstack_free (&tv_obst, tv);
1321       return NULL;
1322     }
1323     tv->u.chil = a->u.chil % b->u.chil;
1324     break;
1325   case irm_Z:
1326 #if _TARVAL_GMP_
1327     if (!mpz_cmp_ui (&b->u.Z, 0)) goto fail;
1328     mpz_init (&tv->u.Z);
1329     mpz_mod (&tv->u.Z, &a->u.Z, &b->u.Z);
1330 #else
1331     goto fail;
1332 #endif
1333     break;
1334     /* strange */
1335   case irm_b: tv->u.b = a->u.b ^ b->u.b; break; /* u.b is in canonical form */
1336   default: assert(0);
1337   }
1338
1339   return tarval_identify (tv);
1340 }
1341
1342 /* Return |a| if computable, else Null. */
1343 /*  is -max == min?? */
1344 tarval *
1345 tarval_abs (tarval *a) {
1346   TARVAL_VRFY (a);
1347   if (tv_is_negative(a)) return tarval_neg(a);
1348   return a;
1349 }
1350
1351 int
1352 tv_is_negative(tarval *a) {
1353   TARVAL_VRFY (a);
1354   switch (get_mode_modecode(a->mode)) {
1355     /* floating */
1356   case irm_f: return (a->u.f<0); break;
1357   case irm_d: return (a->u.d<0); break;
1358     /* unsigned */
1359   case irm_C: case irm_H: case irm_I: case irm_L:
1360     return 0;
1361     break;
1362     /* signed */
1363   case irm_c: case irm_h: case irm_i: case irm_l:
1364     return (a->u.chil < 0);
1365     break;
1366   case irm_Z:
1367     break;
1368   case irm_b: break;
1369   default: assert(0);
1370   }
1371
1372   return 0;
1373 }
1374
1375
1376 /* Return `a&b'.  Modes must be equal.  */
1377 tarval *
1378 tarval_and (tarval *a, tarval *b)
1379 {
1380   tarval *tv;
1381
1382   TARVAL_VRFY (a); TARVAL_VRFY (b);
1383   assert (a->mode == b->mode);
1384
1385   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1386
1387   tv->mode = a->mode;
1388
1389   switch (get_mode_modecode(a->mode)) {
1390     /* unsigned */
1391   case irm_C: case irm_H: case irm_I: case irm_L:
1392     tv->u.CHIL = a->u.CHIL & b->u.CHIL; break;
1393     /* signed */
1394   case irm_c: case irm_h: case irm_i: case irm_l:
1395     tv->u.chil = a->u.chil & b->u.chil; break;
1396   case irm_Z:
1397 #if _TARVAL_GMP_
1398     mpz_init (&tv->u.Z);
1399     mpz_and (&tv->u.Z, &a->u.Z, &b->u.Z);
1400 #else
1401     assert(0);
1402 #endif
1403     break;
1404     /* strange */
1405   case irm_b: tv->u.b = a->u.b & b->u.b; break; /* u.b is in canonical form */
1406   default: assert(0);
1407   }
1408
1409   return tarval_identify (tv);
1410 }
1411
1412
1413 /* Return `a|b'.  Modes must be equal.  */
1414 tarval *
1415 tarval_or (tarval *a, tarval *b)
1416 {
1417   tarval *tv;
1418
1419   TARVAL_VRFY (a); TARVAL_VRFY (b);
1420   assert (a->mode == b->mode);
1421
1422   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1423
1424   tv->mode = a->mode;
1425
1426   switch (get_mode_modecode(a->mode)) {
1427     /* unsigned */
1428   case irm_C: case irm_H: case irm_I: case irm_L:
1429     tv->u.CHIL = a->u.CHIL | b->u.CHIL; break;
1430     /* signed */
1431   case irm_c: case irm_h: case irm_i: case irm_l:
1432     tv->u.chil = a->u.chil | b->u.chil; break;
1433   case irm_Z:
1434 #if _TARVAL_GMP_
1435     mpz_init (&tv->u.Z);
1436     mpz_ior (&tv->u.Z, &a->u.Z, &b->u.Z);
1437 #else
1438     assert(0);
1439 #endif
1440     break;
1441     /* strange */
1442   case irm_b: tv->u.b = a->u.b | b->u.b; break; /* u.b is in canonical form */
1443   default: assert(0);
1444   }
1445
1446   return tarval_identify (tv);
1447 }
1448
1449
1450 /* Return `a^b'.  Modes must be equal.  */
1451 tarval *
1452 tarval_eor (tarval *a, tarval *b)
1453 {
1454   tarval *tv;
1455
1456   TARVAL_VRFY (a); TARVAL_VRFY (b);
1457   assert (a->mode == b->mode);
1458
1459 #if 1 /* see case irm_Z below */
1460   if (a->mode == mode_Z) return NULL;
1461 #endif
1462
1463   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1464
1465   tv->mode = a->mode;
1466
1467   switch (get_mode_modecode(a->mode)) {
1468     /* unsigned */
1469   case irm_C: case irm_H: case irm_I: case irm_L:
1470     tv->u.CHIL = a->u.CHIL ^ b->u.CHIL; break;
1471     /* signed */
1472   case irm_c: case irm_h: case irm_i: case irm_l:
1473     tv->u.chil = a->u.chil ^ b->u.chil; break;
1474   case irm_Z:
1475 #if 0
1476     /* gmp-1.3.2 declares but does not define mpz_xor() */
1477     mpz_init (&tv->u.Z);
1478     mpz_xor (&tv->u.Z, &a->u.Z, &b->u.Z);
1479 #endif
1480     break;
1481     /* strange */
1482   case irm_b: tv->u.b = a->u.b ^ b->u.b; break; /* u.b is in canonical form */
1483   default: assert(0);
1484   }
1485
1486   return tarval_identify (tv);
1487 }
1488
1489
1490 /* Return `a<<b' if computable, else NULL.  */
1491 tarval *
1492 tarval_shl (tarval *a, tarval *b)
1493 {
1494   int b_is_huge;
1495   long shift;
1496   tarval *tv;
1497
1498   TARVAL_VRFY (a); TARVAL_VRFY (b);
1499
1500   shift = tarval_ord (b, &b_is_huge);
1501   if (   b_is_huge
1502       || (shift < 0)
1503       || ((shift >= get_mode_size(mode_l)*target_bits) && (a->mode != mode_Z))) {
1504     return NULL;
1505   }
1506
1507   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1508   tv->mode = a->mode;
1509
1510   switch (get_mode_modecode(a->mode)) {
1511     /* unsigned */
1512   case irm_C: case irm_H: case irm_I: case irm_L:
1513     tv->u.CHIL = a->u.CHIL << shift;
1514     break;
1515     /* signed */
1516   case irm_c: case irm_h: case irm_i: case irm_l:
1517     tv->u.chil = a->u.chil << shift;
1518     break;
1519   case irm_Z:
1520 #if _TARVAL_GMP_
1521     mpz_init (&tv->u.Z);
1522     mpz_mul_2exp (&tv->u.Z, &a->u.Z, shift);
1523 #else
1524     assert(0);
1525 #endif
1526     break;
1527   default: assert (0);
1528   }
1529
1530   return tarval_identify (tv);
1531 }
1532
1533
1534 /* Return `a>>b' if computable, else NULL.
1535    The interpretation of >> (sign extended or not) is implementaion
1536    dependent, i.e. this is neither shr nor shrs!! */
1537 tarval *
1538 tarval_shr (tarval *a, tarval *b)
1539 {
1540   int b_is_huge;
1541   long shift;
1542   tarval *tv;
1543
1544   TARVAL_VRFY (a); TARVAL_VRFY (b);
1545
1546   shift = tarval_ord (b, &b_is_huge);
1547   if (   b_is_huge
1548       || (shift < 0)
1549       || ((shift >= get_mode_size(mode_l)*target_bits) && (a->mode != mode_Z))) {
1550     return NULL;
1551   }
1552
1553   tv = (tarval *)obstack_alloc (&tv_obst, sizeof (tarval));
1554   tv->mode = a->mode;
1555
1556   switch (get_mode_modecode(a->mode)) {
1557     /* unsigned */
1558   case irm_C: case irm_H: case irm_I: case irm_L:
1559     tv->u.CHIL = a->u.CHIL >> shift;
1560     break;
1561     /* signed */
1562   case irm_c: case irm_h: case irm_i: case irm_l:
1563     tv->u.chil = a->u.chil >> shift;
1564     break;
1565   case irm_Z:
1566 #if _TARVAL_GMP_
1567     mpz_init (&tv->u.Z);
1568     mpz_div_2exp (&tv->u.Z, &a->u.Z, shift);
1569 #else
1570     assert(0);
1571 #endif
1572     break;
1573   default: assert (0);
1574   }
1575
1576   return tarval_identify (tv);
1577 }
1578
1579
1580 /* Classify `tv', which may be NULL.
1581    Return 0 if `tv' is the additive neutral element, 1 if `tv' is the
1582    multiplicative neutral element, and -1 if `tv' is the neutral
1583    element of bitwise and.  */
1584 long
1585 tarval_classify (tarval *tv)
1586 {
1587   if (!tv) return 2;
1588
1589   TARVAL_VRFY (tv);
1590
1591   switch (get_mode_modecode(tv->mode)) {
1592     /* floating */
1593   case irm_f: case irm_d:
1594     return 2;
1595     /* unsigned */
1596   case irm_C:
1597     return (long)((tv->u.CHIL+1) & tv_val_CHIL (get_mode_max(mode_C))) - 1;
1598   case irm_H:
1599     return (long)((tv->u.CHIL+1) & tv_val_CHIL (get_mode_max(mode_H))) - 1;
1600   case irm_I:
1601     return (long)((tv->u.CHIL+1) & tv_val_CHIL (get_mode_max(mode_I))) - 1;
1602   case irm_L:
1603     return (long)((tv->u.CHIL+1) & tv_val_CHIL (get_mode_max(mode_L))) - 1;
1604     /* signed */
1605   case irm_c: case irm_h: case irm_i: case irm_l:
1606     return tv->u.chil;
1607   case irm_Z:
1608 #if _TARVAL_GMP_
1609     if      (mpz_cmp_si (&tv->u.Z, 0)) return 0;
1610     else if (mpz_cmp_si (&tv->u.Z, 1)) return 1;
1611     else if (mpz_cmp_si (&tv->u.Z,-1)) return -1;
1612 #endif
1613     return 2;
1614     /* strange */
1615   case irm_b:
1616     return tv->u.b;
1617   default:
1618     return 2;
1619   }
1620 }
1621
1622
1623 #if _TARVAL_GMP_
1624 bool
1625 tarval_s_fits (tarval *tv, long min, long max) {
1626   return ((  mpz_cmp_si (&tv->u.Z, min) >= 0)
1627           && mpz_cmp_si (&tv->u.Z, max) <= 0);
1628 }
1629
1630 bool
1631 tarval_u_fits (tarval *tv, unsigned long max) {
1632   return ((  mpz_sgn (&tv->u.Z) >= 0)
1633           && mpz_cmp_si (&tv->u.Z, max) <= 0);
1634 }
1635 #endif
1636
1637 /* Convert `tv' into type `long', set `fail' if not representable.
1638    If `fail' gets set for an unsigned `tv', the correct result can be
1639    obtained by casting the result to `unsigned long'.  */
1640 long
1641 tarval_ord (tarval *tv, int *fail)
1642 {
1643   TARVAL_VRFY (tv);
1644
1645   switch (get_mode_modecode(tv->mode)) {
1646     /* unsigned */
1647   case irm_C: case irm_H: case irm_I: case irm_L:
1648     *fail = tv->u.CHIL > tv_val_CHIL (get_mode_max(mode_l));
1649     return tv->u.CHIL;
1650     /* signed */
1651   case irm_c: case irm_h: case irm_i: case irm_l:
1652     *fail = 0;
1653     return tv->u.chil;
1654   case irm_Z:
1655 #if _TARVAL_GMP_
1656     *fail = (   (mpz_cmp_si (&tv->u.Z, tv_val_chil(get_mode_max(mode_l))) > 0)
1657              || (mpz_cmp_si (&tv->u.Z, tv_val_chil(get_mode_max(mode_l))) < 0));
1658     return mpz_get_si (&tv->u.Z);
1659 #else
1660     *fail = 1;
1661     return 0;
1662 #endif
1663     /* strange */
1664   case irm_b:
1665     *fail = 0;
1666     return tv->u.b;
1667   default: ;
1668     *fail = 1;
1669     return 0;
1670   }
1671 }
1672
1673 \f
1674 int
1675 tarval_print (XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN)
1676 {
1677   tarval *val = XP_GETARG (tarval *, 0);
1678   int printed;
1679   char buf[40];
1680
1681   TARVAL_VRFY (val);
1682
1683   switch (get_mode_modecode(val->mode)) {
1684
1685   case irm_T:                   /* none */
1686     printed = XPSR ("<bad>");
1687     break;
1688
1689   case irm_f:                   /* float */
1690     sprintf (buf, "%1.9e", (float)(val->u.f));
1691     printed = XPF1R ("%s", buf);
1692     break;
1693   case irm_d:                   /* double */
1694     printed = XPF1R ("%1.30g", (double)(val->u.d));
1695     break;
1696
1697   case irm_c:                   /* signed char */
1698   case irm_C:                   /* unsigned char */
1699     if (isprint (val->u.chil)) {
1700       printed = XPF1R ("'%c'", val->u.chil);
1701     } else {
1702       printed = XPF1R ("0x%x", (unsigned long)val->u.chil);
1703     }
1704     break;
1705
1706   case irm_h: case irm_i: case irm_l: /* signed num */
1707     printed = XPF1R ("%ld", (long)val->u.chil);
1708     break;
1709   case irm_H: case irm_I: case irm_L: /* unsigned num */
1710     printed = XPF1R ("%lu", (unsigned long)val->u.CHIL);
1711     break;
1712
1713   case irm_Z:                   /* mp int */
1714     printed = XPF1R ("%Z", &val->u.Z);
1715     break;
1716
1717   case irm_p:                   /* pointer */
1718     if (val->u.p.xname) {
1719       printed = XPR (val->u.p.xname);
1720     } else if (val->u.p.ent) {
1721       if (get_entity_peculiarity(val->u.p.ent) == existent)
1722         printed = XPF1R ("&(%I)", get_entity_ld_ident(val->u.p.ent));
1723       else
1724         printed = XPSR ("(NULL)");
1725     } else {
1726       assert (val == tarval_p_void);
1727       printed = XPSR ("(void)");
1728     }
1729     break;
1730
1731   case irm_b:                   /* boolean */
1732     if (val->u.b) printed = XPSR ("true");
1733     else          printed = XPSR ("false");
1734     break;
1735
1736   case irm_B:                   /* universal bits */
1737     printed = XPSR ("<@@@ some bits>");
1738     break;
1739
1740   case irm_s:                   /* string */
1741   case irm_S:
1742     { size_t i;
1743       char *buf = alloca (val->u.s.n + 2);
1744       char *bp;
1745
1746       printed = 0;
1747       buf[0] = '\'';
1748       bp = buf + 1;
1749       for (i = 0;  i < val->u.s.n;  ++i) {
1750         if (isprint (val->u.s.p[i])) {
1751           *bp++ = val->u.s.p[i];
1752         } else {
1753           if (bp != buf) {
1754             XPM (buf, bp-buf);
1755             bp = buf;
1756           }
1757           XPF1 ("'\\%03o'", val->u.s.p[i]);
1758         }
1759       }
1760       *bp++ = '\'';
1761       XPM (buf, bp-buf);
1762       break;
1763     }
1764
1765
1766   case irm_M:                   /* memory */
1767   case irm_R:                   /* region */
1768   default:
1769     assert (0);
1770   }
1771
1772   return printed;
1773 }
1774
1775
1776 ir_mode *
1777 get_tv_mode (tarval *tv)
1778 {
1779   return tv->mode;
1780 }
1781
1782
1783 entity *get_tv_entity(tarval *tv)
1784 {
1785   /*assert(??? && "not a pointer to an entity");*/
1786   return tv->u.p.ent;
1787 }