aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPer Bothner <bothner@gcc.gnu.org>1994-09-08 11:59:33 -0700
committerPer Bothner <bothner@gcc.gnu.org>1994-09-08 11:59:33 -0700
commitbca949e2511608b06398451ddb7c9bbea0cdc8b3 (patch)
tree243e838b856d8fa2146acdf673081d3d2ca6b995 /gcc
parentbabfe4370ee988230f9c4911e98975f5954542b1 (diff)
downloadgcc-bca949e2511608b06398451ddb7c9bbea0cdc8b3.zip
gcc-bca949e2511608b06398451ddb7c9bbea0cdc8b3.tar.gz
gcc-bca949e2511608b06398451ddb7c9bbea0cdc8b3.tar.bz2
(get_set_constructor_bits, get_set_constructor_words): New functions.
From-SVN: r8044
Diffstat (limited to 'gcc')
-rw-r--r--gcc/tree.c99
-rw-r--r--gcc/tree.h3
2 files changed, 102 insertions, 0 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 95be3652..85ea6c0 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4001,3 +4001,102 @@ get_file_function_name (kind)
return get_identifier (buf);
}
+
+/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
+ The result is placed in BUFFER (which has length BIT_SIZE),
+ with one bit in each char ('\000' or '\001').
+
+ If the constructor is constant, NULL_TREE is returned.
+ Otherwise, a TREE_LIST of the non-constant elements is emitted. */
+
+tree
+get_set_constructor_bits (init, buffer, bit_size)
+ tree init;
+ char *buffer;
+ int bit_size;
+{
+ int i;
+ tree vals;
+ HOST_WIDE_INT domain_min
+ = TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (init))));
+ tree non_const_bits = NULL_TREE;
+ for (i = 0; i < bit_size; i++)
+ buffer[i] = 0;
+
+ for (vals = TREE_OPERAND (init, 1);
+ vals != NULL_TREE; vals = TREE_CHAIN (vals))
+ {
+ if (TREE_CODE (TREE_VALUE (vals)) != INTEGER_CST
+ || (TREE_PURPOSE (vals) != NULL_TREE
+ && TREE_CODE (TREE_PURPOSE (vals)) != INTEGER_CST))
+ non_const_bits =
+ tree_cons (TREE_PURPOSE (vals), TREE_VALUE (vals), non_const_bits);
+ else if (TREE_PURPOSE (vals) != NULL_TREE)
+ {
+ /* Set a range of bits to ones. */
+ HOST_WIDE_INT lo_index
+ = TREE_INT_CST_LOW (TREE_PURPOSE (vals)) - domain_min;
+ HOST_WIDE_INT hi_index
+ = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
+ if (lo_index < 0 || lo_index >= bit_size
+ || hi_index < 0 || hi_index >= bit_size)
+ abort ();
+ for ( ; lo_index <= hi_index; lo_index++)
+ buffer[lo_index] = 1;
+ }
+ else
+ {
+ /* Set a single bit to one. */
+ HOST_WIDE_INT index
+ = TREE_INT_CST_LOW (TREE_VALUE (vals)) - domain_min;
+ if (index < 0 || index >= bit_size)
+ {
+ error ("invalid initializer for bit string");
+ return NULL_TREE;
+ }
+ buffer[index] = 1;
+ }
+ }
+ return non_const_bits;
+}
+
+/* Expand (the constant part of) a SET_TYPE CONTRUCTOR node.
+ The result is placed in BUFFER (which is an array of WD_SIZE
+ words). TYPE_ALIGN bits are stored in each element of BUFFER.
+ If the constructor is constant, NULL_TREE is returned.
+ Otherwise, a TREE_LIST of the non-constant elements is emitted. */
+
+tree
+get_set_constructor_words (init, buffer, wd_size)
+ tree init;
+ HOST_WIDE_INT *buffer;
+ int wd_size;
+{
+ int i;
+ tree vals = TREE_OPERAND (init, 1);
+ int set_word_size = TYPE_ALIGN (TREE_TYPE (init));
+ int bit_size = wd_size * set_word_size;
+ int bit_pos = 0;
+ HOST_WIDE_INT *wordp = buffer;
+ char *bit_buffer = (char*)alloca(bit_size);
+ tree non_const_bits = get_set_constructor_bits (init, bit_buffer, bit_size);
+
+ for (i = 0; i < wd_size; i++)
+ buffer[i] = 0;
+
+ for (i = 0; i < bit_size; i++)
+ {
+ if (bit_buffer[i])
+ {
+#if BITS_BIG_ENDIAN
+ *wordp |= (1 << (set_word_size - 1 - bit_pos));
+#else
+ *wordp |= 1 << bit_pos;
+#endif
+ }
+ bit_pos++;
+ if (bit_pos >= set_word_size)
+ bit_pos = 0, wordp++;
+ }
+ return non_const_bits;
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index bfb82f2..5976437 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1498,6 +1498,9 @@ extern void (*incomplete_decl_finalize_hook) ();
/* In tree.c */
extern char *perm_calloc PROTO((int, long));
+extern tree get_set_constructor_bits PROTO((tree, char*, int));
+extern tree get_set_constructor_words PROTO((tree,
+ HOST_WIDE_INT*, int));
/* In stmt.c */