public inbox for jit@gcc.gnu.org
 help / color / mirror / Atom feed
From: Andrea Corallo <Andrea.Corallo@arm.com>
To: David Malcolm <dmalcolm@redhat.com>
Cc: Andrea Corallo <Andrea.Corallo@arm.com>,
	"gcc-patches@gcc.gnu.org"	<gcc-patches@gcc.gnu.org>,
	"jit@gcc.gnu.org" <jit@gcc.gnu.org>, nd	<nd@arm.com>
Subject: Re: [PATCH][gcc] libgccjit: add bitfield support
Date: Tue, 01 Jan 2019 00:00:00 -0000	[thread overview]
Message-ID: <gkrd0j0a9lv.fsf@arm.com> (raw)
In-Reply-To: <1561410326.3885.34.camel@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2389 bytes --]

Hi David,
thanks for the suggestions.
Updated version for the bitfield libgccjit support patch here
addressing comments.

test-error-gcc_jit_context_new_bitfield-invalid-width.c is reworked
and now assume that the long of the compiler compiling the test is of
the same size of the libgccjit long.
I'm not sure this assumption is sufficent, in case is not we have to
find another way around this.

Checked with make check-jit runs clean.

Bests

  Andrea


2019-06-20  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-06-20  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.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gcc_jit_context_new_bitfield.patch --]
[-- Type: text/x-diff; name="gcc_jit_context_new_bitfield.patch", Size: 26634 bytes --]

diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index abefa56..da64920 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -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`
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 1d2dcd4..37d9d01 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -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)
 
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index 1d96cc3..e747d96 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -119,6 +119,7 @@ namespace recording {
 	class union_;
       class vector_type;
     class field;
+      class bitfield;
     class fields;
     class function;
     class block;
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index b74495c..ae8a732 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -47,6 +47,12 @@ 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
+   This is 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 +269,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 +341,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 +1250,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 +1286,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 +1298,7 @@ jit_mark_addressable (tree exp)
 	TREE_ADDRESSABLE (x) = 1;
 	/* fallthrough */
       default:
-	return;
+	return true;
       }
 }
 
@@ -1251,8 +1315,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.
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index bc4de9c..d4b148e 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -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 */
-
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index a332fe8..495ac7f 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -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.  */
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index b9f2250..13ec7ea 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -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
 {
diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index 55aebca..0c5be5a 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -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,
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index e4f17f8..abf7019 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -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
 {
 };
@@ -556,6 +560,42 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
 
 /* 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
    gcc::jit::recording::memento::as_object method (a field is a
    memento), in jit-recording.h.  */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index beeb747..9c5f23b 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -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);
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 16f5253..40e1c78 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -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
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 9a10418..0272e6f8 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -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
index 0000000..5e80351
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-accessing-bitfield.c
@@ -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
index 0000000..d2ef5a8
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c
@@ -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
index 0000000..67db120
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c
@@ -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
index 0000000..f102a6a
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c
@@ -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");
+}

  reply	other threads:[~2019-06-26 11:07 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-01  0:00 Andrea Corallo
2019-01-01  0:00 ` PING: " Andrea Corallo
2019-01-01  0:00 ` David Malcolm
2019-01-01  0:00   ` Andrea Corallo
2019-01-01  0:00   ` Andrea Corallo
2019-01-01  0:00     ` David Malcolm
2019-01-01  0:00       ` Andrea Corallo [this message]
2019-01-01  0:00         ` David Malcolm
2019-01-01  0:00           ` Andrea Corallo
2019-01-01  0:00             ` Andrea Corallo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=gkrd0j0a9lv.fsf@arm.com \
    --to=andrea.corallo@arm.com \
    --cc=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jit@gcc.gnu.org \
    --cc=nd@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).