Added two new modes: mode_BAD the mode of tarval_bad and mode_ANY, the mode of tarval...
[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 /****i* tv/implementation
7  *
8  * AUTHORS
9  *    Christian von Roques
10  *    Matthias Heil
11  *
12  * NOTES
13  *    Internal storage for tarvals, 1st draft:
14  *   Integers as well as pointers are stored in a hex formatted string holding
15  *   16 characters. Booleans are not stored as there are only two of them.
16  *
17  *    Floats are just reinterpreted as byte strings, because I am not sure if
18  *   there is loss if I convert float to long double and back and furthermore
19  *   the implementation of a fully ieee compatible floating point emulation
20  *   is not sensible for now
21  *    With this information it is easy to decide the kind of stored value:
22  *   Integers have size 16, floats 4, doubles 8, long doubles 12.
23  ******/
24
25 /* This implementation assumes:
26    * both host and target have IEEE-754 floating-point arithmetic.  */
27
28 /* !!! float and double divides MUST NOT SIGNAL !!! */
29 /* @@@ query the floating-point expception status flags */
30
31 /* @@@ Problem: All Values are stored twice, once as Univ_*s and a 2nd
32    time in their real target mode. :-( */
33
34 #define MAX_INT_LENGTH 8
35 #define CHAR_BUFFER_SIZE ((MAX_INT_LENGTH) * 2)
36
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40
41 #include <assert.h>         /* assertions */
42 #include <stdlib.h>         /* atoi() */
43 #include <string.h>         /* nice things for strings */
44
45 #include <stdlib.h>
46 #include "tv_t.h"
47 #include "set.h"            /* to store tarvals in */
48 #include "tune.h"           /* some constants */
49 #include "entity_t.h"       /* needed to store pointers to entities */
50 #include "irmode.h"         /* defines modes etc */
51 #include "irmode_t.h"
52 #include "irnode.h"         /* defines boolean return values */
53 #include "host.h"
54 #include "strcalc.h"
55 #include "fltcalc.h"
56
57 /****************************************************************************
58  *   local definitions and macros
59  ****************************************************************************/
60 #ifndef NDEBUG
61 #  define TARVAL_VERIFY(a) tarval_verify((a))
62 #else
63 #  define TARVAL_VERIFY(a) ((void)0)
64 #endif
65
66 #define INSERT_TARVAL(tv) ((tarval*)set_insert(tarvals, (tv), sizeof(tarval), hash_tv((tv))))
67 #define FIND_TARVAL(tv) ((tarval*)set_find(tarvals, (tv), sizeof(tarval), hash_tv((tv))))
68
69 #define INSERT_VALUE(val, size) (set_insert(values, (val), size, hash_val((val), size)))
70 #define FIND_VALUE(val, size) (set_find(values, (val), size, hash_val((val), size)))
71
72 #define fail_verify(a) _fail_verify((a), __FILE__, __LINE__)
73 #if 0
74 static long long count = 0;
75 #  define ANNOUNCE() printf(__FILE__": call no. %lld (%s)\n", count++, __FUNCTION__);
76 #else
77 #  define ANNOUNCE() ((void)0)
78 #endif
79 /****************************************************************************
80  *   private variables
81  ****************************************************************************/
82 static struct set *tarvals;   /* container for tarval structs */
83 static struct set *values;    /* container for values */
84
85 /****************************************************************************
86  *   private functions
87  ****************************************************************************/
88 #ifndef NDEBUG
89 static int hash_val(const void *value, unsigned int length);
90 static int hash_tv(tarval *tv);
91 static void _fail_verify(tarval *tv, const char* file, int line)
92 {
93   /* print a memory image of the tarval and throw an assertion */
94   if (tv)
95     printf("%s:%d: Invalid tarval:\n  mode: %s\n value: [%p]\n", file, line, get_mode_name(tv->mode), tv->value);
96   else
97     printf("%s:%d: Invalid tarval (null)", file, line);
98   assert(0);
99 }
100
101 inline static void tarval_verify(tarval *tv)
102 {
103   assert(tv);
104   assert(tv->mode);
105   assert(tv->value);
106
107   if ((tv == tarval_bad) || (tv == tarval_undefined)) return;
108   if ((tv == tarval_b_true) || (tv == tarval_b_false)) return;
109
110   if (!FIND_TARVAL(tv)) fail_verify(tv);
111   if (tv->length > 0 && !FIND_VALUE(tv->value, tv->length)) fail_verify(tv);
112
113   return;
114 }
115 #endif /* NDEBUG */
116
117 static int hash_tv(tarval *tv)
118 {
119   return ((unsigned int)tv->value ^ (unsigned int)tv->mode) + tv->length;
120 }
121
122 static int hash_val(const void *value, unsigned int length)
123 {
124   unsigned int i;
125   unsigned int hash = 0;
126
127   /* scramble the byte - array */
128   for (i = 0; i < length; i++)
129   {
130     hash += (hash << 5) ^ (hash >> 27) ^ ((char*)value)[i];
131     hash += (hash << 11) ^ (hash >> 17);
132   }
133
134   return hash;
135 }
136
137 /* finds tarval with value/mode or creates new tarval */
138 static tarval *get_tarval(const void *value, int length, ir_mode *mode)
139 {
140   tarval tv;
141
142   tv.mode = mode;
143   tv.length = length;
144   if (length > 0)
145     /* if there already is such a value, it is returned, else value
146      * is copied into the set */
147     tv.value = INSERT_VALUE(value, length);
148   else
149     tv.value = value;
150
151   /* if there is such a tarval, it is returned, else tv is copied
152    * into the set */
153   return (tarval *)INSERT_TARVAL(&tv);
154 }
155
156 /**
157  * Returns non-zero if a tarval overflows.
158  *
159  * @todo Implementation did not work on all modes
160  */
161 static int overflows(tarval *tv)
162 {
163   switch (get_mode_sort(tv->mode))
164   {
165     case irms_character:
166     case irms_int_number:
167       if (sc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1;
168       if (sc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1;
169       break;
170
171     case irms_float_number:
172       /*
173        * TODO: check NaNs
174        */
175       if (fc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1;
176       if (fc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1;
177       break;
178
179     default:
180       break;
181   }
182
183   return 0;
184 }
185
186 /*
187  *   public variables declared in tv.h
188  */
189 tarval *tarval_bad;
190 tarval *tarval_undefined;
191 tarval *tarval_b_false;
192 tarval *tarval_b_true;
193 tarval *tarval_P_void;
194
195 /*
196  *   public functions declared in tv.h
197  */
198
199 /*
200  * Constructors =============================================================
201  */
202 tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
203 {
204   ANNOUNCE();
205   assert(str);
206   assert(len);
207   assert(mode);
208
209   switch (get_mode_sort(mode))
210   {
211     case irms_auxiliary:
212       assert(0);
213       break;
214
215     case irms_internal_boolean:
216       /* match tTrRuUeE/fFaAlLsSeE */
217       if (strcasecmp(str, "true")) return tarval_b_true;
218       else if (strcasecmp(str, "false")) return tarval_b_true;
219       else
220         return atoi(str) ? tarval_b_true : tarval_b_false;
221
222     case irms_float_number:
223       fc_val_from_str(str, len);
224       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
225
226     case irms_int_number:
227     case irms_character:
228       sc_val_from_str(str, len);
229       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
230
231     case irms_reference:
232       return get_tarval(str, len, mode);
233   }
234
235   assert(0);  /* can't be reached, can it? */
236   return NULL;
237 }
238
239 #if 0
240 int tarval_is_str(tarval *tv)
241 {
242   ANNOUNCE();
243   assert(tv);
244
245   return ((get_mode_sort(tv->mode) == reference) && (tv->value != NULL) && (tv->length > 0));
246 }
247 char *tarval_to_str(tarval *tv)
248 {
249   ANNOUNCE();
250   assert(tarval_is_str(tv));
251   return (char *)tv->value;
252 }
253 #endif
254
255 /*
256  * helper function, create a tarval from long
257  */
258 tarval *new_tarval_from_long(long l, ir_mode *mode)
259 {
260   ANNOUNCE();
261   assert(mode && !(get_mode_sort(mode) == irms_auxiliary));
262
263   switch(get_mode_sort(mode))
264   {
265     case irms_internal_boolean:
266       /* XXX C-Semantics ! */
267       return l ? tarval_b_true : tarval_b_false ;
268
269     case irms_int_number:
270     case irms_character:
271       sc_val_from_long(l);
272       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
273
274     case irms_float_number:
275       return new_tarval_from_double((long double)l, mode);
276
277     case irms_reference:
278       return l ? tarval_bad : get_tarval(NULL, 0, mode);  /* null pointer or tarval_bad */
279
280     default:
281       assert(0);
282   }
283   return NULL;
284 }
285
286 /* returns non-zero if can be converted to long */
287 int tarval_is_long(tarval *tv)
288 {
289   ANNOUNCE();
290   return ((get_mode_sort(tv->mode) == irms_int_number) || (get_mode_sort(tv->mode) == irms_character));
291 }
292
293 /* this might overflow the machine's long, so use only with small values */
294 long tarval_to_long(tarval* tv)
295 {
296   ANNOUNCE();
297   assert(tv && get_mode_sort(tv->mode) == irms_int_number);
298
299   return sc_val_to_long(tv->value); /* might overflow */
300 }
301
302 tarval *new_tarval_from_double(long double d, ir_mode *mode)
303 {
304   ANNOUNCE();
305   assert(mode && (get_mode_sort(mode) == irms_float_number));
306
307   fc_val_from_float(d);
308   return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
309 }
310
311 /* returns non-zero if can be converted to double */
312 int tarval_is_double(tarval *tv)
313 {
314   ANNOUNCE();
315   assert(tv);
316
317   return (get_mode_sort(tv->mode) == irms_float_number);
318 }
319
320 long double tarval_to_double(tarval *tv)
321 {
322   ANNOUNCE();
323   assert(tarval_is_double(tv));
324
325   return fc_val_to_float(tv->value);
326 }
327
328 /* The tarval represents the address of the entity.  As the address must
329    be constant the entity must have as owner the global type. */
330 tarval *new_tarval_from_entity (entity *ent, ir_mode *mode)
331 {
332   ANNOUNCE();
333   assert(ent);
334   assert(mode && (get_mode_sort(mode) == irms_reference));
335
336   return get_tarval((void *)ent, 0, mode);
337 }
338 int tarval_is_entity(tarval *tv)
339 {
340   ANNOUNCE();
341   assert(tv);
342   /* tv->value == NULL means dereferencing a null pointer */
343   return ((get_mode_sort(tv->mode) == irms_reference) && (tv->value != NULL) && (tv->length == 0));
344 }
345
346 entity *tarval_to_entity(tarval *tv)
347 {
348   ANNOUNCE();
349   assert(tv);
350
351   if (tarval_is_entity(tv))
352     return (entity *)tv->value;
353   else {
354     assert(0 && "tarval did not represent an entity");
355     return NULL;
356   }
357 }
358
359 void free_tarval_entity(entity *ent) {
360   /* There can be a tarval referencing this entity.  Even if the
361      tarval is not used by the code any more, it can still reference
362      the entity as tarvals live indepently of the entity referenced.
363      Further the tarval is hashed into a set. If a hash function
364      evaluation happens to collide with this tarval, we will vrfy that
365      it contains a proper entity and we will crash if the entity is
366      freed.
367
368      Unluckily, tarvals can neither be changed nor deleted, and to find
369      one, all existing reference modes have to be tried -> a facility
370      to retrieve all modes of a kind is needed. */
371   ANNOUNCE();
372 }
373
374 /*
375  * Access routines for tarval fields ========================================
376  */
377 ir_mode *get_tarval_mode (tarval *tv)       /* get the mode of the tarval */
378 {
379   ANNOUNCE();
380   assert(tv);
381   return tv->mode;
382 }
383
384 /*
385  * Special value query functions ============================================
386  *
387  * These functions calculate and return a tarval representing the requested
388  * value.
389  * The functions get_mode_{Max,Min,...} return tarvals retrieved from these
390  * functions, but these are stored on initialization of the irmode module and
391  * therefore the irmode functions should be prefered to the functions below.
392  */
393
394 tarval *get_tarval_bad(void)
395 {
396   ANNOUNCE();
397   return tarval_bad;
398 }
399 tarval *get_tarval_undefined(void)
400 {
401   ANNOUNCE();
402   return tarval_undefined;
403 }
404 tarval *get_tarval_b_false(void)
405 {
406   ANNOUNCE();
407   return tarval_b_false;
408 }
409 tarval *get_tarval_b_true(void)
410 {
411   ANNOUNCE();
412   return tarval_b_true;
413 }
414 tarval *get_tarval_P_void(void)
415 {
416   ANNOUNCE();
417   return tarval_P_void;
418 }
419
420 tarval *get_tarval_max(ir_mode *mode)
421 {
422   ANNOUNCE();
423   assert(mode);
424
425   switch(get_mode_sort(mode))
426   {
427     case irms_reference:
428     case irms_auxiliary:
429       assert(0);
430       break;
431
432     case irms_internal_boolean:
433       return tarval_b_true;
434
435     case irms_float_number:
436       fc_get_max(get_mode_size_bits(mode));
437       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
438
439     case irms_int_number:
440     case irms_character:
441       sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(mode));
442       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
443   }
444   return tarval_bad;
445 }
446
447 tarval *get_tarval_min(ir_mode *mode)
448 {
449   ANNOUNCE();
450   assert(mode);
451
452   switch(get_mode_sort(mode))
453   {
454     case irms_reference:
455     case irms_auxiliary:
456       assert(0);
457       break;
458
459     case irms_internal_boolean:
460       return tarval_b_false;
461
462     case irms_float_number:
463       fc_get_min(get_mode_size_bits(mode));
464       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
465
466     case irms_int_number:
467     case irms_character:
468       sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(mode));
469       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
470   }
471   return tarval_bad;
472 }
473
474 tarval *get_tarval_null(ir_mode *mode)
475 {
476   ANNOUNCE();
477   assert(mode);
478
479   switch(get_mode_sort(mode))
480   {
481     case irms_auxiliary:
482     case irms_internal_boolean:
483       assert(0);
484       break;
485
486     case irms_float_number:
487       return new_tarval_from_double(0.0, mode);
488
489     case irms_int_number:
490     case irms_character:
491       return new_tarval_from_long(0l,  mode);
492
493     case irms_reference:
494       return tarval_P_void;
495   }
496   return tarval_bad;
497 }
498
499 tarval *get_tarval_one(ir_mode *mode)
500 {
501   ANNOUNCE();
502   assert(mode);
503
504   switch(get_mode_sort(mode))
505   {
506     case irms_auxiliary:
507     case irms_internal_boolean:
508     case irms_reference:
509       assert(0);
510       break;
511
512     case irms_float_number:
513       return new_tarval_from_double(1.0, mode);
514
515     case irms_int_number:
516     case irms_character:
517       return new_tarval_from_long(1l, mode);
518       break;
519   }
520   return tarval_bad;
521 }
522
523 tarval *get_tarval_nan(ir_mode *mode)
524 {
525   ANNOUNCE();
526   assert(mode);
527
528   if (get_mode_sort(mode) == irms_float_number) {
529     fc_get_nan();
530     return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
531   }
532   else {
533     assert(0 && "tarval is not floating point");
534     return tarval_bad;
535   }
536 }
537
538 tarval *get_tarval_inf(ir_mode *mode)
539 {
540   ANNOUNCE();
541   assert(mode);
542
543   if (get_mode_sort(mode) == irms_float_number) {
544     fc_get_inf();
545     return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
546   }
547   else {
548     assert(0 && "tarval is not floating point");
549     return tarval_bad;
550   }
551 }
552
553 /*
554  * Arithmethic operations on tarvals ========================================
555  */
556
557 /*
558  * test if negative number, 1 means 'yes'
559  */
560 int tarval_is_negative(tarval *a)
561 {
562   ANNOUNCE();
563   assert(a);
564
565   switch (get_mode_sort(a->mode))
566   {
567     case irms_int_number:
568       if (!mode_is_signed(a->mode)) return 0;
569       else
570         return sc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
571
572     case irms_float_number:
573       return fc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
574
575     default:
576       assert(0 && "not implemented");
577       return 0;
578   }
579 }
580
581 /*
582  * test if null, 1 means 'yes'
583  */
584 int tarval_is_null(tarval *a)
585 {
586   ir_mode *m = get_tarval_mode(a);
587
588   return a == get_tarval_null(m);
589 }
590
591 /*
592  * comparison
593  */
594 pnc_number tarval_cmp(tarval *a, tarval *b)
595 {
596   ANNOUNCE();
597   assert(a);
598   assert(b);
599
600   if (a == tarval_bad || b == tarval_bad) assert(0 && "Comparison with tarval_bad");
601   if (a == tarval_undefined || b == tarval_undefined) return False;
602   if (a == b) return Eq;
603   if (get_tarval_mode(a) != get_tarval_mode(b)) return Uo;
604
605   /* Here the two tarvals are unequal and of the same mode */
606   switch (get_mode_sort(a->mode))
607   {
608     case irms_auxiliary:
609       return False;
610
611     case irms_float_number:
612       return (fc_comp(a->value, b->value)==1)?(Gt):(Lt);
613
614     case irms_int_number:
615     case irms_character:
616       return (sc_comp(a->value, b->value)==1)?(Gt):(Lt);
617
618     case irms_internal_boolean:
619       return (a == tarval_b_true)?(Gt):(Lt);
620
621     case irms_reference:
622       return Uo;
623   }
624   return False;
625 }
626
627 /*
628  * convert to other mode
629  */
630 tarval *tarval_convert_to(tarval *src, ir_mode *m)
631 {
632   ANNOUNCE();
633   tarval tv;
634
635   assert(src);
636   assert(m);
637
638   if (src->mode == m) return src;
639
640   switch (get_mode_sort(src->mode))
641   {
642     case irms_auxiliary:
643       break;
644
645     case irms_float_number:
646       switch (get_mode_sort(m)) {
647         case irms_float_number:
648           tv.mode   = m;
649           tv.length = src->length;
650           tv.value  = src->value;
651           if (overflows(&tv)) {
652             return tarval_bad;
653           }
654
655           return INSERT_TARVAL(&tv);
656
657         default:
658           break;
659       }
660       break;
661
662     case irms_int_number:
663       switch (get_mode_sort(m)) {
664         case irms_int_number:
665         case irms_character:
666           tv.mode   = m;
667           tv.length = src->length;
668           tv.value  = src->value;
669           if (overflows(&tv))
670             return tarval_bad;
671
672           return INSERT_TARVAL(&tv);
673
674         case irms_internal_boolean:
675           /* XXX C semantics */
676           if (src == get_mode_null(src->mode)) return tarval_b_false;
677           else return tarval_b_true;
678
679         default:
680           break;
681       }
682       break;
683
684     case irms_internal_boolean:
685       switch (get_mode_sort(m))
686       {
687         case irms_int_number:
688           if (src == tarval_b_true) return get_mode_one(m);
689           else return get_mode_null(m);
690
691         default:
692           break;
693       }
694       break;
695
696     case irms_character:
697       break;
698     case irms_reference:
699       break;
700   }
701
702   return tarval_bad;
703 }
704
705 /*
706  * negation
707  */
708 tarval *tarval_neg(tarval *a)
709 {
710   ANNOUNCE();
711   assert(a);
712   assert(mode_is_num(a->mode)); /* negation only for numerical values */
713   assert(mode_is_signed(a->mode)); /* negation is difficult without negative numbers, isn't it */
714
715   switch (get_mode_sort(a->mode))
716   {
717     case irms_int_number:
718       sc_neg(a->value);
719       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
720
721     case irms_float_number:
722       fc_neg(a->value);
723       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
724
725     default:
726       return tarval_bad;
727   }
728 }
729
730 /*
731  * addition
732  */
733 tarval *tarval_add(tarval *a, tarval *b)
734 {
735   ANNOUNCE();
736   assert(a);
737   assert(b);
738   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
739
740   switch (get_mode_sort(a->mode))
741   {
742     case irms_character:
743     case irms_int_number:
744       /* modes of a,b are equal, so result has mode of a as this might be the character */
745       sc_add(a->value, b->value);
746       /* FIXME: Check for overflow */
747       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
748
749     case irms_float_number:
750       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
751       fc_add(a->value, b->value);
752       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
753
754     default:
755       return tarval_bad;
756   }
757 }
758
759 /*
760  * subtraction
761  */
762 tarval *tarval_sub(tarval *a, tarval *b)
763 {
764   ANNOUNCE();
765   assert(a);
766   assert(b);
767   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
768
769   switch (get_mode_sort(a->mode))
770   {
771     case irms_character:
772     case irms_int_number:
773       /* modes of a,b are equal, so result has mode of a as this might be the character */
774       sc_sub(a->value, b->value);
775       /* FIXME: check for overflow */
776       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
777
778     case irms_float_number:
779       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
780       fc_add(a->value, b->value);
781       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
782
783     default:
784       return tarval_bad;
785   }
786 }
787
788 /*
789  * multiplication
790  */
791 tarval *tarval_mul(tarval *a, tarval *b)
792 {
793   ANNOUNCE();
794   assert(a);
795   assert(b);
796   assert((a->mode == b->mode) && mode_is_num(a->mode));
797
798   switch (get_mode_sort(a->mode))
799   {
800     case irms_int_number:
801       /* modes of a,b are equal */
802       sc_mul(a->value, b->value);
803       /* FIXME: check for overflow */
804       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
805
806     case irms_float_number:
807       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
808       fc_add(a->value, b->value);
809       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
810
811     default:
812       return tarval_bad;
813   }
814 }
815
816 /*
817  * floating point division
818  */
819 tarval *tarval_quo(tarval *a, tarval *b)
820 {
821   ANNOUNCE();
822   assert(a);
823   assert(b);
824   assert((a->mode == b->mode) && mode_is_float(a->mode));
825
826   /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
827   fc_div(a->value, b->value);
828   return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
829 }
830
831 /*
832  * integer division
833  */
834 tarval *tarval_div(tarval *a, tarval *b)
835 {
836   ANNOUNCE();
837   assert(a);
838   assert(b);
839   assert((a->mode == b->mode) && mode_is_int(a->mode));
840
841   /* modes of a,b are equal */
842   sc_div(a->value, b->value);
843   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
844 }
845
846 /*
847  * remainder
848  */
849 tarval *tarval_mod(tarval *a, tarval *b)
850 {
851   ANNOUNCE();
852   assert(a);
853   assert(b);
854   assert((a->mode == b->mode) && mode_is_int(a->mode));
855
856   /* modes of a,b are equal */
857   sc_mod(a->value, b->value);
858   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
859 }
860
861 /*
862  * absolute value
863  */
864 tarval *tarval_abs(tarval *a)
865 {
866   ANNOUNCE();
867   assert(a);
868   assert(mode_is_num(a->mode));
869
870   switch (get_mode_sort(a->mode))
871   {
872     case irms_int_number:
873       if (sc_comp(a->value, get_mode_null(a->mode)->value) == -1)
874       {
875         sc_neg(a->value);
876         return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
877       }
878       return a;
879
880     case irms_float_number:
881       break;
882
883     default:
884       return tarval_bad;
885   }
886   return tarval_bad;
887 }
888
889 /*
890  * bitwise and
891  */
892 tarval *tarval_and(tarval *a, tarval *b)
893 {
894   ANNOUNCE();
895   assert(a);
896   assert(b);
897   assert(a->mode == b->mode);
898
899   /* GL: needed for easy optimization. */
900   if (a->mode == mode_b) return (a == tarval_b_false) ? a : b;
901
902   assert(mode_is_int(a->mode));
903
904   sc_and(a->value, b->value);
905   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
906 }
907
908 /*
909  * bitwise or
910  */
911 tarval *tarval_or (tarval *a, tarval *b)
912 {
913   ANNOUNCE();
914   assert(a);
915   assert(b);
916   assert(a->mode == b->mode);
917
918   /* GL: needed for easy optimization. */
919   if (a->mode == mode_b) return (a == tarval_b_true) ? a : b;
920
921
922   assert(mode_is_int(a->mode));
923
924   sc_or(a->value, b->value);
925   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
926 }
927
928 /*
929  * bitwise exclusive or (xor)
930  */
931 tarval *tarval_eor(tarval *a, tarval *b)
932 {
933   ANNOUNCE();
934   assert(a);
935   assert(b);
936   assert((a->mode == b->mode) && mode_is_int(a->mode));
937
938   sc_or(a->value, b->value);
939   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
940 }
941
942 /*
943  * bitwise left shift
944  */
945 tarval *tarval_shl(tarval *a, tarval *b)
946 {
947   ANNOUNCE();
948   assert(a);
949   assert(b);
950   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
951
952   sc_shl(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
953   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
954 }
955
956 /*
957  * bitwise unsigned right shift
958  */
959 tarval *tarval_shr(tarval *a, tarval *b)
960 {
961   ANNOUNCE();
962   assert(a);
963   assert(b);
964   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
965
966   sc_shr(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
967   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
968 }
969
970 /*
971  * bitwise signed right shift
972  */
973 tarval *tarval_shrs(tarval *a, tarval *b)
974 {
975   ANNOUNCE();
976   assert(a);
977   assert(b);
978   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
979
980   sc_shrs(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
981   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
982 }
983
984 /*
985  * bitwise rotation
986  */
987 tarval *tarval_rot(tarval *a, tarval *b)
988 {
989   ANNOUNCE();
990   assert(a);
991   assert(b);
992   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
993
994   sc_rot(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
995   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
996 }
997
998
999 /*
1000  * Output of tarvals
1001  */
1002 int tarval_snprintf(char *buf, size_t len, tarval *tv)
1003 {
1004   static const tarval_mode_info default_info = { TVO_NATIVE, NULL, NULL };
1005
1006   const char *str;
1007   char tv_buf[100];
1008   const tarval_mode_info *mode_info;
1009   const char *prefix, *suffix;
1010
1011   ANNOUNCE();
1012
1013   mode_info = tv->mode->tv_priv;
1014   if (! mode_info)
1015     mode_info = &default_info;
1016   prefix = mode_info->mode_prefix ? mode_info->mode_prefix : "";
1017   suffix = mode_info->mode_suffix ? mode_info->mode_suffix : "";
1018
1019   switch (get_mode_sort(tv->mode))
1020   {
1021     case irms_int_number:
1022     case irms_character:
1023       switch (mode_info->mode_output) {
1024
1025       case TVO_DECIMAL:
1026         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC);
1027         break;
1028
1029       case TVO_OCTAL:
1030         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT);
1031         break;
1032
1033       case TVO_HEX:
1034       case TVO_NATIVE:
1035       default:
1036         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX);
1037         break;
1038       }
1039       return snprintf(buf, len, "%s%s%s", prefix, str, suffix);
1040
1041     case irms_float_number:
1042       return snprintf(buf, len, "%s%s%s", prefix, fc_print_dec(tv->value, tv_buf, sizeof(tv_buf)), suffix);
1043
1044     case irms_reference:
1045       if (tv->value != NULL)
1046         if (tarval_is_entity(tv)) {
1047           if (get_entity_peculiarity((entity *)tv->value) == existent)
1048             return snprintf(buf, len, "%s%s%s", prefix, get_entity_ld_name((entity *)tv->value), suffix);
1049           else {
1050             if (mode_info->mode_output == TVO_NATIVE)
1051               return snprintf(buf, len, "NULL");
1052             else
1053               return snprintf(buf, len, "0");
1054           }
1055         }
1056         else {
1057           if (size > tv->length) {
1058             memcpy(buf, tv->value, tv->length);
1059             buf[tv->length] = '\0';
1060           }
1061           else {
1062             /* truncated */
1063             memcpy(buf, tv->value, size-1);
1064             buf[size-1] = '\0';
1065           }
1066           return tv->length;
1067         }
1068       else
1069         return snprintf(buf, len, "void");
1070
1071     case irms_internal_boolean:
1072       switch (mode_info->mode_output) {
1073
1074       case TVO_DECIMAL:
1075       case TVO_OCTAL:
1076       case TVO_HEX:
1077       case TVO_BINARY:
1078         return snprintf(buf, len, "%s%c%s", prefix, (tv == tarval_b_true) ? '1' : '0', suffix);
1079
1080       case TVO_NATIVE:
1081       default:
1082         return snprintf(buf, len, "%s%s%s", prefix, (tv == tarval_b_true) ? "true" : "false", suffix);
1083       }
1084
1085     case irms_auxiliary:
1086       return snprintf(buf, len, "<BAD>");
1087   }
1088
1089   return 0;
1090 }
1091
1092
1093 /**
1094  * Output of tarvals to stdio.
1095  */
1096 int tarval_printf(tarval *tv) {
1097   char buf[1024];
1098   int res;
1099
1100   res = tarval_snprintf(buf, sizeof(buf), tv);
1101   assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
1102   printf(buf);
1103   return res;
1104 }
1105
1106
1107 char *tarval_bitpattern(tarval *tv)
1108 {
1109   return NULL;
1110 }
1111
1112 /*
1113  * access to the bitpattern
1114  */
1115 unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs)
1116 {
1117   switch (get_mode_sort(tv->mode)) {
1118     case irms_int_number:
1119     case irms_character:
1120       return sc_sub_bits(tv->value, tv->length, byte_ofs);
1121
1122     case irms_float_number:
1123       return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs);
1124
1125     default:
1126       return 0;
1127   }
1128 }
1129
1130 /*
1131  * Specify the output options of one mode.
1132  *
1133  * This functions stores the modinfo, so DO NOT DESTROY it.
1134  *
1135  * Returns zero on success.
1136  */
1137 int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo)
1138 {
1139   assert(mode);
1140
1141   mode->tv_priv = modeinfo;
1142   return 0;
1143 }
1144
1145 /* Identifying some tarvals ??? */
1146 /* Implemented in old tv.c as such:
1147  *   return 0 for additive neutral,
1148  *   1 for multiplicative neutral,
1149  *   -1 for bitwise-and neutral
1150  *   2 else
1151  *
1152  * Implemented for completeness */
1153 long tarval_classify(tarval *tv)
1154 {
1155   ANNOUNCE();
1156   if (!tv || tv == tarval_bad) return 2;
1157
1158   if (tv == get_mode_null(tv->mode)) return 0;
1159   else if (tv == get_mode_one(tv->mode)) return 1;
1160   else if ((get_mode_sort(tv->mode) == irms_int_number)
1161            && (tv == new_tarval_from_long(-1, tv->mode))) return -1;
1162
1163   return 2;
1164 }
1165
1166 /*
1167  * Initialization of the tarval module: called before init_mode()
1168  */
1169 void init_tarval_1(void)
1170 {
1171   ANNOUNCE();
1172   /* initialize the sets holding the tarvals with a comparison function and
1173    * an initial size, which is the expected number of constants */
1174   tarvals = new_set(memcmp, TUNE_NCONSTANTS);
1175   values = new_set(memcmp, TUNE_NCONSTANTS);
1176   /* init with default precision */
1177   init_strcalc(0);
1178   /* init_fltcalc(0); not yet*/
1179 }
1180
1181 /**
1182  * default mode_info for output as HEX
1183  */
1184 static const tarval_mode_info hex_output = {
1185   TVO_HEX,
1186   "0x",
1187   NULL,
1188 };
1189
1190 /**
1191  * default mode_info for output as reference
1192  */
1193 static const tarval_mode_info reference_output = {
1194   TVO_NATIVE,
1195   "&(",
1196   ")",
1197 };
1198
1199
1200 /*
1201  * Initialization of the tarval module: called after init_mode()
1202  */
1203 void init_tarval_2(void)
1204 {
1205   ANNOUNCE();
1206
1207   tarval_bad = (tarval*)malloc(sizeof(tarval));
1208   tarval_bad->mode = mode_BAD;
1209
1210   tarval_undefined = (tarval*)malloc(sizeof(tarval));
1211   tarval_undefined->mode = mode_ANY;
1212
1213   tarval_b_true = (tarval*)malloc(sizeof(tarval));
1214   tarval_b_true->mode = mode_b;
1215
1216   tarval_b_false = (tarval*)malloc(sizeof(tarval));
1217   tarval_b_false->mode = mode_b;
1218
1219   tarval_P_void = (tarval*)malloc(sizeof(tarval));
1220   tarval_P_void->mode = mode_P;
1221
1222   /*
1223    * assign output modes that are compatible with the
1224    * old implementation: Hex output
1225    */
1226   tarval_set_mode_output_option(mode_U,  &hex_output);
1227   tarval_set_mode_output_option(mode_C,  &hex_output);
1228   tarval_set_mode_output_option(mode_Bs, &hex_output);
1229   tarval_set_mode_output_option(mode_Bu, &hex_output);
1230   tarval_set_mode_output_option(mode_Hs, &hex_output);
1231   tarval_set_mode_output_option(mode_Hu, &hex_output);
1232   tarval_set_mode_output_option(mode_Hs, &hex_output);
1233   tarval_set_mode_output_option(mode_Hu, &hex_output);
1234   tarval_set_mode_output_option(mode_Is, &hex_output);
1235   tarval_set_mode_output_option(mode_Iu, &hex_output);
1236   tarval_set_mode_output_option(mode_Ls, &hex_output);
1237   tarval_set_mode_output_option(mode_Lu, &hex_output);
1238   tarval_set_mode_output_option(mode_P,  &reference_output);
1239 }
1240
1241 /****************************************************************************
1242  *   end of tv.c
1243  ****************************************************************************/