Added prefix/suffix for irms_reference (mode_P)
[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  * comparison
583  */
584 pnc_number tarval_cmp(tarval *a, tarval *b)
585 {
586   ANNOUNCE();
587   assert(a);
588   assert(b);
589
590   if (a == tarval_bad || b == tarval_bad) assert(0 && "Comparison with tarval_bad");
591   if (a == tarval_undefined || b == tarval_undefined) return False;
592   if (a == b) return Eq;
593   if (get_tarval_mode(a) != get_tarval_mode(b)) return Uo;
594
595   /* Here the two tarvals are unequal and of the same mode */
596   switch (get_mode_sort(a->mode))
597   {
598     case irms_auxiliary:
599       return False;
600
601     case irms_float_number:
602       return (fc_comp(a->value, b->value)==1)?(Gt):(Lt);
603
604     case irms_int_number:
605     case irms_character:
606       return (sc_comp(a->value, b->value)==1)?(Gt):(Lt);
607
608     case irms_internal_boolean:
609       return (a == tarval_b_true)?(Gt):(Lt);
610
611     case irms_reference:
612       return Uo;
613   }
614   return False;
615 }
616
617 /*
618  * convert to other mode
619  */
620 tarval *tarval_convert_to(tarval *src, ir_mode *m)
621 {
622   ANNOUNCE();
623   tarval tv;
624
625   assert(src);
626   assert(m);
627
628   if (src->mode == m) return src;
629
630   switch (get_mode_sort(src->mode))
631   {
632     case irms_auxiliary:
633       break;
634
635     case irms_float_number:
636       switch (get_mode_sort(m)) {
637         case irms_float_number:
638           tv.mode   = m;
639           tv.length = src->length;
640           tv.value  = src->value;
641           if (overflows(&tv)) {
642             return tarval_bad;
643           }
644
645           return INSERT_TARVAL(&tv);
646
647         default:
648           break;
649       }
650       break;
651
652     case irms_int_number:
653       switch (get_mode_sort(m)) {
654         case irms_int_number:
655         case irms_character:
656           tv.mode   = m;
657           tv.length = src->length;
658           tv.value  = src->value;
659           if (overflows(&tv))
660             return tarval_bad;
661
662           return INSERT_TARVAL(&tv);
663
664         case irms_internal_boolean:
665           /* XXX C semantics */
666           if (src == get_mode_null(src->mode)) return tarval_b_false;
667           else return tarval_b_true;
668
669         default:
670           break;
671       }
672       break;
673
674     case irms_internal_boolean:
675       switch (get_mode_sort(m))
676       {
677         case irms_int_number:
678           if (src == tarval_b_true) return get_mode_one(m);
679           else return get_mode_null(m);
680
681         default:
682           break;
683       }
684       break;
685
686     case irms_character:
687       break;
688     case irms_reference:
689       break;
690   }
691
692   return tarval_bad;
693 }
694
695 /*
696  * negation
697  */
698 tarval *tarval_neg(tarval *a)
699 {
700   ANNOUNCE();
701   assert(a);
702   assert(mode_is_num(a->mode)); /* negation only for numerical values */
703   assert(mode_is_signed(a->mode)); /* negation is difficult without negative numbers, isn't it */
704
705   switch (get_mode_sort(a->mode))
706   {
707     case irms_int_number:
708       sc_neg(a->value);
709       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
710
711     case irms_float_number:
712       fc_neg(a->value);
713       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
714
715     default:
716       return tarval_bad;
717   }
718 }
719
720 /*
721  * addition
722  */
723 tarval *tarval_add(tarval *a, tarval *b)
724 {
725   ANNOUNCE();
726   assert(a);
727   assert(b);
728   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
729
730   switch (get_mode_sort(a->mode))
731   {
732     case irms_character:
733     case irms_int_number:
734       /* modes of a,b are equal, so result has mode of a as this might be the character */
735       sc_add(a->value, b->value);
736       /* FIXME: Check for overflow */
737       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
738
739     case irms_float_number:
740       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
741       fc_add(a->value, b->value);
742       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
743
744     default:
745       return tarval_bad;
746   }
747 }
748
749 /*
750  * subtraction
751  */
752 tarval *tarval_sub(tarval *a, tarval *b)
753 {
754   ANNOUNCE();
755   assert(a);
756   assert(b);
757   assert((a->mode == b->mode) || (get_mode_sort(a->mode) == irms_character && mode_is_int(b->mode)));
758
759   switch (get_mode_sort(a->mode))
760   {
761     case irms_character:
762     case irms_int_number:
763       /* modes of a,b are equal, so result has mode of a as this might be the character */
764       sc_sub(a->value, b->value);
765       /* FIXME: check for overflow */
766       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
767
768     case irms_float_number:
769       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
770       fc_add(a->value, b->value);
771       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
772
773     default:
774       return tarval_bad;
775   }
776 }
777
778 /*
779  * multiplication
780  */
781 tarval *tarval_mul(tarval *a, tarval *b)
782 {
783   ANNOUNCE();
784   assert(a);
785   assert(b);
786   assert((a->mode == b->mode) && mode_is_num(a->mode));
787
788   switch (get_mode_sort(a->mode))
789   {
790     case irms_int_number:
791       /* modes of a,b are equal */
792       sc_mul(a->value, b->value);
793       /* FIXME: check for overflow */
794       return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
795
796     case irms_float_number:
797       /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
798       fc_add(a->value, b->value);
799       return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
800
801     default:
802       return tarval_bad;
803   }
804 }
805
806 /*
807  * floating point division
808  */
809 tarval *tarval_quo(tarval *a, tarval *b)
810 {
811   ANNOUNCE();
812   assert(a);
813   assert(b);
814   assert((a->mode == b->mode) && mode_is_float(a->mode));
815
816   /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
817   fc_div(a->value, b->value);
818   return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
819 }
820
821 /*
822  * integer division
823  */
824 tarval *tarval_div(tarval *a, tarval *b)
825 {
826   ANNOUNCE();
827   assert(a);
828   assert(b);
829   assert((a->mode == b->mode) && mode_is_int(a->mode));
830
831   /* modes of a,b are equal */
832   sc_div(a->value, b->value);
833   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
834 }
835
836 /*
837  * remainder
838  */
839 tarval *tarval_mod(tarval *a, tarval *b)
840 {
841   ANNOUNCE();
842   assert(a);
843   assert(b);
844   assert((a->mode == b->mode) && mode_is_int(a->mode));
845
846   /* modes of a,b are equal */
847   sc_mod(a->value, b->value);
848   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
849 }
850
851 /*
852  * absolute value
853  */
854 tarval *tarval_abs(tarval *a)
855 {
856   ANNOUNCE();
857   assert(a);
858   assert(mode_is_num(a->mode));
859
860   switch (get_mode_sort(a->mode))
861   {
862     case irms_int_number:
863       if (sc_comp(a->value, get_mode_null(a->mode)->value) == -1)
864       {
865         sc_neg(a->value);
866         return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
867       }
868       return a;
869
870     case irms_float_number:
871       break;
872
873     default:
874       return tarval_bad;
875   }
876   return tarval_bad;
877 }
878
879 /*
880  * bitwise and
881  */
882 tarval *tarval_and(tarval *a, tarval *b)
883 {
884   ANNOUNCE();
885   assert(a);
886   assert(b);
887   assert((a->mode == b->mode) && mode_is_int(a->mode));
888
889   sc_and(a->value, b->value);
890   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
891 }
892
893 /*
894  * bitwise or
895  */
896 tarval *tarval_or (tarval *a, tarval *b)
897 {
898   ANNOUNCE();
899   assert(a);
900   assert(b);
901   assert((a->mode == b->mode) && mode_is_int(a->mode));
902
903   sc_or(a->value, b->value);
904   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
905 }
906
907 /*
908  * bitwise exclusive or (xor)
909  */
910 tarval *tarval_eor(tarval *a, tarval *b)
911 {
912   ANNOUNCE();
913   assert(a);
914   assert(b);
915   assert((a->mode == b->mode) && mode_is_int(a->mode));
916
917   sc_or(a->value, b->value);
918   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
919 }
920
921 /*
922  * bitwise left shift
923  */
924 tarval *tarval_shl(tarval *a, tarval *b)
925 {
926   ANNOUNCE();
927   assert(a);
928   assert(b);
929   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
930
931   sc_shl(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
932   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
933 }
934
935 /*
936  * bitwise unsigned right shift
937  */
938 tarval *tarval_shr(tarval *a, tarval *b)
939 {
940   ANNOUNCE();
941   assert(a);
942   assert(b);
943   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
944
945   sc_shr(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
946   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
947 }
948
949 /*
950  * bitwise signed right shift
951  */
952 tarval *tarval_shrs(tarval *a, tarval *b)
953 {
954   ANNOUNCE();
955   assert(a);
956   assert(b);
957   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
958
959   sc_shrs(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
960   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
961 }
962
963 /*
964  * bitwise rotation
965  */
966 tarval *tarval_rot(tarval *a, tarval *b)
967 {
968   ANNOUNCE();
969   assert(a);
970   assert(b);
971   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
972
973   sc_rot(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
974   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
975 }
976
977
978 /*
979  * Output of tarvals
980  */
981 int tarval_snprintf(char *buf, size_t len, tarval *tv)
982 {
983   static const tarval_mode_info default_info = { TVO_NATIVE, NULL, NULL };
984
985   const char *str;
986   char tv_buf[100];
987   const tarval_mode_info *mode_info;
988   const char *prefix, *suffix;
989
990   ANNOUNCE();
991
992   mode_info = tv->mode->tv_priv;
993   if (! mode_info)
994     mode_info = &default_info;
995   prefix = mode_info->mode_prefix ? mode_info->mode_prefix : "";
996   suffix = mode_info->mode_suffix ? mode_info->mode_suffix : "";
997
998   switch (get_mode_sort(tv->mode))
999   {
1000     case irms_int_number:
1001     case irms_character:
1002       switch (mode_info->mode_output) {
1003
1004       case TVO_DECIMAL:
1005         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC);
1006         break;
1007
1008       case TVO_OCTAL:
1009         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT);
1010         break;
1011
1012       case TVO_HEX:
1013       case TVO_NATIVE:
1014       default:
1015         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX);
1016         break;
1017       }
1018       return snprintf(buf, len, "%s%s%s", prefix, str, suffix);
1019
1020     case irms_float_number:
1021       return snprintf(buf, len, "%s%s%s", prefix, fc_print_dec(tv->value, tv_buf, sizeof(tv_buf)), suffix);
1022
1023     case irms_reference:
1024       if (tv->value != NULL)
1025         if (tarval_is_entity(tv)) {
1026           if (get_entity_peculiarity((entity *)tv->value) == existent)
1027             return snprintf(buf, len, "%s%s%s", prefix, get_entity_ld_name((entity *)tv->value), suffix);
1028           else {
1029             if (mode_info->mode_output == TVO_NATIVE)
1030               return snprintf(buf, len, "NULL");
1031             else
1032               return snprintf(buf, len, "0");
1033           }
1034         }
1035         else {
1036           if (size > tv->length) {
1037             memcpy(buf, tv->value, tv->length);
1038             buf[tv->length] = '\0';
1039           }
1040           else {
1041             /* truncated */
1042             memcpy(buf, tv->value, size-1);
1043             buf[size-1] = '\0';
1044           }
1045           return tv->length;
1046         }
1047       else
1048         return snprintf(buf, len, "void");
1049
1050     case irms_internal_boolean:
1051       switch (mode_info->mode_output) {
1052
1053       case TVO_DECIMAL:
1054       case TVO_OCTAL:
1055       case TVO_HEX:
1056       case TVO_BINARY:
1057         return snprintf(buf, len, "%s%c%s", prefix, (tv == tarval_b_true) ? '1' : '0', suffix);
1058
1059       case TVO_NATIVE:
1060       default:
1061         return snprintf(buf, len, "%s%s%s", prefix, (tv == tarval_b_true) ? "true" : "false", suffix);
1062       }
1063
1064     case irms_auxiliary:
1065       return snprintf(buf, len, "<BAD>");
1066   }
1067
1068   return 0;
1069 }
1070
1071 char *tarval_bitpattern(tarval *tv)
1072 {
1073   return NULL;
1074 }
1075
1076 /*
1077  * access to the bitpattern
1078  */
1079 unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs)
1080 {
1081   switch (get_mode_sort(tv->mode)) {
1082     case irms_int_number:
1083     case irms_character:
1084       return sc_sub_bits(tv->value, tv->length, byte_ofs);
1085
1086     case irms_float_number:
1087       return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs);
1088
1089     default:
1090       return 0;
1091   }
1092 }
1093
1094 /*
1095  * Specify the output options of one mode.
1096  *
1097  * This functions stores the modinfo, so DO NOT DESTROY it.
1098  *
1099  * Returns zero on success.
1100  */
1101 int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo)
1102 {
1103   assert(mode);
1104
1105   mode->tv_priv = modeinfo;
1106   return 0;
1107 }
1108
1109 /* Identifying some tarvals ??? */
1110 /* Implemented in old tv.c as such:
1111  *   return 0 for additive neutral,
1112  *   1 for multiplicative neutral,
1113  *   -1 for bitwise-and neutral
1114  *   2 else
1115  *
1116  * Implemented for completeness */
1117 long tarval_classify(tarval *tv)
1118 {
1119   ANNOUNCE();
1120   if (!tv || tv == tarval_bad) return 2;
1121
1122   if (tv == get_mode_null(tv->mode)) return 0;
1123   else if (tv == get_mode_one(tv->mode)) return 1;
1124   else if ((get_mode_sort(tv->mode) == irms_int_number)
1125            && (tv == new_tarval_from_long(-1, tv->mode))) return -1;
1126
1127   return 2;
1128 }
1129
1130 /*
1131  * Initialization of the tarval module: called before init_mode()
1132  */
1133 void init_tarval_1(void)
1134 {
1135   ANNOUNCE();
1136   /* initialize the sets holding the tarvals with a comparison function and
1137    * an initial size, which is the expected number of constants */
1138   tarvals = new_set(memcmp, TUNE_NCONSTANTS);
1139   values = new_set(memcmp, TUNE_NCONSTANTS);
1140   /* init with default precision */
1141   init_strcalc(0);
1142   /* init_fltcalc(0); not yet*/
1143 }
1144
1145 /**
1146  * default mode_info for output as HEX
1147  */
1148 static const tarval_mode_info hex_output = {
1149   TVO_HEX,
1150   "0x",
1151   NULL,
1152 };
1153
1154 /**
1155  * default mode_info for output as reference
1156  */
1157 static const tarval_mode_info reference_output = {
1158   TVO_NATIVE,
1159   "&(",
1160   ")",
1161 };
1162
1163
1164 /*
1165  * Initialization of the tarval module: called after init_mode()
1166  */
1167 void init_tarval_2(void)
1168 {
1169   ANNOUNCE();
1170
1171   tarval_bad = (tarval*)malloc(sizeof(tarval));
1172   tarval_bad->mode = NULL;
1173
1174   tarval_undefined = (tarval*)malloc(sizeof(tarval));
1175   tarval_undefined->mode = NULL;
1176
1177   tarval_b_true = (tarval*)malloc(sizeof(tarval));
1178   tarval_b_true->mode = mode_b;
1179
1180   tarval_b_false = (tarval*)malloc(sizeof(tarval));
1181   tarval_b_false->mode = mode_b;
1182
1183   tarval_P_void = (tarval*)malloc(sizeof(tarval));
1184   tarval_P_void->mode = mode_P;
1185
1186   /*
1187    * assign output modes that are compatible with the
1188    * old implementation: Hex output
1189    */
1190   tarval_set_mode_output_option(mode_U,  &hex_output);
1191   tarval_set_mode_output_option(mode_C,  &hex_output);
1192   tarval_set_mode_output_option(mode_Bs, &hex_output);
1193   tarval_set_mode_output_option(mode_Bu, &hex_output);
1194   tarval_set_mode_output_option(mode_Hs, &hex_output);
1195   tarval_set_mode_output_option(mode_Hu, &hex_output);
1196   tarval_set_mode_output_option(mode_Hs, &hex_output);
1197   tarval_set_mode_output_option(mode_Hu, &hex_output);
1198   tarval_set_mode_output_option(mode_Is, &hex_output);
1199   tarval_set_mode_output_option(mode_Iu, &hex_output);
1200   tarval_set_mode_output_option(mode_Ls, &hex_output);
1201   tarval_set_mode_output_option(mode_Lu, &hex_output);
1202   tarval_set_mode_output_option(mode_P,  &reference_output);
1203 }
1204
1205 /****************************************************************************
1206  *   end of tv.c
1207  ****************************************************************************/