From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-relay-3.sys.kth.se (smtp-relay-3.sys.kth.se [IPv6:2001:6b0:1:1200:250:56ff:fead:700c]) by sourceware.org (Postfix) with ESMTPS id 8BBAA3857C6B for ; Tue, 30 Nov 2021 14:37:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8BBAA3857C6B Received: from exdb5.ug.kth.se (exdb5.ug.kth.se [192.168.32.60]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp-relay-3.sys.kth.se (Postfix) with ESMTPS id 4J3Ptm0p71zPRyC; Tue, 30 Nov 2021 15:37:03 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp-relay-3.sys.kth.se 4J3Ptm0p71zPRyC Received: from exdb6.ug.kth.se (192.168.32.61) by exdb5.ug.kth.se (192.168.32.60) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 30 Nov 2021 15:37:03 +0100 Received: from exdb6.ug.kth.se ([192.168.32.61]) by exdb6.ug.kth.se ([192.168.32.61]) with mapi id 15.02.0986.014; Tue, 30 Nov 2021 15:37:03 +0100 From: Petter Tomner To: David Malcolm , Antoni Boucher , "jit@gcc.gnu.org" Subject: SV: SV: [PATCH] libgccjit: Add function to set the initial value of a global variable [PR96089] Thread-Topic: SV: [PATCH] libgccjit: Add function to set the initial value of a global variable [PR96089] Thread-Index: AQHX4A5BvSF/jycHYEaAgABQ/pvBR6wQ4v/4gApg9oCAAM6UVg== Date: Tue, 30 Nov 2021 14:37:03 +0000 Message-ID: <4287fbb8dd3644849ea57aaf070de870@kth.se> References: <7d6762623f658712a4b802cc3d6524c106affa2b.camel@zoho.com> <62c178b5bb0ab004def3c7869da2b03846e5134c.camel@zoho.com> , , In-Reply-To: Accept-Language: sv-SE, en-US Content-Language: sv-SE X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [192.168.32.250] Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, WEIRD_QUOTING autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: jit@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Jit mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 Nov 2021 14:37:14 -0000 Hi! > It sounds like I should review Petter's patch, but obviously I want > Antoni's input to be sure that it works for the rustc backend. He asked you to review my patch and wrote that he would check if it worked= =20 for his work when back from a vacation, in a follow up mail. Maybe you miss= ed it: https://gcc.gnu.org/pipermail/jit/2021q4/001394.html I tidied up the patch and mailed it for review to the list: https://gcc.gnu.org/pipermail/jit/2021q4/001399.html but it is about the same code as you reviewed so your points still appy, except that I fixed some docs, whitespace etc and split up the entry points= and made them compatible with how Antoni used them. I.e. the user can=20 leave out the fields arg and just have the values being applied in=20 struct field definition order. > It's a size_t in the docs, but an "int" in the header. Let's make it a > size_t. Ye need to sync those. Are you sure you want size_t though? Neither array or struct types can have more elements/fields than int due to the entrypoints for making those have int args (which were the reason I=20 changed to int, forgot to change the docs).=20 > Reading the docs, it seems that this function seems to be doing 3 > different things. > > Would it be better to have 3 different API entrypoints? > >Perhaps something like: > >extern gcc_jit_rvalue * >gcc_jit_context_new_struct_constructor (gcc_jit_context *ctxt, ... >extern gcc_jit_rvalue * >gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt, ... >extern gcc_jit_rvalue * >gcc_jit_context_new_union_constructor (gcc_jit_context *ctxt, > > Would that be better? I'm not sure, but I think it's clearer. Funnely enough the exact signature I chose. But with gcc_jit_type instead of gcc_jit_struct. Ye it is way clearer. One entrypoint made it too crammed and the documentation got very confusing. > They could potentially share the memento class internally, or be split > out. The code is very similair for arrays and UNION are kinda RECORDs with=20 no offsets, so I guess it makes sense to keep the internal class together. > Would "initializer" be better than "constructor"? (I'm not sure) They can be used for assigning to variables at any time, so initializer would probably be confusing, if people think in C or C++ terms. >> If I remember correctly there need to be alot of folding to not >> segfault deeper into gcc on >> expressions that are not one literal, for e.g. pointer arithmetic. > >Can we fail to fold to a const? If so, should this function return >NULL_TREE instead? (and the callers be adjusted accordingly) I could not construct something that failed to fold=20 "enough" so that varasm.c coulnd't handle it and that also was=20 TREE_CONSTANT. playback::context::global_set_init_rvalue searches for variables without DECL_INITIAL set (which would make downstream code unhappy) and checks that the rvalue is also TREE_CONSTANT. fold_const_var () just lets things it can't fold through, like fold () does= . I guess returning NULL_TREE on failing to fold would add alot of checking everywhere it is used. > Two fields called "c" here, FWIW. > But given that these are different field instances, it should complain > about that, also. Ye the name of that "c" field doesn't really matter since the the size check is before the "is this field object one of the field objects that cre= ated the type"-check. That is checked in: test-error-ctor-struct-wrong-field-name.c I'll fix the other comments too, and prepare a new patch. Regards, Fr=E5n: David Malcolm Skickat: den 30 november 2021 02:34 Till: Petter Tomner; Antoni Boucher; jit@gcc.gnu.org =C4mne: Re: SV: [PATCH] libgccjit: Add function to set the initial value of= a global variable [PR96089] =A0 =20 On Tue, 2021-11-23 at 10:51 +0000, Petter Tomner wrote: > Hi! >=20 > Does it work with pointers to other symbols and unions? I don't think > constant symbols end > up in the .rdata section unless they are marked for that. >=20 > I did a similar patch that I just dropped in a RFC mail some time ago. > (See attachment). Petter and Antoni, thanks for the patches. It sounds like I should review Petter's patch, but obviously I want Antoni's input to be sure that it works for the rustc backend. Also, Antoni has much more experience than me of creating initializers in libgccjit. >=20 > If I remember correctly there need to be alot of folding to not > segfault deeper into gcc on > expressions that are not one literal, for e.g. pointer arithmetic. >=20 > Regards, > Petter=20 >=20 >=20 > Fr=E5n: Gcc-patches f= =F6r > Antoni Boucher via Gcc-patches > Skickat: den 23 november 2021 03:01 > Till: David Malcolm > Kopia: jit@gcc.gnu.org; gcc-patches@gcc.gnu.org > =C4mne: Re: [PATCH] libgccjit: Add function to set the initial value of a > global variable [PR96089] > =A0=A0=A0=20 > Hi David! >=20 > I updated the patch to allow initializing global variables with values > of type array or struct. >=20 > I also fixed the bug I was talking in my previous message by using the > following workaround: I create a new memento for the action of setting > the global variable initial value and as such, both the global variable > and the initial value are bound to exist when setting the global > variable initializer. > Is that workaround good enough? > (I guess that workaround could be used to fix the same issue that we > have for inline assembly.) >=20 > Thanks for the review! >=20 > Le vendredi 11 juin 2021 =E0 16:44 -0400, Antoni Boucher a =E9crit=A0: > > David: this one wasn't reviewed yet by you, so you can review it. > >=20 > > Le jeudi 20 mai 2021 =E0 21:27 -0400, Antoni Boucher a =E9crit=A0: > > > Hi. > > >=20 > > > I made this patch to set an arbitrary value to a global variable. > > >=20 > > > This patch suffers from the same issue as inline assembly > > > (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D100380), i.e. it > > > segfaults if the `rvalue` is created after the global variable. > > > It seems to be a design issue so I'm not sure what would be the fix > > > for > > > it and having it fixed would allow me to test this new function > > > much > > > more and see if things are missing (i.e. it might require a way to > > > create a constant struct). > > > See the link above for an explanation of this issue. > > >=20 > > > Thanks for the review. > >=20 >=20 > =A0=A0=A0=20 > From e6850f3417bc0c35d9712e850e5274117527021c Mon Sep 17 00:00:00 2001 > From: Petter Tomner > Date: Sun, 24 Oct 2021 21:13:44 +0200 > Subject: [PATCH 3/5] Add suport for global rvalue initialization and ctor= s >=20 > This patch adds support for initialization of global variables > with rvalues and creating constructors for array, struct and > union types which can be used as rvalues. > [...snip...] Review comments follow inline throughout below... > diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/ex= pressions.rst > index 30a3b9780f9..3b38cab025c 100644 > --- a/gcc/jit/docs/topics/expressions.rst > +++ b/gcc/jit/docs/topics/expressions.rst > @@ -176,6 +176,91 @@ Simple expressions >=A0=A0=A0=A0 underlying string, so it is valid to pass in a pointer to an = on-stack >=A0=A0=A0=A0 buffer. >=A0=20 > +.. function:: gcc_jit_rvalue *\ > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_context_new_constructor (gcc_jit_= context *ctxt,\ > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_= location *loc,\ > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_type *typ= e,\ > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 size_t arr_length= ,\ It's a size_t in the docs, but an "int" in the header.=A0 Let's make it a size_t. > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_field **f= ields,\ > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_rvalue **= values) > + > +=A0=A0 Create a constructor for an array, union or struct as a rvalue. > + > +=A0=A0 Returns NULL on error. The two parameter arrays are copied and > +=A0=A0 do not have to outlive the context. > + > +=A0=A0 ``type`` specifies what the constructor will build. > + > +=A0=A0 ``arr_length`` specifies the number of elements in ``values``. > +=A0=A0=20 > +=A0=A0 Constructing structs > +=A0=A0 """""""""""""""""""" > + > +=A0=A0 For a struct, each field in ``fields`` specifies > +=A0=A0 which field in the struct to set to the corresponding > +=A0=A0 value in ``values``. ``fields`` and ``values`` are paired by inde= x > +=A0=A0 and the pair need to have the same unqualified type. > + > +=A0=A0 A NULL value in ``values`` is a shorthand for zero initialization > +=A0=A0 of the corresponding field or array element. > + > +=A0=A0 The fields in ``fields`` have to be in definition order, but ther= e > +=A0=A0 can be gaps. Any field in the struct that is not specified in > +=A0=A0 ``fields`` will be zeroed. > + > +=A0=A0 The fields in ``fields`` need to be the same objects that were us= ed > +=A0=A0 to create the struct. > + > +=A0=A0 ``fields`` need to have the same length as ``values``.=20 > +=A0=A0=20 > +=A0=A0 If ``arr_length`` is 0, the array parameters will be > +=A0=A0 ignored and zero initialization will be used. > +=A0=A0=20 > + > +=A0=A0 Constructing arrays > +=A0=A0 """"""""""""""""""" > +=A0=A0=20 > +=A0=A0 For an array type, the ``fields`` parameter is ignored. > + > +=A0=A0 Each value in ``values`` sets the corresponding value in the arra= y. > +=A0=A0 If the array type itself has more elements than ``values``, the > +=A0=A0 left-over elements will be zeroed. > + > +=A0=A0 Each value in ``values`` need to be the same unqualified type as = the > +=A0=A0 array type's elements' type. > + > +=A0=A0 If ``arr_length`` is 0, the array parameters will be > +=A0=A0 ignored and zero initialization will be used. > + > +=A0=A0 Constructing unions > +=A0=A0 """"""""""""""""""" > + > +=A0=A0 For unions, ``arr_length`` need to be 1. There need to be one fie= ld > +=A0=A0 in ``fields`` and one value in ``values`` which specified which f= ield > +=A0=A0 in the union to set to what value. The pair need to have the same > +=A0=A0 unqualified type. > + > +=A0=A0 The field in ``fields`` need to be one of the objects that were u= sed > +=A0=A0 to create the union. > + > +=A0=A0 Remarks > +=A0=A0 """"""" > + > +=A0=A0 The constructor rvalue can be used for assignment to locals. > +=A0=A0 It can be used to initialize global variables with > +=A0=A0 :func:`gcc_jit_global_set_initializer_rvalue`. It can also be use= d as a > +=A0=A0 temporary value for function calls and return values. > + > +=A0=A0 The constructor can contain nested constructors. Note that a stri= ng > +=A0=A0 literal rvalue can't be used to construct a char array. It need o= ne > +=A0=A0 rvalue for each char. > + > +=A0=A0 This entrypoint was added in :ref:`LIBGCCJIT_ABI_16`; you can tes= t for its > +=A0=A0 presense using: > + > +=A0=A0 .. code-block:: c > +=A0=A0=A0=A0 #ifdef LIBGCCJIT_HAVE_CTORS > + Reading the docs, it seems that this function seems to be doing 3 different things. Would it be better to have 3 different API entrypoints? Perhaps something like: extern gcc_jit_rvalue * gcc_jit_context_new_struct_constructor (gcc_jit_context *ctxt, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_location *loc, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_struct *type, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 size_t num_fields, // and values =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_field **fields, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_rvalue **values); extern gcc_jit_rvalue * gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_location *loc, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_type *element_type, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 size_t num_values, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_rvalue **values); extern gcc_jit_rvalue * gcc_jit_context_new_union_constructor (gcc_jit_context *ctxt, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_location *loc, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_type *union_type, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_field *field, =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 gcc_jit_rvalue *value); Would that be better?=A0 I'm not sure, but I think it's clearer. They could potentially share the memento class internally, or be split out. Would "initializer" be better than "constructor"?=A0 (I'm not sure) [...snip...] > +/* Flags for global variables class. For when the playback of the > +=A0=A0 global need to know what will happen to it later. */ > +enum global_var_flags > +{ > +=A0 GLOBAL_VAR_FLAGS_NONE =3D 0, > +=A0 GLOBAL_VAR_FLAGS_WILL_BE_RVAL_INIT =3D 1, > +=A0 GLOBAL_VAR_FLAGS_WILL_BE_BLOB_INIT =3D 2, > +}; > + >=A0 } // namespace gcc::jit >=A0=20 >=A0 } // namespace gcc > diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c > index 1f4dc31a1c1..71f0e7283ba 100644 > --- a/gcc/jit/jit-playback.c > +++ b/gcc/jit/jit-playback.c > @@ -107,6 +107,43 @@ namespace jit { >=A0=A0 Playback. >=A0=A0 *******************************************************************= ***/ >=A0=20 > +/* Fold a readonly non-volatile variable with an initial constant value, > +=A0=A0 to that value. > + > +=A0=A0 Otherwise return the argument unchanged. > + > +=A0=A0 This fold is needed for setting a variable's DECL_INITIAL to the = value > +=A0=A0 of a const variable. The c-frontend does this in its own special > +=A0=A0 fold(), so we lift this part out and do it explicitly where there= is a > +=A0=A0 potential for variables to be used as rvalues. */ > +static tree > +fold_const_var (tree node) > +{ > +=A0 /* See c_fully_fold_internal in c-fold.c and decl_constant_value_1 > +=A0=A0=A0=A0 in c-typeck.c */ > +=A0 if (VAR_P (node) > +=A0=A0=A0=A0=A0 && TREE_READONLY (node) > +=A0=A0=A0=A0=A0 && !TREE_THIS_VOLATILE (node) > +=A0=A0=A0=A0=A0 && DECL_INITIAL (node) !=3D NULL_TREE > +=A0=A0=A0=A0=A0 /* "This is invalid if initial value is not constant. > +=A0=A0=A0=A0=A0=A0 If it has either a function call, a memory reference, > +=A0=A0=A0=A0=A0=A0 or a variable, then re-evaluating it could give diffe= rent > +=A0=A0=A0=A0=A0=A0 results." */ > +=A0=A0=A0=A0=A0 && TREE_CONSTANT (DECL_INITIAL (node))) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 tree ret =3D DECL_INITIAL (node); > +=A0=A0=A0=A0=A0 /* "Avoid unwanted tree sharing between the initializer = and current > +=A0=A0=A0=A0=A0=A0 function's body where the tree can be modified e.g. b= y the > +=A0=A0=A0=A0=A0=A0 gimplifier."=A0 */ > +=A0=A0=A0=A0=A0 if (TREE_STATIC (node)) > +=A0=A0=A0=A0 ret =3D unshare_expr (ret); > + > +=A0=A0=A0=A0=A0 return ret; > +=A0=A0=A0 } > + > +=A0 return node; > +} You mentioned above: > If I remember correctly there need to be alot of folding to not > segfault deeper into gcc on > expressions that are not one literal, for e.g. pointer arithmetic. Can we fail to fold to a const?=A0 If so, should this function return NULL_TREE instead? (and the callers be adjusted accordingly) [...snip...] > +void > +playback::context:: > +global_set_init_rvalue (lvalue* variable, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 rvalue* ini= t) > +{ > +=A0 tree inner =3D variable->as_tree (); > + > +=A0 /* We need to fold all expressions as much as possible. The code > +=A0=A0=A0=A0 for a DECL_INITIAL only handles some operations, > +=A0=A0=A0=A0 etc addition, minus, 'address of'. See output_addressed_con= stants() > +=A0=A0=A0=A0 in varasm.c=A0 */ > +=A0 tree init_tree =3D init->as_tree (); > +=A0 tree folded =3D fold_const_var (init_tree); > + > +=A0 /* Find any VAR_DECL without DECL_INITIAL set. > +=A0=A0=A0=A0 Assume that any ..._CST is OK to save some CPU. > +=A0=A0=A0=A0 Handle CONSTRUCTORs explicitly to avoid tree walks > +=A0=A0=A0=A0 on array inits consisting of only ..._CSTs. */ > +=A0 tree sinner =3D NULL_TREE; > + > +=A0 if (TREE_CODE (folded) =3D=3D CONSTRUCTOR) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 unsigned HOST_WIDE_INT idx; > +=A0=A0=A0=A0=A0 tree elt; > +=A0=A0=A0=A0=A0 FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (folded), i= dx, elt) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 if (!CONSTANT_CLASS_P (elt)) > +=A0=A0=A0=A0=A0=A0=A0=A0 sinner =3D walk_tree (&elt, validate_var_has_in= it, NULL, NULL); > +=A0=A0=A0=A0=A0=A0 if (sinner !=3D NULL_TREE) > +=A0=A0=A0=A0=A0=A0=A0=A0 break; > +=A0=A0=A0=A0 } > +=A0=A0=A0 } > +=A0 else if (!CONSTANT_CLASS_P (folded)) > +=A0=A0=A0 sinner =3D walk_tree (&folded, validate_var_has_init, NULL, NU= LL); > + > +=A0 if (sinner !=3D NULL_TREE) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 tree name =3D DECL_NAME (inner); > +=A0=A0=A0=A0=A0 tree rvname =3D DECL_NAME (sinner); > +=A0=A0=A0=A0=A0 add_error (NULL, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "can't initialize %s with %s sin= ce it has no " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "initial value set", What is "it" in this message?=A0 Is it "the latter"? > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 name !=3D NULL_TREE ? IDENTIFIER= _POINTER (name) : NULL, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 rvname !=3D NULL_TREE ? IDENTIFI= ER_POINTER (rvname) : NULL); > +=A0=A0=A0=A0=A0 return; > +=A0=A0=A0 } > + > +=A0 if (!TREE_CONSTANT (folded)) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 tree name =3D DECL_NAME (inner); > + > +=A0=A0=A0=A0=A0 add_error (NULL, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "init rvalue for the global vari= able %s does not seem" > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 " to be constant", Maybe reword to =A0 "unable to convert initial value for the global variable %s to a compil= e-time constant" or somesuch? [...snip...] > +enum strip_flags { > +=A0 STRIP_FLAG_NONE, > +=A0 STRIP_FLAG_ARR, > +=A0 STRIP_FLAG_VEC > +}; > + > +/* Strips type down to array, vector or base type (whichever comes first= ) > + > +=A0=A0 Also saves 'ptr_depth' and sets 'flags' for array or vector types= */ > +static > +recording::type * > +strip_and_count (recording::type *type_to_strip, Can the type be made const? > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int &ptr_depth, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 strip_flags &flags) > +{ > +=A0 recording::type *t =3D type_to_strip; > + > +=A0 while (true) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 if (!t) > +=A0=A0=A0=A0 gcc_unreachable (); /* Should only happen on corrupt input = */ > + > +=A0=A0=A0=A0=A0 recording::type *pointed_to_type =3D t->is_pointer(); > +=A0=A0=A0=A0=A0 if (pointed_to_type !=3D NULL) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 ptr_depth++; > +=A0=A0=A0=A0=A0=A0 t =3D pointed_to_type; > +=A0=A0=A0=A0=A0=A0 continue; > +=A0=A0=A0=A0 } > + > +=A0=A0=A0=A0=A0 recording::type *array_el =3D t->is_array (); > +=A0=A0=A0=A0=A0 if (array_el !=3D NULL) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 flags =3D STRIP_FLAG_ARR; > +=A0=A0=A0=A0=A0=A0 break; > +=A0=A0=A0=A0 } > + > +=A0=A0=A0=A0=A0 recording::type *vec =3D t->dyn_cast_vector_type (); > +=A0=A0=A0=A0=A0 if (vec !=3D NULL) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 flags =3D STRIP_FLAG_VEC; > +=A0=A0=A0=A0=A0=A0 break; > +=A0=A0=A0=A0 } > + > +=A0=A0=A0=A0=A0 /* unqualified() returns 'this' on base types */ > +=A0=A0=A0=A0=A0 recording::type *next =3D t->unqualified (); > +=A0=A0=A0=A0=A0 if (next =3D=3D t) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 break; > +=A0=A0=A0=A0 } > +=A0=A0=A0=A0=A0 t =3D next; > +=A0=A0=A0 } > + > +=A0 return t; > +} > + > +/* Strip qualifiers and count pointer depth, returning true > +=A0=A0 if the types' base type and pointer depth are > +=A0=A0 the same, otherwise false. > + > +=A0=A0 For array and vector types the number of element also > +=A0=A0 has to match. > + > +=A0=A0 Do not call this directly. Call 'types_kinda_same' */ > +bool > +types_kinda_same_internal (recording::type *a, recording::type *b) Likewise, can these types be made const? > +{ > +=A0 int ptr_depth_a =3D 0; > +=A0 int ptr_depth_b =3D 0; > +=A0 recording::type *base_a; > +=A0 recording::type *base_b; > + > +=A0 strip_flags flags_a =3D STRIP_FLAG_NONE; > +=A0 strip_flags flags_b =3D STRIP_FLAG_NONE; > + > +=A0 base_a =3D strip_and_count (a, ptr_depth_a, flags_a); > +=A0 base_b =3D strip_and_count (b, ptr_depth_b, flags_b); > + > +=A0 if (ptr_depth_a !=3D ptr_depth_b) > +=A0=A0=A0 return false; > + > +=A0 if (base_a =3D=3D base_b) > +=A0=A0=A0 return true; > + > +=A0 if (flags_a !=3D flags_b) > +=A0=A0=A0 return false; > + > +=A0 /* If the "base type" is an array or vector we might need to > +=A0=A0=A0=A0 check deeper. */ > +=A0 if (flags_a =3D=3D STRIP_FLAG_ARR) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 recording::array_type *arr_a =3D > +=A0=A0=A0=A0 static_cast (base_a); > +=A0=A0=A0=A0=A0 recording::array_type *arr_b =3D > +=A0=A0=A0=A0 static_cast (base_b); > + > +=A0=A0=A0=A0=A0 if (arr_a->num_elements () !=3D arr_b->num_elements ()) > +=A0=A0=A0=A0 return false; > + > +=A0=A0=A0=A0=A0 /* is_array returns element type */ > +=A0=A0=A0=A0=A0 recording::type *el_a =3D arr_a->is_array (); > +=A0=A0=A0=A0=A0 recording::type *el_b =3D arr_b->is_array (); > + > +=A0=A0=A0=A0=A0 if (el_a =3D=3D el_b) > +=A0=A0=A0=A0 return true; > + > +=A0=A0=A0=A0=A0 return types_kinda_same_internal (el_a, el_b); > +=A0=A0=A0 } > +=A0 if (flags_a =3D=3D STRIP_FLAG_VEC) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 recording::vector_type *arr_a =3D > +=A0=A0=A0=A0 static_cast (base_a); > +=A0=A0=A0=A0=A0 recording::vector_type *arr_b =3D > +=A0=A0=A0=A0 static_cast (base_b); > + > +=A0=A0=A0=A0=A0 if (arr_a->get_num_units () !=3D arr_b->get_num_units ()= ) > +=A0=A0=A0=A0 return false; > + > +=A0=A0=A0=A0=A0 recording::type *el_a =3D arr_a->get_element_type (); > +=A0=A0=A0=A0=A0 recording::type *el_b =3D arr_b->get_element_type (); > + > +=A0=A0=A0=A0=A0 if (el_a =3D=3D el_b) > +=A0=A0=A0=A0 return true; > + > +=A0=A0=A0=A0=A0 return types_kinda_same_internal (el_a, el_b); > +=A0=A0=A0 } > + > +=A0 return false; > +} > + > +recording::type * > +strip_outer_qualifiers (recording::type *type) ...and again, can the return type and input type be const? > +{ > +=A0 while (true) > +=A0=A0=A0 { > +=A0=A0=A0=A0=A0 if (!type) > +=A0=A0=A0=A0 gcc_unreachable (); /* Should only happen on corrupt input = */ > + > +=A0=A0=A0=A0=A0 /* unqualified() returns 'this' on base types, vector, a= rrays and > +=A0=A0=A0=A0=A0 pointers. */ > +=A0=A0=A0=A0=A0 recording::type *next =3D type->unqualified (); > +=A0=A0=A0=A0=A0 if (next =3D=3D type) > +=A0=A0=A0=A0 { > +=A0=A0=A0=A0=A0=A0 break; > +=A0=A0=A0=A0 } > +=A0=A0=A0=A0=A0 type =3D next; > +=A0=A0=A0 } > + > +=A0 return type; > +} > + > +recording::type * > +get_stripped_subtype (recording::type *type) ...and again. > +{ > +=A0 recording::type *stripped =3D strip_outer_qualifiers (type); > +=A0 recording::type *subtype; > + > +=A0 if ((subtype =3D stripped->is_pointer())) > +=A0=A0=A0 return strip_outer_qualifiers (subtype); > + > +=A0 if ((subtype =3D stripped->is_array ())) > +=A0=A0=A0 return strip_outer_qualifiers (subtype); > + > +=A0 if ((subtype =3D stripped->dyn_cast_vector_type ())) > +=A0=A0=A0 return strip_outer_qualifiers (subtype); > + > +=A0 return NULL; > +} > + >=A0 } // namespace gcc::jit > [...snip...] > diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h > index b94cdc85c8e..019172854a7 100644 > --- a/gcc/jit/libgccjit++.h > +++ b/gcc/jit/libgccjit++.h > @@ -206,6 +206,11 @@ namespace gccjit >=A0=A0=A0=A0=A0 rvalue new_rvalue (type vector_type, >=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 std::ve= ctor elements) const; >=A0=20 > +=A0=A0=A0 rvalue new_constructor (type type_, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= std::vector &fields, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= std::vector &values, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= location loc =3D location ()); Similar considerations as per the C API. [...snip...] >=A0 /* Set an initial value for a global, which must be an array of > diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map > index 4022dbb6fbc..c5a1afdeacf 100644 > --- a/gcc/jit/libgccjit.map > +++ b/gcc/jit/libgccjit.map > @@ -208,9 +208,11 @@ LIBGCCJIT_ABI_15 { >=A0=20 >=A0 LIBGCCJIT_ABI_16 { >=A0=A0=A0 global: > +=A0=A0=A0 gcc_jit_context_new_constructor; >=A0=A0=A0=A0=A0 gcc_jit_context_new_rvalue_from_complex_double; >=A0=A0=A0=A0=A0 gcc_jit_context_new_rvalue_from_complex_long_double; > -=A0=A0=A0 gcc_jit_context_set_bool_enable_complex_types; >=A0=A0=A0=A0=A0 gcc_jit_context_new_rvalue_from_long_double; >=A0=A0=A0=A0=A0 gcc_jit_context_new_rvalue_from_long_long; > +=A0=A0=A0 gcc_jit_context_set_bool_enable_complex_types; > +=A0=A0=A0 gcc_jit_global_set_initializer_rvalue; >=A0 } LIBGCCJIT_ABI_15; LIBGCCJIT_ABI_16 is in trunk, so we'll need a new ID for this. > \ 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 8416b312bad..26f45fe0811 100644 > --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h > +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h > @@ -211,6 +211,13 @@ >=A0 #undef create_code >=A0 #undef verify_code >=A0=20 > +/* test-global-init-rvalue.c */ > +#define create_code create_code_global_init_rvalue > +#define verify_code verify_code_global_init_rvalue > +#include "test-global-init-rvalue.c" > +#undef create_code > +#undef verify_code > + >=A0 /* test-global-set-initializer.c */ >=A0 #define create_code create_code_global_set_initializer >=A0 #define verify_code verify_code_global_set_initializer > @@ -232,6 +239,13 @@ >=A0 #undef create_code >=A0 #undef verify_code >=A0=20 > +/* test-local-init-rvalue.c */ > +#define create_code create_code_local_init_rvalue > +#define verify_code verify_code_local_init_rvalue > +#include "test-local-init-rvalue.c" > +#undef create_code > +#undef verify_code > + >=A0 /* test-long-names.c */ >=A0 #define create_code create_code_long_names >=A0 #define verify_code verify_code_long_names You should add entries for the above to the "testcases" array at the bottom of the file. Thanks for all the error-handling test coverage... > diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c b/gcc/= testsuite/jit.dg/test-error-ctor-struct-too-big.c > new file mode 100644 > index 00000000000..a66b894dfde > --- /dev/null > +++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-too-big.c > @@ -0,0 +1,86 @@ > +/* > + > +=A0 Test that the proper error is triggered when we build a ctor > +=A0 for an struct type, but have too many fields. > + > +*/ > + > +#include > +#include > + > +#include "libgccjit.h" > +#include "harness.h" > + > +void > +create_code (gcc_jit_context *ctxt, void *user_data) > +{ > +=A0 gcc_jit_type *int_type =3D gcc_jit_context_get_type (ctxt, > +=A0=A0=A0 GCC_JIT_TYPE_INT); > +=A0=20 > +=A0 gcc_jit_field *b1 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "a"); > +=A0 gcc_jit_field *b2 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "b"); > +=A0 gcc_jit_field *b3 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "c"); > +=A0 gcc_jit_field *fields_b[] =3D {b1, b2, b3}; > + > +=A0 gcc_jit_type *struct_bar_type =3D > +=A0=A0=A0 gcc_jit_struct_as_type ( > +=A0=A0=A0=A0=A0 gcc_jit_context_new_struct_type (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "bar", > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 3, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 fields_b)); > +=A0=20 > +=A0 gcc_jit_field *b11 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "a"); > +=A0 gcc_jit_field *b22 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "b"); > +=A0 gcc_jit_field *b33 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "c"); > +=A0 gcc_jit_field *b44 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "c"); Two fields called "c" here, FWIW. But given that these are different field instances, it should complain about that, also. > + > +=A0 gcc_jit_field *fields_ctor[] =3D {b11, b22, b33, b44}; > +=A0 gcc_jit_rvalue *values[] =3D {0,0,0,0}; > + > +=A0 gcc_jit_rvalue *ctor =3D gcc_jit_context_new_constructor > +=A0=A0=A0 (ctxt, 0, > +=A0=A0=A0=A0 struct_bar_type, > +=A0=A0=A0=A0 4, > +=A0=A0=A0=A0 fields_ctor, > +=A0=A0=A0=A0 values); > + > +=A0 CHECK_VALUE (ctor, NULL); > +} > + > +void > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) > +{ > +=A0 /* Ensure that the bad API usage prevents the API giving a bogus > +=A0=A0=A0=A0 result back.=A0 */ > +=A0 CHECK_VALUE (result, NULL); > + > +=A0 /* Verify that the correct error message was emitted. */ > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: more fields in " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "constructor than= in the target struct or union"); > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: more fields in " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "constructor than= in the target struct or union"); > +} > diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name= .c b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c > new file mode 100644 > index 00000000000..2b31b2fc123 > --- /dev/null > +++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-field-name.c > @@ -0,0 +1,83 @@ > +/* > + > +=A0 Test that the proper error is triggered when we build a ctor > +=A0 for an struct type, but has the name wrong on a field. > + > +*/ > + > +#include > +#include > + > +#include "libgccjit.h" > +#include "harness.h" > + > +void > +create_code (gcc_jit_context *ctxt, void *user_data) > +{ > +=A0 gcc_jit_type *int_type =3D gcc_jit_context_get_type (ctxt, > +=A0=A0=A0 GCC_JIT_TYPE_INT); > + > +=A0 gcc_jit_field *b1 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "a"); > +=A0 gcc_jit_field *b2 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "b"); > +=A0 gcc_jit_field *b3 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "c"); > +=A0 gcc_jit_field *b4 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "d"); > +=A0 gcc_jit_field *b5 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "d"); Should this be named "e"? > +=A0 gcc_jit_field *fields_b[] =3D {b1, b2, b3, b4, b5}; > + > +=A0 gcc_jit_type *struct_bar_type =3D > +=A0=A0=A0 gcc_jit_struct_as_type ( > +=A0=A0=A0=A0=A0 gcc_jit_context_new_struct_type (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "bar", > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 5, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 fields_b)); > + > + > +=A0 gcc_jit_field *b44 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "d"); Maybe call this "something_else" for clarity? > + > +=A0 gcc_jit_field *fields_ctor[] =3D {b1, b2, b44, b5}; > +=A0 gcc_jit_rvalue *values[] =3D {0,0,0,0}; > + > +=A0 gcc_jit_rvalue *ctor =3D gcc_jit_context_new_constructor > +=A0=A0=A0 (ctxt, 0, > +=A0=A0=A0=A0 struct_bar_type, > +=A0=A0=A0=A0 4, > +=A0=A0=A0=A0 fields_ctor, > +=A0=A0=A0=A0 values); > + > +=A0 CHECK_VALUE (ctor, NULL); > +} > + > +void > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) > +{ > +=A0 /* Ensure that the bad API usage prevents the API giving a bogus > +=A0=A0=A0=A0 result back.=A0 */ > +=A0 CHECK_VALUE (result, NULL); > + > +=A0 /* Verify that the correct error message was emitted. */ > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: field at index 2, was " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "not used when cr= eating the union or struct (d)"); > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: field at index 2, was " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "not used when cr= eating the union or struct (d)"); Ideally the error message should contain both the struct/union name, and the bad field name e.g.: =A0 gcc_jit_context_new_constructor: field at index 2 (d) is not an element of struct "bar" > diff --git a/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c b/g= cc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c > new file mode 100644 > index 00000000000..987b6b8fcbd > --- /dev/null > +++ b/gcc/testsuite/jit.dg/test-error-ctor-struct-wrong-type.c > @@ -0,0 +1,76 @@ > +/* > + > +=A0 Test that the proper error is triggered when we build a ctor > +=A0 for an struct type, but has the type wrong on a field. > + > +*/ > + > +#include > +#include > + > +#include "libgccjit.h" > +#include "harness.h" > + > +void > +create_code (gcc_jit_context *ctxt, void *user_data) > +{ > +=A0 gcc_jit_type *int_type =3D gcc_jit_context_get_type (ctxt, > +=A0=A0=A0 GCC_JIT_TYPE_INT); > +=A0 gcc_jit_type *float_type =3D gcc_jit_context_get_type (ctxt, > +=A0=A0=A0 GCC_JIT_TYPE_FLOAT); > + > +=A0 gcc_jit_field *b1 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "a"); > +=A0 gcc_jit_field *b2 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "b"); > +=A0 gcc_jit_field *b3 =3D gcc_jit_context_new_field (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 int_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "c"); > +=A0 gcc_jit_field *fields_b[] =3D {b1, b2, b3}; > + > +=A0 gcc_jit_type *struct_bar_type =3D > +=A0=A0=A0 gcc_jit_struct_as_type ( > +=A0=A0=A0=A0=A0 gcc_jit_context_new_struct_type (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "bar", > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 3, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 fields_b)); > +=A0 gcc_jit_rvalue *frv =3D gcc_jit_context_new_rvalue_from_double (ctxt= , > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 float_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 12); > + > +=A0 gcc_jit_field *fields_ctor[] =3D {b2}; > +=A0 gcc_jit_rvalue *values[] =3D {frv}; > + > +=A0 gcc_jit_rvalue *ctor =3D gcc_jit_context_new_constructor > +=A0=A0=A0 (ctxt, 0, > +=A0=A0=A0=A0 struct_bar_type, > +=A0=A0=A0=A0 1, > +=A0=A0=A0=A0 fields_ctor, > +=A0=A0=A0=A0 values); > + > +=A0 CHECK_VALUE (ctor, NULL); > +} > + > +void > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) > +{ > +=A0 /* Ensure that the bad API usage prevents the API giving a bogus > +=A0=A0=A0=A0 result back.=A0 */ > +=A0 CHECK_VALUE (result, NULL); > + > +=A0 /* Verify that the correct error message was emitted. */ > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: value and field not " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "the same unquali= fied type, " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "at index 0 (fiel= d type: int)(value type: float)"); > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: value and field not " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "the same unquali= fied type, " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "at index 0 (fiel= d type: int)(value type: float)"); This is good; even better would be to also give the name of the field and name of the struct. [...snip...] > diff --git a/gcc/testsuite/jit.dg/test-error-global-allready-init.c b/gcc= /testsuite/jit.dg/test-error-global-allready-init.c > new file mode 100644 > index 00000000000..7eaf182029d > --- /dev/null > +++ b/gcc/testsuite/jit.dg/test-error-global-allready-init.c > @@ -0,0 +1,46 @@ > +/* > + > +=A0 Test that we can't set the initializer on a global twice. > + > +*/ > + > +#include > +#include > + > +#include "libgccjit.h" > +#include "harness.h" > + > +void > +create_code (gcc_jit_context *ctxt, void *user_data) > +{ > +=A0 gcc_jit_type *int_type =3D gcc_jit_context_get_type (ctxt, GCC_JIT_T= YPE_INT); > + > +=A0 gcc_jit_lvalue *bar =3D=A0 gcc_jit_context_new_global ( > +=A0=A0=A0 ctxt, NULL, > +=A0=A0=A0 GCC_JIT_GLOBAL_EXPORTED, > +=A0=A0=A0 int_type, > +=A0=A0=A0 "global_lvalueinit_int_0"); > + > +=A0 gcc_jit_global_set_initializer_rvalue ( > +=A0=A0=A0 bar, > +=A0=A0=A0 gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1)); > +=A0 gcc_jit_global_set_initializer_rvalue ( > +=A0=A0=A0 bar, > +=A0=A0=A0 gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 1)); > +} > + > +void > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) > +{ > +=A0 /* Ensure that the bad API usage prevents the API giving a bogus > +=A0=A0=A0=A0 result back.=A0 */ > +=A0 CHECK_VALUE (result, NULL); > + > +=A0 /* Verify that the correct error message was emitted. */ > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_global_s= et_initializer_rvalue: global variable " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "allready initial= ized: global_lvalueinit_int_0"); "allready" -> "already" (in the implementation, of course) > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_global_s= et_initializer_rvalue: global variable " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "allready initial= ized: global_lvalueinit_int_0"); > +} [...snip...] > diff --git a/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.= c b/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c > new file mode 100644 > index 00000000000..137bae6c6b5 > --- /dev/null > +++ b/gcc/testsuite/jit.dg/test-error-global-init-too-small-array.c > @@ -0,0 +1,64 @@ > +/* > + > +=A0 Test that the proper error is triggered when we initialize > +=A0 a global with another non-const global's rvalue. > + > +=A0 Using gcc_jit_global_set_initializer_rvalue() > + > +*/ > + > +#include > +#include > + > +#include "libgccjit.h" > +#include "harness.h" > + > +void > +create_code (gcc_jit_context *ctxt, void *user_data) > +{ /* float foo[1] =3D {1,2}; */ > + > +=A0 gcc_jit_type *float_type =3D gcc_jit_context_get_type (ctxt, > +=A0=A0=A0 GCC_JIT_TYPE_FLOAT); > +=A0 gcc_jit_type *arr_type =3D gcc_jit_context_new_array_type (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 float_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 1); > +=A0 gcc_jit_rvalue *rval_1 =3D gcc_jit_context_new_rvalue_from_int ( > +=A0=A0=A0 ctxt, float_type, 1); > +=A0 gcc_jit_rvalue *rval_2 =3D gcc_jit_context_new_rvalue_from_int ( > +=A0=A0=A0 ctxt, float_type, 2); > + > +=A0 gcc_jit_rvalue *values[] =3D {rval_1, rval_2}; > + > +=A0 gcc_jit_rvalue *ctor =3D gcc_jit_context_new_constructor (ctxt, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 arr_type, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 2, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 0, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 values); > +=A0 if (!ctor) > +=A0=A0=A0 return; > +=A0=20 > +=A0 gcc_jit_lvalue *foo =3D=A0 gcc_jit_context_new_global ( > +=A0=A0=A0 ctxt, NULL, > +=A0=A0=A0 GCC_JIT_GLOBAL_EXPORTED, > +=A0=A0=A0 arr_type, > +=A0=A0=A0 "global_floatarr_12"); > +=A0 gcc_jit_global_set_initializer_rvalue (foo, ctor); > +} > + > +void > +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) > +{ > +=A0 /* Ensure that the bad API usage prevents the API giving a bogus > +=A0=A0=A0=A0 result back.=A0 */ > +=A0 CHECK_VALUE (result, NULL); > + > +=A0 /* Verify that the correct error message was emitted. */ > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_first_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: array constructor has" > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 " more values tha= n the array type's length"); > +=A0 CHECK_STRING_VALUE (gcc_jit_context_get_last_error (ctxt), > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 "gcc_jit_context_= new_constructor: array constructor has" > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 " more values tha= n the array type's length"); > +} Ideally would also tell the user the specific values. [...snip...] Thanks again for the patches; hope this is constructive.=A0 As noted above, I'm keen on hearing Antoni's opinion of the patch. Dave =