1 /* TV --- Target Values, aka Constant Table.
2 Copyright (C) 1995, 1996 Christian von Roques */
6 /****i* tv/implementation
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.
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.
25 /* This implementation assumes:
26 * both host and target have IEEE-754 floating-point arithmetic. */
28 /* !!! float and double divides MUST NOT SIGNAL !!! */
29 /* @@@ query the floating-point expception status flags */
31 /* @@@ Problem: All Values are stored twice, once as Univ_*s and a 2nd
32 time in their real target mode. :-( */
34 #define MAX_INT_LENGTH 8
35 #define CHAR_BUFFER_SIZE ((MAX_INT_LENGTH) * 2)
41 #include <assert.h> /* assertions */
42 #include <stdlib.h> /* atoi() */
43 #include <string.h> /* nice things for strings */
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 "irnode.h" /* defines boolean return values */
58 /****************************************************************************
59 * local definitions and macros
60 ****************************************************************************/
62 # define TARVAL_VERIFY(a) tarval_verify((a))
64 # define TARVAL_VERIFY(a) ((void)0)
67 #define INSERT_TARVAL(tv) ((tarval*)set_insert(tarvals, (tv), sizeof(tarval), hash_tv((tv))))
68 #define FIND_TARVAL(tv) ((tarval*)set_find(tarvals, (tv), sizeof(tarval), hash_tv((tv))))
70 #define INSERT_VALUE(val, size) (set_insert(values, (val), size, hash_val((val), size)))
71 #define FIND_VALUE(val, size) (set_find(values, (val), size, hash_val((val), size)))
73 #define fail_verify(a) _fail_verify((a), __FILE__, __LINE__)
75 static long long count = 0;
76 # define ANNOUNCE() printf(__FILE__": call no. %lld (%s)\n", count++, __FUNCTION__);
78 # define ANNOUNCE() ((void)0)
80 /****************************************************************************
82 ****************************************************************************/
83 static struct set *tarvals; /* container for tarval structs */
84 static struct set *values; /* container for values */
86 /****************************************************************************
88 ****************************************************************************/
90 static int hash_val(const void *value, unsigned int length);
91 static int hash_tv(tarval *tv);
92 static void _fail_verify(tarval *tv, const char* file, int line)
94 /* print a memory image of the tarval and throw an assertion */
96 printf("%s:%d: Invalid tarval:\n mode: %s\n value: [%p]\n", file, line, get_mode_name(tv->mode), tv->value);
98 printf("%s:%d: Invalid tarval (null)", file, line);
102 static void tarval_verify(tarval *tv)
108 if ((tv == tarval_bad) || (tv == tarval_undefined)) return;
109 if ((tv == tarval_b_true) || (tv == tarval_b_false)) return;
111 if (!FIND_TARVAL(tv)) fail_verify(tv);
112 if (tv->length > 0 && !FIND_VALUE(tv->value, tv->length)) fail_verify(tv);
118 static int hash_tv(tarval *tv)
120 return ((unsigned int)tv->value ^ (unsigned int)tv->mode) + tv->length;
123 static int hash_val(const void *value, unsigned int length)
126 unsigned int hash = 0;
128 /* scramble the byte - array */
129 for (i = 0; i < length; i++)
131 hash += (hash << 5) ^ (hash >> 27) ^ ((char*)value)[i];
132 hash += (hash << 11) ^ (hash >> 17);
138 /* finds tarval with value/mode or creates new tarval*/
139 static tarval *get_tarval(const void *value, int length, ir_mode *mode)
146 /* if there already is such a value, it is returned, else value
147 * is copied into the set */
148 tv.value = INSERT_VALUE(value, length);
152 /* if there is such a tarval, it is returned, else tv is copied
154 return (tarval *)INSERT_TARVAL(&tv);
158 * Returns non-zero if a tarval overflows.
160 * @todo Implementation did not work on all modes
162 static int overflows(tarval *tv)
164 switch (get_mode_sort(tv->mode))
168 if (sc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1;
169 if (sc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1;
173 if (fc_comp(tv->value, get_mode_max(tv->mode)->value) == 1) return 1;
174 if (fc_comp(tv->value, get_mode_min(tv->mode)->value) == -1) return 1;
184 /****************************************************************************
185 * public variables declared in tv.h
186 ****************************************************************************/
188 tarval *tarval_undefined;
189 tarval *tarval_b_false;
190 tarval *tarval_b_true;
191 tarval *tarval_P_void;
193 /****************************************************************************
194 * public functions declared in tv.h
195 ****************************************************************************/
197 * Constructors =============================================================
199 tarval *new_tarval_from_str(const char *str, size_t len, ir_mode *mode)
206 switch (get_mode_sort(mode))
212 case internal_boolean:
213 /* match tTrRuUeE/fFaAlLsSeE */
214 if (strcasecmp(str, "true")) return tarval_b_true;
215 else if (strcasecmp(str, "false")) return tarval_b_true;
217 return atoi(str) ? tarval_b_true : tarval_b_false;
220 fc_val_from_str(str, len);
221 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
225 sc_val_from_str(str, len);
226 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
229 return get_tarval(str, len, mode);
232 assert(0); /* can't be reached, can it? */
237 int tarval_is_str(tarval *tv)
242 return ((get_mode_sort(tv->mode) == reference) && (tv->value != NULL) && (tv->length > 0));
244 char *tarval_to_str(tarval *tv)
247 assert(tarval_is_str(tv));
248 return (char *)tv->value;
252 tarval *new_tarval_from_long(long l, ir_mode *mode)
255 assert(mode && !(get_mode_sort(mode) == auxiliary));
257 switch(get_mode_sort(mode))
259 case internal_boolean:
260 /* XXX C-Semantics ! */
261 return l ? tarval_b_true : tarval_b_false ;
266 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
269 return new_tarval_from_double((long double)l, mode);
272 return l ? tarval_bad : get_tarval(NULL, 0, mode); /* null pointer or tarval_bad */
280 int tarval_is_long(tarval *tv)
283 return ((get_mode_sort(tv->mode) == int_number) || (get_mode_sort(tv->mode) == character));
286 /* this might overflow the machine's long, so use only with small values */
287 long tarval_to_long(tarval* tv)
290 assert(tv && get_mode_sort(tv->mode) == int_number);
292 return sc_val_to_long(tv->value); /* might overflow */
295 tarval *new_tarval_from_double(long double d, ir_mode *mode)
298 assert(mode && (get_mode_sort(mode) == float_number));
300 fc_val_from_float(d);
301 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
304 int tarval_is_double(tarval *tv)
309 return (get_mode_sort(tv->mode) == float_number);
312 long double tarval_to_double(tarval *tv)
315 assert(tarval_is_double(tv));
317 return fc_val_to_float(tv->value);
320 /* The tarval represents the address of the entity. As the address must
321 be constant the entity must have as owner the global type. */
322 tarval *new_tarval_from_entity (entity *ent, ir_mode *mode)
326 assert(mode && (get_mode_sort(mode) == reference));
328 return get_tarval((void *)ent, 0, mode);
330 int tarval_is_entity(tarval *tv)
334 /* tv->value == NULL means dereferencing a null pointer */
335 return ((get_mode_sort(tv->mode) == reference) && (tv->value != NULL) && (tv->length == 0));
338 entity *tarval_to_entity(tarval *tv)
343 if (tarval_is_entity(tv))
344 return (entity *)tv->value;
346 assert(0 && "tarval did not represent an entity");
352 * Access routines for tarval fields ========================================
354 #ifdef TARVAL_ACCESS_DEFINES
355 # undef get_tarval_mode
357 ir_mode *get_tarval_mode (tarval *tv) /* get the mode of the tarval */
363 #ifdef TARVAL_ACCESS_DEFINES
364 # define get_tarval_mode(tv) (tv)->mode
368 * Special value query functions ============================================
370 * These functions calculate and return a tarval representing the requested
372 * The functions get_mode_{Max,Min,...} return tarvals retrieved from these
373 * functions, but these are stored on initialization of the irmode module and
374 * therefore the irmode functions should be prefered to the functions below.
377 tarval *get_tarval_bad(void)
382 tarval *get_tarval_undefined(void)
385 return tarval_undefined;
387 tarval *get_tarval_b_false(void)
390 return tarval_b_false;
392 tarval *get_tarval_b_true(void)
395 return tarval_b_true;
397 tarval *get_tarval_P_void(void)
400 return tarval_P_void;
403 tarval *get_tarval_max(ir_mode *mode)
408 switch(get_mode_sort(mode))
415 case internal_boolean:
416 return tarval_b_true;
419 fc_get_max(get_mode_size_bits(mode));
420 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
424 sc_max_from_bits(get_mode_size_bits(mode), mode_is_signed(mode));
425 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
430 tarval *get_tarval_min(ir_mode *mode)
435 switch(get_mode_sort(mode))
442 case internal_boolean:
443 return tarval_b_false;
446 fc_get_min(get_mode_size_bits(mode));
447 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
451 sc_min_from_bits(get_mode_size_bits(mode), mode_is_signed(mode));
452 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), mode);
457 tarval *get_tarval_null(ir_mode *mode)
462 switch(get_mode_sort(mode))
465 case internal_boolean:
470 return new_tarval_from_double(0.0, mode);
474 return new_tarval_from_long(0l, mode);
477 return tarval_P_void;
482 tarval *get_tarval_one(ir_mode *mode)
487 switch(get_mode_sort(mode))
490 case internal_boolean:
496 return new_tarval_from_double(1.0, mode);
500 return new_tarval_from_long(1l, mode);
506 tarval *get_tarval_nan(ir_mode *mode)
510 assert(get_mode_sort(mode) == float_number);
513 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
516 tarval *get_tarval_inf(ir_mode *mode)
520 assert(get_mode_sort(mode) == float_number);
523 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), mode);
527 * Arithmethic operations on tarvals ========================================
530 /* test if negative number, 1 means 'yes' */
531 int tarval_is_negative(tarval *a)
536 switch (get_mode_sort(a->mode))
539 if (!mode_is_signed(a->mode)) return 0;
541 return sc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
544 return fc_comp(a->value, get_mode_null(a->mode)->value) == -1 ? 1 : 0;
547 assert(0 && "not implemented");
552 pnc_number tarval_cmp(tarval *a, tarval *b)
558 if (a == tarval_bad || b == tarval_bad) assert(0 && "Comparison with tarval_bad");
559 if (a == tarval_undefined || b == tarval_undefined) return False;
560 if (a == b) return Eq;
561 if (get_tarval_mode(a) != get_tarval_mode(b)) return Uo;
563 /* Here the two tarvals are unequal and of the same mode */
564 switch (get_mode_sort(a->mode))
570 return (fc_comp(a->value, b->value)==1)?(Gt):(Lt);
574 return (sc_comp(a->value, b->value)==1)?(Gt):(Lt);
576 case internal_boolean:
577 return (a == tarval_b_true)?(Gt):(Lt);
585 tarval *tarval_convert_to(tarval *src, ir_mode *m)
593 if (src->mode == m) return src;
595 switch (get_mode_sort(src->mode))
604 switch (get_mode_sort(m))
609 tv.length = src->length;
610 tv.value = src->value;
615 return INSERT_TARVAL(&tv);
617 case internal_boolean:
618 /* XXX C semantics */
619 if (src == get_mode_null(src->mode)) return tarval_b_false;
620 else return tarval_b_true;
627 case internal_boolean:
628 switch (get_mode_sort(m))
631 if (src == tarval_b_true) return get_mode_one(m);
632 else return get_mode_null(m);
648 tarval *tarval_neg(tarval *a) /* negation */
652 assert(mode_is_num(a->mode)); /* negation only for numerical values */
653 assert(mode_is_signed(a->mode)); /* negation is difficult without negative numbers, isn't it */
655 switch (get_mode_sort(a->mode))
659 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
663 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
670 tarval *tarval_add(tarval *a, tarval *b) /* addition */
675 assert((a->mode == b->mode) || (get_mode_sort(a->mode) == character && mode_is_int(b->mode)));
677 switch (get_mode_sort(a->mode))
681 /* modes of a,b are equal, so result has mode of a as this might be the character */
682 sc_add(a->value, b->value);
683 /* FIXME: Check for overflow */
684 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
687 /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
688 fc_add(a->value, b->value);
689 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
696 tarval *tarval_sub(tarval *a, tarval *b) /* subtraction */
701 assert((a->mode == b->mode) || (get_mode_sort(a->mode) == character && mode_is_int(b->mode)));
703 switch (get_mode_sort(a->mode))
707 /* modes of a,b are equal, so result has mode of a as this might be the character */
708 sc_sub(a->value, b->value);
709 /* FIXME: check for overflow */
710 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
713 /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
714 fc_add(a->value, b->value);
715 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
722 tarval *tarval_mul(tarval *a, tarval *b) /* multiplication */
727 assert((a->mode == b->mode) && mode_is_num(a->mode));
729 switch (get_mode_sort(a->mode))
732 /* modes of a,b are equal */
733 sc_mul(a->value, b->value);
734 /* FIXME: check for overflow */
735 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
738 /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
739 fc_add(a->value, b->value);
740 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
747 tarval *tarval_quo(tarval *a, tarval *b) /* floating point division */
752 assert((a->mode == b->mode) && mode_is_float(a->mode));
754 /* FIXME: Overflow/Underflow/transition to inf when mode < 80bit */
755 fc_div(a->value, b->value);
756 return get_tarval(fc_get_buffer(), fc_get_buffer_length(), a->mode);
759 tarval *tarval_div(tarval *a, tarval *b) /* integer division */
764 assert((a->mode == b->mode) && mode_is_int(a->mode));
766 /* modes of a,b are equal */
767 sc_div(a->value, b->value);
768 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
771 tarval *tarval_mod(tarval *a, tarval *b) /* remainder */
776 assert((a->mode == b->mode) && mode_is_int(a->mode));
778 /* modes of a,b are equal */
779 sc_mod(a->value, b->value);
780 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
783 tarval *tarval_abs(tarval *a) /* absolute value */
787 assert(mode_is_num(a->mode));
789 switch (get_mode_sort(a->mode))
792 if (sc_comp(a->value, get_mode_null(a->mode)->value) == -1)
795 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
808 tarval *tarval_and(tarval *a, tarval *b) /* bitwise and */
813 assert((a->mode == b->mode) && mode_is_int(a->mode));
815 sc_and(a->value, b->value);
816 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
818 tarval *tarval_or (tarval *a, tarval *b) /* bitwise or */
823 assert((a->mode == b->mode) && mode_is_int(a->mode));
825 sc_or(a->value, b->value);
826 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
828 tarval *tarval_eor(tarval *a, tarval *b) /* bitwise exclusive or (xor) */
833 assert((a->mode == b->mode) && mode_is_int(a->mode));
835 sc_or(a->value, b->value);
836 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
839 tarval *tarval_shl(tarval *a, tarval *b) /* bitwise left shift */
844 assert(mode_is_int(a->mode) && mode_is_int(b->mode));
846 sc_shl(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
847 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
849 tarval *tarval_shr(tarval *a, tarval *b) /* bitwise unsigned right shift */
854 assert(mode_is_int(a->mode) && mode_is_int(b->mode));
856 sc_shr(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
857 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
859 tarval *tarval_shrs(tarval *a, tarval *b) /* bitwise signed right shift */
864 assert(mode_is_int(a->mode) && mode_is_int(b->mode));
866 sc_shrs(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
867 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
869 tarval *tarval_rot(tarval *a, tarval *b) /* bitwise rotation */
874 assert(mode_is_int(a->mode) && mode_is_int(b->mode));
876 sc_rot(a->value, b->value, get_mode_size_bits(a->mode), mode_is_signed(a->mode));
877 return get_tarval(sc_get_buffer(), sc_get_buffer_length(), a->mode);
880 /** *********** Output of tarvals *********** **/
881 int tarval_print(XP_PAR1, const xprintf_info *info ATTRIBUTE((unused)), XP_PARN)
889 tv = XP_GETARG(tarval *, 0);
890 switch (get_mode_sort(tv->mode))
894 offset = 16 - (get_mode_size_bits(tv->mode)/4);
895 str = sc_print_hex(tv->value);
896 return XPF1R("0x%s", str + offset);
899 return XPF1R("%s", fc_print_dec(tv->value, buf, sizeof(buf)));
902 if (tv->value != NULL)
903 if (tarval_is_entity(tv))
904 if (get_entity_peculiarity((entity *)tv->value) == existent)
905 return XPF1R("&(%I)", get_entity_ld_ident((entity *)tv->value));
909 return XPMR((char*)tv->value, tv->length);
913 case internal_boolean:
914 if (tv == tarval_b_true) return XPSR("true");
915 else return XPSR("false");
918 return XPSR("<BAD>");
924 char *tarval_bitpattern(tarval *tv)
930 * access to the bitpattern
932 unsigned char tarval_sub_bits(tarval *tv, unsigned byte_ofs)
934 switch (get_mode_sort(tv->mode)) {
937 return sc_sub_bits(tv->value, tv->length, byte_ofs);
940 return fc_sub_bits(tv->value, get_mode_size_bits(tv->mode), byte_ofs);
947 /* Identifying some tarvals ??? */
948 /* Implemented in old tv.c as such:
949 * return 0 for additive neutral,
950 * 1 for multiplicative neutral,
951 * -1 for bitwise-and neutral
954 * Implemented for completeness */
955 long tarval_classify(tarval *tv)
958 if (!tv || tv == tarval_bad) return 2;
960 if (tv == get_mode_null(tv->mode)) return 0;
961 else if (tv == get_mode_one(tv->mode)) return 1;
962 else if ((get_mode_sort(tv->mode) == int_number)
963 && (tv == new_tarval_from_long(-1, tv->mode))) return -1;
968 /* Initialization of the tarval module: called before init_mode() */
969 void init_tarval_1(void)
972 /* initialize the sets holding the tarvals with a comparison function and
973 * an initial size, which is the expected number of constants */
974 tarvals = new_set(memcmp, TUNE_NCONSTANTS);
975 values = new_set(memcmp, TUNE_NCONSTANTS);
978 /* Initialization of the tarval module: called after init_mode() */
979 void init_tarval_2(void)
983 tarval_bad = (tarval*)malloc(sizeof(tarval));
984 tarval_bad->mode = NULL;
986 tarval_undefined = (tarval*)malloc(sizeof(tarval));
987 tarval_undefined->mode = NULL;
989 tarval_b_true = (tarval*)malloc(sizeof(tarval));
990 tarval_b_true->mode = mode_b;
992 tarval_b_false = (tarval*)malloc(sizeof(tarval));
993 tarval_b_false->mode = mode_b;
995 tarval_P_void = (tarval*)malloc(sizeof(tarval));
996 tarval_P_void->mode = mode_P;
999 /****************************************************************************
1001 ****************************************************************************/
1004 free_tarval_entity(entity *ent) {
1005 /* There can be a tarval referencing this entity. Even if the
1006 tarval is not used by the code any more, it can still reference
1007 the entity as tarvals live forever (They live on an obstack.).
1008 Further the tarval is hashed into a set. If a hash function
1009 evaluation happens to collide with this tarval, we will vrfy that
1010 it contains a proper entity and we will crash if the entity is
1011 freed. We cannot remove tarvals from the obstack but we can
1012 remove the entry in the hash table. */
1013 /* this will be re-implemented later */