aboutsummaryrefslogtreecommitdiff
path: root/gcc/jit
diff options
context:
space:
mode:
authorAntoni Boucher <bouanto@zoho.com>2023-01-23 17:21:15 -0500
committerAntoni Boucher <bouanto@zoho.com>2024-11-20 14:03:57 -0500
commit87f0136fa46c9b0352aa47f637d2f6678b8beb5b (patch)
tree71f636c53d2bdedac4dd4c365a3da41724e0ede5 /gcc/jit
parentbeab0a3ecb2fa839295869fcff1c10237b99d085 (diff)
downloadgcc-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.rst10
-rw-r--r--gcc/jit/docs/topics/functions.rst19
-rw-r--r--gcc/jit/dummy-frontend.cc205
-rw-r--r--gcc/jit/jit-builtins.cc6
-rw-r--r--gcc/jit/jit-playback.cc12
-rw-r--r--gcc/jit/jit-playback.h5
-rw-r--r--gcc/jit/jit-recording.cc76
-rw-r--r--gcc/jit/jit-recording.h110
-rw-r--r--gcc/jit/libgccjit.cc18
-rw-r--r--gcc/jit/libgccjit.h13
-rw-r--r--gcc/jit/libgccjit.map5
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;