#include <coretypes.h>
#include <tm.h>
#include <tree.h>
+#include <hashtab.h>
#include "aop.h"
#include "aop-type.h"
.size = 16,
};
+static htab_t type_table = NULL;
+
+/* Compare strings but safe to pass NULL strings. Two NULL inputs are
+ considered equal. */
+static bool
+safe_str_equal (const char *a, const char *b)
+{
+ if (a == NULL && b == NULL)
+ return true;
+ else if (a == NULL || b == NULL)
+ return false;
+ else
+ return (strcmp (a, b) == 0);
+}
+
+/* Equality function for the type_table hash table. */
+static int
+eq_type_table (const void *table_ptr, const void *key_ptr)
+{
+ const struct aop_type *type_in_table = (const struct aop_type *)table_ptr;
+ const struct aop_type *key_type = (const struct aop_type *)key_ptr;
+
+ return ((type_in_table->kind == key_type->kind)
+ && (type_in_table->pointer_levels == key_type->pointer_levels)
+ && safe_str_equal (type_in_table->tag, key_type->tag)
+ && (type_in_table->size == key_type->size));
+}
+
+/* Hash function for the type_table hash table. */
+static hashval_t
+hash_type_table (const void *ptr)
+{
+ hashval_t hash;
+ const struct aop_type *type = (const struct aop_type *)ptr;
+
+ /* We start the hash off by hashing the tag string if there is one
+ or an arbitrary seed if there isn't. */
+ hash = (type->tag != NULL) ? htab_hash_string (type->tag) : 8675309;
+ hash = iterative_hash (&type->kind, sizeof (type->kind), hash);
+ hash = iterative_hash (&type->pointer_levels, sizeof (type->pointer_levels),
+ hash);
+ hash = iterative_hash (&type->size, sizeof (type->size), hash);
+
+ return hash;
+}
+
+/* Function to destroy an element in the type table after it is
+ deleted (or when the whole table is destroyed). */
+static void
+del_type_table (void *ptr)
+{
+ struct aop_type *type = (struct aop_type *)ptr;
+
+ if (type->tag != NULL)
+ free ((char *)type->tag);
+
+ free (type);
+}
+
+/* Return a pointer to a type object that is identical to the supplied
+ type object. If you pass two identical type objects to
+ get_dedup_type(), you will get the same pointer back. The objects
+ that get_dedup_type() returns are valid for the rest of the
+ compiler's execution. */
+static const struct aop_type *
+get_dedup_type (struct aop_type *type)
+{
+ struct aop_type **type_slot;
+
+ aop_assert (type_table != NULL);
+
+ type_slot = (struct aop_type **)htab_find_slot (type_table, type, INSERT);
+ if (*type_slot == NULL)
+ {
+ *type_slot = xmalloc (sizeof (struct aop_type));
+ memcpy (*type_slot, type, sizeof (struct aop_type));
+
+ if (type->tag != NULL)
+ (*type_slot)->tag = xstrdup (type->tag);
+ }
+
+ return *type_slot;
+}
+
+void
+init_type_table ()
+{
+ type_table = htab_create_alloc (10, hash_type_table, eq_type_table,
+ del_type_table, xcalloc, free);
+ aop_assert (type_table != NULL);
+}
+
+void
+free_type_table ()
+{
+ aop_assert (type_table != NULL);
+ htab_delete (type_table);
+ type_table = NULL;
+}
+
/**
* \defgroup type InterAspect Types
* \{
return &_aop_t_float128;
}
+const struct aop_type *
+aop_t_pointer_to (const struct aop_type *type)
+{
+ struct aop_type pointer_type;
+
+ memcpy (&pointer_type, type, sizeof (struct aop_type));
+ pointer_type.pointer_levels++;
+
+ return get_dedup_type (&pointer_type);
+}
+
/* Close Doxygen defgroup block. */
/**
* \}
bool
does_type_match (tree gcc_type, const struct aop_type *aop_type)
{
+ int pointer_levels;
+
aop_assert (gcc_type != NULL && aop_type != NULL);
- if (aop_type->kind == ATK_ALL_POINTER)
+ pointer_levels = aop_type->pointer_levels;
+ while (pointer_levels > 0)
{
- return (TREE_CODE (gcc_type) == POINTER_TYPE);
+ if (TREE_CODE (gcc_type) != POINTER_TYPE)
+ return false;
+
+ /* What type does it point to? */
+ gcc_type = TREE_TYPE (gcc_type);
+ pointer_levels--;
}
- else if (aop_type->pointer_levels == 0)
+
+ switch (aop_type->kind)
{
- switch (aop_type->kind)
- {
- case ATK_SIGNED_INT:
- case ATK_UNSIGNED_INT:
- return does_int_type_match (gcc_type, aop_type->kind, aop_type->size);
- case ATK_FP:
- return does_fp_type_match (gcc_type, aop_type->size);
- default:
- break;
- }
+ case ATK_ALL_POINTER:
+ return (TREE_CODE (gcc_type) == POINTER_TYPE);
+ case ATK_SIGNED_INT:
+ case ATK_UNSIGNED_INT:
+ return does_int_type_match (gcc_type, aop_type->kind, aop_type->size);
+ case ATK_FP:
+ return does_fp_type_match (gcc_type, aop_type->size);
+ default:
+ aop_assert (0);
}
-
- aop_assert (0);
}