This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[jit] Reject creating arrays of fieldless structs


Committed the following to branch dmalcolm/jit:

Investigating a bug in a project using libgccjit revealed a problem where
fields within a struct within the JIT-created code weren't laid out in the
same places as the supposedly same struct in normally-built code:

  struct foo
  {
    int a;
    int b;
    int c;
  };

  struct bar
  {
    int d;
    struct foo e[20];
    int f; /* <<< error here */
  };

Field "f" was erroneously compiled as if "e" was only 4 bytes in size.

The root cause turned out to be that the client code was creating the
array type for
    struct foo e[20]
before the fields of "struct foo" had been set, hence the call to
layout_type for the array type would fail this conditional:
  2168  /* We need to know both bounds in order to compute the size.  */
  2169  if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
  2170      && TYPE_SIZE (element))
because TYPE_SIZE(element) was 0 at that time.

Add an error for this case, to ensure that client code can only create an
array of structs once the fields of the struct have been set up.

gcc/jit/
	* internal-api.c (gcc::jit::recording::context::new_array_type):
	Reject attempts to create an array of a struct if the fields of
	the struct haven't yet been set.
	* internal-api.h (gcc::jit::recording::type::dyn_cast_struct): New
	virtual function.
	(gcc::jit::recording::struct_::dyn_cast_struct): New, overriding
	for this subclass.
	(gcc::jit::recording::struct_::get_name): New.
---
 gcc/jit/ChangeLog.jit  | 11 +++++++++++
 gcc/jit/internal-api.c |  9 +++++++++
 gcc/jit/internal-api.h |  6 +++++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index f5c4742..65fba51 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,14 @@
+2014-07-14  David Malcolm  <dmalcolm@redhat.com>
+
+	* internal-api.c (gcc::jit::recording::context::new_array_type):
+	Reject attempts to create an array of a struct if the fields of
+	the struct haven't yet been set.
+	* internal-api.h (gcc::jit::recording::type::dyn_cast_struct): New
+	virtual function.
+	(gcc::jit::recording::struct_::dyn_cast_struct): New, overriding
+	for this subclass.
+	(gcc::jit::recording::struct_::get_name): New.
+
 2014-05-07  David Malcolm  <dmalcolm@redhat.com>
 
 	* Make-lang.in (LIBGCCJIT_LINKER_NAME): New.
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index f45595e..768d41c 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -345,6 +345,15 @@ recording::context::new_array_type (recording::location *loc,
 				    recording::type *element_type,
 				    int num_elements)
 {
+  if (struct_ *s = element_type->dyn_cast_struct ())
+    if (!s->get_fields ())
+      {
+	add_error (NULL,
+		   "cannot create an array of type %s"
+		   " until the fields have been set",
+		   s->get_name ()->c_str ());
+	return NULL;
+      }
   recording::type *result =
     new recording::array_type (this, loc, element_type, num_elements);
   record (result);
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 34c1de3..1612a22 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -477,8 +477,9 @@ public:
      The caller is responsible for setting an error.  */
   virtual type *dereference () = 0;
 
-  /* Dynamic cast.  */
+  /* Dynamic casts.  */
   virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
+  virtual struct_ *dyn_cast_struct () { return NULL; }
 
   /* Is it typesafe to copy to this type from rtype?  */
   virtual bool accepts_writes_from (type *rtype)
@@ -755,9 +756,12 @@ public:
 	   location *loc,
 	   string *name);
 
+  struct_ *dyn_cast_struct () { return this; }
+
   type *
   as_type () { return this; }
 
+  string *get_name () const { return m_name; }
   fields * get_fields () { return m_fields; }
 
   void
-- 
1.8.5.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]