#include <tm.h>
#include <tree.h>
#include <hashtab.h>
+#include <toplev.h>
#include "aop.h"
#include "aop-type.h"
return *type_slot;
}
+/* Return a deduplicated pointer to an aop_type object. The pointer
+ is valid for the rest of the compiler's execution. */
+static const struct aop_type *
+init_aop_type (enum aop_tykind kind, int pointer_levels, const char *tag,
+ int size)
+{
+ struct aop_type type;
+ type.kind = kind;
+ type.pointer_levels = pointer_levels;
+ type.tag = tag;
+ type.size = size;
+
+ return get_dedup_type (&type);
+}
+
void
init_type_table ()
{
return &_aop_t_float128;
}
+const struct aop_type *
+aop_t_struct (const char *tag)
+{
+ if (tag == NULL)
+ fatal_error ("(InterAspect) Must supply a non-NULL tag when specifying a"
+ " struct type.");
+
+ return init_aop_type (ATK_STRUCT, 0, tag, -1);
+}
+
+const struct aop_type *
+aop_t_union (const char *tag)
+{
+ if (tag == NULL)
+ fatal_error ("(InterAspect) Must supply a non-NULL tag when specifying a"
+ " union type.");
+
+ return init_aop_type (ATK_UNION, 0, tag, -1);
+}
+
/**
* Return a type that will match pointers to the specified type.
*
&& type->size <= 0);
}
+/* Given a type node, get that type node's identifier. */
+static tree
+get_type_identifier (tree gcc_type)
+{
+ tree type_name = TYPE_NAME (gcc_type);
+
+ /* On rare occasion, TYPE_NAME() mysteriously gives us a TYPE_DECL
+ instead of the IDENTIFIER_NODE we really wanted for Christmas.
+ Documentation in tree.h promises that you can use
+ DECL_ORIGINAL_TYPE to get through to the _actual_ type, which has
+ the real IDENTIFIER_NODE.*/
+ while (type_name != NULL && TREE_CODE (type_name) == TYPE_DECL)
+ if (DECL_ORIGINAL_TYPE (type_name) != NULL)
+ type_name = TYPE_NAME (DECL_ORIGINAL_TYPE (type_name));
+ else
+ type_name = NULL;
+ gcc_assert(type_name == NULL || TREE_CODE (type_name) == IDENTIFIER_NODE);
+ return type_name;
+}
+
+/* Given a type node, get that type node's name, or NULL if it has no
+ name. */
+static const char *
+get_type_name (tree gcc_type)
+{
+ tree type_name = get_type_identifier (gcc_type);
+ return (type_name != NULL) ? IDENTIFIER_POINTER (type_name) : NULL;
+}
+
static bool
does_int_type_match (tree gcc_type, enum aop_tykind kind, int aop_size)
{
}
}
+static bool
+does_custom_type_match (tree gcc_type, enum aop_tykind kind, const char *tag)
+{
+ aop_assert (kind == ATK_STRUCT || kind == ATK_UNION);
+
+ if ((kind == ATK_STRUCT && TREE_CODE (gcc_type) == RECORD_TYPE)
+ || (kind == ATK_UNION && TREE_CODE (gcc_type) == UNION_TYPE))
+ {
+ aop_assert (tag != NULL);
+ return safe_str_equal (tag, get_type_name (gcc_type));
+ }
+ else
+ {
+ return false;
+ }
+}
+
/* Match an actual GCC type with an AOP type specification. */
bool
does_type_match (tree gcc_type, const struct aop_type *aop_type)
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);
+ case ATK_STRUCT:
+ case ATK_UNION:
+ return does_custom_type_match (gcc_type, aop_type->kind, aop_type->tag);
default:
aop_assert (0);
}