On Thu, 2024-11-14 at 15:27 -0500, Antoni Boucher wrote: > It seems we don't need to do the cleanup in i386-builtins.cc anymore, > so > I removed it. > David: Is it possible that your recent fixes for the GC within > libgccjit > also fixed the issue here? > > Here's the updated patch and answers below. > > (GitHub link if you find it easier for review: > https://github.com/antoyo/libgccjit/pull/5) > > Thanks.
Thanks; I looked over the patch via the above link and it looks good to me for trunk. Dave > > Le 2024-06-26 à 18 h 49, David Malcolm a écrit : > > On Thu, 2023-11-23 at 17:17 -0500, Antoni Boucher wrote: > > > Hi. > > > I did split the patch and sent one for the bfloat16 support and > > > another > > > one for the vector support. > > > > > > Here's the updated patch for the machine-dependent builtins. > > > > > > > Thanks for the patch; sorry about the long delay in reviewing it. > > > > CCing Jan and Uros re the i386 part of that patch; for reference > > the > > patch being discussed is here: > > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638027.html > > > > > From e025f95f4790ae861e709caf23cbc0723c1a3804 Mon Sep 17 > > > 00:00:00 2001 > > > From: Antoni Boucher <boua...@zoho.com> > > > Date: Mon, 23 Jan 2023 17:21:15 -0500 > > > Subject: [PATCH] libgccjit: Add support for machine-dependent > > > builtins > > > > [...snip...] > > > > > diff --git a/gcc/config/i386/i386-builtins.cc > > > b/gcc/config/i386/i386-builtins.cc > > > index 42fc3751676..5cc1d6f4d2e 100644 > > > --- a/gcc/config/i386/i386-builtins.cc > > > +++ b/gcc/config/i386/i386-builtins.cc > > > @@ -225,6 +225,22 @@ static GTY(()) tree ix86_builtins[(int) > > > IX86_BUILTIN_MAX]; > > > > > > struct builtin_isa ix86_builtins_isa[(int) IX86_BUILTIN_MAX]; > > > > > > +static void > > > +clear_builtin_types (void) > > > +{ > > > + for (int i = 0 ; i < IX86_BT_LAST_CPTR + 1 ; i++) > > > + ix86_builtin_type_tab[i] = NULL; > > > + > > > + for (int i = 0 ; i < IX86_BUILTIN_MAX ; i++) > > > + { > > > + ix86_builtins[i] = NULL; > > > + ix86_builtins_isa[i].set_and_not_built_p = true; > > > + } > > > + > > > + for (int i = 0 ; i < IX86_BT_LAST_ALIAS + 1 ; i++) > > > + ix86_builtin_func_type_tab[i] = NULL; > > > +} > > > + > > > tree get_ix86_builtin (enum ix86_builtins c) > > > { > > > return ix86_builtins[c]; > > > @@ -1483,6 +1499,8 @@ ix86_init_builtins (void) > > > { > > > tree ftype, decl; > > > > > > + clear_builtin_types (); > > > + > > > ix86_init_builtin_types (); > > > > > > /* Builtins to get CPU type and features. */ > > > > Please can one of the i386 maintainers check this? > > (CCing Jan and Uros: this is for the case where the compiler code > > runs > > multiple times in-process due to being linked into libgccjit.so. > > We > > want to restore state within i386-builtins.cc to an initial state, > > and > > ensure that no GC-managed objects persist from previous in-memory > > compiles). > > > > > diff --git a/gcc/jit/docs/topics/compatibility.rst > > b/gcc/jit/docs/topics/compatibility.rst > > > index ebede440ee4..764de23341e 100644 > > > --- a/gcc/jit/docs/topics/compatibility.rst > > > +++ b/gcc/jit/docs/topics/compatibility.rst > > > @@ -378,3 +378,12 @@ alignment of a variable: > > > -------------------- > > > ``LIBGCCJIT_ABI_25`` covers the addition of > > > :func:`gcc_jit_type_get_restrict` > > > + > > > +.. _LIBGCCJIT_ABI_26: > > > + > > > +``LIBGCCJIT_ABI_26`` > > > +-------------------- > > > + > > > +``LIBGCCJIT_ABI_26`` covers the addition of a function to get > > > target builtins: > > > + > > > + * :func:`gcc_jit_context_get_target_builtin_function` > > > diff --git a/gcc/jit/docs/topics/functions.rst > > > b/gcc/jit/docs/topics/functions.rst > > > index cf5cb716daf..e9b77fdb892 100644 > > > --- a/gcc/jit/docs/topics/functions.rst > > > +++ b/gcc/jit/docs/topics/functions.rst > > > @@ -140,6 +140,25 @@ Functions > > > uses such a parameter will lead to an error being emitted > > > within > > > the context. > > > > > > +.. function:: gcc_jit_function *\ > > > + gcc_jit_context_get_target_builtin_function > > > (gcc_jit_context *ctxt,\ > > > + > > > const char *name) > > > + > > > + Get the :type:`gcc_jit_function` for the built-in function > > > with the > > > + given name. For example: > > > > Might be nice to add the "(sometimes called intrinsic functions)" > > text > > you have in the header here. > > Done > > > > > [...snip....] > > > > > diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy- > > > frontend.cc > > > index a729086bafb..3ca9702d429 100644 > > > --- a/gcc/jit/dummy-frontend.cc > > > +++ b/gcc/jit/dummy-frontend.cc > > > > [...] > > > > > @@ -29,8 +30,14 @@ along with GCC; see the file COPYING3. If not > > > see > > > #include "options.h" > > > #include "stringpool.h" > > > #include "attribs.h" > > > +#include "jit-recording.h" > > > +#include "print-tree.h" > > > > > > #include <mpfr.h> > > > +#include <unordered_map> > > > +#include <string> > > > + > > > +using namespace gcc::jit; > > > > > > /* Attribute handling. */ > > > > > > @@ -86,6 +93,11 @@ static const struct attribute_spec::exclusions > > > attr_const_pure_exclusions[] = > > > ATTR_EXCL (NULL, false, false, false) > > > }; > > > > > > +hash_map<nofree_string_hash, tree> target_builtins{}; > > > > I was wondering if this needs a GTY marker, but I don't think it > > does: > > presumably it's only used within jit_langhook_parse_file where no > > GC > > can happen - unless jit_langhook_write_globals makes use of it? > > It is also used in jit-playback.cc: does that mean it needs a GTY > marker? > > > > > > +std::unordered_map<std::string, recording::function_type*> > > target_function_types > > > +{}; > > > +recording::context target_builtins_ctxt{NULL}; > > > > Please add a comment to target_builtins_ctxt saying what it's for. > > As > > far as I can tell, it's for getting at recording::types from > > tree_type_to_jit_type; we then use a new "copy" mechanism to copy > > objects from target_builtins_ctxt for use with the real > > recording::context. > > I added a comment. > > > > > This feels ugly, but maybe it's the only way to make it work. > > > > Could tree_type_to_jit_type take a recording::context as a param? > > The > > only non-recursive uses of tree_type_to_jit_type seem to be in > > jit_langhook_builtin_function. Could that use the > > recording::context > > of the current playback::context? You can get the current > > playback::context from gcc::jit::active_playback_ctxt and then > > access > > that playback::context's m_recording_ctxt. > > > > Or is there some need to have this work as a global cache? (which > > is > > what the target_builtins_ctxt effectively does). > > It looks like target_function_types might be a cache... > > Indeed, this is used as a global cache, as you noticed below. > > > > > > + > > > /* Table of machine-independent attributes supported in > > > libgccjit. */ > > > const struct attribute_spec jit_attribute_table[] = > > > { > > > @@ -594,6 +606,7 @@ jit_langhook_init (void) > > > > > > build_common_tree_nodes (false); > > > > > > + target_builtins.empty (); > > > build_common_builtin_nodes (); > > > > > > /* The default precision for floating point numbers. This is > > > used > > > @@ -601,6 +614,8 @@ jit_langhook_init (void) > > > eventually be controllable by a command line option. */ > > > mpfr_set_default_prec (256); > > > > > > + targetm.init_builtins (); > > > + > > > return true; > > > } > > > > > > @@ -668,11 +683,198 @@ jit_langhook_type_for_mode (machine_mode > > > mode, int unsignedp) > > > return NULL; > > > } > > > > > > -/* Record a builtin function. We just ignore builtin > > > functions. */ > > > +recording::type* tree_type_to_jit_type (tree type) > > > +{ > > > + if (TREE_CODE (type) == VECTOR_TYPE) > > > + { > > > + tree inner_type = TREE_TYPE (type); > > > + recording::type* element_type = tree_type_to_jit_type > > > (inner_type); > > > + poly_uint64 size = TYPE_VECTOR_SUBPARTS (type); > > > + long constant_size = size.to_constant (); > > > + if (element_type != NULL) > > > + return element_type->get_vector (constant_size); > > > + return NULL; > > > + } > > > + if (TREE_CODE (type) == REFERENCE_TYPE) > > > + // For __builtin_ms_va_start. > > > + // FIXME: wrong type. > > > + return new recording::memento_of_get_type > > > (&target_builtins_ctxt, > > > + > > > GCC_JIT_TYPE_VOID); > > > > The various "// FIXME: wrong type" cases in this function feel like > > a > > timebomb; could we instead fail hard on them, rather than > > potentially > > silently generate bad code? > > While it is a timebomb, we cannot error out here as this process all > the > builtins, so any unsupported type needs to be processed. > The current way allows to use most builtins and usage of a few > builtins > will have incorrect type checking. > > > > > [...snip...] > > > > > +/* Record a builtin function. We save their types to be able to > > > check types > > > + in recording and for reflection. */ > > > > Aha! This comment makes it clearer that the stuff above is a > > cache, so > > maybe it has to be done the way you have it above (with the > > recursive > > copying to the appropriate recording::context). > > > > > static tree > > > jit_langhook_builtin_function (tree decl) > > > { > > > + if (TREE_CODE (decl) == FUNCTION_DECL) > > > + { > > > + const char* name = IDENTIFIER_POINTER (DECL_NAME (decl)); > > > + target_builtins.put (name, decl); > > > + > > > + std::string string_name (name); > > > + if (target_function_types.count (string_name) == 0) > > > + { > > > + tree function_type = TREE_TYPE (decl); > > > + tree arg = TYPE_ARG_TYPES (function_type); > > > + bool is_variadic = false; > > > + > > > + auto_vec <recording::type *> param_types; > > > + > > > + while (arg != void_list_node) > > > + { > > > + if (arg == NULL) > > > + { > > > + is_variadic = true; > > > + break; > > > + } > > > + if (arg != void_list_node) > > > + { > > > + recording::type* arg_type = tree_type_to_jit_type > > > (TREE_VALUE (arg)); > > > + if (arg_type == NULL) > > > + return decl; > > > + param_types.safe_push (arg_type); > > > + } > > > + arg = TREE_CHAIN (arg); > > > + } > > > + > > > + tree result_type = TREE_TYPE (function_type); > > > + recording::type* return_type = tree_type_to_jit_type > > > (result_type); > > > + > > > + if (return_type == NULL) > > > + return decl; > > > + > > > + recording::function_type* func_type = > > > + new recording::function_type (&target_builtins_ctxt, > > > return_type, > > > + param_types.length (), > > > + param_types.address (), > > > is_variadic, > > > + false); > > > + > > > + target_function_types[string_name] = func_type; > > > + } > > > + } > > > return decl; > > > } > > > > > > > [...snip...] > > > > > diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc > > > index 18cc4da25b8..d71ee2b61a7 100644 > > > --- a/gcc/jit/jit-playback.cc > > > +++ b/gcc/jit/jit-playback.cc > > > @@ -509,7 +509,8 @@ new_function (location *loc, > > > const char *name, > > > const auto_vec<param *> *params, > > > int is_variadic, > > > - enum built_in_function builtin_id) > > > + enum built_in_function builtin_id, > > > + int is_target_builtin) > > > { > > > int i; > > > param *param; > > > @@ -543,6 +544,14 @@ new_function (location *loc, > > > DECL_RESULT (fndecl) = resdecl; > > > DECL_CONTEXT (resdecl) = fndecl; > > > > > > + if (is_target_builtin) > > > + { > > > + tree *decl = target_builtins.get (name); > > > + if (decl != NULL) > > > + fndecl = *decl; > > > + else > > > + add_error (loc, "cannot find target builtin %s", name); > > > + } > > > > It looks like is_target_builtin is only ever used as a flag, so for > > clarity's sake, can it and the various m_is_target_builtin be a > > bool > > rather than an int? > > Done. > > > > > > > > if (builtin_id) > > > { > > > gcc_assert (loc == NULL); > > > diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h > > > index f9e29d0baec..06128b4d640 100644 > > > --- a/gcc/jit/jit-playback.h > > > +++ b/gcc/jit/jit-playback.h > > > @@ -104,7 +104,8 @@ public: > > > const char *name, > > > const auto_vec<param *> *params, > > > int is_variadic, > > > - enum built_in_function builtin_id); > > > + enum built_in_function builtin_id, > > > + int is_target_builtin); > > > > > > lvalue * > > > new_global (location *loc, > > > @@ -818,4 +819,6 @@ extern playback::context > > > *active_playback_ctxt; > > > > > > } // namespace gcc > > > > > > +extern hash_map<nofree_string_hash, tree> target_builtins; > > > + > > > #endif /* JIT_PLAYBACK_H */ > > > > [...snip...] > > > > Assuming that the i386 maintainers are OK with the change to i386- > > builtins.cc, this is OK for trunk if you fix the various nitpicks I > > mention above (and you'll probably need to do the usual refreshing > > of > > the ABI version) > > > > On Thu, 2023-11-23 at 17:21 -0500, Antoni Boucher wrote: > > > I will need to not forget to update the function > > > tree_type_to_jit_type > > > in dummy-frontend.cc to add back the support for bfloat16 when > > > the > > > patch for it is merged. > > > > Adding this here as a reminder. > > Done as well. > > > > > Thanks again for the patch. > > Dave