#include <config.h>
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "java-tree.h"
#include "parse.h"
#include "toplev.h"
static void mark_reference_fields (tree, unsigned HOST_WIDE_INT *,
unsigned HOST_WIDE_INT *, unsigned int,
int *, int *, int *, HOST_WIDE_INT *);
static void set_bit (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *,
unsigned int);
static void
set_bit (unsigned HOST_WIDE_INT *low, unsigned HOST_WIDE_INT *high,
unsigned int n)
{
unsigned HOST_WIDE_INT *which;
if (n >= HOST_BITS_PER_WIDE_INT)
{
n -= HOST_BITS_PER_WIDE_INT;
which = high;
}
else
which = low;
*which |= (unsigned HOST_WIDE_INT) 1 << n;
}
static void
mark_reference_fields (tree field,
unsigned HOST_WIDE_INT *low,
unsigned HOST_WIDE_INT *high,
unsigned int ubit,
int *pointer_after_end,
int *all_bits_set,
int *last_set_index,
HOST_WIDE_INT *last_view_index)
{
if (DECL_NAME (field) == NULL_TREE)
{
mark_reference_fields (TYPE_FIELDS (TREE_TYPE (field)),
low, high, ubit,
pointer_after_end, all_bits_set,
last_set_index, last_view_index);
field = TREE_CHAIN (field);
}
for (; field != NULL_TREE; field = TREE_CHAIN (field))
{
HOST_WIDE_INT offset;
HOST_WIDE_INT size_bytes;
if (FIELD_STATIC (field))
continue;
offset = int_byte_position (field);
size_bytes = int_size_in_bytes (TREE_TYPE (field));
if (JREFERENCE_TYPE_P (TREE_TYPE (field))
&& TREE_TYPE (field) != rawdata_ptr_type_node)
{
unsigned int count;
unsigned int size_words;
unsigned int i;
if (offset <= *last_view_index)
abort ();
count = offset * BITS_PER_UNIT / POINTER_SIZE;
size_words = size_bytes * BITS_PER_UNIT / POINTER_SIZE;
*last_set_index = count;
for (i = 0; i < size_words; ++i)
set_bit (low, high, ubit - count - i - 1);
if (count >= ubit - 2)
*pointer_after_end = 1;
if (! *all_bits_set)
*all_bits_set = -1;
}
else if (*all_bits_set > 0)
*all_bits_set = 0;
*last_view_index = offset;
}
}
tree
get_boehm_type_descriptor (tree type)
{
unsigned int count, log2_size, ubit;
int bit;
int all_bits_set = 1;
int last_set_index = 0;
HOST_WIDE_INT last_view_index = -1;
int pointer_after_end = 0;
unsigned HOST_WIDE_INT low = 0, high = 0;
tree field, value, value_type;
if (! flag_use_boehm_gc)
return null_pointer_node;
value_type = java_type_for_mode (ptr_mode, 1);
if (int_size_in_bytes (type) == -1)
goto procedure_object_descriptor;
bit = POINTER_SIZE / BITS_PER_UNIT;
log2_size = exact_log2 (bit);
if (bit == -1 || (log2_size != 2 && log2_size != 3))
{
return null_pointer_node;
}
bit *= BITS_PER_UNIT;
ubit = (unsigned int) bit;
if (type == class_type_node)
goto procedure_object_descriptor;
field = TYPE_FIELDS (type);
mark_reference_fields (field, &low, &high, ubit,
&pointer_after_end, &all_bits_set,
&last_set_index, &last_view_index);
if (all_bits_set != -1)
{
count = 0;
low = 0;
high = 0;
++last_set_index;
while (last_set_index)
{
if ((last_set_index & 1))
set_bit (&low, &high, log2_size + count);
last_set_index >>= 1;
++count;
}
value = build_int_cst_wide (value_type, low, high);
}
else if (! pointer_after_end)
{
set_bit (&low, &high, 0);
value = build_int_cst_wide (value_type, low, high);
}
else
{
procedure_object_descriptor:
value = build_int_cst (value_type, 2);
}
return value;
}