tarval_is_null() function added
[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) && mode_is_int(a->mode));
898
899   sc_and(a->value, b->value);
900   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
901 }
902
903 /*
904  * bitwise or
905  */
906 tarval *tarval_or (tarval *a, tarval *b)
907 {
908   ANNOUNCE();
909   assert(a);
910   assert(b);
911   assert((a->mode == b->mode) && mode_is_int(a->mode));
912
913   sc_or(a->value, b->value);
914   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
915 }
916
917 /*
918  * bitwise exclusive or (xor)
919  */
920 tarval *tarval_eor(tarval *a, tarval *b)
921 {
922   ANNOUNCE();
923   assert(a);
924   assert(b);
925   assert((a->mode == b->mode) && mode_is_int(a->mode));
926
927   sc_or(a->value, b->value);
928   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
929 }
930
931 /*
932  * bitwise left shift
933  */
934 tarval *tarval_shl(tarval *a, tarval *b)
935 {
936   ANNOUNCE();
937   assert(a);
938   assert(b);
939   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
940
941   sc_shl(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
942   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
943 }
944
945 /*
946  * bitwise unsigned right shift
947  */
948 tarval *tarval_shr(tarval *a, tarval *b)
949 {
950   ANNOUNCE();
951   assert(a);
952   assert(b);
953   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
954
955   sc_shr(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
956   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
957 }
958
959 /*
960  * bitwise signed right shift
961  */
962 tarval *tarval_shrs(tarval *a, tarval *b)
963 {
964   ANNOUNCE();
965   assert(a);
966   assert(b);
967   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
968
969   sc_shrs(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
970   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
971 }
972
973 /*
974  * bitwise rotation
975  */
976 tarval *tarval_rot(tarval *a, tarval *b)
977 {
978   ANNOUNCE();
979   assert(a);
980   assert(b);
981   assert(mode_is_int(a->mode) && mode_is_int(b->mode));
982
983   sc_rot(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
984   return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
985 }
986
987
988 /*
989  * Output of tarvals
990  */
991 int tarval_snprintf(char *buf, size_t len, tarval *tv)
992 {
993   static const tarval_mode_info default_info = { TVO_NATIVE, NULL, NULL };
994
995   const char *str;
996   char tv_buf[100];
997   const tarval_mode_info *mode_info;
998   const char *prefix, *suffix;
999
1000   ANNOUNCE();
1001
1002   mode_info = tv->mode->tv_priv;
1003   if (! mode_info)
1004     mode_info = &default_info;
1005   prefix = mode_info->mode_prefix ? mode_info->mode_prefix : "";
1006   suffix = mode_info->mode_suffix ? mode_info->mode_suffix : "";
1007
1008   switch (get_mode_sort(tv->mode))
1009   {
1010     case irms_int_number:
1011     case irms_character:
1012       switch (mode_info->mode_output) {
1013
1014       case TVO_DECIMAL:
1015         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_DEC);
1016         break;
1017
1018       case TVO_OCTAL:
1019         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_OCT);
1020         break;
1021
1022       case TVO_HEX:
1023       case TVO_NATIVE:
1024       default:
1025         str = sc_print(tv->value, get_mode_size_bits(tv->mode), SC_HEX);
1026         break;
1027       }
1028       return snprintf(buf, len, "%s%s%s", prefix, str, suffix);
1029
1030     case irms_float_number:
1031       return snprintf(buf, len, "%s%s%s", prefix, fc_print_dec(tv->value, tv_buf, sizeof(tv_buf)), suffix);
1032
1033     case irms_reference:
1034       if (tv->value != NULL)
1035         if (tarval_is_entity(tv)) {
1036           if (get_entity_peculiarity((entity *)tv->value) == existent)
1037             return snprintf(buf, len, "%s%s%s", prefix, get_entity_ld_name((entity *)tv->value), suffix);
1038           else {
1039             if (mode_info->mode_output == TVO_NATIVE)
1040               return snprintf(buf, len, "NULL");
1041             else
1042               return snprintf(buf, len, "0");
1043           }
1044         }
1045         else {
1046           if (size > tv->length) {
1047             memcpy(buf, tv->value, tv->length);
1048             buf[tv->length] = '\0';
1049           }
1050           else {
1051             /* truncated */
1052             memcpy(buf, tv->value, size-1);
1053             buf[size-1] = '\0';
1054           }
1055           return tv->length;
1056         }
1057       else
1058         return snprintf(buf, len, "void");
1059
1060     case irms_internal_boolean:
1061       switch (mode_info->mode_output) {
1062
1063       case TVO_DECIMAL:
1064       case TVO_OCTAL:
1065       case TVO_HEX:
1066       case TVO_BINARY:
1067         return snprintf(buf, len, "%s%c%s", prefix, (tv == tarval_b_true) ? '1' : '0', suffix);
1068
1069       case TVO_NATIVE:
1070       default:
1071         return snprintf(buf, len, "%s%s%s", prefix, (tv == tarval_b_true) ? "true" : "false", suffix);
1072       }
1073
1074     case irms_auxiliary:
1075       return snprintf(buf, len, "<BAD>");
1076   }
1077
1078   return 0;
1079 }
1080
1081 char *tarval_bitpattern(tarval *tv)
1082 {
1083   return NULL;
1084 }
1085
1086 /*
1087  * access to the bitpattern
1088  */
1089 unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs)
1090 {
1091   switch (get_mode_sort(tv->mode)) {
1092     case irms_int_number:
1093     case irms_character:
1094       return sc_sub_bits(tv->value, tv->length, byte_ofs);
1095
1096     case irms_float_number:
1097       return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs);
1098
1099     default:
1100       return 0;
1101   }
1102 }
1103
1104 /*
1105  * Specify the output options of one mode.
1106  *
1107  * This functions stores the modinfo, so DO NOT DESTROY it.
1108  *
1109  * Returns zero on success.
1110  */
1111 int tarval_set_mode_output_option(ir_mode *mode, const tarval_mode_info *modeinfo)
1112 {
1113   assert(mode);
1114
1115   mode->tv_priv = modeinfo;
1116   return 0;
1117 }
1118
1119 /* Identifying some tarvals ??? */
1120 /* Implemented in old tv.c as such:
1121  *   return 0 for additive neutral,
1122  *   1 for multiplicative neutral,
1123  *   -1 for bitwise-and neutral
1124  *   2 else
1125  *
1126  * Implemented for completeness */
1127 long tarval_classify(tarval *tv)
1128 {
1129   ANNOUNCE();
1130   if (!tv || tv == tarval_bad) return 2;
1131
1132   if (tv == get_mode_null(tv->mode)) return 0;
1133   else if (tv == get_mode_one(tv->mode)) return 1;
1134   else if ((get_mode_sort(tv->mode) == irms_int_number)
1135            && (tv == new_tarval_from_long(-1, tv->mode))) return -1;
1136
1137   return 2;
1138 }
1139
1140 /*
1141  * Initialization of the tarval module: called before init_mode()
1142  */
1143 void init_tarval_1(void)
1144 {
1145   ANNOUNCE();
1146   /* initialize the sets holding the tarvals with a comparison function and
1147    * an initial size, which is the expected number of constants */
1148   tarvals = new_set(memcmp, TUNE_NCONSTANTS);
1149   values = new_set(memcmp, TUNE_NCONSTANTS);
1150   /* init with default precision */
1151   init_strcalc(0);
1152   /* init_fltcalc(0); not yet*/
1153 }
1154
1155 /**
1156  * default mode_info for output as HEX
1157  */
1158 static const tarval_mode_info hex_output = {
1159   TVO_HEX,
1160   "0x",
1161   NULL,
1162 };
1163
1164 /**
1165  * default mode_info for output as reference
1166  */
1167 static const tarval_mode_info reference_output = {
1168   TVO_NATIVE,
1169   "&(",
1170   ")",
1171 };
1172
1173
1174 /*
1175  * Initialization of the tarval module: called after init_mode()
1176  */
1177 void init_tarval_2(void)
1178 {
1179   ANNOUNCE();
1180
1181   tarval_bad = (tarval*)malloc(sizeof(tarval));
1182   tarval_bad->mode = NULL;
1183
1184   tarval_undefined = (tarval*)malloc(sizeof(tarval));
1185   tarval_undefined->mode = NULL;
1186
1187   tarval_b_true = (tarval*)malloc(sizeof(tarval));
1188   tarval_b_true->mode = mode_b;
1189
1190   tarval_b_false = (tarval*)malloc(sizeof(tarval));
1191   tarval_b_false->mode = mode_b;
1192
1193   tarval_P_void = (tarval*)malloc(sizeof(tarval));
1194   tarval_P_void->mode = mode_P;
1195
1196   /*
1197    * assign output modes that are compatible with the
1198    * old implementation: Hex output
1199    */
1200   tarval_set_mode_output_option(mode_U,  &hex_output);
1201   tarval_set_mode_output_option(mode_C,  &hex_output);
1202   tarval_set_mode_output_option(mode_Bs, &hex_output);
1203   tarval_set_mode_output_option(mode_Bu, &hex_output);
1204   tarval_set_mode_output_option(mode_Hs, &hex_output);
1205   tarval_set_mode_output_option(mode_Hu, &hex_output);
1206   tarval_set_mode_output_option(mode_Hs, &hex_output);
1207   tarval_set_mode_output_option(mode_Hu, &hex_output);
1208   tarval_set_mode_output_option(mode_Is, &hex_output);
1209   tarval_set_mode_output_option(mode_Iu, &hex_output);
1210   tarval_set_mode_output_option(mode_Ls, &hex_output);
1211   tarval_set_mode_output_option(mode_Lu, &hex_output);
1212   tarval_set_mode_output_option(mode_P,  &reference_output);
1213 }
1214
1215 /****************************************************************************
1216  *   end of tv.c
1217  ****************************************************************************/