This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Move "types deeply equal" code from py-type.c to gdbtypes.c
- From: Doug Evans <xdje42 at gmail dot com>
- To: Tom Tromey <tromey at redhat dot com>
- Cc: Stan Shebs <stanshebs at earthlink dot net>, gdb-patches at sourceware dot org
- Date: Sat, 09 Nov 2013 11:54:34 -0800
- Subject: Re: [PATCH] Move "types deeply equal" code from py-type.c to gdbtypes.c
- Authentication-results: sourceware.org; auth=none
- References: <CAA8o+=Q2ur7dAZYRRgOeRV1=KW_2azOwRY8meVHYKaOx3Yh9GQ at mail dot gmail dot com> <527AB482 dot 80600 at earthlink dot net> <87ppqd1a0t dot fsf at fleche dot redhat dot com> <m3li10bsbj dot fsf at seba dot sebabeach dot org> <87r4asz3be dot fsf at fleche dot redhat dot com> <CAA8o+=T2a8WLE8zi1NO=u8B460KmwOvA2m2pzVJCkAsXw6vHBw at mail dot gmail dot com> <CAA8o+=RBU=AkLmW=Q+J16jZgJZ-Fpp8nPajK-FDH-AyrEJgQyQ at mail dot gmail dot com> <CAA8o+=RLzeC6o8X2ZBsc_HGq_aJAUYVGuyWJe49No9UcyAS4yA at mail dot gmail dot com>
Doug Evans <dje@sebabeach.org> writes:
> WTF? Where'd the patch go?
> Let's try this again.
>
> On Sat, Nov 9, 2013 at 11:47 AM, Doug Evans <dje@sebabeach.org> wrote:
>> On Thu, Nov 7, 2013 at 8:40 AM, Doug Evans <dje@sebabeach.org> wrote:
>>> On Thu, Nov 7, 2013 at 6:36 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>>>>> "Doug" == Doug Evans <dje@sebabeach.org> writes:
>>>>
>>>> Doug> Tom Tromey <tromey@redhat.com> writes:
>>>> Stan> +/* A helper function for tyscm_richcompare that checks two types for
>>>> Stan> + "deep" equality. Returns non-zero if the types are considered the
>>>> Stan> + same, zero otherwise. */
>>>>>>
>>>> Stan> "tyscm_richcompare"? Should that be typy_... ?
>>>>>>
>>>>>> It would be helpful if Doug could list all the change he made when
>>>>>> moving the code.
>>>>
>>>> Doug> I don't understand.
>>>> Doug> Which changes? While useful beyond its present state, this is in
>>>> Doug> essence just a cleanup.
>>>>
>>>> I had thought this patch was more or less a straight move of the code.
>>>> But Stan's note revealed a change from what is currently in the tree.
>>>> So the question is, can you say what else changed?
>>>> That would be handy so I don't have to go over it line-by-line myself.
>>>
>>> Ah. Except for the comment (*1) the only substantive change is in the result:
>>> Py_{NE,EQ} -> 0.1.
>>>
>>> (*1): Early on I made a copy because I wasn't sure how things would end up,
>>> and left in a FIXME to remind myself to revisit.
>>> I revisited and realized there's no need for the copy, but missed the
>>> comment. Blech.
>>> "diff -b before after" shows nothing of note to me.
>>
>> Here's v2 of the patch.
>>
>> I fixed the comment and added an assert to check type1,type2 != NULL.
>>
>> I changed the email address in the ChangeLog entry 'cus I'm having
>> problems with this domain.
>> After this email hopefully the switchover is complete.
Well that's weird.
Ok, no more attachment.
2013-11-09 Doug Evans <xdje42@gmail.com>
* gdbtypes.c: #include bcache.h, dwarf2loc.h.
(type_equality_entry): Move here from python/py-type.c.
(type_equality_entry_d): Ditto.
(compare_maybe_null_strings, check_types_equal): Ditto.
(check_types_worklist, types_deeply_equal): Ditto.
* gdbtypes.h (types_deeply_equal): Declare.
* python/py-type.c: Remove inclusion of bcache.h, dwarf2loc.h.
(typy_richcompare): Update.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 9069a11..70a7fb5 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -38,6 +38,8 @@
#include "hashtab.h"
#include "exceptions.h"
#include "cp-support.h"
+#include "bcache.h"
+#include "dwarf2loc.h"
/* Initialize BADNESS constants. */
@@ -2494,7 +2496,217 @@ types_equal (struct type *a, struct type *b)
return 0;
}
+
+/* Deep comparison of types. */
+
+/* An entry in the type-equality bcache. */
+
+typedef struct type_equality_entry
+{
+ struct type *type1, *type2;
+} type_equality_entry_d;
+
+DEF_VEC_O (type_equality_entry_d);
+
+/* A helper function to compare two strings. Returns 1 if they are
+ the same, 0 otherwise. Handles NULLs properly. */
+
+static int
+compare_maybe_null_strings (const char *s, const char *t)
+{
+ if (s == NULL && t != NULL)
+ return 0;
+ else if (s != NULL && t == NULL)
+ return 0;
+ else if (s == NULL && t== NULL)
+ return 1;
+ return strcmp (s, t) == 0;
+}
+
+/* A helper function for check_types_worklist that checks two types for
+ "deep" equality. Returns non-zero if the types are considered the
+ same, zero otherwise. */
+
+static int
+check_types_equal (struct type *type1, struct type *type2,
+ VEC (type_equality_entry_d) **worklist)
+{
+ CHECK_TYPEDEF (type1);
+ CHECK_TYPEDEF (type2);
+
+ if (type1 == type2)
+ return 1;
+
+ if (TYPE_CODE (type1) != TYPE_CODE (type2)
+ || TYPE_LENGTH (type1) != TYPE_LENGTH (type2)
+ || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)
+ || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2)
+ || TYPE_VARARGS (type1) != TYPE_VARARGS (type2)
+ || TYPE_VECTOR (type1) != TYPE_VECTOR (type2)
+ || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2)
+ || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2)
+ || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
+ return 0;
+
+ if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
+ TYPE_TAG_NAME (type2)))
+ return 0;
+ if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
+ return 0;
+
+ if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
+ {
+ if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2),
+ sizeof (*TYPE_RANGE_DATA (type1))) != 0)
+ return 0;
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < TYPE_NFIELDS (type1); ++i)
+ {
+ const struct field *field1 = &TYPE_FIELD (type1, i);
+ const struct field *field2 = &TYPE_FIELD (type2, i);
+ struct type_equality_entry entry;
+
+ if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2)
+ || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
+ || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
+ return 0;
+ if (!compare_maybe_null_strings (FIELD_NAME (*field1),
+ FIELD_NAME (*field2)))
+ return 0;
+ switch (FIELD_LOC_KIND (*field1))
+ {
+ case FIELD_LOC_KIND_BITPOS:
+ if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2))
+ return 0;
+ break;
+ case FIELD_LOC_KIND_ENUMVAL:
+ if (FIELD_ENUMVAL (*field1) != FIELD_ENUMVAL (*field2))
+ return 0;
+ break;
+ case FIELD_LOC_KIND_PHYSADDR:
+ if (FIELD_STATIC_PHYSADDR (*field1)
+ != FIELD_STATIC_PHYSADDR (*field2))
+ return 0;
+ break;
+ case FIELD_LOC_KIND_PHYSNAME:
+ if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1),
+ FIELD_STATIC_PHYSNAME (*field2)))
+ return 0;
+ break;
+ case FIELD_LOC_KIND_DWARF_BLOCK:
+ {
+ struct dwarf2_locexpr_baton *block1, *block2;
+
+ block1 = FIELD_DWARF_BLOCK (*field1);
+ block2 = FIELD_DWARF_BLOCK (*field2);
+ if (block1->per_cu != block2->per_cu
+ || block1->size != block2->size
+ || memcmp (block1->data, block2->data, block1->size) != 0)
+ return 0;
+ }
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, _("Unsupported field kind "
+ "%d by check_types_equal"),
+ FIELD_LOC_KIND (*field1));
+ }
+
+ entry.type1 = FIELD_TYPE (*field1);
+ entry.type2 = FIELD_TYPE (*field2);
+ VEC_safe_push (type_equality_entry_d, *worklist, &entry);
+ }
+ }
+
+ if (TYPE_TARGET_TYPE (type1) != NULL)
+ {
+ struct type_equality_entry entry;
+
+ if (TYPE_TARGET_TYPE (type2) == NULL)
+ return 0;
+
+ entry.type1 = TYPE_TARGET_TYPE (type1);
+ entry.type2 = TYPE_TARGET_TYPE (type2);
+ VEC_safe_push (type_equality_entry_d, *worklist, &entry);
+ }
+ else if (TYPE_TARGET_TYPE (type2) != NULL)
+ return 0;
+
+ return 1;
+}
+
+/* Check types on a worklist for equality. Returns zero if any pair
+ is not equal, non-zero if they are all considered equal. */
+
+static int
+check_types_worklist (VEC (type_equality_entry_d) **worklist,
+ struct bcache *cache)
+{
+ while (!VEC_empty (type_equality_entry_d, *worklist))
+ {
+ struct type_equality_entry entry;
+ int added;
+
+ entry = *VEC_last (type_equality_entry_d, *worklist);
+ VEC_pop (type_equality_entry_d, *worklist);
+
+ /* If the type pair has already been visited, we know it is
+ ok. */
+ bcache_full (&entry, sizeof (entry), cache, &added);
+ if (!added)
+ continue;
+ if (check_types_equal (entry.type1, entry.type2, worklist) == 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return non-zero if types TYPE1 and TYPE2 are equal, as determined by a
+ "deep comparison". Otherwise return zero. */
+
+int
+types_deeply_equal (struct type *type1, struct type *type2)
+{
+ volatile struct gdb_exception except;
+ int result = 0;
+ struct bcache *cache;
+ VEC (type_equality_entry_d) *worklist = NULL;
+ struct type_equality_entry entry;
+
+ gdb_assert (type1 != NULL && type2 != NULL);
+
+ /* Early exit for the simple case. */
+ if (type1 == type2)
+ return 1;
+
+ cache = bcache_xmalloc (NULL, NULL);
+
+ entry.type1 = type1;
+ entry.type2 = type2;
+ VEC_safe_push (type_equality_entry_d, worklist, &entry);
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ result = check_types_worklist (&worklist, cache);
+ }
+ /* check_types_worklist calls several nested helper functions,
+ some of which can raise a GDB Exception, so we just check
+ and rethrow here. If there is a GDB exception, a comparison
+ is not capable (or trusted), so exit. */
+ bcache_xfree (cache);
+ VEC_free (type_equality_entry_d, worklist);
+ /* Rethrow if there was a problem. */
+ if (except.reason < 0)
+ throw_exception (except);
+
+ return result;
+}
+
/* Compare one type (PARM) for compatibility with another (ARG).
* PARM is intended to be the parameter type of a function; and
* ARG is the supplied argument's type. This function tests if
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index d7fdedf..c7bef5f 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1664,4 +1664,6 @@ extern struct type *copy_type (const struct type *type);
extern int types_equal (struct type *, struct type *);
+extern int types_deeply_equal (struct type *, struct type *);
+
#endif /* GDBTYPES_H */
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 337e307..628a764 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -28,8 +28,6 @@
#include "objfiles.h"
#include "language.h"
#include "vec.h"
-#include "bcache.h"
-#include "dwarf2loc.h"
#include "typeprint.h"
typedef struct pyty_type_object
@@ -961,173 +959,6 @@ typy_str (PyObject *self)
return result;
}
-/* An entry in the type-equality bcache. */
-
-typedef struct type_equality_entry
-{
- struct type *type1, *type2;
-} type_equality_entry_d;
-
-DEF_VEC_O (type_equality_entry_d);
-
-/* A helper function to compare two strings. Returns 1 if they are
- the same, 0 otherwise. Handles NULLs properly. */
-
-static int
-compare_maybe_null_strings (const char *s, const char *t)
-{
- if (s == NULL && t != NULL)
- return 0;
- else if (s != NULL && t == NULL)
- return 0;
- else if (s == NULL && t== NULL)
- return 1;
- return strcmp (s, t) == 0;
-}
-
-/* A helper function for typy_richcompare that checks two types for
- "deep" equality. Returns Py_EQ if the types are considered the
- same, Py_NE otherwise. */
-
-static int
-check_types_equal (struct type *type1, struct type *type2,
- VEC (type_equality_entry_d) **worklist)
-{
- CHECK_TYPEDEF (type1);
- CHECK_TYPEDEF (type2);
-
- if (type1 == type2)
- return Py_EQ;
-
- if (TYPE_CODE (type1) != TYPE_CODE (type2)
- || TYPE_LENGTH (type1) != TYPE_LENGTH (type2)
- || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2)
- || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2)
- || TYPE_VARARGS (type1) != TYPE_VARARGS (type2)
- || TYPE_VECTOR (type1) != TYPE_VECTOR (type2)
- || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2)
- || TYPE_INSTANCE_FLAGS (type1) != TYPE_INSTANCE_FLAGS (type2)
- || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
- return Py_NE;
-
- if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
- TYPE_TAG_NAME (type2)))
- return Py_NE;
- if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
- return Py_NE;
-
- if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
- {
- if (memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2),
- sizeof (*TYPE_RANGE_DATA (type1))) != 0)
- return Py_NE;
- }
- else
- {
- int i;
-
- for (i = 0; i < TYPE_NFIELDS (type1); ++i)
- {
- const struct field *field1 = &TYPE_FIELD (type1, i);
- const struct field *field2 = &TYPE_FIELD (type2, i);
- struct type_equality_entry entry;
-
- if (FIELD_ARTIFICIAL (*field1) != FIELD_ARTIFICIAL (*field2)
- || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
- || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
- return Py_NE;
- if (!compare_maybe_null_strings (FIELD_NAME (*field1),
- FIELD_NAME (*field2)))
- return Py_NE;
- switch (FIELD_LOC_KIND (*field1))
- {
- case FIELD_LOC_KIND_BITPOS:
- if (FIELD_BITPOS (*field1) != FIELD_BITPOS (*field2))
- return Py_NE;
- break;
- case FIELD_LOC_KIND_ENUMVAL:
- if (FIELD_ENUMVAL (*field1) != FIELD_ENUMVAL (*field2))
- return Py_NE;
- break;
- case FIELD_LOC_KIND_PHYSADDR:
- if (FIELD_STATIC_PHYSADDR (*field1)
- != FIELD_STATIC_PHYSADDR (*field2))
- return Py_NE;
- break;
- case FIELD_LOC_KIND_PHYSNAME:
- if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1),
- FIELD_STATIC_PHYSNAME (*field2)))
- return Py_NE;
- break;
- case FIELD_LOC_KIND_DWARF_BLOCK:
- {
- struct dwarf2_locexpr_baton *block1, *block2;
-
- block1 = FIELD_DWARF_BLOCK (*field1);
- block2 = FIELD_DWARF_BLOCK (*field2);
- if (block1->per_cu != block2->per_cu
- || block1->size != block2->size
- || memcmp (block1->data, block2->data, block1->size) != 0)
- return Py_NE;
- }
- break;
- default:
- internal_error (__FILE__, __LINE__, _("Unsupported field kind "
- "%d by check_types_equal"),
- FIELD_LOC_KIND (*field1));
- }
-
- entry.type1 = FIELD_TYPE (*field1);
- entry.type2 = FIELD_TYPE (*field2);
- VEC_safe_push (type_equality_entry_d, *worklist, &entry);
- }
- }
-
- if (TYPE_TARGET_TYPE (type1) != NULL)
- {
- struct type_equality_entry entry;
-
- if (TYPE_TARGET_TYPE (type2) == NULL)
- return Py_NE;
-
- entry.type1 = TYPE_TARGET_TYPE (type1);
- entry.type2 = TYPE_TARGET_TYPE (type2);
- VEC_safe_push (type_equality_entry_d, *worklist, &entry);
- }
- else if (TYPE_TARGET_TYPE (type2) != NULL)
- return Py_NE;
-
- return Py_EQ;
-}
-
-/* Check types on a worklist for equality. Returns Py_NE if any pair
- is not equal, Py_EQ if they are all considered equal. */
-
-static int
-check_types_worklist (VEC (type_equality_entry_d) **worklist,
- struct bcache *cache)
-{
- while (!VEC_empty (type_equality_entry_d, *worklist))
- {
- struct type_equality_entry entry;
- int added;
-
- entry = *VEC_last (type_equality_entry_d, *worklist);
- VEC_pop (type_equality_entry_d, *worklist);
-
- /* If the type pair has already been visited, we know it is
- ok. */
- bcache_full (&entry, sizeof (entry), cache, &added);
- if (!added)
- continue;
-
- if (check_types_equal (entry.type1, entry.type2, worklist) == Py_NE)
- return Py_NE;
- }
-
- return Py_EQ;
-}
-
/* Implement the richcompare method. */
static PyObject *
@@ -1150,30 +981,16 @@ typy_richcompare (PyObject *self, PyObject *other, int op)
result = Py_EQ;
else
{
- struct bcache *cache;
- VEC (type_equality_entry_d) *worklist = NULL;
- struct type_equality_entry entry;
-
- cache = bcache_xmalloc (NULL, NULL);
-
- entry.type1 = type1;
- entry.type2 = type2;
- VEC_safe_push (type_equality_entry_d, worklist, &entry);
-
TRY_CATCH (except, RETURN_MASK_ALL)
{
- result = check_types_worklist (&worklist, cache);
+ result = types_deeply_equal (type1, type2);
}
- /* check_types_worklist calls several nested Python helper
- functions, some of which can raise a GDB Exception, so we
- just check and convert here. If there is a GDB exception, a
- comparison is not capable (or trusted), so exit. */
- bcache_xfree (cache);
- VEC_free (type_equality_entry_d, worklist);
+ /* If there is a GDB exception, a comparison is not capable
+ (or trusted), so exit. */
GDB_PY_HANDLE_EXCEPTION (except);
}
- if (op == result)
+ if (op == (result ? Py_EQ : Py_NE))
Py_RETURN_TRUE;
Py_RETURN_FALSE;
}