From: Andrea Corallo Date: Thu, 4 Jul 2019 15:46:00 +0000 (+0000) Subject: introduce gcc_jit_context_new_bitfield X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ee118c14f71f43a4b82c439cd4381e034bd2786a;p=gcc.git introduce gcc_jit_context_new_bitfield gcc/jit/ChangeLog: 2019-07-04 Andrea Corallo * 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 * 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 --- diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 9958db15ee0..8323e2f488e 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,35 @@ +2019-07-04 Andrea Corallo + + * 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 * jit-recording.c (reproducer::m_set_identifiers): Use false as Lazy diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index abefa56f37d..da649206cec 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 1d2dcd43f13..37d9d01a958 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 1d96cc352c8..e747d9611f2 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 b74495c58b2..942c7304ebf 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -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 *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. diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index bc4de9c035a..d4b148e3e57 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 a332fe87514..495ac7f1ae9 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 b9f2250802f..13ec7eabefa 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 55aebcac4f5..0c5be5a85f3 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 &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 &fields, diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index e4f17f8b350..abf701919a2 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 { }; @@ -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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index beeb747ca8f..9c5f23bada5 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 16f5253ab23..40e1c78f2bb 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/ChangeLog b/gcc/testsuite/ChangeLog index a89a21893be..e7db610ab78 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2019-07-04 Andrea Corallo + + * 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 * gcc.dg/tree-ssa/alias-access-path-3.c: New testcase. @@ -122,7 +133,7 @@ PR tree-optimization/91033 * gcc.target/i386/pr91033.c: New test. - + 2019-07-03 Bob Duff * gnat.dg/task2.adb, gnat.dg/task2_pkg.adb, diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 9a10418b308..0272e6f846f 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 00000000000..5e80351e371 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-accessing-bitfield.c @@ -0,0 +1,130 @@ +#include +#include + +#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, ¶m_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 00000000000..d2ef5a88c3d --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-type.c @@ -0,0 +1,53 @@ +#include +#include + +#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 00000000000..67db120dee2 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_context_new_bitfield-invalid-width.c @@ -0,0 +1,44 @@ +#include +#include + +#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 00000000000..f102a6a7389 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-error-gcc_jit_lvalue_get_address-bitfield.c @@ -0,0 +1,66 @@ +#include +#include + +#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"); +}