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