introduce gcc_jit_context_new_bitfield
authorAndrea Corallo <andrea.corallo@arm.com>
Thu, 4 Jul 2019 15:46:00 +0000 (15:46 +0000)
committerAndrea Corallo <akrl@gcc.gnu.org>
Thu, 4 Jul 2019 15:46:00 +0000 (15:46 +0000)
gcc/jit/ChangeLog:
2019-07-04  Andrea Corallo <andrea.corallo@arm.com>

* docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag.
* docs/topics/types.rst: Add gcc_jit_context_new_bitfield.
* jit-common.h (namespace recording): Add class bitfield.
* jit-playback.c:
(DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): Add macros.
(playback::context::new_bitfield): New method.
(playback::compound_type::set_fields): Add bitfield support.
(playback::lvalue::mark_addressable): Was jit_mark_addressable make this
a method of lvalue plus return a bool to communicate success.
(playback::lvalue::get_address): Check for jit_mark_addressable return
value.
* jit-playback.h (new_bitfield): New method.
(class bitfield): New class.
(class lvalue): Add jit_mark_addressable method.
* jit-recording.c (recording::context::new_bitfield): New method.
(recording::bitfield::replay_into): New method.
(recording::bitfield::write_to_dump): Likewise.
(recording::bitfield::make_debug_string): Likewise.
(recording::bitfield::write_reproducer): Likewise.
* jit-recording.h (class context): Add new_bitfield method.
(class field): Make it derivable by class bitfield.
(class bitfield): Add new class.
* libgccjit++.h (class context): Add new_bitfield method.
* libgccjit.c (struct gcc_jit_bitfield): New structure.
(gcc_jit_context_new_bitfield): New function.
* libgccjit.h
(LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield) New macro.
(gcc_jit_context_new_bitfield): New function.
* libgccjit.map (LIBGCCJIT_ABI_12) New ABI tag.

gcc/testsuite/ChangeLog:
2019-07-04  Andrea Corallo <andrea.corallo@arm.com>

* jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c.
* jit.dg/test-accessing-bitfield.c: New testcase.
* jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c:
Likewise.
* jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c:
Likewise.
* jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c:
Likewise.

From-SVN: r273086

18 files changed:
gcc/jit/ChangeLog
gcc/jit/docs/topics/compatibility.rst
gcc/jit/docs/topics/types.rst
gcc/jit/jit-common.h
gcc/jit/jit-playback.c
gcc/jit/jit-playback.h
gcc/jit/jit-recording.c
gcc/jit/jit-recording.h
gcc/jit/libgccjit++.h
gcc/jit/libgccjit.c
gcc/jit/libgccjit.h
gcc/jit/libgccjit.map
gcc/testsuite/ChangeLog
gcc/testsuite/jit.dg/all-non-failing-tests.h
gcc/testsuite/jit.dg/test-accessing-bitfield.c [new file with mode: 0644]
gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c [new file with mode: 0644]
gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c [new file with mode: 0644]
gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c [new file with mode: 0644]

index 9958db15ee0159f5e0cccae2dc974eff29ab6b0e..8323e2f488e5dfd52d8245a7ff67258c0a2c041c 100644 (file)
@@ -1,3 +1,35 @@
+2019-07-04  Andrea Corallo <andrea.corallo@arm.com>
+
+       * docs/topics/compatibility.rst (LIBGCCJIT_ABI_12): New ABI tag.
+       * docs/topics/types.rst: Add gcc_jit_context_new_bitfield.
+       * jit-common.h (namespace recording): Add class bitfield.
+       * jit-playback.c:
+       (DECL_C_BIT_FIELD, SET_DECL_C_BIT_FIELD): Add macros.
+       (playback::context::new_bitfield): New method.
+       (playback::compound_type::set_fields): Add bitfield support.
+       (playback::lvalue::mark_addressable): Was jit_mark_addressable make this
+       a method of lvalue plus return a bool to communicate success.
+       (playback::lvalue::get_address): Check for jit_mark_addressable return
+       value.
+       * jit-playback.h (new_bitfield): New method.
+       (class bitfield): New class.
+       (class lvalue): Add jit_mark_addressable method.
+       * jit-recording.c (recording::context::new_bitfield): New method.
+       (recording::bitfield::replay_into): New method.
+       (recording::bitfield::write_to_dump): Likewise.
+       (recording::bitfield::make_debug_string): Likewise.
+       (recording::bitfield::write_reproducer): Likewise.
+       * jit-recording.h (class context): Add new_bitfield method.
+       (class field): Make it derivable by class bitfield.
+       (class bitfield): Add new class.
+       * libgccjit++.h (class context): Add new_bitfield method.
+       * libgccjit.c (struct gcc_jit_bitfield): New structure.
+       (gcc_jit_context_new_bitfield): New function.
+       * libgccjit.h
+       (LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield) New macro.
+       (gcc_jit_context_new_bitfield): New function.
+       * libgccjit.map (LIBGCCJIT_ABI_12) New ABI tag.
+
 2019-03-21  Jakub Jelinek  <jakub@redhat.com>
 
        * jit-recording.c (reproducer::m_set_identifiers): Use false as Lazy
index abefa56f37d032b814d814c75ee228ca576a364c..da649206cec5a2f7b871b7ff9815f7c8a46c9c19 100644 (file)
@@ -177,3 +177,8 @@ entrypoints:
 --------------------
 ``LIBGCCJIT_ABI_11`` covers the addition of
 :func:`gcc_jit_context_add_driver_option`
+
+``LIBGCCJIT_ABI_12``
+--------------------
+``LIBGCCJIT_ABI_12`` covers the addition of
+:func:`gcc_jit_context_new_bitfield`
index 1d2dcd43f13a787e50cd64aab7a1f7ff389a0222..37d9d01a958d8d0ced39b60f1bf4be2d30ed5e46 100644 (file)
@@ -247,6 +247,30 @@ You can model C `struct` types by creating :c:type:`gcc_jit_struct *` and
    underlying string, so it is valid to pass in a pointer to an on-stack
    buffer.
 
+.. function:: gcc_jit_field *\
+              gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,\
+                                            gcc_jit_location *loc,\
+                                            gcc_jit_type *type,\
+                                            int width,\
+                                            const char *name)
+
+   Construct a new bit field, with the given type width and name.
+
+   The parameter ``name`` must be non-NULL.  The call takes a copy of the
+   underlying string, so it is valid to pass in a pointer to an on-stack
+   buffer.
+
+   The parameter ``type`` must be an integer type.
+
+   The parameter ``width`` must be a positive integer that does not exceed the
+   size of ``type``.
+
+   This API entrypoint was added in :ref:`LIBGCCJIT_ABI_12`; you can test
+   for its presence using
+   .. code-block:: c
+
+      #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+
 .. function:: gcc_jit_object *\
               gcc_jit_field_as_object (gcc_jit_field *field)
 
index 1d96cc352c81344e2e39978da3ce09399ee51e9a..e747d9611f2e63a786a7128187f199be1c16d5ee 100644 (file)
@@ -119,6 +119,7 @@ namespace recording {
        class union_;
       class vector_type;
     class field;
+      class bitfield;
     class fields;
     class function;
     class block;
index b74495c58b2cca694a54b3d13bd4df3c40156cd0..942c7304ebf78774d77bc2f7425a491ce1ef8194 100644 (file)
@@ -47,6 +47,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "jit-builtins.h"
 #include "jit-tempdir.h"
 
+/* Compare with gcc/c-family/c-common.h: DECL_C_BIT_FIELD,
+   SET_DECL_C_BIT_FIELD.
+   These are redefined here to avoid depending from the C frontend.  */
+#define DECL_JIT_BIT_FIELD(NODE) \
+  (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
+#define SET_DECL_JIT_BIT_FIELD(NODE) \
+  (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
 
 /* gcc::jit::playback::context::build_cast uses the convert.h API,
    which in turn requires the frontend to provide a "convert"
@@ -263,6 +270,46 @@ new_field (location *loc,
   return new field (decl);
 }
 
+/* Construct a playback::bitfield instance (wrapping a tree).  */
+
+playback::field *
+playback::context::
+new_bitfield (location *loc,
+             type *type,
+             int width,
+             const char *name)
+{
+  gcc_assert (type);
+  gcc_assert (name);
+  gcc_assert (width);
+
+  /* compare with c/c-decl.c:grokfield,  grokdeclarator and
+     check_bitfield_type_and_width.  */
+
+  tree tree_type = type->as_tree ();
+  gcc_assert (INTEGRAL_TYPE_P (tree_type));
+  tree tree_width = build_int_cst (integer_type_node, width);
+  if (compare_tree_int (tree_width, TYPE_PRECISION (tree_type)) > 0)
+    {
+      add_error (
+       loc,
+       "width of bit-field %s (width: %i) is wider than its type (width: %i)",
+       name, width, TYPE_PRECISION (tree_type));
+      return NULL;
+    }
+
+  tree decl = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
+                         get_identifier (name), type->as_tree ());
+  DECL_NONADDRESSABLE_P (decl) = true;
+  DECL_INITIAL (decl) = tree_width;
+  SET_DECL_JIT_BIT_FIELD (decl);
+
+  if (loc)
+    set_tree_location (decl, loc);
+
+  return new field (decl);
+}
+
 /* Construct a playback::compound_type instance (wrapping a tree).  */
 
 playback::compound_type *
@@ -295,8 +342,15 @@ playback::compound_type::set_fields (const auto_vec<playback::field *> *fields)
   for (unsigned i = 0; i < fields->length (); i++)
     {
       field *f = (*fields)[i];
-      DECL_CONTEXT (f->as_tree ()) = t;
-      fieldlist = chainon (f->as_tree (), fieldlist);
+      tree x = f->as_tree ();
+      DECL_CONTEXT (x) = t;
+      if (DECL_JIT_BIT_FIELD (x))
+       {
+         unsigned HOST_WIDE_INT width = tree_to_uhwi (DECL_INITIAL (x));
+         DECL_SIZE (x) = bitsize_int (width);
+         DECL_BIT_FIELD (x) = 1;
+       }
+      fieldlist = chainon (x, fieldlist);
     }
   fieldlist = nreverse (fieldlist);
   TYPE_FIELDS (t) = fieldlist;
@@ -1197,20 +1251,31 @@ dereference (location *loc)
   return new lvalue (get_context (), datum);
 }
 
-/* Mark EXP saying that we need to be able to take the
+/* Mark the lvalue saying that we need to be able to take the
    address of it; it should not be allocated in a register.
-   Compare with e.g. c/c-typeck.c: c_mark_addressable.  */
+   Compare with e.g. c/c-typeck.c: c_mark_addressable really_atomic_lvalue.
+   Returns false if a failure occurred (an error will already have been
+   added to the active context for this case).  */
 
-static void
-jit_mark_addressable (tree exp)
+bool
+playback::lvalue::
+mark_addressable (location *loc)
 {
-  tree x = exp;
+  tree x = as_tree ();;
 
   while (1)
     switch (TREE_CODE (x))
       {
       case COMPONENT_REF:
-       /* (we don't yet support bitfields)  */
+       if (DECL_JIT_BIT_FIELD (TREE_OPERAND (x, 1)))
+         {
+           gcc_assert (gcc::jit::active_playback_ctxt);
+           gcc::jit::
+             active_playback_ctxt->add_error (loc,
+                                              "cannot take address of "
+                                              "bit-field");
+           return false;
+         }
        /* fallthrough */
       case ADDR_EXPR:
       case ARRAY_REF:
@@ -1222,7 +1287,7 @@ jit_mark_addressable (tree exp)
       case COMPOUND_LITERAL_EXPR:
       case CONSTRUCTOR:
        TREE_ADDRESSABLE (x) = 1;
-       return;
+       return true;
 
       case VAR_DECL:
       case CONST_DECL:
@@ -1234,7 +1299,7 @@ jit_mark_addressable (tree exp)
        TREE_ADDRESSABLE (x) = 1;
        /* fallthrough */
       default:
-       return;
+       return true;
       }
 }
 
@@ -1251,8 +1316,10 @@ get_address (location *loc)
   tree ptr = build1 (ADDR_EXPR, t_ptrtype, t_lvalue);
   if (loc)
     get_context ()->set_tree_location (ptr, loc);
-  jit_mark_addressable (t_lvalue);
-  return new rvalue (get_context (), ptr);
+  if (mark_addressable (loc))
+    return new rvalue (get_context (), ptr);
+  else
+    return NULL;
 }
 
 /* The wrapper subclasses are GC-managed, but can own non-GC memory.
index bc4de9c035ab1f235dc3dc284ead6cc2e5413d2d..d4b148e3e57bf5afdd2fe5267515133f21e0c341 100644 (file)
@@ -75,6 +75,12 @@ public:
             type *type,
             const char *name);
 
+  field *
+  new_bitfield (location *loc,
+               type *type,
+               int width,
+               const char *name);
+
   compound_type *
   new_compound_type (location *loc,
                     const char *name,
@@ -426,6 +432,8 @@ private:
   tree m_inner;
 };
 
+class bitfield : public field {};
+
 class function : public wrapper
 {
 public:
@@ -614,6 +622,8 @@ public:
   rvalue *
   get_address (location *loc);
 
+private:
+  bool mark_addressable (location *loc);
 };
 
 class param : public lvalue
@@ -703,4 +713,3 @@ extern playback::context *active_playback_ctxt;
 } // namespace gcc
 
 #endif /* JIT_PLAYBACK_H */
-
index a332fe87514cad675c2057ff5f158fb830837906..495ac7f1ae945c207307635926fbf69c51ffdc31 100644 (file)
@@ -872,6 +872,24 @@ recording::context::new_field (recording::location *loc,
   return result;
 }
 
+/* Create a recording::bitfield instance and add it to this context's list
+   of mementos.
+
+   Implements the post-error-checking part of
+   gcc_jit_context_new_bitfield.  */
+
+recording::field *
+recording::context::new_bitfield (recording::location *loc,
+                                 recording::type *type,
+                                 int width,
+                                 const char *name)
+{
+  recording::field *result =
+    new recording::bitfield (this, loc, type, width, new_string (name));
+  record (result);
+  return result;
+}
+
 /* Create a recording::struct_ instance and add it to this context's
    list of mementos and list of compound types.
 
@@ -2962,7 +2980,7 @@ recording::field::replay_into (replayer *r)
    recording::memento::write_to_dump.  Dump each field
    by dumping a line of the form:
       TYPE NAME;
-   so that we can build up a struct/union field-byfield.  */
+   so that we can build up a struct/union field by field.  */
 
 void
 recording::field::write_to_dump (dump &d)
@@ -2999,6 +3017,66 @@ recording::field::write_reproducer (reproducer &r)
          m_name->get_debug_string ());
 }
 
+/* The implementation of class gcc::jit::recording::bitfield.  */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+   for recording::bitfield.  */
+
+void
+recording::bitfield::replay_into (replayer *r)
+{
+  set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
+                                    m_type->playback_type (),
+                                    m_width,
+                                    playback_string (m_name)));
+}
+
+/* Override the default implementation of
+   recording::memento::write_to_dump.  Dump each bit field
+   by dumping a line of the form:
+      TYPE NAME:WIDTH;
+   so that we can build up a struct/union field by field.  */
+
+void
+recording::bitfield::write_to_dump (dump &d)
+{
+  d.write ("  %s %s:%d;\n",
+          m_type->get_debug_string (),
+          m_name->c_str (),
+          m_width);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+   results of new_bitfield.  */
+
+recording::string *
+recording::bitfield::make_debug_string ()
+{
+  return string::from_printf (m_ctxt,
+                             "%s:%d",
+                             m_name->c_str (), m_width);
+}
+
+/* Implementation of recording::memento::write_reproducer for bitfields.  */
+
+void
+recording::bitfield::write_reproducer (reproducer &r)
+{
+  const char *id = r.make_identifier (this, "bitfield");
+  r.write ("  gcc_jit_field *%s =\n"
+          "    gcc_jit_context_new_bitfield (%s,\n"
+          "                               %s, /* gcc_jit_location *loc */\n"
+          "                               %s, /* gcc_jit_type *type, */\n"
+          "                               %d, /* int width, */\n"
+          "                               %s); /* const char *name */\n",
+          id,
+          r.get_identifier (get_context ()),
+          r.get_identifier (m_loc),
+          r.get_identifier_as_type (m_type),
+          m_width,
+          m_name->get_debug_string ());
+}
+
 /* The implementation of class gcc::jit::recording::compound_type */
 
 /* The constructor for gcc::jit::recording::compound_type.  */
index b9f2250802fb3eea5d2532594ec69ad1f9ba7e14..13ec7eabefab5d66b4e6634978d1e9b9989701e2 100644 (file)
@@ -95,6 +95,12 @@ public:
             type *type,
             const char *name);
 
+  field *
+  new_bitfield (location *loc,
+                type *type,
+                int width,
+                const char *name);
+
   struct_ *
   new_struct_type (location *loc,
                   const char *name);
@@ -822,9 +828,9 @@ public:
   compound_type * get_container () const { return m_container; }
   void set_container (compound_type *c) { m_container = c; }
 
-  void replay_into (replayer *) FINAL OVERRIDE;
+  void replay_into (replayer *) OVERRIDE;
 
-  void write_to_dump (dump &d) FINAL OVERRIDE;
+  void write_to_dump (dump &d) OVERRIDE;
 
   playback::field *
   playback_field () const
@@ -833,16 +839,41 @@ public:
   }
 
 private:
-  string * make_debug_string () FINAL OVERRIDE;
-  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+  string * make_debug_string () OVERRIDE;
+  void write_reproducer (reproducer &r) OVERRIDE;
 
-private:
+protected:
   location *m_loc;
   type *m_type;
   string *m_name;
   compound_type *m_container;
 };
 
+
+class bitfield : public field
+{
+public:
+  bitfield (context *ctxt,
+           location *loc,
+           type *type,
+           int width,
+           string *name)
+    : field (ctxt, loc, type, name),
+      m_width (width)
+  {}
+
+  void replay_into (replayer *) FINAL OVERRIDE;
+
+  void write_to_dump (dump &d) FINAL OVERRIDE;
+
+private:
+  string * make_debug_string () FINAL OVERRIDE;
+  void write_reproducer (reproducer &r) FINAL OVERRIDE;
+
+private:
+  int m_width;
+};
+
 /* Base class for struct_ and union_ */
 class compound_type : public type
 {
index 55aebcac4f54017f4d20ec789014714a67f665bb..0c5be5a85f39cfa60a9c3cda1f89b5ce687180bd 100644 (file)
@@ -152,6 +152,9 @@ namespace gccjit
     field new_field (type type_, const std::string &name,
                     location loc = location ());
 
+    field new_bitfield (type type_, int width, const std::string &name,
+                       location loc = location ());
+
     struct_ new_struct_type (const std::string &name,
                             std::vector<field> &fields,
                             location loc = location ());
@@ -757,6 +760,17 @@ context::new_field (type type_, const std::string &name, location loc)
                                           name.c_str ()));
 }
 
+inline field
+context::new_bitfield (type type_, int width, const std::string &name,
+                      location loc)
+{
+  return field (gcc_jit_context_new_bitfield (m_inner_ctxt,
+                                             loc.get_inner_location (),
+                                             type_.get_inner_type (),
+                                             width,
+                                             name.c_str ()));
+}
+
 inline struct_
 context::new_struct_type (const std::string &name,
                          std::vector<field> &fields,
index e4f17f8b35082bcb203c49d4ac0686924c2b4aa5..abf701919a293cb8ea3e4b04cac8a619c9770f1b 100644 (file)
@@ -62,6 +62,10 @@ struct gcc_jit_field : public gcc::jit::recording::field
 {
 };
 
+struct gcc_jit_bitfield : public gcc::jit::recording::bitfield
+{
+};
+
 struct gcc_jit_function : public gcc::jit::recording::function
 {
 };
@@ -554,6 +558,42 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
   return (gcc_jit_field *)ctxt->new_field (loc, type, name);
 }
 
+/* Public entrypoint.  See description in libgccjit.h.
+
+   After error-checking, the real work is done by the
+   gcc::jit::recording::context::new_bitfield method, in
+   jit-recording.c.  */
+
+gcc_jit_field *
+gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,
+                             gcc_jit_location *loc,
+                             gcc_jit_type *type,
+                             int width,
+                             const char *name)
+{
+  RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+  JIT_LOG_FUNC (ctxt->get_logger ());
+  /* LOC can be NULL.  */
+  RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
+  RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+  RETURN_NULL_IF_FAIL_PRINTF2 (type->is_int () || type->is_bool (),
+                              ctxt, loc,
+                              "bit-field %s has non integral type %s",
+                              name, type->get_debug_string ());
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    width > 0, ctxt, loc,
+    "invalid width %d for bitfield \"%s\" (must be > 0)",
+    width, name);
+  RETURN_NULL_IF_FAIL_PRINTF2 (
+    type->has_known_size (),
+    ctxt, loc,
+    "unknown size for field \"%s\" (type: %s)",
+    name,
+    type->get_debug_string ());
+
+  return (gcc_jit_field *)ctxt->new_bitfield (loc, type, width, name);
+}
+
 /* Public entrypoint.  See description in libgccjit.h.
 
    After error-checking, this calls the trivial
index beeb747ca8fc210d2347bc28f0338d37b59103d7..9c5f23bada5ffafb00aee534ad06ed25be1a92d0 100644 (file)
@@ -602,6 +602,21 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
                           gcc_jit_type *type,
                           const char *name);
 
+#define LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+
+/* Create a bit field, for use within a struct or union.
+
+   This API entrypoint was added in LIBGCCJIT_ABI_12; you can test for its
+   presence using
+     #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield
+*/
+extern gcc_jit_field *
+gcc_jit_context_new_bitfield (gcc_jit_context *ctxt,
+                             gcc_jit_location *loc,
+                             gcc_jit_type *type,
+                             int width,
+                             const char *name);
+
 /* Upcasting from field to object.  */
 extern gcc_jit_object *
 gcc_jit_field_as_object (gcc_jit_field *field);
index 16f5253ab23f4a35c7b2ae3742714ffd2aa7586b..40e1c78f2bbbe71cdcab390b530c54514227f132 100644 (file)
@@ -174,4 +174,9 @@ LIBGCCJIT_ABI_10 {
 LIBGCCJIT_ABI_11 {
   global:
     gcc_jit_context_add_driver_option;
-} LIBGCCJIT_ABI_10;
\ No newline at end of file
+} LIBGCCJIT_ABI_10;
+
+LIBGCCJIT_ABI_12 {
+  global:
+    gcc_jit_context_new_bitfield;
+} LIBGCCJIT_ABI_11;
\ No newline at end of file
index a89a21893be33526658c0da5065ca6c141a49720..e7db610ab78714a8cb053927053a3a0e611108fe 100644 (file)
@@ -1,3 +1,14 @@
+2019-07-04  Andrea Corallo <andrea.corallo@arm.com>
+
+       * jit.dg/all-non-failing-tests.h: Add test-accessing-bitfield.c.
+       * jit.dg/test-accessing-bitfield.c: New testcase.
+       * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c:
+       Likewise.
+       * jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c:
+       Likewise.
+       * jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c:
+       Likewise.
+
 2019-07-04  Jan Hubicka  <jh@suse.cz>
 
        * gcc.dg/tree-ssa/alias-access-path-3.c: New testcase.
 
        PR tree-optimization/91033
        * gcc.target/i386/pr91033.c: New test.
-       
+
 2019-07-03  Bob Duff  <duff@adacore.com>
 
        * gnat.dg/task2.adb, gnat.dg/task2_pkg.adb,
index 9a10418b308cf7aa9944b697d74ea50c52dfc56e..0272e6f846fbb4fd0aae0808793d8d2160fa0315 100644 (file)
@@ -8,6 +8,13 @@
    hooks provided by each test case.  */
 #define COMBINED_TEST
 
+/* test-accessing-bitfield.c */
+#define create_code create_code_accessing_bitfield
+#define verify_code verify_code_accessing_bitfield
+#include "test-accessing-bitfield.c"
+#undef create_code
+#undef verify_code
+
 /* test-accessing-struct.c */
 #define create_code create_code_accessing_struct
 #define verify_code verify_code_accessing_struct
@@ -266,6 +273,9 @@ struct testcase
 };
 
 const struct testcase testcases[] = {
+  {"accessing_bitfield",
+   create_code_accessing_bitfield,
+   verify_code_accessing_bitfield},
   {"accessing_struct",
    create_code_accessing_struct,
    verify_code_accessing_struct},
diff --git a/gcc/testsuite/jit.dg/test-accessing-bitfield.c b/gcc/testsuite/jit.dg/test-accessing-bitfield.c
new file mode 100644 (file)
index 0000000..5e80351
--- /dev/null
@@ -0,0 +1,130 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+struct bit_foo
+{
+  int i:3;
+  int x:5;
+  int y:5;
+  int z:10;
+  int j:3;
+};
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+     void
+     test_bitfield_access (struct bit_foo *f)
+     {
+        f->z = f->x + f->y;
+     }
+  */
+  gcc_jit_type *void_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_field *i =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 3,
+                                 "i");
+  gcc_jit_field *x =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 5,
+                                 "x");
+  gcc_jit_field *y =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 5,
+                                 "y");
+  gcc_jit_field *z =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 10,
+                                 "z");
+  gcc_jit_field *j =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 3,
+                                 "j");
+  gcc_jit_field *fields[] = {i, x, y, z, j};
+  gcc_jit_struct *struct_type =
+    gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 5, fields);
+  gcc_jit_type *ptr_type =
+    gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
+
+  /* Build the test function.  */
+  gcc_jit_param *param_f =
+    gcc_jit_context_new_param (ctxt, NULL, ptr_type, "f");
+  gcc_jit_function *test_fn =
+    gcc_jit_context_new_function (ctxt, NULL,
+                                  GCC_JIT_FUNCTION_EXPORTED,
+                                  void_type,
+                                  "test_bitfield_access",
+                                  1, &param_f,
+                                  0);
+
+  /* f->x + f->y */
+  gcc_jit_rvalue *sum =
+    gcc_jit_context_new_binary_op (
+      ctxt, NULL,
+      GCC_JIT_BINARY_OP_PLUS,
+      int_type,
+      gcc_jit_lvalue_as_rvalue (
+       gcc_jit_rvalue_dereference_field (
+         gcc_jit_param_as_rvalue (param_f),
+         NULL,
+         x)),
+      gcc_jit_lvalue_as_rvalue (
+       gcc_jit_rvalue_dereference_field (
+       gcc_jit_param_as_rvalue (param_f),
+       NULL,
+       y)));
+
+  /* f->z = ... */
+  gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);
+  gcc_jit_block_add_assignment (
+    block,
+    NULL,
+    gcc_jit_rvalue_dereference_field (
+      gcc_jit_param_as_rvalue (param_f),
+      NULL,
+      z),
+    sum);
+  gcc_jit_block_end_with_void_return (block, NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  typedef void (*fn_type) (struct bit_foo *);
+  CHECK_NON_NULL (result);
+
+  fn_type test_bitfield_access =
+    (fn_type)gcc_jit_result_get_code (result, "test_bitfield_access");
+  CHECK_NON_NULL (test_bitfield_access);
+
+  struct bit_foo tmp;
+  tmp.i = 3;
+  tmp.x = 5;
+  tmp.y = 7;
+  tmp.z = 0;
+  tmp.j = 3;
+
+  /* Call the JIT-generated function.  */
+  test_bitfield_access (&tmp);
+
+  /* Verify that the code correctly modified the field "z".  */
+  CHECK_VALUE (tmp.z, 12);
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c
new file mode 100644 (file)
index 0000000..d2ef5a8
--- /dev/null
@@ -0,0 +1,53 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to declare a bit-field with invalid type.  */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *bool_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_type *long_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG);
+  gcc_jit_type *float_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
+
+  gcc_jit_context_new_bitfield (ctxt,
+                               NULL,
+                               bool_type,
+                               3,
+                               "b");
+  gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 3,
+                                 "i");
+  gcc_jit_context_new_bitfield (ctxt,
+                               NULL,
+                               long_type,
+                               3,
+                               "l");
+  gcc_jit_context_new_bitfield (ctxt,
+                               NULL,
+                               float_type,
+                               5,
+                               "f");
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.         */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+                     "gcc_jit_context_new_bitfield: bit-field f has non "
+                     "integral type float");
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c
new file mode 100644 (file)
index 0000000..67db120
--- /dev/null
@@ -0,0 +1,44 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to declare a bit-field with invalid width.  */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  gcc_jit_type *short_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SHORT);
+  gcc_jit_field *i =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 short_type,
+                                 3,
+                                 "i");
+  gcc_jit_field *j =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 short_type,
+                                 157,
+                                 "j");
+  gcc_jit_field *fields[] = {i, j};
+  gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+  char error_str[256];
+  snprintf (error_str, sizeof (error_str),
+           "width of bit-field j (width: 157) is wider than its type "
+           "(width: %zu)", 8 * sizeof (short));
+
+  /* Verify that the correct error message was emitted.  */
+
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+                     error_str);
+}
diff --git a/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c
new file mode 100644 (file)
index 0000000..f102a6a
--- /dev/null
@@ -0,0 +1,66 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+/* Try to dereference a bit-field.  */
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+  /* Let's try to inject the equivalent of:
+
+     struct bit_foo
+     {
+       int i:3;
+       int j:3;
+     };
+
+     struct bit_foo f;
+     &(f.j)
+  */
+  gcc_jit_type *int_type =
+    gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+  gcc_jit_field *i =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 3,
+                                 "i");
+  gcc_jit_field *j =
+    gcc_jit_context_new_bitfield (ctxt,
+                                 NULL,
+                                 int_type,
+                                 3,
+                                 "j");
+  gcc_jit_field *fields[] = {i, j};
+  gcc_jit_type *struct_type =
+    gcc_jit_struct_as_type (
+      gcc_jit_context_new_struct_type (ctxt, NULL, "bit_foo", 2, fields));
+
+  gcc_jit_lvalue *f_struct =
+    gcc_jit_context_new_global (ctxt,
+                               NULL,
+                               GCC_JIT_GLOBAL_INTERNAL,
+                               struct_type,
+                               "f");
+
+  gcc_jit_lvalue_get_address (
+    gcc_jit_lvalue_access_field (
+      f_struct,
+      NULL,
+      j),
+    NULL);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+  CHECK_VALUE (result, NULL);
+
+  /* Verify that the correct error message was emitted.  */
+  CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt),
+                     "cannot take address of bit-field");
+}