diff options
author | Antoni Boucher <bouanto@zoho.com> | 2023-01-23 17:21:15 -0500 |
---|---|---|
committer | Antoni Boucher <bouanto@zoho.com> | 2024-11-20 14:03:57 -0500 |
commit | 87f0136fa46c9b0352aa47f637d2f6678b8beb5b (patch) | |
tree | 71f636c53d2bdedac4dd4c365a3da41724e0ede5 /gcc/jit | |
parent | beab0a3ecb2fa839295869fcff1c10237b99d085 (diff) | |
download | gcc-87f0136fa46c9b0352aa47f637d2f6678b8beb5b.zip gcc-87f0136fa46c9b0352aa47f637d2f6678b8beb5b.tar.gz gcc-87f0136fa46c9b0352aa47f637d2f6678b8beb5b.tar.bz2 |
libgccjit: Add support for machine-dependent builtins
gcc/jit/ChangeLog:
PR jit/108762
* docs/topics/compatibility.rst (LIBGCCJIT_ABI_32): New ABI tag.
* docs/topics/functions.rst: Add documentation for the function
gcc_jit_context_get_target_builtin_function.
* dummy-frontend.cc: Include headers target.h, jit-recording.h,
print-tree.h, unordered_map and string, new variables (target_builtins,
target_function_types, and target_builtins_ctxt), new function
(tree_type_to_jit_type).
* jit-builtins.cc: Specify that the function types are not from
target builtins.
* jit-playback.cc: New argument is_target_builtin to new_function.
* jit-playback.h: New argument is_target_builtin to
new_function.
* jit-recording.cc: New argument is_target_builtin to
new_function_type, function_type constructor and function
constructor, new function
(get_target_builtin_function).
* jit-recording.h: Include headers string and unordered_map, new
variable target_function_types, new argument is_target_builtin
to new_function_type, function_type and function, new functions
(get_target_builtin_function, copy).
* libgccjit.cc: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.h: New function
(gcc_jit_context_get_target_builtin_function).
* libgccjit.map: New functions
(gcc_jit_context_get_target_builtin_function).
gcc/testsuite:
PR jit/108762
* jit.dg/all-non-failing-tests.h: New test test-target-builtins.c.
* jit.dg/test-target-builtins.c: New test.
Diffstat (limited to 'gcc/jit')
-rw-r--r-- | gcc/jit/docs/topics/compatibility.rst | 10 | ||||
-rw-r--r-- | gcc/jit/docs/topics/functions.rst | 19 | ||||
-rw-r--r-- | gcc/jit/dummy-frontend.cc | 205 | ||||
-rw-r--r-- | gcc/jit/jit-builtins.cc | 6 | ||||
-rw-r--r-- | gcc/jit/jit-playback.cc | 12 | ||||
-rw-r--r-- | gcc/jit/jit-playback.h | 5 | ||||
-rw-r--r-- | gcc/jit/jit-recording.cc | 76 | ||||
-rw-r--r-- | gcc/jit/jit-recording.h | 110 | ||||
-rw-r--r-- | gcc/jit/libgccjit.cc | 18 | ||||
-rw-r--r-- | gcc/jit/libgccjit.h | 13 | ||||
-rw-r--r-- | gcc/jit/libgccjit.map | 5 |
11 files changed, 458 insertions, 21 deletions
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 77b4c5d..bfef40a 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -418,7 +418,6 @@ on functions and variables: -------------------- ``LIBGCCJIT_ABI_30`` covers the addition of :func:`gcc_jit_context_convert_vector` -======= .. _LIBGCCJIT_ABI_31: @@ -428,3 +427,12 @@ on functions and variables: * :func:`gcc_jit_context_new_rvalue_vector_perm` * :func:`gcc_jit_context_new_vector_access` + +.. _LIBGCCJIT_ABI_32: + +``LIBGCCJIT_ABI_32`` +-------------------- + +``LIBGCCJIT_ABI_32`` 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 804605e..16e82a3 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 (sometimes called + intrinsic functions) with the given name. For example: + + .. code-block:: c + + gcc_jit_function *fn + = gcc_jit_context_get_target_builtin_function (ctxt, "__builtin_ia32_pmuldq512_mask"); + + .. note:: Due to technical limitations with how libgccjit interacts with + the insides of GCC, not all built-in functions are supported. More + precisely, not all types are supported for parameters of built-in + functions from libgccjit. Attempts to get a built-in function that + uses such a parameter will lead to an error being emitted within + the context. + .. function:: gcc_jit_object *\ gcc_jit_function_as_object (gcc_jit_function *func) diff --git a/gcc/jit/dummy-frontend.cc b/gcc/jit/dummy-frontend.cc index 327e8de..047c0c2 100644 --- a/gcc/jit/dummy-frontend.cc +++ b/gcc/jit/dummy-frontend.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "target.h" #include "jit-playback.h" #include "stor-layout.h" #include "debug.h" @@ -34,8 +35,12 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "diagnostic-format-text.h" #include "make-unique.h" +#include "print-tree.h" #include <mpfr.h> +#include <unordered_map> + +using namespace gcc::jit; /* Attribute handling. */ @@ -140,6 +145,14 @@ static const struct attribute_spec::exclusions attr_target_exclusions[] = ATTR_EXCL (NULL, false, false, false), }; +/* These variables act as a cache for the target builtins. This is needed in + order to be able to type-check the calls since we can only get those types + in the playback phase while we need them in the recording phase. */ +hash_map<nofree_string_hash, tree> target_builtins{}; +std::unordered_map<std::string, recording::function_type*> target_function_types +{}; +recording::context target_builtins_ctxt{NULL}; + /* Table of machine-independent attributes supported in libgccjit. */ static const attribute_spec jit_gnu_attributes[] = { @@ -1079,6 +1092,7 @@ jit_langhook_init (void) build_common_tree_nodes (flag_signed_char); + target_builtins.empty (); build_common_builtin_nodes (); /* The default precision for floating point numbers. This is used @@ -1086,6 +1100,8 @@ jit_langhook_init (void) eventually be controllable by a command line option. */ mpfr_set_default_prec (256); + targetm.init_builtins (); + return true; } @@ -1153,11 +1169,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); + if (TREE_CODE (type) == RECORD_TYPE) + // For __builtin_sysv_va_copy. + // FIXME: wrong type. + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID); + /* TODO: Remove when we add support for sized floating-point types. */ + for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) + if (type == FLOATN_NX_TYPE_NODE (i)) + // FIXME: wrong type. + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID); + if (type == void_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID); + else if (type == ptr_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID_PTR); + else if (type == const_ptr_type_node) + { + // Void const ptr. + recording::type* result = + new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID_PTR); + return new recording::memento_of_get_const (result); + } + else if (type == unsigned_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_UNSIGNED_INT); + else if (type == long_unsigned_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_UNSIGNED_LONG); + else if (type == integer_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_INT); + else if (type == long_integer_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_LONG); + else if (type == long_long_integer_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_LONG_LONG); + else if (type == signed_char_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_SIGNED_CHAR); + else if (type == char_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_CHAR); + else if (type == unsigned_intQI_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_UINT8_T); + else if (type == short_integer_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_SHORT); + else if (type == short_unsigned_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_UNSIGNED_SHORT); + else if (type == complex_float_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_COMPLEX_FLOAT); + else if (type == complex_double_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_COMPLEX_DOUBLE); + else if (type == complex_long_double_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE); + else if (type == float_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_FLOAT); + else if (type == double_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_DOUBLE); + else if (type == long_double_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_LONG_DOUBLE); + else if (type == bfloat16_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_BFLOAT16); + else if (type == dfloat128_type_node) + // FIXME: wrong type. + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_VOID); + else if (type == long_long_unsigned_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_UNSIGNED_LONG_LONG); + else if (type == boolean_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_BOOL); + else if (type == size_type_node) + return new recording::memento_of_get_type (&target_builtins_ctxt, + GCC_JIT_TYPE_SIZE_T); + else if (TREE_CODE (type) == POINTER_TYPE) + { + tree inner_type = TREE_TYPE (type); + recording::type* element_type = tree_type_to_jit_type (inner_type); + return element_type->get_pointer (); + } + else + { + // Attempt to find an unqualified type when the current type has qualifiers. + tree tp = TYPE_MAIN_VARIANT (type); + for ( ; tp != NULL ; tp = TYPE_NEXT_VARIANT (tp)) + { + if (TYPE_QUALS (tp) == 0 && type != tp) + { + recording::type* result = tree_type_to_jit_type (tp); + if (result != NULL) + { + if (TYPE_READONLY (tp)) + result = new recording::memento_of_get_const (result); + if (TYPE_VOLATILE (tp)) + result = new recording::memento_of_get_volatile (result); + return result; + } + } + } + + fprintf (stderr, "Unknown type:\n"); + debug_tree (type); + abort (); + } + + return NULL; +} + +/* Record a builtin function. We save their types to be able to check types + in recording and for reflection. */ 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; } diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc index 0c13c8d..4d08486 100644 --- a/gcc/jit/jit-builtins.cc +++ b/gcc/jit/jit-builtins.cc @@ -215,7 +215,8 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id) param_types.length (), params, func_type->is_variadic (), - builtin_id); + builtin_id, + false); delete[] params; /* PR/64020 - If the client code is using builtin cos or sin, @@ -582,7 +583,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type, result = m_ctxt->new_function_type (return_type, num_args, param_types, - is_variadic); + is_variadic, + false); error: delete[] param_types; diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index 142a8db..e8887e9 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -572,7 +572,8 @@ new_function (location *loc, std::string>> &string_attributes, const std::vector<std::pair<gcc_jit_fn_attribute, std::vector<int>>> - &int_array_attributes) + &int_array_attributes, + bool is_target_builtin) { int i; param *param; @@ -608,6 +609,15 @@ new_function (location *loc, tree fn_attributes = NULL_TREE; + 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); + } + if (builtin_id) { gcc_assert (loc == NULL); diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 8097b80..2f5e411 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -121,7 +121,8 @@ public: std::string>> &string_attributes, const std::vector<std::pair<gcc_jit_fn_attribute, std::vector<int>>> - &int_array_attributes); + &int_array_attributes, + bool is_target_builtin); lvalue * new_global (location *loc, @@ -869,4 +870,6 @@ extern playback::context *active_playback_ctxt; } // namespace gcc +extern hash_map<nofree_string_hash, tree> target_builtins; + #endif /* JIT_PLAYBACK_H */ diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 90ac5bd..7c1b3fd 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -935,14 +935,16 @@ recording::function_type * recording::context::new_function_type (recording::type *return_type, int num_params, recording::type **param_types, - int is_variadic) + int is_variadic, + bool is_target_builtin) { recording::function_type *fn_type = new function_type (this, return_type, num_params, param_types, - is_variadic); + is_variadic, + is_target_builtin); record (fn_type); return fn_type; } @@ -964,7 +966,8 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc = new_function_type (return_type, num_params, param_types, - is_variadic); + is_variadic, + false); /* Return a pointer-type to the function type. */ return fn_type->get_pointer (); @@ -1007,7 +1010,7 @@ recording::context::new_function (recording::location *loc, loc, kind, return_type, new_string (name), num_params, params, is_variadic, - builtin_id); + builtin_id, false); record (result); m_functions.safe_push (result); @@ -1046,6 +1049,53 @@ recording::context::get_builtin_function (const char *name) return bm->get_builtin_function (name); } +/* Create a recording::function instance for a target-specific builtin. + + Implements the post-error-checking part of + gcc_jit_context_get_target_builtin_function. */ + +recording::function * +recording::context::get_target_builtin_function (const char *name) +{ + const char *asm_name = name; + if (target_function_types.count (name) == 0) + { + fprintf (stderr, "Cannot find target builtin %s\n", name); + return NULL; + } + + recording::function_type* func_type = target_function_types[name] + ->copy (this)->dyn_cast_function_type (); + const vec<type *>& param_types = func_type->get_param_types (); + recording::param **params = new recording::param *[param_types.length ()]; + + int i; + recording::type *param_type; + FOR_EACH_VEC_ELT (param_types, i, param_type) + { + char buf[16]; + snprintf (buf, 16, "arg%d", i); + params[i] = new_param (NULL, + param_type, + buf); + } + + recording::function *result = + new recording::function (this, + NULL, + GCC_JIT_FUNCTION_IMPORTED, + func_type->get_return_type (), + new_string (asm_name), + param_types.length (), + params, + func_type->is_variadic (), + BUILT_IN_NONE, + true); + record (result); + + return result; +} + /* Create a recording::global instance and add it to this context's list of mementos. @@ -3251,11 +3301,13 @@ recording::function_type::function_type (context *ctxt, type *return_type, int num_params, type **param_types, - int is_variadic) + int is_variadic, + bool is_target_builtin) : type (ctxt), m_return_type (return_type), m_param_types (), - m_is_variadic (is_variadic) + m_is_variadic (is_variadic), + m_is_target_builtin (is_target_builtin) { for (int i = 0; i< num_params; i++) m_param_types.safe_push (param_types[i]); @@ -4204,7 +4256,8 @@ recording::function::function (context *ctxt, int num_params, recording::param **params, int is_variadic, - enum built_in_function builtin_id) + enum built_in_function builtin_id, + bool is_target_builtin) : memento (ctxt), m_loc (loc), m_kind (kind), @@ -4218,7 +4271,8 @@ recording::function::function (context *ctxt, m_fn_ptr_type (NULL), m_attributes (), m_string_attributes (), - m_int_array_attributes () + m_int_array_attributes (), + m_is_target_builtin (is_target_builtin) { for (int i = 0; i< num_params; i++) { @@ -4280,7 +4334,8 @@ recording::function::replay_into (replayer *r) m_builtin_id, m_attributes, m_string_attributes, - m_int_array_attributes)); + m_int_array_attributes, + m_is_target_builtin)); } /* Create a recording::local instance and add it to @@ -4547,7 +4602,8 @@ recording::function::get_address (recording::location *loc) = m_ctxt->new_function_type (m_return_type, m_params.length (), param_types.address (), - m_is_variadic); + m_is_variadic, + m_is_target_builtin); m_fn_ptr_type = fn_type->get_pointer (); } gcc_assert (m_fn_ptr_type); diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index ab4b0ff..fa25487 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -28,12 +28,16 @@ along with GCC; see the file COPYING3. If not see #include <string> #include <vector> +#include <unordered_map> + class timer; +extern std::unordered_map<std::string, gcc::jit::recording::function_type*> + target_function_types; + namespace gcc { namespace jit { - extern const char * const unary_op_reproducer_strings[]; extern const char * const binary_op_reproducer_strings[]; @@ -125,7 +129,8 @@ public: new_function_type (type *return_type, int num_params, type **param_types, - int is_variadic); + int is_variadic, + bool is_target_builtin); type * new_function_ptr_type (location *loc, @@ -152,6 +157,9 @@ public: function * get_builtin_function (const char *name); + function * + get_target_builtin_function (const char *name); + lvalue * new_global (location *loc, enum gcc_jit_global_kind kind, @@ -574,6 +582,8 @@ public: these types. */ virtual size_t get_size () { gcc_unreachable (); } + virtual type* copy (context* ctxt) = 0; + /* Dynamic casts. */ virtual function_type *dyn_cast_function_type () { return NULL; } virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; } @@ -661,6 +671,11 @@ public: size_t get_size () final override; + type* copy (context* ctxt) final override + { + return ctxt->get_type (m_kind); + } + bool accepts_writes_from (type *rtype) final override { if (m_kind == GCC_JIT_TYPE_VOID_PTR) @@ -705,6 +720,13 @@ public: type *dereference () final override { return m_other_type; } + type* copy (context* ctxt) final override + { + type* result = new memento_of_get_pointer (m_other_type->copy (ctxt)); + ctxt->record (result); + return result; + } + size_t get_size () final override; bool accepts_writes_from (type *rtype) final override; @@ -768,6 +790,13 @@ public: return false; } + type* copy (context* ctxt) final override + { + type* result = new memento_of_get_const (m_other_type->copy (ctxt)); + ctxt->record (result); + return result; + } + /* Strip off the "const", giving the underlying type. */ type *unqualified () final override { return m_other_type; } @@ -801,6 +830,13 @@ public: return m_other_type->is_same_type_as (other->is_volatile ()); } + type* copy (context* ctxt) final override + { + type* result = new memento_of_get_volatile (m_other_type->copy (ctxt)); + ctxt->record (result); + return result; + } + /* Strip off the "volatile", giving the underlying type. */ type *unqualified () final override { return m_other_type; } @@ -827,6 +863,13 @@ public: return m_other_type->is_same_type_as (other->is_restrict ()); } + type* copy (context* ctxt) final override + { + type* result = new memento_of_get_restrict (m_other_type->copy (ctxt)); + ctxt->record (result); + return result; + } + /* Strip off the "restrict", giving the underlying type. */ type *unqualified () final override { return m_other_type; } @@ -860,6 +903,14 @@ public: type *is_aligned () final override { return m_other_type; } + type* copy (context* ctxt) final override + { + type* result = new memento_of_get_aligned (m_other_type->copy (ctxt), + m_alignment_in_bytes); + ctxt->record (result); + return result; + } + /* Strip off the alignment, giving the underlying type. */ type *unqualified () final override { return m_other_type; } @@ -902,6 +953,13 @@ public: return true; } + type* copy (context* ctxt) final override + { + type* result = new vector_type (m_other_type->copy (ctxt), m_num_units); + ctxt->record (result); + return result; + } + size_t get_num_units () const { return m_num_units; } vector_type *dyn_cast_vector_type () final override { return this; } @@ -955,6 +1013,14 @@ class array_type : public type array_type *dyn_cast_array_type () final override { return this; } + type* copy (context* ctxt) final override + { + type* result = new array_type (ctxt, m_loc, m_element_type->copy (ctxt), + m_num_elements); + ctxt->record (result); + return result; + } + bool is_int () const final override { return false; } bool is_float () const final override { return false; } bool is_bool () const final override { return false; } @@ -982,7 +1048,8 @@ public: type *return_type, int num_params, type **param_types, - int is_variadic); + int is_variadic, + bool is_target_builtin); type *dereference () final override; function_type *dyn_cast_function_type () final override { return this; } @@ -990,6 +1057,20 @@ public: bool is_same_type_as (type *other) final override; + type* copy (context* ctxt) final override + { + auto_vec<type *> new_params{}; + for (size_t i = 0; i < m_param_types.length (); i++) + new_params.safe_push (m_param_types[i]->copy (ctxt)); + + type* result = new function_type (ctxt, m_return_type->copy (ctxt), + m_param_types.length (), + new_params.address (), + m_is_variadic, m_is_target_builtin); + ctxt->record (result); + return result; + } + bool is_int () const final override { return false; } bool is_float () const final override { return false; } bool is_bool () const final override { return false; } @@ -1018,6 +1099,7 @@ private: type *m_return_type; auto_vec<type *> m_param_types; int m_is_variadic; + bool m_is_target_builtin; }; class field : public memento @@ -1119,9 +1201,11 @@ public: return static_cast <playback::compound_type *> (m_playback_obj); } -private: +protected: location *m_loc; string *m_name; + +private: fields *m_fields; }; @@ -1134,6 +1218,13 @@ public: struct_ *dyn_cast_struct () final override { return this; } + type* copy (context* ctxt) final override + { + type* result = new struct_ (ctxt, m_loc, m_name); + ctxt->record (result); + return result; + } + type * as_type () { return this; } @@ -1181,6 +1272,13 @@ public: void replay_into (replayer *r) final override; + type* copy (context* ctxt) final override + { + type* result = new union_ (ctxt, m_loc, m_name); + ctxt->record (result); + return result; + } + bool is_union () const final override { return true; } private: @@ -1407,7 +1505,8 @@ public: int num_params, param **params, int is_variadic, - enum built_in_function builtin_id); + enum built_in_function builtin_id, + bool is_target_builtin); void replay_into (replayer *r) final override; @@ -1469,6 +1568,7 @@ private: std::vector<gcc_jit_fn_attribute> m_attributes; std::vector<std::pair<gcc_jit_fn_attribute, std::string>> m_string_attributes; std::vector<std::pair<gcc_jit_fn_attribute, std::vector<int>>> m_int_array_attributes; + bool m_is_target_builtin; }; class block : public memento diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 3a7a4e2..17cefa6 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -1774,6 +1774,24 @@ gcc_jit_context_new_array_constructor (gcc_jit_context *ctxt, reinterpret_cast<gcc::jit::recording::rvalue**>(values)); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::get_target_builtin_function method, in + jit-recording.c. */ + +gcc_jit_function * +gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt, + const char *name) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name"); + + return static_cast <gcc_jit_function *> ( + ctxt->get_target_builtin_function (name)); +} + /* Public entrypoint. See description in libgccjit.h. */ extern gcc_jit_lvalue * diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 1274a1b..18a3436 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1040,6 +1040,19 @@ extern gcc_jit_lvalue * gcc_jit_global_set_initializer_rvalue (gcc_jit_lvalue *global, gcc_jit_rvalue *init_value); +#define LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function + +/* Create a reference to a machine-specific builtin function (sometimes called + intrinsic functions). + + This API entrypoint was added in LIBGCCJIT_ABI_32; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_get_target_builtin_function +*/ +extern gcc_jit_function * +gcc_jit_context_get_target_builtin_function (gcc_jit_context *ctxt, + const char *name); + #define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer /* 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 d8fb86e..b1c14b5 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -310,3 +310,8 @@ LIBGCCJIT_ABI_31 { gcc_jit_context_new_vector_access; gcc_jit_context_new_rvalue_vector_perm; } LIBGCCJIT_ABI_30; + +LIBGCCJIT_ABI_32 { + global: + gcc_jit_context_get_target_builtin_function; +} LIBGCCJIT_ABI_31; |