From patchwork Mon Jun 3 09:51:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Corallo X-Patchwork-Id: 1109173 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-502182-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45HVhW2Tx6z9s4Y for ; Mon, 3 Jun 2019 19:52:08 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type:mime-version; q=dns; s=default; b=Qz30uscZ3FLSNVySjTiUayqXPPPwugWy755pmHsL7BW9WaGnxa NS8uLk+RkKqHevZKvNf2DdlqRe98wZ4pr5Iz+uRNR/elU+OD5cKT2qsewtA9oAAJ Nnr2vgIIwkbU07VDnqJ2jQyONyyj1gBya3T+tXy4W1dTarGy1wv1bBZ7U= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type:mime-version; s= default; bh=BO/dA/xUtmF7TdUabkaCdl26r/8=; b=ASRktszQgzJiqpsRh4HH SZ1+rq5TfocutrCWEo/NU14t4d1gxI1PnedUxszVjeTu1PuMg3PnZxyCNTtikxDH ioQN927cOZvxTq7dC4Xd+DHvKsrFnEHBBe6S+TUkqKSlBJUzHZd63wZbne4tfle1 oxb7SCZ6k5+IBQVEZ1ktJuA= Received: (qmail 94090 invoked by alias); 3 Jun 2019 09:51:58 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 93717 invoked by uid 89); 3 Jun 2019 09:51:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 spammy=compound, WIDTH, cfamily, c-family X-HELO: EUR02-AM5-obe.outbound.protection.outlook.com Received: from mail-eopbgr00081.outbound.protection.outlook.com (HELO EUR02-AM5-obe.outbound.protection.outlook.com) (40.107.0.81) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 03 Jun 2019 09:51:53 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=HX8yizc0VvCEh4GmQe5YJ222sJKynpSFafYd4cWPEaY=; b=TMeSlTw8GnRTzDDxPH2NY9SWKP0PjLeGiTvqM6sf8uBIziMQaKMykxMvbAL+DneWraZ1uXoYMPhdsofgF/YUIClZduIsVOe/Vehy7l+yCOksSvtoCv30q3w+YZ35W6ZRPwX78RsnkGpnOgnZXG24KnYlB95K0OPrrD/ZDjDevCg= Received: from AM5PR0801MB1986.eurprd08.prod.outlook.com (10.168.157.145) by AM5PR0801MB1619.eurprd08.prod.outlook.com (10.169.247.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1943.22; Mon, 3 Jun 2019 09:51:49 +0000 Received: from AM5PR0801MB1986.eurprd08.prod.outlook.com ([fe80::5485:1401:62b0:ee04]) by AM5PR0801MB1986.eurprd08.prod.outlook.com ([fe80::5485:1401:62b0:ee04%2]) with mapi id 15.20.1943.018; Mon, 3 Jun 2019 09:51:49 +0000 From: Andrea Corallo To: "gcc-patches@gcc.gnu.org" , "jit@gcc.gnu.org" CC: nd Subject: [PATCH][gcc] libgccjit: add bitfield support Date: Mon, 3 Jun 2019 09:51:49 +0000 Message-ID: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Andrea.Corallo@arm.com; x-ms-oob-tlc-oobclassifiers: OLM:5797; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 MIME-Version: 1.0 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Andrea.Corallo@arm.com Hi all, I would like to submit this patch that aims to introduce bitfields support into libgccjit. A new entry point gcc_jit_context_new_bitfield is added plus relative testcase. Checked with make check-jit does not introduce regressions. Feedbacks are very welcome. Bests Andrea 2019-06-01 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: Include "c-family/c-common.h" (playback::context::new_bitfield): New method. (playback::compound_type::set_fields): Add bitfield support. (playback::lvalue::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-01 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. 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..094f9fd 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..7676e55 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "convert.h" #include "stor-layout.h" #include "print-tree.h" +#include "c-family/c-common.h" #include "gimplify.h" #include "gcc-driver-name.h" #include "attribs.h" @@ -263,6 +264,48 @@ 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 (); + if (TREE_CODE (tree_type) != INTEGER_TYPE + && TREE_CODE (tree_type) != BOOLEAN_TYPE) + { + add_error (loc, "bit-field %s has invalid type", name); + return NULL; + } + tree tree_width = build_int_cst (integer_type_node, width); + if (compare_tree_int (tree_width, TYPE_PRECISION (tree_type)) > 0) + { + add_error (loc, "bit-field %s exceeds its type", name); + 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_C_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 +338,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_C_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 +1247,30 @@ 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 true if successful. */ -static void -jit_mark_addressable (tree exp) +bool +playback::lvalue:: +jit_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_C_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 +1282,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 +1294,7 @@ jit_mark_addressable (tree exp) TREE_ADDRESSABLE (x) = 1; /* fallthrough */ default: - return; + return true; } } @@ -1251,8 +1311,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 (jit_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..c59f614 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 jit_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..0678d07 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. @@ -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-byfield. */ + +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..5e2d64e 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 *); - void write_to_dump (dump &d) FINAL OVERRIDE; + void write_to_dump (dump &d); playback::field * playback_field () const @@ -833,16 +839,40 @@ public: } private: - string * make_debug_string () FINAL OVERRIDE; - void write_reproducer (reproducer &r) FINAL OVERRIDE; + string * make_debug_string (); + void write_reproducer (reproducer &r); -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..e5a769a 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 e4f17f8..f1265a5 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,35 @@ 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 (type, ctxt, loc, "NULL type"); + RETURN_NULL_IF_FAIL (width > 0, ctxt, NULL, "invalid width"); + RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL 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..f7af8e9 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 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..6ca8b24 --- /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_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_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_access = + (fn_type)gcc_jit_result_get_code (result, "test_access"); + CHECK_NON_NULL (test_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_access (&tmp); + + /* Verify that the code correctly modified the field "z". */ + CHECK_VALUE (tmp.z, 12); +}