diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000000000..03ab299a1dc39
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,32 @@
+name: CI
+
+on:
+ - push
+ - pull_request
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install mpfr
+ run: sudo apt-get install gcc-10 libmpfr-dev libmpc-dev
+
+ - name: Build libgccjit
+ run: |
+ cd ..
+ ls
+ mkdir build install
+ cd build
+ ../gcc/configure --enable-host-shared --enable-languages=jit,c++ --disable-bootstrap --disable-multilib --enable-checking=release --prefix=$(pwd)/../install
+ make -j4
+
+ - uses: actions/upload-artifact@v2
+ with:
+ name: libgccjit.so
+ path: /home/runner/work/gcc/build/gcc/libgccjit.so
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa1a9283..66612d9729ee5 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
.. _LIBGCCJIT_ABI_15:
``LIBGCCJIT_ABI_15``
------------------------
+--------------------
``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
embedding assembler instructions:
@@ -243,3 +243,71 @@ embedding assembler instructions:
* :func:`gcc_jit_extended_asm_add_input_operand`
* :func:`gcc_jit_extended_asm_add_clobber`
* :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+ * :func:`gcc_jit_function_get_return_type`
+
+ * :func:`gcc_jit_function_get_param_count`
+
+ * :func:`gcc_jit_type_is_array`
+
+ * :func:`gcc_jit_type_is_bool`
+
+ * :func:`gcc_jit_type_is_integral`
+
+ * :func:`gcc_jit_type_is_pointer`
+
+ * :func:`gcc_jit_type_is_struct`
+
+ * :func:`gcc_jit_type_is_vector`
+
+ * :func:`gcc_jit_type_unqualified`
+
+ * :func:`gcc_jit_type_is_function_ptr_type`
+
+ * :func:`gcc_jit_function_type_get_return_type`
+
+ * :func:`gcc_jit_function_type_get_param_count`
+
+ * :func:`gcc_jit_function_type_get_param_type`
+
+ * :func:`gcc_jit_vector_type_get_num_units`
+
+ * :func:`gcc_jit_vector_type_get_element_type`
+
+ * :func:`gcc_jit_struct_get_field`
+
+ * :func:`gcc_jit_struct_get_field_count`
+
+.. _LIBGCCJIT_ABI_17:
+
+``LIBGCCJIT_ABI_17``
+-----------------------
+``LIBGCCJIT_ABI_17`` covers the addition of an API entrypoint to set the
+thread-local storage model of a variable:
+
+ * :func:`gcc_jit_lvalue_set_tls_model`
+
+.. _LIBGCCJIT_ABI_18:
+
+``LIBGCCJIT_ABI_18``
+-----------------------
+``LIBGCCJIT_ABI_18`` covers the addition of an API entrypoint to set the link
+section of a variable:
+
+ * :func:`gcc_jit_lvalue_set_link_section`
+
+.. _LIBGCCJIT_ABI_19:
+
+``LIBGCCJIT_ABI_19``
+-----------------------
+``LIBGCCJIT_ABI_19`` covers the addition of an API entrypoint to set the value
+of a global variable:
+
+ * :func:`gcc_jit_global_set_initializer_value`
diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst
index 396259ef07eb4..c681feb303a18 100644
--- a/gcc/jit/docs/topics/expressions.rst
+++ b/gcc/jit/docs/topics/expressions.rst
@@ -539,6 +539,46 @@ where the rvalue is computed by reading from the storage area.
in C.
+.. function:: void
+ gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue,
+ const char *name)
+
+ Set the link section of a variable; analogous to:
+
+ .. code-block:: c
+
+ int variable __attribute__((section(".section")));
+
+ in C.
+
+.. function:: void\
+ gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,\
+ enum gcc_jit_tls_model model)
+
+ Make a variable a thread-local variable.
+
+ The "model" parameter determines the thread-local storage model of the "lvalue":
+
+ .. type:: enum gcc_jit_tls_model
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_INITIAL_EXEC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_LOCAL_EXEC
+
+ .. c:macro:: GCC_JIT_TLS_MODEL_DEFAULT
+
+ This is analogous to:
+
+ .. code-block:: c
+
+ _Thread_local int foo;
+
+ in C.
+
Global variables
****************
@@ -603,6 +643,20 @@ Global variables
#ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
+.. function:: void
+ gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,\
+ gcc_jit_rvalue *value)
+
+ Set an initializer for ``global`` using the specified value.
+ ``global`` must be the same type as ``value``.
+
+ This entrypoint was added in :ref:`LIBGCCJIT_ABI_19`; you can test for
+ its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+
Working with pointers, structs and unions
-----------------------------------------
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239aa0aa1..950da4e5a7682 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
underlying string, so it is valid to pass in a pointer to an on-stack
buffer.
+.. function:: ssize_t \
+ gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+ Get the number of parameters of the function.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+ Get the return type of the function.
+
+ The API entrypoints relating to getting info about parameters and return
+ types:
+
+ * :c:func:`gcc_jit_function_get_return_type`
+
+ * :c:func:`gcc_jit_function_get_param_count`
+
+ were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+ .. type:: gcc_jit_case
+
Blocks
------
.. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b679a85..8c569f8f5ae23 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -76,6 +76,16 @@ Standard types
:c:data:`GCC_JIT_TYPE_UNSIGNED_LONG` C's ``unsigned long``
:c:data:`GCC_JIT_TYPE_LONG_LONG` C99's ``long long`` (signed)
:c:data:`GCC_JIT_TYPE_UNSIGNED_LONG_LONG` C99's ``unsigned long long``
+ :c:data:`GCC_JIT_TYPE_UINT8_T` C99's ``uint8_t``
+ :c:data:`GCC_JIT_TYPE_UINT16_T` C99's ``uint16_t``
+ :c:data:`GCC_JIT_TYPE_UINT32_T` C99's ``uint32_t``
+ :c:data:`GCC_JIT_TYPE_UINT64_T` C99's ``uint64_t``
+ :c:data:`GCC_JIT_TYPE_UINT128_T` C99's ``__uint128_t``
+ :c:data:`GCC_JIT_TYPE_INT8_T` C99's ``int8_t``
+ :c:data:`GCC_JIT_TYPE_INT16_T` C99's ``int16_t``
+ :c:data:`GCC_JIT_TYPE_INT32_T` C99's ``int32_t``
+ :c:data:`GCC_JIT_TYPE_INT64_T` C99's ``int64_t``
+ :c:data:`GCC_JIT_TYPE_INT128_T` C99's ``__int128_t``
:c:data:`GCC_JIT_TYPE_FLOAT`
:c:data:`GCC_JIT_TYPE_DOUBLE`
:c:data:`GCC_JIT_TYPE_LONG_DOUBLE`
@@ -345,3 +355,125 @@ Function pointer types
Function pointer types can be created using
:c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_is_array (gcc_jit_type *type)
+
+ Get the element type of an array type or NULL if it's not an array.
+
+.. function:: int\
+ gcc_jit_type_is_bool (gcc_jit_type *type)
+
+ Return non-zero if the type is a bool.
+
+.. function:: gcc_jit_function_type *\
+ gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+
+ Return the function type if it is one or NULL.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+ Given a function type, return its return type.
+
+.. function:: ssize_t\
+ gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+ Given a function type, return its number of parameters.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index)
+
+ Given a function type, return the type of the specified parameter.
+
+.. function:: int\
+ gcc_jit_type_is_integral (gcc_jit_type *type)
+
+ Return non-zero if the type is an integral.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+ Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function:: gcc_jit_vector_type *\
+ gcc_jit_type_is_vector (gcc_jit_type *type)
+
+ Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function:: gcc_jit_struct *\
+ gcc_jit_type_is_struct (gcc_jit_type *type)
+
+ Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function:: ssize_t\
+ gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+ Given a vector type, return the number of units it contains.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+ Given a vector type, return the type of its elements.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_unqualified (gcc_jit_type *type)
+
+ Given a type, return the unqualified type, removing "const", "volatile" and
+ alignment qualifiers.
+
+.. function:: gcc_jit_field *\
+ gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index)
+
+ Get a struct field by index.
+
+.. function:: ssize_t\
+ gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+ Get the number of fields in the struct.
+
+ The API entrypoints related to the reflection API:
+
+ * :c:func:`gcc_jit_function_type_get_return_type`
+
+ * :c:func:`gcc_jit_function_type_get_param_count`
+
+ * :c:func:`gcc_jit_function_type_get_param_type`
+
+ * :c:func:`gcc_jit_type_unqualified`
+
+ * :c:func:`gcc_jit_type_is_array`
+
+ * :c:func:`gcc_jit_type_is_bool`
+
+ * :c:func:`gcc_jit_type_is_function_ptr_type`
+
+ * :c:func:`gcc_jit_type_is_integral`
+
+ * :c:func:`gcc_jit_type_is_pointer`
+
+ * :c:func:`gcc_jit_type_is_vector`
+
+ * :c:func:`gcc_jit_vector_type_get_element_type`
+
+ * :c:func:`gcc_jit_vector_type_get_num_units`
+
+ * :c:func:`gcc_jit_struct_get_field`
+
+ * :c:func:`gcc_jit_type_is_struct`
+
+ * :c:func:`gcc_jit_struct_get_field_count`
+
+ were added in :ref:`LIBGCCJIT_ABI_15`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+ .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index 1ea96f4e0253f..d4e9b14106b39 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -483,6 +483,7 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
case BT_UINT16: return m_ctxt->get_int_type (2, false);
case BT_UINT32: return m_ctxt->get_int_type (4, false);
case BT_UINT64: return m_ctxt->get_int_type (8, false);
+ case BT_UINT128: return m_ctxt->get_int_type (16, false);
// case BT_WORD:
// case BT_UNWINDWORD:
case BT_FLOAT: return m_ctxt->get_type (GCC_JIT_TYPE_FLOAT);
@@ -541,11 +542,11 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
// case BT_DFLOAT128:
// case BT_VALIST_REF:
// case BT_VALIST_ARG:
- // case BT_I1:
- // case BT_I2:
- // case BT_I4:
- // case BT_I8:
- // case BT_I16:
+ case BT_I1: return m_ctxt->get_int_type (1, true);
+ case BT_I2: return m_ctxt->get_int_type (2, true);
+ case BT_I4: return m_ctxt->get_int_type (4, true);
+ case BT_I8: return m_ctxt->get_int_type (8, true);
+ case BT_I16: return m_ctxt->get_int_type (16, true);
// case BT_PTR_CONST_STRING:
}
}
diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h
index f88e6755b00bf..2898db7dd758b 100644
--- a/gcc/jit/jit-common.h
+++ b/gcc/jit/jit-common.h
@@ -117,6 +117,7 @@ namespace recording {
class compound_type;
class struct_;
class union_;
+ class array_type;
class vector_type;
class field;
class bitfield;
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index c613630124304..ab7a668eaab5f 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -62,22 +62,39 @@ along with GCC; see the file COPYING3. If not see
/* gcc::jit::playback::context::build_cast uses the convert.h API,
which in turn requires the frontend to provide a "convert"
- function, apparently as a fallback.
-
- Hence we provide this dummy one, with the requirement that any casts
- are handled before reaching this. */
+ function, apparently as a fallback for casts that can be simplified
+ (truncation, extension). */
extern tree convert (tree type, tree expr);
tree
convert (tree dst_type, tree expr)
{
- gcc_assert (gcc::jit::active_playback_ctxt);
- gcc::jit::active_playback_ctxt->add_error (NULL, "unhandled conversion");
- fprintf (stderr, "input expression:\n");
- debug_tree (expr);
- fprintf (stderr, "requested type:\n");
- debug_tree (dst_type);
- return error_mark_node;
+ tree t_ret = NULL;
+ t_ret = targetm.convert_to_type (dst_type, expr);
+ if (t_ret)
+ return t_ret;
+ enum tree_code dst_code = TREE_CODE (dst_type);
+ switch (dst_code)
+ {
+ case INTEGER_TYPE:
+ case ENUMERAL_TYPE:
+ t_ret = convert_to_integer (dst_type, expr);
+ goto maybe_fold;
+
+ default:
+ gcc_assert (gcc::jit::active_playback_ctxt);
+ gcc::jit::active_playback_ctxt->add_error (NULL, "unhandled conversion");
+ fprintf (stderr, "input expression:\n");
+ debug_tree (expr);
+ fprintf (stderr, "requested type:\n");
+ debug_tree (dst_type);
+ return error_mark_node;
+
+ maybe_fold:
+ if (TREE_CODE (t_ret) != C_MAYBE_CONST_EXPR)
+ t_ret = fold (t_ret);
+ return t_ret;
+ }
}
namespace gcc {
@@ -193,6 +210,27 @@ get_tree_node_for_type (enum gcc_jit_types type_)
case GCC_JIT_TYPE_UNSIGNED_INT:
return unsigned_type_node;
+ case GCC_JIT_TYPE_UINT8_T:
+ return unsigned_intQI_type_node;
+ case GCC_JIT_TYPE_UINT16_T:
+ return uint16_type_node;
+ case GCC_JIT_TYPE_UINT32_T:
+ return uint32_type_node;
+ case GCC_JIT_TYPE_UINT64_T:
+ return uint64_type_node;
+ case GCC_JIT_TYPE_UINT128_T:
+ return uint128_type_node;
+ case GCC_JIT_TYPE_INT8_T:
+ return intQI_type_node;
+ case GCC_JIT_TYPE_INT16_T:
+ return intHI_type_node;
+ case GCC_JIT_TYPE_INT32_T:
+ return intSI_type_node;
+ case GCC_JIT_TYPE_INT64_T:
+ return intDI_type_node;
+ case GCC_JIT_TYPE_INT128_T:
+ return intTI_type_node;
+
case GCC_JIT_TYPE_LONG:
return long_integer_type_node;
case GCC_JIT_TYPE_UNSIGNED_LONG:
@@ -434,7 +472,8 @@ new_function (location *loc,
const char *name,
const auto_vec *params,
int is_variadic,
- enum built_in_function builtin_id)
+ enum built_in_function builtin_id,
+ enum gcc_jit_inline_mode inline_mode)
{
int i;
param *param;
@@ -458,6 +497,30 @@ new_function (location *loc,
/* FIXME: this uses input_location: */
tree fndecl = build_fn_decl (name, fn_type);
+ if (inline_mode != GCC_JIT_INLINE_MODE_DEFAULT)
+ {
+ switch (inline_mode)
+ {
+ case GCC_JIT_INLINE_MODE_DEFAULT:
+ break;
+ case GCC_JIT_INLINE_MODE_ALWAYS_INLINE:
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1; // FIXME: this line breaks compilation of sysroot, but seems required to make inlining work.
+ // FIXME: could it be because it's calling an external function?
+ DECL_ATTRIBUTES (fndecl) =
+ tree_cons (get_identifier ("always_inline"),
+ NULL,
+ DECL_ATTRIBUTES (fndecl));
+ break;
+ case GCC_JIT_INLINE_MODE_NO_INLINE:
+ DECL_UNINLINABLE (fndecl) = 1;
+ break;
+ case GCC_JIT_INLINE_MODE_INLINE:
+ DECL_DECLARED_INLINE_P (fndecl) = 1;
+ break;
+ }
+ }
+
if (loc)
set_tree_location (fndecl, loc);
@@ -664,6 +727,39 @@ new_global_initialized (location *loc,
return global_finalize_lvalue (inner);
}
+playback::lvalue *
+playback::context::
+new_global_with_value (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ playback::rvalue *value,
+ const char *name)
+{
+ tree inner = global_new_decl (loc, kind, type, name);
+
+ tree inner_type = type->as_tree ();
+ tree initial = value->as_tree ();
+ gcc_assert (TREE_CONSTANT (initial));
+ DECL_INITIAL (inner) = initial;
+
+ return global_finalize_lvalue (inner);
+}
+
+void
+playback::context::
+set_global_initial_value (playback::lvalue *global,
+ playback::rvalue *value)
+{
+ tree initial = value->as_tree ();
+ if (!TREE_CONSTANT(initial))
+ {
+ add_error (NULL, "initial value for global is not a constant");
+ debug_tree (initial);
+ gcc_assert(TREE_CONSTANT(initial));
+ }
+ DECL_INITIAL (global->as_tree ()) = initial;
+}
+
/* Implementation of the various
gcc::jit::playback::context::new_rvalue_from_const
methods.
@@ -814,6 +910,46 @@ playback::context::new_rvalue_from_vector (location *,
return new rvalue (this, t_ctor);
}
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ struct. */
+
+playback::rvalue *
+playback::context::new_rvalue_from_struct (location *,
+ type *type,
+ const auto_vec &fields)
+{
+ vec *v;
+ vec_alloc (v, fields.length ());
+ tree field_decl = TYPE_FIELDS (type->as_tree ());
+ for (unsigned i = 0; i < fields.length (); ++i)
+ {
+ CONSTRUCTOR_APPEND_ELT (v, field_decl, fields[i]->as_tree ());
+ field_decl = TREE_CHAIN (field_decl);
+ }
+
+ tree t_ctor = build_constructor (type->as_tree (), v);
+ return new rvalue (this, t_ctor);
+}
+
+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ array. */
+
+playback::rvalue *
+playback::context::new_rvalue_from_array (location *,
+ type *type,
+ const auto_vec &elements)
+{
+ vec *v;
+ vec_alloc (v, elements.length ());
+ for (unsigned i = 0; i < elements.length (); ++i)
+ {
+ tree index = build_int_cst (long_unsigned_type_node, i);
+ CONSTRUCTOR_APPEND_ELT (v, index, elements[i]->as_tree ());
+ }
+ tree t_ctor = build_constructor (type->as_tree (), v);
+ return new rvalue (this, t_ctor);
+}
+
/* Coerce a tree expression into a boolean tree expression. */
tree
@@ -1199,6 +1335,20 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}
+playback::rvalue *
+playback::context::
+new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ // TODO: use loc?
+ tree t_bitcast = build1 (VIEW_CONVERT_EXPR,
+ type_->as_tree (), expr->as_tree ());
+ if (loc)
+ set_tree_location (t_bitcast, loc);
+ return new rvalue (this, t_bitcast);
+}
+
/* Construct a playback::lvalue instance (wrapping a tree) for an
array access. */
diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h
index 825a3e172e92d..c81061fa8ea2f 100644
--- a/gcc/jit/jit-playback.h
+++ b/gcc/jit/jit-playback.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include // for std::pair
#include "timevar.h"
+#include "varasm.h"
#include "jit-recording.h"
@@ -103,7 +104,8 @@ class context : public log_user
const char *name,
const auto_vec *params,
int is_variadic,
- enum built_in_function builtin_id);
+ enum built_in_function builtin_id,
+ enum gcc_jit_inline_mode inline_mode);
lvalue *
new_global (location *loc,
@@ -120,6 +122,17 @@ class context : public log_user
const void *initializer,
const char *name);
+ lvalue*
+ new_global_with_value (location *loc,
+ enum gcc_jit_global_kind kind,
+ type *type,
+ rvalue *value,
+ const char *name);
+
+ void
+ set_global_initial_value (playback::lvalue *global,
+ playback::rvalue *value);
+
template
rvalue *
new_rvalue_from_const (type *type,
@@ -133,6 +146,16 @@ class context : public log_user
type *type,
const auto_vec &elements);
+ rvalue *
+ new_rvalue_from_struct (location *loc,
+ type *type,
+ const auto_vec &fields);
+
+ rvalue *
+ new_rvalue_from_array (location *loc,
+ type *type,
+ const auto_vec &elements);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
@@ -167,6 +190,11 @@ class context : public log_user
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -650,6 +678,8 @@ class rvalue : public wrapper
private:
context *m_ctxt;
+
+protected:
tree m_inner;
};
@@ -670,6 +700,26 @@ class lvalue : public rvalue
rvalue *
get_address (location *loc);
+ void
+ set_link_section (const char* name)
+ {
+ set_decl_section_name (m_inner, name);
+ }
+
+ void
+ set_tls_model (enum tls_model tls_model)
+ {
+ set_decl_tls_model (m_inner, tls_model);
+ }
+
+ void
+ set_reg_name (const char* reg_name)
+ {
+ set_user_assembler_name (m_inner, reg_name);
+ DECL_REGISTER (m_inner) = 1;
+ DECL_HARD_REGISTER (m_inner) = 1;
+ }
+
private:
bool mark_addressable (location *loc);
};
diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c
index 117ff70114ca3..c2436d7779aa8 100644
--- a/gcc/jit/jit-recording.c
+++ b/gcc/jit/jit-recording.c
@@ -822,6 +822,10 @@ recording::context::get_int_type (int num_bytes, int is_signed)
return get_type (is_signed
? GCC_JIT_TYPE_LONG_LONG
: GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
+ if (num_bits == 128)
+ return get_type (is_signed
+ ? GCC_JIT_TYPE_INT128_T
+ : GCC_JIT_TYPE_UINT128_T);
/* Some other size, not corresponding to the C int types. */
/* To be written: support arbitrary other sizes, sharing by
@@ -1062,6 +1066,21 @@ recording::context::new_global (recording::location *loc,
return result;
}
+/* Create a memento instance to initialize a global variable and add it to this
+ * context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_global_set_initializer_value. */
+
+void
+recording::context::new_global_value_initializer (recording::lvalue *global,
+ recording::rvalue *value)
+{
+ recording::global_initializer *result =
+ new recording::global_initializer (global, value);
+ record (result);
+}
+
/* Create a recording::memento_of_new_string_literal instance and add it
to this context's list of mementos.
@@ -1077,6 +1096,40 @@ recording::context::new_string_literal (const char *value)
return result;
}
+/* Create a recording::memento_of_new_rvalue_from_struct instance and add it
+ to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_struct. */
+
+recording::rvalue *
+recording::context::new_rvalue_from_struct (location *loc,
+ struct_ *type,
+ rvalue **fields)
+{
+ recording::rvalue *result =
+ new memento_of_new_rvalue_from_struct (this, loc, type, fields);
+ record (result);
+ return result;
+}
+
+/* Create a recording::memento_of_new_rvalue_from_array instance and add it
+ to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_array. */
+
+recording::rvalue *
+recording::context::new_rvalue_from_array (location *loc,
+ array_type *type,
+ rvalue **elements)
+{
+ recording::rvalue *result =
+ new memento_of_new_rvalue_from_array (this, loc, type, elements);
+ record (result);
+ return result;
+}
+
/* Create a recording::memento_of_new_rvalue_from_vector instance and add it
to this context's list of mementos.
@@ -1164,6 +1217,22 @@ recording::context::new_cast (recording::location *loc,
return result;
}
+/* Create a recording::bitcast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_bitcast. */
+
+recording::rvalue *
+recording::context::new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_)
+{
+ recording::rvalue *result = new bitcast (this, loc, expr, type_);
+ record (result);
+ return result;
+}
+
/* Create a recording::call instance and add it to this context's list
of mementos.
@@ -2247,6 +2316,18 @@ recording::memento_of_get_type::get_size ()
case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
size = LONG_LONG_TYPE_SIZE;
break;
+ case GCC_JIT_TYPE_UINT8_T:
+ case GCC_JIT_TYPE_UINT16_T:
+ case GCC_JIT_TYPE_UINT32_T:
+ case GCC_JIT_TYPE_UINT64_T:
+ case GCC_JIT_TYPE_UINT128_T:
+ case GCC_JIT_TYPE_INT8_T:
+ case GCC_JIT_TYPE_INT16_T:
+ case GCC_JIT_TYPE_INT32_T:
+ case GCC_JIT_TYPE_INT64_T:
+ case GCC_JIT_TYPE_INT128_T:
+ size = 128;
+ break;
case GCC_JIT_TYPE_FLOAT:
size = FLOAT_TYPE_SIZE;
break;
@@ -2295,6 +2376,16 @@ recording::memento_of_get_type::dereference ()
case GCC_JIT_TYPE_UNSIGNED_LONG:
case GCC_JIT_TYPE_LONG_LONG:
case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ case GCC_JIT_TYPE_UINT8_T:
+ case GCC_JIT_TYPE_UINT16_T:
+ case GCC_JIT_TYPE_UINT32_T:
+ case GCC_JIT_TYPE_UINT64_T:
+ case GCC_JIT_TYPE_UINT128_T:
+ case GCC_JIT_TYPE_INT8_T:
+ case GCC_JIT_TYPE_INT16_T:
+ case GCC_JIT_TYPE_INT32_T:
+ case GCC_JIT_TYPE_INT64_T:
+ case GCC_JIT_TYPE_INT128_T:
case GCC_JIT_TYPE_FLOAT:
case GCC_JIT_TYPE_DOUBLE:
case GCC_JIT_TYPE_LONG_DOUBLE:
@@ -2347,6 +2438,16 @@ recording::memento_of_get_type::is_int () const
case GCC_JIT_TYPE_UNSIGNED_LONG:
case GCC_JIT_TYPE_LONG_LONG:
case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ case GCC_JIT_TYPE_UINT8_T:
+ case GCC_JIT_TYPE_UINT16_T:
+ case GCC_JIT_TYPE_UINT32_T:
+ case GCC_JIT_TYPE_UINT64_T:
+ case GCC_JIT_TYPE_UINT128_T:
+ case GCC_JIT_TYPE_INT8_T:
+ case GCC_JIT_TYPE_INT16_T:
+ case GCC_JIT_TYPE_INT32_T:
+ case GCC_JIT_TYPE_INT64_T:
+ case GCC_JIT_TYPE_INT128_T:
return true;
case GCC_JIT_TYPE_FLOAT:
@@ -2400,6 +2501,16 @@ recording::memento_of_get_type::is_float () const
case GCC_JIT_TYPE_UNSIGNED_LONG:
case GCC_JIT_TYPE_LONG_LONG:
case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ case GCC_JIT_TYPE_UINT8_T:
+ case GCC_JIT_TYPE_UINT16_T:
+ case GCC_JIT_TYPE_UINT32_T:
+ case GCC_JIT_TYPE_UINT64_T:
+ case GCC_JIT_TYPE_UINT128_T:
+ case GCC_JIT_TYPE_INT8_T:
+ case GCC_JIT_TYPE_INT16_T:
+ case GCC_JIT_TYPE_INT32_T:
+ case GCC_JIT_TYPE_INT64_T:
+ case GCC_JIT_TYPE_INT128_T:
return false;
case GCC_JIT_TYPE_FLOAT:
@@ -2453,6 +2564,16 @@ recording::memento_of_get_type::is_bool () const
case GCC_JIT_TYPE_UNSIGNED_LONG:
case GCC_JIT_TYPE_LONG_LONG:
case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
+ case GCC_JIT_TYPE_UINT8_T:
+ case GCC_JIT_TYPE_UINT16_T:
+ case GCC_JIT_TYPE_UINT32_T:
+ case GCC_JIT_TYPE_UINT64_T:
+ case GCC_JIT_TYPE_UINT128_T:
+ case GCC_JIT_TYPE_INT8_T:
+ case GCC_JIT_TYPE_INT16_T:
+ case GCC_JIT_TYPE_INT32_T:
+ case GCC_JIT_TYPE_INT64_T:
+ case GCC_JIT_TYPE_INT128_T:
return false;
case GCC_JIT_TYPE_FLOAT:
@@ -2511,6 +2632,17 @@ static const char * const get_type_strings[] = {
"long long", /* GCC_JIT_TYPE_LONG_LONG */
"unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
+ "__uint8_t", /* GCC_JIT_TYPE_UINT8_T */
+ "__uint16_t", /* GCC_JIT_TYPE_UINT16_T */
+ "__uint32_t", /* GCC_JIT_TYPE_UINT32_T */
+ "__uint64_t", /* GCC_JIT_TYPE_UINT64_T */
+ "__uint128_t", /* GCC_JIT_TYPE_UINT128_T */
+ "__int8_t", /* GCC_JIT_TYPE_INT8_T */
+ "__int16_t", /* GCC_JIT_TYPE_INT16_T */
+ "__int32_t", /* GCC_JIT_TYPE_INT32_T */
+ "__int64_t", /* GCC_JIT_TYPE_INT64_T */
+ "__int128_t", /* GCC_JIT_TYPE_INT128_T */
+
"float", /* GCC_JIT_TYPE_FLOAT */
"double", /* GCC_JIT_TYPE_DOUBLE */
"long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
@@ -2551,6 +2683,16 @@ static const char * const get_type_enum_strings[] = {
"GCC_JIT_TYPE_UNSIGNED_LONG",
"GCC_JIT_TYPE_LONG_LONG",
"GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
+ "GCC_JIT_TYPE_UINT8_T",
+ "GCC_JIT_TYPE_UINT16_T",
+ "GCC_JIT_TYPE_UINT32_T",
+ "GCC_JIT_TYPE_UINT64_T",
+ "GCC_JIT_TYPE_UINT128_T",
+ "GCC_JIT_TYPE_INT8_T",
+ "GCC_JIT_TYPE_INT16_T",
+ "GCC_JIT_TYPE_INT32_T",
+ "GCC_JIT_TYPE_INT64_T",
+ "GCC_JIT_TYPE_INT128_T",
"GCC_JIT_TYPE_FLOAT",
"GCC_JIT_TYPE_DOUBLE",
"GCC_JIT_TYPE_LONG_DOUBLE",
@@ -2598,8 +2740,18 @@ recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
return false;
/* It's OK to assign to a (const T *) from a (T *). */
- return m_other_type->unqualified ()
- ->accepts_writes_from (rtype_points_to);
+ if (m_other_type->unqualified ()
+ ->accepts_writes_from (rtype_points_to)) {
+ return true;
+ }
+
+ /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
+ if (m_other_type->unqualified ()->unqualified ()
+ ->accepts_writes_from (rtype_points_to->unqualified ())) {
+ return true;
+ }
+
+ return false;
}
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -3713,6 +3865,22 @@ recording::lvalue::get_address (recording::location *loc)
return result;
}
+void recording::lvalue::set_link_section (const char *name)
+{
+ m_link_section = new_string (name);
+}
+
+void
+recording::lvalue::set_tls_model (enum gcc_jit_tls_model model)
+{
+ m_tls_model = model;
+}
+
+void recording::lvalue::set_register_name (const char *reg_name)
+{
+ m_reg_name = new_string (reg_name);
+}
+
/* The implementation of class gcc::jit::recording::param. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -3789,7 +3957,8 @@ recording::function::function (context *ctxt,
m_builtin_id (builtin_id),
m_locals (),
m_blocks (),
- m_fn_ptr_type (NULL)
+ m_fn_ptr_type (NULL),
+ m_inline_mode(GCC_JIT_INLINE_MODE_DEFAULT)
{
for (int i = 0; i< num_params; i++)
{
@@ -3848,7 +4017,8 @@ recording::function::replay_into (replayer *r)
m_name->c_str (),
¶ms,
m_is_variadic,
- m_builtin_id));
+ m_builtin_id,
+ m_inline_mode));
}
/* Create a recording::local instance and add it to
@@ -4062,6 +4232,15 @@ recording::function::dump_to_dot (const char *path)
fclose (fp);
}
+/* Implements the post-error-checking part of
+ gcc_jit_function_set_inline_mode. */
+
+void
+recording::function::set_inline_mode(enum gcc_jit_inline_mode inline_mode)
+{
+ m_inline_mode = inline_mode;
+}
+
/* Implements the post-error-checking part of
gcc_jit_function_get_address. */
@@ -4539,6 +4718,15 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
# pragma GCC diagnostic pop
#endif
+namespace recording {
+static const enum tls_model tls_models[] = {
+ TLS_MODEL_GLOBAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
+ TLS_MODEL_LOCAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
+ TLS_MODEL_INITIAL_EXEC, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
+ TLS_MODEL_LOCAL_EXEC, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
+};
+} /* namespace recording */
+
/* The implementation of class gcc::jit::recording::global. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -4547,20 +4735,43 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
void
recording::global::replay_into (replayer *r)
{
- set_playback_obj (
- m_initializer
- ? r->new_global_initialized (playback_location (r, m_loc),
+ playback::lvalue *global;
+ if (m_initializer)
+ {
+ global = r->new_global_initialized (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
m_type->dereference ()->get_size (),
m_initializer_num_bytes
/ m_type->dereference ()->get_size (),
m_initializer,
- playback_string (m_name))
- : r->new_global (playback_location (r, m_loc),
+ playback_string (m_name));
+ }
+ else if (m_initializer_value)
+ {
+ global = r->new_global_with_value (playback_location (r, m_loc),
+ m_kind,
+ m_type->playback_type (),
+ m_initializer_value->playback_rvalue (),
+ playback_string (m_name));
+ }
+ else
+ {
+ global = r->new_global (playback_location (r, m_loc),
m_kind,
m_type->playback_type (),
- playback_string (m_name)));
+ playback_string (m_name));
+ }
+ if (m_link_section != NULL)
+ {
+ global->set_link_section (m_link_section->c_str ());
+ }
+
+ if (m_tls_model != GCC_JIT_TLS_MODEL_DEFAULT)
+ {
+ global->set_tls_model (recording::tls_models[m_tls_model]);
+ }
+ set_playback_obj (global);
}
/* Override the default implementation of
@@ -4658,6 +4869,14 @@ recording::global::write_initializer_reproducer (const char *id, reproducer &r)
/* Implementation of recording::memento::write_reproducer for globals. */
+static const char * const tls_model_enum_strings[] = {
+ "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
+ "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
+ "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
+ "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
+ "GCC_JIT_TLS_MODEL_DEFAULT",
+};
+
void
recording::global::write_reproducer (reproducer &r)
{
@@ -4675,6 +4894,30 @@ recording::global::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()),
m_name->get_debug_string ());
+ if (m_link_section != NULL)
+ {
+ r.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
+ " \"%s\"); /* */\n",
+ id,
+ m_link_section->c_str ());
+ }
+
+ if (m_tls_model)
+ {
+ r.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
+ " %s); /* enum gcc_jit_tls_model model */\n",
+ id,
+ tls_model_enum_strings[m_tls_model]);
+ }
+
+ if (m_initializer_value)
+ {
+ r.write (" gcc_jit_global_set_initializer_value (%s, /* gcc_jit_lvalue *global */\n"
+ " %s/* gcc_jit_rvalue *value */);\n",
+ id,
+ r.get_identifier_as_rvalue (m_initializer_value));
+ }
+
if (m_initializer)
switch (m_type->dereference ()->get_size ())
{
@@ -4697,6 +4940,49 @@ recording::global::write_reproducer (reproducer &r)
}
}
+/* The implementation of class gcc::jit::recording::global_initializer. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::global_initializer. */
+
+void
+recording::global_initializer::replay_into (replayer *r)
+{
+ r->set_global_initial_value(m_global->playback_lvalue (), m_value->playback_rvalue ());
+}
+
+/* Override the default implementation of
+ recording::memento::write_to_dump for globals.
+ This will be of the form:
+
+ TODO
+
+ These are written to the top of the dump by
+ recording::context::dump_to_file. */
+
+void
+recording::global_initializer::write_to_dump (dump &d)
+{
+ // TODO
+}
+
+recording::string *
+recording::global_initializer::make_debug_string ()
+{
+ // TODO
+ return string::from_printf (m_ctxt,
+ "",
+ (void *)this);
+}
+
+/* Implementation of recording::memento::write_reproducer for global initializers. */
+
+void
+recording::global_initializer::write_reproducer (reproducer &r)
+{
+ // TODO
+}
+
/* The implementation of the various const-handling classes:
gcc::jit::recording::memento_of_new_rvalue_from_const . */
@@ -5070,6 +5356,148 @@ recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
elements_id);
}
+/* The implementation of class
+ gcc::jit::recording::memento_of_new_rvalue_from_struct. */
+
+/* The constructor for
+ gcc::jit::recording::memento_of_new_rvalue_from_struct. */
+
+recording::memento_of_new_rvalue_from_struct::
+memento_of_new_rvalue_from_struct (context *ctxt,
+ location *loc,
+ struct_ *type,
+ rvalue **fields)
+: rvalue (ctxt, loc, type),
+ m_struct_type (type),
+ m_fields ()
+{
+ for (int i = 0; i < type->get_fields ()->length (); i++)
+ m_fields.safe_push (fields[i]);
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_struct. */
+
+void
+recording::memento_of_new_rvalue_from_struct::replay_into (replayer *r)
+{
+ auto_vec playback_fields;
+ playback_fields.create (m_fields.length ());
+ for (unsigned i = 0; i< m_fields.length (); i++)
+ playback_fields.safe_push (m_fields[i]->playback_rvalue ());
+
+ set_playback_obj (r->new_rvalue_from_struct (playback_location (r, m_loc),
+ m_type->playback_type (),
+ playback_fields));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::memento_of_new_rvalue_from_struct. */
+
+void
+recording::memento_of_new_rvalue_from_struct::visit_children (rvalue_visitor *v)
+{
+ for (unsigned i = 0; i< m_fields.length (); i++)
+ v->visit (m_fields[i]);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ vectors. */
+
+recording::string *
+recording::memento_of_new_rvalue_from_struct::make_debug_string ()
+{
+ comma_separated_string fields (m_fields, get_precedence ());
+
+ /* Now build a string. */
+ string *result = string::from_printf (m_ctxt,
+ "{%s}",
+ fields.as_char_ptr ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vectors. */
+
+void
+recording::memento_of_new_rvalue_from_struct::write_reproducer (reproducer &r)
+{
+ // TODO
+}
+
+/* The implementation of class
+ gcc::jit::recording::memento_of_new_rvalue_from_array. */
+
+/* The constructor for
+ gcc::jit::recording::memento_of_new_rvalue_from_array. */
+
+recording::memento_of_new_rvalue_from_array::
+memento_of_new_rvalue_from_array (context *ctxt,
+ location *loc,
+ array_type *type,
+ rvalue **elements)
+: rvalue (ctxt, loc, type),
+ m_array_type (type),
+ m_elements ()
+{
+ for (int i = 0; i < type->num_elements (); i++)
+ m_elements.safe_push (elements[i]);
+}
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_array. */
+
+void
+recording::memento_of_new_rvalue_from_array::replay_into (replayer *r)
+{
+ auto_vec playback_elements;
+ playback_elements.create (m_elements.length ());
+ for (unsigned i = 0; i< m_elements.length (); i++)
+ playback_elements.safe_push (m_elements[i]->playback_rvalue ());
+
+ set_playback_obj (r->new_rvalue_from_array (playback_location (r, m_loc),
+ m_type->playback_type (),
+ playback_elements));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::memento_of_new_rvalue_from_array. */
+
+void
+recording::memento_of_new_rvalue_from_array::visit_children (rvalue_visitor *v)
+{
+ for (unsigned i = 0; i< m_elements.length (); i++)
+ v->visit (m_elements[i]);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ vectors. */
+
+recording::string *
+recording::memento_of_new_rvalue_from_array::make_debug_string ()
+{
+ comma_separated_string elements (m_elements, get_precedence ());
+
+ /* Now build a string. */
+ string *result = string::from_printf (m_ctxt,
+ "{%s}",
+ elements.as_char_ptr ());
+
+ return result;
+
+}
+
+/* Implementation of recording::memento::write_reproducer for
+ vectors. */
+
+void
+recording::memento_of_new_rvalue_from_array::write_reproducer (reproducer &r)
+{
+ // TODO
+}
+
/* The implementation of class gcc::jit::recording::unary_op. */
/* Implementation of pure virtual hook recording::memento::replay_into
@@ -5403,6 +5831,56 @@ recording::cast::write_reproducer (reproducer &r)
r.get_identifier_as_type (get_type ()));
}
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::bitcast. */
+
+void
+recording::bitcast::replay_into (replayer *r)
+{
+ set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
+ m_rvalue->playback_rvalue (),
+ get_type ()->playback_type ()));
+}
+
+/* Implementation of pure virtual hook recording::rvalue::visit_children
+ for recording::bitcast. */
+void
+recording::bitcast::visit_children (rvalue_visitor *v)
+{
+ v->visit (m_rvalue);
+}
+
+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
+recording::string *
+recording::bitcast::make_debug_string ()
+{
+ enum precedence prec = get_precedence ();
+ return string::from_printf (m_ctxt,
+ "bitcast(%s, %s)",
+ m_rvalue->get_debug_string_parens (prec),
+ get_type ()->get_debug_string ());
+}
+
+/* Implementation of recording::memento::write_reproducer for casts. */
+
+void
+recording::bitcast::write_reproducer (reproducer &r)
+{
+ const char *id = r.make_identifier (this, "rvalue");
+ r.write (" gcc_jit_rvalue *%s =\n"
+ " gcc_jit_context_new_bitcast (%s,\n"
+ " %s, /* gcc_jit_location *loc */\n"
+ " %s, /* gcc_jit_rvalue *rvalue */\n"
+ " %s); /* gcc_jit_type *type */\n",
+ id,
+ r.get_identifier (get_context ()),
+ r.get_identifier (m_loc),
+ r.get_identifier_as_rvalue (m_rvalue),
+ r.get_identifier_as_type (get_type ()));
+}
+
/* The implementation of class gcc::jit::recording::base_call. */
/* The constructor for gcc::jit::recording::base_call. */
@@ -6006,11 +6484,15 @@ recording::function_pointer::write_reproducer (reproducer &r)
void
recording::local::replay_into (replayer *r)
{
- set_playback_obj (
- m_func->playback_function ()
+ playback::lvalue *obj = m_func->playback_function ()
->new_local (playback_location (r, m_loc),
m_type->playback_type (),
- playback_string (m_name)));
+ playback_string (m_name));
+ if (m_reg_name != NULL)
+ {
+ obj->set_reg_name(m_reg_name->c_str());
+ }
+ set_playback_obj (obj);
}
/* Override the default implementation of
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa1160cf088..e598869298261 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -149,6 +149,10 @@ class context : public log_user
type *type,
const char *name);
+ void
+ new_global_value_initializer (recording::lvalue *global,
+ recording::rvalue *value);
+
template
rvalue *
new_rvalue_from_const (type *type,
@@ -162,6 +166,16 @@ class context : public log_user
vector_type *type,
rvalue **elements);
+ rvalue *
+ new_rvalue_from_struct (location *loc,
+ struct_ *type,
+ rvalue **fields);
+
+ rvalue *
+ new_rvalue_from_array (location *loc,
+ array_type *type,
+ rvalue **elements);
+
rvalue *
new_unary_op (location *loc,
enum gcc_jit_unary_op op,
@@ -194,6 +208,11 @@ class context : public log_user
rvalue *expr,
type *type_);
+ rvalue *
+ new_bitcast (location *loc,
+ rvalue *expr,
+ type *type_);
+
lvalue *
new_array_access (location *loc,
rvalue *ptr,
@@ -522,6 +541,7 @@ class type : public memento
virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; }
virtual struct_ *dyn_cast_struct () { return NULL; }
virtual vector_type *dyn_cast_vector_type () { return NULL; }
+ virtual array_type *dyn_cast_array_type () { return NULL; }
/* Is it typesafe to copy to this type from rtype? */
virtual bool accepts_writes_from (type *rtype)
@@ -546,7 +566,9 @@ class type : public memento
virtual bool is_bool () const = 0;
virtual type *is_pointer () = 0;
virtual type *is_array () = 0;
+ virtual struct_ *is_struct () { return NULL; }
virtual bool is_void () const { return false; }
+ virtual vector_type *is_vector () { return NULL; }
virtual bool has_known_size () const { return true; }
bool is_numeric () const
@@ -663,6 +685,7 @@ class decorated_type : public type
bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+ struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
protected:
type *m_other_type;
@@ -745,6 +768,8 @@ class vector_type : public decorated_type
void replay_into (replayer *) FINAL OVERRIDE;
+ vector_type *is_vector () FINAL OVERRIDE { return this; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -768,6 +793,8 @@ class array_type : public type
type *dereference () FINAL OVERRIDE;
+ array_type *dyn_cast_array_type () FINAL OVERRIDE { return this; }
+
bool is_int () const FINAL OVERRIDE { return false; }
bool is_float () const FINAL OVERRIDE { return false; }
bool is_bool () const FINAL OVERRIDE { return false; }
@@ -951,6 +978,8 @@ class struct_ : public compound_type
const char *access_as_type (reproducer &r) FINAL OVERRIDE;
+ struct_ *is_struct () FINAL OVERRIDE { return this; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1105,7 +1134,10 @@ class lvalue : public rvalue
lvalue (context *ctxt,
location *loc,
type *type_)
- : rvalue (ctxt, loc, type_)
+ : rvalue (ctxt, loc, type_),
+ m_link_section (NULL),
+ m_reg_name (NULL),
+ m_tls_model (GCC_JIT_TLS_MODEL_DEFAULT)
{}
playback::lvalue *
@@ -1127,6 +1159,19 @@ class lvalue : public rvalue
const char *access_as_rvalue (reproducer &r) OVERRIDE;
virtual const char *access_as_lvalue (reproducer &r);
virtual bool is_global () const { return false; }
+ void set_link_section (const char *name);
+ void set_tls_model (enum gcc_jit_tls_model model);
+ void set_register_name (const char *reg_name);
+
+ // TODO: does the following make sense?
+ bool is_constant () const FINAL OVERRIDE {
+ return is_global();
+ }
+
+protected:
+ string *m_link_section;
+ string *m_reg_name;
+ enum gcc_jit_tls_model m_tls_model;
};
class param : public lvalue
@@ -1218,6 +1263,8 @@ class function : public memento
void dump_to_dot (const char *path);
+ void set_inline_mode(enum gcc_jit_inline_mode);
+
rvalue *get_address (location *loc);
private:
@@ -1235,6 +1282,7 @@ class function : public memento
auto_vec m_locals;
auto_vec m_blocks;
type *m_fn_ptr_type;
+ gcc_jit_inline_mode m_inline_mode;
};
class block : public memento
@@ -1360,6 +1408,7 @@ class global : public lvalue
m_name (name)
{
m_initializer = NULL;
+ m_initializer_value = NULL;
m_initializer_num_bytes = 0;
}
~global ()
@@ -1386,6 +1435,12 @@ class global : public lvalue
m_initializer_num_bytes = num_bytes;
}
+ void
+ set_initializer_value (rvalue* value)
+ {
+ m_initializer_value = value;
+ }
+
private:
string * make_debug_string () FINAL OVERRIDE { return m_name; }
template
@@ -1400,9 +1455,30 @@ class global : public lvalue
enum gcc_jit_global_kind m_kind;
string *m_name;
void *m_initializer;
+ rvalue *m_initializer_value;
size_t m_initializer_num_bytes;
};
+class global_initializer : public memento
+{
+public:
+ void write_to_dump (dump &d) FINAL OVERRIDE;
+ void replay_into (replayer *) FINAL OVERRIDE;
+
+ global_initializer (lvalue *global, rvalue *value)
+ : memento (global->m_ctxt),
+ m_global (global),
+ m_value (value) {}
+
+private:
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ string * make_debug_string () FINAL OVERRIDE;
+
+private:
+ lvalue *m_global;
+ rvalue *m_value;
+};
+
template
class memento_of_new_rvalue_from_const : public rvalue
{
@@ -1447,6 +1523,8 @@ class memento_of_new_string_literal : public rvalue
void visit_children (rvalue_visitor *) FINAL OVERRIDE {}
+ virtual bool is_constant () const { return true; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1484,6 +1562,78 @@ class memento_of_new_rvalue_from_vector : public rvalue
auto_vec m_elements;
};
+class memento_of_new_rvalue_from_array : public rvalue
+{
+public:
+ memento_of_new_rvalue_from_array (context *ctxt,
+ location *loc,
+ array_type *type,
+ rvalue **elements);
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *) FINAL OVERRIDE;
+
+ virtual bool is_constant () const {
+ for (rvalue *element : m_elements)
+ {
+ if (!element->is_constant ())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_PRIMARY;
+ }
+
+private:
+ array_type *m_array_type;
+ auto_vec m_elements;
+};
+
+class memento_of_new_rvalue_from_struct : public rvalue
+{
+public:
+ memento_of_new_rvalue_from_struct (context *ctxt,
+ location *loc,
+ struct_ *type,
+ rvalue **fields);
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *) FINAL OVERRIDE;
+
+ virtual bool is_constant () const {
+ for (rvalue *field : m_fields)
+ {
+ if (!field->is_constant ())
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_PRIMARY;
+ }
+
+private:
+ struct_ *m_struct_type;
+ auto_vec m_fields;
+};
+
class unary_op : public rvalue
{
public:
@@ -1531,6 +1681,10 @@ class binary_op : public rvalue
void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+ virtual bool is_constant () const {
+ return m_a->is_constant () && m_b->is_constant ();
+ }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1585,6 +1739,41 @@ class cast : public rvalue
void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+ virtual bool is_constant () const {
+ return m_rvalue->is_constant ();
+ }
+
+private:
+ string * make_debug_string () FINAL OVERRIDE;
+ void write_reproducer (reproducer &r) FINAL OVERRIDE;
+ enum precedence get_precedence () const FINAL OVERRIDE
+ {
+ return PRECEDENCE_CAST;
+ }
+
+private:
+ rvalue *m_rvalue;
+};
+
+class bitcast : public rvalue
+{
+public:
+ bitcast (context *ctxt,
+ location *loc,
+ rvalue *a,
+ type *type_)
+ : rvalue (ctxt, loc, type_),
+ m_rvalue (a)
+ {}
+
+ void replay_into (replayer *r) FINAL OVERRIDE;
+
+ void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+
+ virtual bool is_constant () const {
+ return m_rvalue->is_constant ();
+ }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1823,6 +2012,10 @@ class get_address_of_lvalue : public rvalue
void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+ virtual bool is_constant () const {
+ return m_lvalue->is_constant ();
+ }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -1849,6 +2042,8 @@ class function_pointer : public rvalue
void visit_children (rvalue_visitor *v) FINAL OVERRIDE;
+ virtual bool is_constant () const { return true; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 7fa948007ad8f..d4a47d8133206 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
{
};
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
struct gcc_jit_field : public gcc::jit::recording::field
{
};
@@ -269,6 +277,17 @@ struct gcc_jit_extended_asm : public gcc::jit::recording::extended_asm
} \
JIT_END_STMT
+#define RETURN_IF_FAIL_PRINTF5(TEST_EXPR, CTXT, LOC, ERR_FMT, A0, A1, A2, A3, \
+ A4) \
+ JIT_BEGIN_STMT \
+ if (!(TEST_EXPR)) \
+ { \
+ jit_error ((CTXT), (LOC), "%s: " ERR_FMT, \
+ __func__, (A0), (A1), (A2), (A3), (A4)); \
+ return; \
+ } \
+ JIT_END_STMT
+
/* Check that BLOCK is non-NULL, and that it's OK to add statements to
it. This will fail if BLOCK has already been terminated by some
kind of jump or a return. */
@@ -515,6 +534,208 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
return (gcc_jit_type *)type->get_volatile ();
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_array method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function::set_inline_mode method, in
+ jit-recording.c. */
+
+void
+gcc_jit_function_set_inline_mode(gcc_jit_function *func, enum gcc_jit_inline_mode inline_mode)
+{
+ RETURN_IF_FAIL (func, NULL, NULL, "NULL function");
+
+ func->set_inline_mode(inline_mode);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_bool method, in
+ jit-recording.c. */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+ RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+ return type->is_bool ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_pointer method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_int method, in
+ jit-recording.c. */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+ RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+ return type->is_int ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_vector method, in
+ jit-recording.c. */
+
+gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+ return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_struct method, in
+ jit-recording.c. */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+ return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::vector_type::get_num_units method, in
+ jit-recording.c. */
+
+ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+ RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type");
+ return vector_type->get_num_units ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::vector_type::get_element_type method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+ RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+ return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::unqualified method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::dyn_cast_function_type method, in
+ jit-recording.c. */
+
+gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::type *func_ptr_type = type->dereference ();
+ RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_return_type method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+ RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+ return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_param_types method, in
+ jit-recording.c. */
+
+ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+ RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL function_type");
+ return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_param_types method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index)
+{
+ RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+ size_t num_params = function_type->get_param_types ().length ();
+ gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+ RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+ ctxt, NULL,
+ "index of %ld is too large (%s has %ld params)",
+ index,
+ function_type->get_debug_string (),
+ num_params);
+ return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -736,6 +957,37 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
(gcc::jit::recording::field **)fields);
}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::fields::get_field method in
+ jit-recording.c. */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index)
+{
+ RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+ RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+ "NULL struct fields");
+ RETURN_NULL_IF_FAIL ((int) index < struct_type->get_fields ()->length (),
+ NULL, NULL, "NULL struct type");
+ return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, this calls the trivial
+ gcc::jit::recording::struct_::get_fields method in
+ jit-recording.h. */
+
+ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+ RETURN_VAL_IF_FAIL (struct_type, -1, NULL, NULL, "NULL struct type");
+ return struct_type->get_fields ()->length ();
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -1017,6 +1269,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
return static_cast (func->get_param (index));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function::get_params method, in
+ jit-recording.h.
+ */
+
+ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+ RETURN_VAL_IF_FAIL (func, -1, NULL, NULL, "NULL function");
+ gcc::jit::recording::context *ctxt = func->m_ctxt;
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ return func->get_params ().length ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function::get_return_type method, in
+ jit-recording.h. */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+ RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+ return (gcc_jit_type *)func->get_return_type ();
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -1161,6 +1442,42 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
return global;
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::global::set_initializer_value method, in
+ jit-recording.c. */
+
+void
+gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,
+ gcc_jit_rvalue *value)
+{
+ // TODO: fail if global kind is imported.
+ RETURN_IF_FAIL (global, NULL, NULL, "NULL global");
+ RETURN_IF_FAIL (value, NULL, NULL, "NULL value");
+ RETURN_IF_FAIL_PRINTF1 (global->is_global (), NULL, NULL,
+ "lvalue \"%s\" not a global",
+ global->get_debug_string ());
+
+ RETURN_IF_FAIL_PRINTF5 (
+ compatible_types (global->get_type (),
+ value->get_type ()),
+ NULL, NULL,
+ "mismatching types for global \"%s\":"
+ " assignment to global %s (type: %s) from %s (type: %s)",
+ global->get_debug_string (),
+ global->get_debug_string (),
+ global->get_type ()->get_debug_string (),
+ value->get_debug_string (),
+ value->get_type ()->get_debug_string ());
+
+ RETURN_IF_FAIL_PRINTF1 (value->is_constant (), NULL, NULL,
+ "rvalue \"%s\" not a constant",
+ value->get_debug_string ());
+
+ global->get_context ()->new_global_value_initializer (global, value);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, this calls the trivial
@@ -1383,6 +1700,112 @@ gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
return (gcc_jit_rvalue *)ctxt->new_string_literal (value);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_rvalue_from_struct method in
+ jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_struct (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_struct *struct_type,
+ size_t num_elements,
+ gcc_jit_rvalue **fields)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (struct_type, ctxt, loc, "NULL struct_type");
+
+ /* "num_elements" must match. */
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ num_elements == (size_t) struct_type->get_fields ()->length (), ctxt, loc,
+ "num_elements != %d", struct_type->get_fields ()->length ());
+
+ /* "fields must be non-NULL. */
+ RETURN_NULL_IF_FAIL (fields, ctxt, loc, "NULL fields");
+
+ /* Each of "fields" must be non-NULL and of the correct type. */
+ for (size_t i = 0; i < num_elements; i++)
+ {
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ fields[i], ctxt, loc, "NULL fields[%zi]", i);
+ gcc::jit::recording::type *field_type
+ = struct_type->get_fields ()->get_field (i)->get_type ();
+ RETURN_NULL_IF_FAIL_PRINTF4 (
+ compatible_types (field_type,
+ fields[i]->get_type ()),
+ ctxt, loc,
+ "mismatching type for field[%zi] (expected type: %s): %s (type: %s)",
+ i,
+ field_type->get_debug_string (),
+ fields[i]->get_debug_string (),
+ fields[i]->get_type ()->get_debug_string ());
+ RETURN_NULL_IF_FAIL_PRINTF2 (fields[i]->is_constant (), ctxt, NULL,
+ "fields[%ld] is not a constant: %s", i,
+ fields[i]->get_debug_string ());
+ }
+
+ return (gcc_jit_rvalue *)ctxt->new_rvalue_from_struct (loc, struct_type, (gcc::jit::recording::rvalue **)fields);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_rvalue_from_array method in
+ jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_array (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *type,
+ size_t num_elements,
+ gcc_jit_rvalue **elements)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+
+ /* "type" must be an array type. */
+ gcc::jit::recording::array_type *array_type
+ = type->dyn_cast_array_type ();
+ RETURN_NULL_IF_FAIL_PRINTF1 (array_type, ctxt, loc,
+ "%s is not an array type",
+ type->get_debug_string ());
+
+ /* "num_elements" must match. */
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ num_elements == (size_t) array_type->num_elements (), ctxt, loc,
+ "num_elements != %d", array_type->num_elements ());
+
+ /* "elements must be non-NULL. */
+ RETURN_NULL_IF_FAIL (elements, ctxt, loc, "NULL elements");
+
+ /* Each of "elements" must be non-NULL and of the correct type. */
+ gcc::jit::recording::type *element_type
+ = array_type->is_array ();
+ for (size_t i = 0; i < num_elements; i++)
+ {
+ RETURN_NULL_IF_FAIL_PRINTF1 (
+ elements[i], ctxt, loc, "NULL elements[%zi]", i);
+ RETURN_NULL_IF_FAIL_PRINTF4 (
+ compatible_types (element_type,
+ elements[i]->get_type ()),
+ ctxt, loc,
+ "mismatching type for array[%zi] (expected type: %s): %s (type: %s)",
+ i,
+ element_type->get_debug_string (),
+ elements[i]->get_debug_string (),
+ elements[i]->get_type ()->get_debug_string ());
+ }
+
+ return (gcc_jit_rvalue *)ctxt->new_rvalue_from_array (loc, array_type, (gcc::jit::recording::rvalue **)elements);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -1740,6 +2163,34 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
return static_cast (ctxt->new_cast (loc, rvalue, type));
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::context::new_bitcast method in jit-recording.c. */
+
+gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ /* LOC can be NULL. */
+ RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
+ RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
+ // TODO: check the sizes.
+ /*RETURN_NULL_IF_FAIL_PRINTF3 (
+ is_valid_cast (rvalue->get_type (), type),
+ ctxt, loc,
+ "cannot cast %s from type: %s to type: %s",
+ rvalue->get_debug_string (),
+ rvalue->get_type ()->get_debug_string (),
+ type->get_debug_string ());*/
+
+ return static_cast (ctxt->new_bitcast (loc, rvalue, type));
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -1953,6 +2404,49 @@ gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue,
return (gcc_jit_rvalue *)lvalue->get_address (loc);
}
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::lvalue::set_section method in jit-recording.c. */
+void
+gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue,
+ const char *name)
+{
+ RETURN_IF_FAIL (name, NULL, NULL, "NULL name");
+ lvalue->set_link_section (name);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::lvalue::set_tls_model method in jit-recording.c. */
+
+void
+gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,
+ enum gcc_jit_tls_model model)
+{
+ RETURN_IF_FAIL (lvalue, NULL, NULL, "NULL lvalue");
+ JIT_LOG_FUNC (lvalue->get_context ()->get_logger ());
+ RETURN_IF_FAIL_PRINTF1 (lvalue->is_global (), NULL, NULL,
+ "lvalue \"%s\" not a global",
+ lvalue->get_debug_string ());
+
+ lvalue->set_tls_model (model);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::lvalue::set_register_name method in jit-recording.c. */
+
+void
+gcc_jit_lvalue_set_register_name (gcc_jit_lvalue *lvalue,
+ const char *reg_name)
+{
+ // TODO: support global variables?
+ lvalue->set_register_name (reg_name);
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 5c722c2c57fff..179cc5c731f2b 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_location
+- gcc_jit_type
+- gcc_jit_struct
+ +- gcc_jit_function_type
+ +- gcc_jit_vector_type
+- gcc_jit_field
+- gcc_jit_function
+- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
the layout for, or an opaque type. */
typedef struct gcc_jit_struct gcc_jit_struct;
+/* A gcc_jit_function_type encapsulates a function type. */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type. */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
/* A gcc_jit_function encapsulates a function: either one that you're
creating yourself, or a reference to one that you're dynamically
linking to within the rest of the process. */
@@ -548,6 +556,17 @@ enum gcc_jit_types
GCC_JIT_TYPE_LONG_LONG, /* signed */
GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
+ GCC_JIT_TYPE_UINT8_T,
+ GCC_JIT_TYPE_UINT16_T,
+ GCC_JIT_TYPE_UINT32_T,
+ GCC_JIT_TYPE_UINT64_T,
+ GCC_JIT_TYPE_UINT128_T,
+ GCC_JIT_TYPE_INT8_T,
+ GCC_JIT_TYPE_INT16_T,
+ GCC_JIT_TYPE_INT32_T,
+ GCC_JIT_TYPE_INT64_T,
+ GCC_JIT_TYPE_INT128_T,
+
/* Floating-point types */
GCC_JIT_TYPE_FLOAT,
@@ -654,6 +673,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
int num_fields,
gcc_jit_field **fields);
+/* Get a field by index. */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index);
+
+/* Get the number of fields. */
+extern ssize_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
/* Unions work similarly to structs. */
extern gcc_jit_type *
gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -722,6 +750,16 @@ enum gcc_jit_function_kind
GCC_JIT_FUNCTION_ALWAYS_INLINE
};
+/* Thread local storage model. */
+enum gcc_jit_tls_model
+{
+ GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC,
+ GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC,
+ GCC_JIT_TLS_MODEL_INITIAL_EXEC,
+ GCC_JIT_TLS_MODEL_LOCAL_EXEC,
+ GCC_JIT_TLS_MODEL_DEFAULT,
+};
+
/* Create a function. */
extern gcc_jit_function *
gcc_jit_context_new_function (gcc_jit_context *ctxt,
@@ -810,6 +848,19 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global,
const void *blob,
size_t num_bytes);
+#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+
+/* Set an initial value for a global, which must be a constant.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_19; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value
+*/
+
+extern void
+gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global,
+ gcc_jit_rvalue *value);
+
/* Upcasting. */
extern gcc_jit_object *
gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue);
@@ -863,6 +914,20 @@ extern gcc_jit_rvalue *
gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
const char *value);
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_struct (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_struct *struct_type,
+ size_t num_elements,
+ gcc_jit_rvalue **fields);
+
+extern gcc_jit_rvalue *
+gcc_jit_context_new_rvalue_from_array (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_type *type,
+ size_t num_elements,
+ gcc_jit_rvalue **elements);
+
enum gcc_jit_unary_op
{
/* Negate an arithmetic value; analogous to:
@@ -1026,6 +1091,15 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue,
gcc_jit_type *type);
+/* Reinterpret a value as another type.
+
+ The types must be of the same size. */
+extern gcc_jit_rvalue *
+gcc_jit_context_new_bitcast (gcc_jit_context *ctxt,
+ gcc_jit_location *loc,
+ gcc_jit_rvalue *rvalue,
+ gcc_jit_type *type);
+
extern gcc_jit_lvalue *
gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_location *loc,
@@ -1072,6 +1146,35 @@ extern gcc_jit_rvalue *
gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue,
gcc_jit_location *loc);
+#define LIBGCCJIT_HAVE_gcc_jit_lvalue_set_link_section
+
+/* Set the link section of a global variable; analogous to:
+ __attribute__((section("section_name")))
+ in C.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_18; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model */
+extern void
+gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue,
+ const char *name);
+
+#define LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model
+
+/* Set the thread-local storage model of a global variable
+
+ This API entrypoint was added in LIBGCCJIT_ABI_17; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model */
+extern void
+gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue,
+ enum gcc_jit_tls_model model);
+
+/* Make this variable a register variable and set its register name. */
+void
+gcc_jit_lvalue_set_register_name (gcc_jit_lvalue *lvalue,
+ const char *reg_name);
+
extern gcc_jit_lvalue *
gcc_jit_function_new_local (gcc_jit_function *func,
gcc_jit_location *loc,
@@ -1621,6 +1724,91 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
gcc_jit_location *loc,
const char *asm_stmts);
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+ a function and whether a type is a bool from the C API.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_15; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function. */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function. */
+extern ssize_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array. */
+extern gcc_jit_type *
+gcc_jit_type_is_array (gcc_jit_type *type);
+
+#define LIBGCCJIT_HAVE_gcc_jit_function_set_inline_mode
+
+enum gcc_jit_inline_mode
+{
+ GCC_JIT_INLINE_MODE_DEFAULT,
+ GCC_JIT_INLINE_MODE_ALWAYS_INLINE,
+ GCC_JIT_INLINE_MODE_NO_INLINE,
+ GCC_JIT_INLINE_MODE_INLINE,
+};
+
+extern void
+gcc_jit_function_set_inline_mode(gcc_jit_function *func, enum gcc_jit_inline_mode inline_mode);
+
+/* Return non-zero if the type is a bool. */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL. */
+extern gcc_jit_function_type *
+gcc_jit_type_is_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters. */
+extern ssize_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index);
+
+/* Return non-zero if the type is an integral. */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer. */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL. */
+extern gcc_jit_vector_type *
+gcc_jit_type_is_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL. */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains. */
+extern ssize_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements. */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers. */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c7fe4b6..78bda91de6063 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,55 @@ LIBGCCJIT_ABI_15 {
gcc_jit_extended_asm_add_clobber;
gcc_jit_context_add_top_level_asm;
} LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+ global:
+ gcc_jit_function_get_return_type;
+ gcc_jit_function_get_param_count;
+ gcc_jit_function_type_get_return_type;
+ gcc_jit_function_type_get_param_count;
+ gcc_jit_function_type_get_param_type;
+ gcc_jit_type_unqualified;
+ gcc_jit_type_is_array;
+ gcc_jit_type_is_bool;
+ gcc_jit_type_is_function_ptr_type;
+ gcc_jit_type_is_integral;
+ gcc_jit_type_is_pointer;
+ gcc_jit_type_is_vector;
+ gcc_jit_vector_type_get_element_type;
+ gcc_jit_vector_type_get_num_units;
+ gcc_jit_struct_get_field;
+ gcc_jit_type_is_struct;
+ gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
+
+LIBGCCJIT_ABI_17 {
+ global:
+ gcc_jit_lvalue_set_tls_model;
+} LIBGCCJIT_ABI_16;
+
+LIBGCCJIT_ABI_18 {
+ global:
+ gcc_jit_lvalue_set_link_section;
+} LIBGCCJIT_ABI_17;
+
+LIBGCCJIT_ABI_19 {
+ gcc_jit_context_new_bitcast;
+} LIBGCCJIT_ABI_18;
+
+LIBGCCJIT_ABI_20 {
+ global:
+ gcc_jit_lvalue_set_register_name;
+} LIBGCCJIT_ABI_19;
+
+LIBGCCJIT_ABI_21 {
+ global:
+ gcc_jit_global_set_initializer_value;
+ gcc_jit_context_new_rvalue_from_struct;
+ gcc_jit_context_new_rvalue_from_array;
+} LIBGCCJIT_ABI_20;
+
+LIBGCCJIT_ABI_22 {
+ global:
+ gcc_jit_function_set_inline_mode;
+} LIBGCCJIT_ABI_21;
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 4202eb7798b70..42e0c6b7e9379 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -98,6 +98,13 @@
#undef create_code
#undef verify_code
+/* test-cast.c */
+#define create_code create_code_cast
+#define verify_code verify_code_cast
+#include "test-cast.c"
+#undef create_code
+#undef verify_code
+
/* test-compound-assignment.c */
#define create_code create_code_compound_assignment
#define verify_code verify_code_compound_assignment
@@ -181,6 +188,27 @@
#undef create_code
#undef verify_code
+/* test-link-section.c */
+#define create_code create_code_link_section
+#define verify_code verify_code_link_section
+#include "test-link-section.c"
+#undef create_code
+#undef verify_code
+
+/* test-tls.c */
+#define create_code create_code_tls
+#define verify_code verify_code_tls
+#include "test-tls.c"
+#undef create_code
+#undef verify_code
+
+/* test-builtin-types.c */
+#define create_code create_code_builtin_types
+#define verify_code verify_code_builtin_types
+#include "test-builtin-types.c"
+#undef create_code
+#undef verify_code
+
/* test-hello-world.c */
#define create_code create_code_hello_world
#define verify_code verify_code_hello_world
@@ -258,6 +286,13 @@
#undef create_code
#undef verify_code
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
@@ -361,6 +396,9 @@ const struct testcase testcases[] = {
{"calling_internal_function",
create_code_calling_internal_function,
verify_code_calling_internal_function},
+ {"cast",
+ create_code_cast,
+ verify_code_cast},
{"compound_assignment",
create_code_compound_assignment,
verify_code_compound_assignment},
@@ -424,6 +462,9 @@ const struct testcase testcases[] = {
{"reading_struct ",
create_code_reading_struct ,
verify_code_reading_struct },
+ {"reflection",
+ create_code_reflection ,
+ verify_code_reflection },
{"string_literal",
create_code_string_literal,
verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-builtin-types.c b/gcc/testsuite/jit.dg/test-builtin-types.c
new file mode 100644
index 0000000000000..e20d71571b5d9
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-builtin-types.c
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+#include
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ CHECK_NON_NULL (gcc_jit_context_get_builtin_function (ctxt, "__atomic_fetch_add_4"));
+
+ gcc_jit_function *atomic_load = gcc_jit_context_get_builtin_function (ctxt, "__atomic_load_8");
+
+ gcc_jit_type *volatile_void_ptr =
+ gcc_jit_type_get_volatile(gcc_jit_type_get_const(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR)));
+ gcc_jit_type *void_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
+ gcc_jit_type *long_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG);
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "atomics", 0, NULL, 0);
+
+ gcc_jit_lvalue *variable = gcc_jit_function_new_local (func, NULL, long_type, "variable");
+ gcc_jit_rvalue *builtin_args[2];
+ gcc_jit_rvalue *param1 = gcc_jit_lvalue_get_address(variable, NULL);
+ builtin_args[0] = gcc_jit_context_new_cast(ctxt, NULL, param1, volatile_void_ptr);
+ builtin_args[1] = gcc_jit_context_new_rvalue_from_long(ctxt, int_type, 0);
+ gcc_jit_context_new_call (ctxt, NULL, atomic_load, 2, builtin_args);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ /* Verify that no errors were emitted. */
+ CHECK_NON_NULL (result);
+}
diff --git a/gcc/testsuite/jit.dg/test-cast.c b/gcc/testsuite/jit.dg/test-cast.c
new file mode 100644
index 0000000000000..2b1e385ae4052
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-cast.c
@@ -0,0 +1,66 @@
+#include
+#include
+#include
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+char
+my_casts (int x)
+{
+ return (char)(long) x;
+}
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_type *long_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_LONG);
+ gcc_jit_type *return_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR);
+
+ gcc_jit_param *x =
+ gcc_jit_context_new_param (
+ ctxt,
+ NULL,
+ int_type, "x");
+ gcc_jit_param *params[1] = {x};
+ gcc_jit_function *func =
+ gcc_jit_context_new_function (ctxt,
+ NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ return_type,
+ "my_casts",
+ 1, params, 0);
+
+ gcc_jit_block *initial =
+ gcc_jit_function_new_block (func, "initial");
+
+ gcc_jit_block_end_with_return(initial, NULL,
+ gcc_jit_context_new_cast(ctxt,
+ NULL,
+ gcc_jit_context_new_cast(ctxt,
+ NULL,
+ gcc_jit_param_as_rvalue(x),
+ long_type
+ ),
+ return_type
+ ));
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*my_casts_fn_type) (int);
+ CHECK_NON_NULL (result);
+ my_casts_fn_type my_casts =
+ (my_casts_fn_type)gcc_jit_result_get_code (result, "my_casts");
+ CHECK_NON_NULL (my_casts);
+ char val = my_casts (10);
+ note ("my_casts returned: %d", val);
+ CHECK_VALUE (val, 10);
+}
diff --git a/gcc/testsuite/jit.dg/test-global-set-initializer.c b/gcc/testsuite/jit.dg/test-global-set-initializer.c
index d38aba7d73f5b..418ed7dcf3fef 100644
--- a/gcc/testsuite/jit.dg/test-global-set-initializer.c
+++ b/gcc/testsuite/jit.dg/test-global-set-initializer.c
@@ -21,6 +21,7 @@ create_code (gcc_jit_context *ctxt, void *user_data)
signed char bin_blob1[] = { 0xc, 0xa, 0xf, 0xf, 0xe };
unsigned bin_blob2[] = { 0x3, 0x2, 0x1, 0x0, 0x1, 0x2, 0x3 };
unsigned char bin_blob3[4096]...
+ unsigned int integer = 42;
*/
gcc_jit_type *unsigned_char_type =
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR);
@@ -56,6 +57,16 @@ create_code (gcc_jit_context *ctxt, void *user_data)
sizeof (test_blob3)),
"bin_blob3");
gcc_jit_global_set_initializer (glob, test_blob3, sizeof (test_blob3));
+
+ gcc_jit_rvalue *forty_two = gcc_jit_context_new_rvalue_from_int (
+ ctxt, unsigned_type, 42);
+
+ glob =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED,
+ unsigned_type,
+ "integer");
+ gcc_jit_global_set_initializer_value (glob, forty_two);
}
void
@@ -75,4 +86,8 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
CHECK_NON_NULL (glob);
CHECK_VALUE (memcmp (test_blob3, glob, sizeof (test_blob3)), 0);
+ glob = gcc_jit_result_get_global (result, "integer");
+ CHECK_NON_NULL (glob);
+ int *value = glob;
+ CHECK_VALUE (*value, 42);
}
diff --git a/gcc/testsuite/jit.dg/test-link-section.c b/gcc/testsuite/jit.dg/test-link-section.c
new file mode 100644
index 0000000000000..546c1e95b9205
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-link-section.c
@@ -0,0 +1,25 @@
+#include
+#include
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+ int foo __attribute__((section(".section")));
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+ gcc_jit_lvalue *foo =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, int_type, "foo");
+ gcc_jit_lvalue_set_link_section(foo, "section");
+}
+
+extern void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+}
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 0000000000000..46ab2c3e88797
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include
+#include
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Do nothing. */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ /* Get the built-in functions. */
+ gcc_jit_function *builtin_sin =
+ gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+ CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+ gcc_jit_type *double_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+ CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+ CHECK (!gcc_jit_type_is_integral(double_type));
+
+ gcc_jit_type *bool_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+ CHECK (gcc_jit_type_is_bool(bool_type));
+ CHECK (!gcc_jit_type_is_integral(bool_type));
+
+ gcc_jit_type *aligned_bool_type =
+ gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+ CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+ CHECK (bool_type != aligned_bool_type);
+ CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+ CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+ CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+ gcc_jit_type *int64 =
+ gcc_jit_context_get_int_type(ctxt, 8, 1);
+ CHECK (gcc_jit_type_is_integral(int64));
+ gcc_jit_type *uint64 =
+ gcc_jit_context_get_int_type(ctxt, 8, 0);
+ CHECK (gcc_jit_type_is_integral(uint64));
+ gcc_jit_type *int8 =
+ gcc_jit_context_get_int_type(ctxt, 1, 1);
+ CHECK (gcc_jit_type_is_integral(int8));
+ gcc_jit_type *uint8 =
+ gcc_jit_context_get_int_type(ctxt, 1, 0);
+ CHECK (gcc_jit_type_is_integral(uint8));
+
+ CHECK (!gcc_jit_type_is_vector(double_type));
+ gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+ gcc_jit_vector_type *vector_type = gcc_jit_type_is_vector(vec_type);
+ CHECK (vector_type);
+ CHECK (vec_type != double_type);
+ CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+ CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+ CHECK (!gcc_jit_type_is_pointer(double_type));
+ CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+ gcc_jit_type* params[2] = {int8, uint64};
+ gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+ CHECK (!gcc_jit_type_is_function_ptr_type (int64));
+ gcc_jit_function_type *function_type = gcc_jit_type_is_function_ptr_type (function_ptr_type);
+ CHECK (function_type);
+ int param_count = gcc_jit_function_type_get_param_count(function_type);
+ CHECK_VALUE (param_count, 2);
+ gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+ CHECK_VALUE (return_type, int64);
+ gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+ CHECK_VALUE (param1, int8);
+ gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+ CHECK_VALUE (param2, uint64);
+
+ gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+ gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+ gcc_jit_field *fields[2] = { field1, field2 };
+ gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+ CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+ CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+ CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+ CHECK (!gcc_jit_type_is_struct(double_type));
+ gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+ CHECK_VALUE (struct_ty, struct_type);
+
+ CHECK (!gcc_jit_type_is_array(double_type));
+ gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+ CHECK_VALUE (gcc_jit_type_is_array(array_type), double_type);
+}
+
diff --git a/gcc/testsuite/jit.dg/test-tls.c b/gcc/testsuite/jit.dg/test-tls.c
new file mode 100644
index 0000000000000..d4508b16c1e8b
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-tls.c
@@ -0,0 +1,29 @@
+#include
+#include
+#include
+#include
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Let's try to inject the equivalent of:
+
+ _Thread_local int foo;
+ */
+ gcc_jit_type *int_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
+
+ gcc_jit_lvalue *foo =
+ gcc_jit_context_new_global (
+ ctxt, NULL, GCC_JIT_GLOBAL_EXPORTED, int_type, "foo");
+ gcc_jit_lvalue_set_tls_model (foo, GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC);
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+}
diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c
index 8debcd7eb82c8..9c66284f193eb 100644
--- a/gcc/testsuite/jit.dg/test-types.c
+++ b/gcc/testsuite/jit.dg/test-types.c
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -29,6 +30,18 @@ struct zoo
long long m_long_long;
unsigned long long m_unsigned_long_long;
+ uint8_t m_u8;
+ uint16_t m_u16;
+ uint32_t m_u32;
+ uint64_t m_u64;
+ __uint128_t m_u128;
+
+ int8_t m_i8;
+ int16_t m_i16;
+ int32_t m_i32;
+ int64_t m_i64;
+ __int128_t m_i128;
+
int m_sized_int_type;
float m_float;
@@ -101,6 +114,28 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_field *field_m_unsigned_long_long =
CREATE_FIELD (GCC_JIT_TYPE_UNSIGNED_LONG_LONG, "m_unsigned_long_long");
+ gcc_jit_field *field_m_u8 =
+ CREATE_FIELD (GCC_JIT_TYPE_UINT8_T, "m_u8");
+ gcc_jit_field *field_m_u16 =
+ CREATE_FIELD (GCC_JIT_TYPE_UINT16_T, "m_u16");
+ gcc_jit_field *field_m_u32 =
+ CREATE_FIELD (GCC_JIT_TYPE_UINT32_T, "m_u32");
+ gcc_jit_field *field_m_u64 =
+ CREATE_FIELD (GCC_JIT_TYPE_UINT64_T, "m_u64");
+ gcc_jit_field *field_m_u128 =
+ CREATE_FIELD (GCC_JIT_TYPE_UINT128_T, "m_u128");
+
+ gcc_jit_field *field_m_i8 =
+ CREATE_FIELD (GCC_JIT_TYPE_INT8_T, "m_i8");
+ gcc_jit_field *field_m_i16 =
+ CREATE_FIELD (GCC_JIT_TYPE_INT16_T, "m_i16");
+ gcc_jit_field *field_m_i32 =
+ CREATE_FIELD (GCC_JIT_TYPE_INT32_T, "m_i32");
+ gcc_jit_field *field_m_i64 =
+ CREATE_FIELD (GCC_JIT_TYPE_INT64_T, "m_i64");
+ gcc_jit_field *field_m_i128 =
+ CREATE_FIELD (GCC_JIT_TYPE_INT128_T, "m_i128");
+
/* Signed int type with sizeof (int): */
gcc_jit_type *sized_int_type =
gcc_jit_context_get_int_type (ctxt, sizeof (int), 1);
@@ -147,6 +182,18 @@ create_code (gcc_jit_context *ctxt, void *user_data)
field_m_long_long,
field_m_unsigned_long_long,
+ field_m_u8,
+ field_m_u16,
+ field_m_u32,
+ field_m_u64,
+ field_m_u128,
+
+ field_m_i8,
+ field_m_i16,
+ field_m_i32,
+ field_m_i64,
+ field_m_i128,
+
field_m_sized_int_type,
field_m_float,
@@ -266,6 +313,58 @@ create_code (gcc_jit_context *ctxt, void *user_data)
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_LONG_LONG),
123456789))
+ ASSIGN(field_m_u8,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT8_T),
+ 123))
+ ASSIGN(field_m_u16,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT16_T),
+ 12345))
+ ASSIGN(field_m_u32,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT32_T),
+ 123456789))
+ ASSIGN(field_m_u64,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT64_T),
+ 123456789))
+ ASSIGN(field_m_u128,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UINT128_T),
+ 123456789))
+
+ ASSIGN(field_m_i8,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT8_T),
+ -1))
+ ASSIGN(field_m_i16,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT16_T),
+ -2))
+ ASSIGN(field_m_i32,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT32_T),
+ -3))
+ ASSIGN(field_m_i64,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT64_T),
+ -4))
+ ASSIGN(field_m_i128,
+ gcc_jit_context_new_rvalue_from_int (
+ ctxt,
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT128_T),
+ -5))
+
ASSIGN(field_m_sized_int_type,
gcc_jit_context_new_rvalue_from_int (
ctxt,
@@ -347,6 +446,18 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
CHECK_VALUE (z.m_long_long, -42);
CHECK_VALUE (z.m_unsigned_long_long, 123456789);
+ CHECK_VALUE (z.m_u8, 123);
+ CHECK_VALUE (z.m_u16, 12345);
+ CHECK_VALUE (z.m_u32, 123456789);
+ CHECK_VALUE (z.m_u64, 123456789);
+ CHECK_VALUE (z.m_u128, 123456789);
+
+ CHECK_VALUE (z.m_i8, -1);
+ CHECK_VALUE (z.m_i16, -2);
+ CHECK_VALUE (z.m_i32, -3);
+ CHECK_VALUE (z.m_i64, -4);
+ CHECK_VALUE (z.m_i128, -5);
+
CHECK_VALUE (z.m_sized_int_type, 500);
CHECK_VALUE (z.m_float, 3.141f);