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..096c89902f7bd 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: @@ -244,6 +282,25 @@ get_type (enum gcc_jit_types type_) return new type (type_node); } +/* Construct a playback::type instance (wrapping a tree) for the given + sign and number of bits. */ + +playback::type * +playback::context:: +make_type (bool is_signed, size_t num_bits) +{ + tree int_type; + if (is_signed) + { + int_type = make_signed_type(num_bits); + } + else + { + int_type = make_unsigned_type(num_bits); + } + return new type (int_type); +} + /* Construct a playback::type instance (wrapping a tree) for the given array type. */ @@ -664,6 +721,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 +904,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 +1329,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..25e0d5cf2f305 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" @@ -65,6 +66,9 @@ class context : public log_user type * get_type (enum gcc_jit_types type); + type * + make_type (bool is_signed, size_t num_bits); + type * new_array_type (location *loc, type *element_type, @@ -120,6 +124,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 +148,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 +192,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 +680,8 @@ class rvalue : public wrapper private: context *m_ctxt; + +protected: tree m_inner; }; @@ -670,6 +702,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..5ea23208f057e 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "pretty-print.h" +#include "tree.h" +#include "stor-layout.h" #include "toplev.h" #include @@ -562,6 +564,8 @@ recording::context::context (context *parent_ctxt) m_compound_types (), m_globals (), m_functions (), + /*m_signed_int_types(), + m_unsigned_int_types(),*/ m_FILE_type (NULL), m_builtins_manager(NULL) { @@ -792,6 +796,10 @@ recording::context::get_type (enum gcc_jit_types kind) Implements the post-error-checking part of gcc_jit_context_get_int_type. */ +int nextPowerOfTwo(int x) { + return 1 << sizeof(x)*8 - __builtin_clz(x); +} + recording::type * recording::context::get_int_type (int num_bytes, int is_signed) { @@ -801,7 +809,7 @@ recording::context::get_int_type (int num_bytes, int is_signed) Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros are in bits, rather than bytes. */ - const int num_bits = num_bytes * 8; + /*const*/ int num_bits = num_bytes * 8; if (num_bits == INT_TYPE_SIZE) return get_type (is_signed ? GCC_JIT_TYPE_INT @@ -822,11 +830,57 @@ 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); + + // TODO: check in num_bits > 0? + /*tree int_type;*/ + /*printf("Before: %d\n", num_bits);*/ + /*num_bits = nextPowerOfTwo(num_bits); + printf("After: %d\n", num_bits);*/ + if (is_signed) + { + /*if (tree type = m_signed_int_types[num_bits]) + { + int_type = type; + } + else + {*/ + // FIXME: seems like we cannot create a type here because the ggc is not initialized: instead, create it in + // playback. + /*int_type = make_signed_type(num_bits);*/ + /*m_signed_int_types[num_bits] = int_type; + }*/ + } + else + { + /*if (tree type = m_unsigned_int_types[num_bits]) + { + int_type = type; + } + else + {*/ + /*int_type = make_unsigned_type(num_bits);*/ + /*m_unsigned_int_types[num_bits] = int_type; + }*/ + } - /* Some other size, not corresponding to the C int types. */ - /* To be written: support arbitrary other sizes, sharing by - memoizing at the recording::context level? */ - gcc_unreachable (); + recording::type *result = new memento_of_make_type (this, is_signed, num_bits); + record (result); + return result; +} + +void +recording::memento_of_make_type::write_reproducer (reproducer &r) +{ + const char *id = r.make_identifier (this, "type"); + r.write (" gcc_jit_type *%s = gcc_jit_context_get_int_type (%s, %ld, %d);\n", + id, + r.get_identifier (get_context ()), + m_num_bits, + true); // TODO } /* Create a recording::type instance and add it to this context's list @@ -1062,6 +1116,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 +1146,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 +1267,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 +2366,26 @@ 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_INT8_T: + size = 8; + break; + case GCC_JIT_TYPE_UINT16_T: + case GCC_JIT_TYPE_INT16_T: + size = 16; + break; + case GCC_JIT_TYPE_UINT32_T: + case GCC_JIT_TYPE_INT32_T: + size = 32; + break; + case GCC_JIT_TYPE_UINT64_T: + case GCC_JIT_TYPE_INT64_T: + size = 64; + break; + case GCC_JIT_TYPE_UINT128_T: + case GCC_JIT_TYPE_INT128_T: + size = 128; + break; case GCC_JIT_TYPE_FLOAT: size = FLOAT_TYPE_SIZE; break; @@ -2256,6 +2395,10 @@ recording::memento_of_get_type::get_size () case GCC_JIT_TYPE_LONG_DOUBLE: size = LONG_DOUBLE_TYPE_SIZE; break; + case GCC_JIT_TYPE_SIZE_T: + size = POINTER_TYPE; + /*size = TYPE_PRECISION(size_type_node); // TODO: check that this code works.*/ + break; default: /* As this function is called by 'gcc_jit_global_set_initializer' and @@ -2295,6 +2438,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 +2500,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: @@ -2370,6 +2533,60 @@ recording::memento_of_get_type::is_int () const } } +/* Implementation of pure virtual hook recording::type::is_signed for + recording::memento_of_get_type. */ + +bool +recording::memento_of_get_type::is_signed () const +{ + switch (m_kind) + { + default: gcc_unreachable (); + + case GCC_JIT_TYPE_SIGNED_CHAR: + case GCC_JIT_TYPE_CHAR: + case GCC_JIT_TYPE_SHORT: + case GCC_JIT_TYPE_INT: + case GCC_JIT_TYPE_LONG: + case GCC_JIT_TYPE_LONG_LONG: + 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_VOID: + case GCC_JIT_TYPE_VOID_PTR: + case GCC_JIT_TYPE_BOOL: + case GCC_JIT_TYPE_UNSIGNED_CHAR: + case GCC_JIT_TYPE_UNSIGNED_SHORT: + case GCC_JIT_TYPE_UNSIGNED_INT: + case GCC_JIT_TYPE_UNSIGNED_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_FLOAT: + case GCC_JIT_TYPE_DOUBLE: + case GCC_JIT_TYPE_LONG_DOUBLE: + + case GCC_JIT_TYPE_CONST_CHAR_PTR: + + case GCC_JIT_TYPE_SIZE_T: + + case GCC_JIT_TYPE_FILE_PTR: + + case GCC_JIT_TYPE_COMPLEX_FLOAT: + case GCC_JIT_TYPE_COMPLEX_DOUBLE: + case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: + return false; + } +} + /* Implementation of pure virtual hook recording::type::is_float for recording::memento_of_get_type. */ @@ -2400,6 +2617,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 +2680,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 +2748,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 +2799,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", @@ -2572,6 +2830,24 @@ recording::memento_of_get_type::write_reproducer (reproducer &r) get_type_enum_strings[m_kind]); } +/* Implementation of pure virtual hook recording::memento::replay_into + for recording::memento_of_make_type. */ + +void +recording::memento_of_make_type::replay_into (replayer *r) +{ + set_playback_obj (r->make_type(m_is_signed, m_num_bits)); +} + +recording::string * +recording::memento_of_make_type::make_debug_string () +{ + char buf[256] = {0}; + buf[0] = 'i'; + sprintf(&buf[1], "%ld", m_num_bits); + return m_ctxt->new_string (buf); +} + /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */ /* Override of default implementation of @@ -2598,8 +2874,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 +3999,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 @@ -4539,6 +4841,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 +4858,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 +4992,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 +5017,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 +5063,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 +5479,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 +5954,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 +6607,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..343cd6c3ac41b 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, @@ -349,6 +368,9 @@ class context : public log_user auto_vec m_top_level_asms; type *m_basic_types[NUM_GCC_JIT_TYPES]; + /* Map from num_bits to integer types. */ + /*tree m_signed_int_types[128]; + tree m_unsigned_int_types[128];*/ type *m_FILE_type; builtins_manager *m_builtins_manager; // lazily created @@ -522,6 +544,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,8 +569,11 @@ 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; } + virtual bool is_signed () const = 0; bool is_numeric () const { @@ -588,12 +614,19 @@ class memento_of_get_type : public type bool accepts_writes_from (type *rtype) FINAL OVERRIDE { if (m_kind == GCC_JIT_TYPE_VOID_PTR) + { if (rtype->is_pointer ()) { /* LHS (this) is type (void *), and the RHS is a pointer: accept it: */ return true; } + } + else if (is_int () && rtype->is_int () && get_size () == rtype->get_size () && is_signed () == rtype->is_signed ()) + { + /* LHS (this) is an integer of the size size and sign as rtype. */ + return true; + } return type::accepts_writes_from (rtype); } @@ -604,6 +637,7 @@ class memento_of_get_type : public type type *is_pointer () FINAL OVERRIDE { return dereference (); } type *is_array () FINAL OVERRIDE { return NULL; } bool is_void () const FINAL OVERRIDE { return m_kind == GCC_JIT_TYPE_VOID; } + bool is_signed () const FINAL OVERRIDE; public: void replay_into (replayer *r) FINAL OVERRIDE; @@ -616,6 +650,47 @@ class memento_of_get_type : public type enum gcc_jit_types m_kind; }; +/* Result of "gcc_jit_context_get_type" for non power of 2 integers. */ +class memento_of_make_type : public type +{ +public: + memento_of_make_type (context *ctxt, + bool is_signed, + size_t num_bits) + : type (ctxt), + m_is_signed (is_signed), + m_num_bits (num_bits) {} + + type *dereference () FINAL OVERRIDE { return NULL; }; + + size_t get_size () FINAL OVERRIDE { return m_num_bits; }; + + bool accepts_writes_from (type *rtype) FINAL OVERRIDE + { + return type::accepts_writes_from (rtype); + } + + bool is_int () const FINAL OVERRIDE { return true; }; + bool is_float () const FINAL OVERRIDE { return false; }; + bool is_bool () const FINAL OVERRIDE { return false; }; + type *is_pointer () FINAL OVERRIDE { return NULL; } + type *is_array () FINAL OVERRIDE { return NULL; } + bool is_void () const FINAL OVERRIDE { return false; } + bool is_signed () const FINAL OVERRIDE { return m_is_signed; } + +public: + void replay_into (replayer *r) FINAL OVERRIDE; + +private: + string * make_debug_string () FINAL OVERRIDE; + void write_reproducer (reproducer &r) FINAL OVERRIDE; + +private: + bool m_is_signed; + size_t m_num_bits; +}; + + /* Result of "gcc_jit_type_get_pointer". */ class memento_of_get_pointer : public type { @@ -637,6 +712,7 @@ class memento_of_get_pointer : public type bool is_bool () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return m_other_type; } type *is_array () FINAL OVERRIDE { return NULL; } + bool is_signed () const FINAL OVERRIDE { return false; } private: string * make_debug_string () FINAL OVERRIDE; @@ -658,11 +734,15 @@ class decorated_type : public type type *dereference () FINAL OVERRIDE { return m_other_type->dereference (); } + size_t get_size () FINAL OVERRIDE { return m_other_type->get_size (); }; + bool is_int () const FINAL OVERRIDE { return m_other_type->is_int (); } bool is_float () const FINAL OVERRIDE { return m_other_type->is_float (); } 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 (); } + bool is_signed () const FINAL OVERRIDE { return m_other_type->is_signed (); } protected: type *m_other_type; @@ -745,6 +825,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,12 +850,15 @@ 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; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return m_element_type; } int num_elements () { return m_num_elements; } + bool is_signed () const FINAL OVERRIDE { return false; } void replay_into (replayer *) FINAL OVERRIDE; @@ -807,6 +892,7 @@ class function_type : public type bool is_bool () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return NULL; } + bool is_signed () const FINAL OVERRIDE { return false; } void replay_into (replayer *) FINAL OVERRIDE; @@ -920,6 +1006,7 @@ class compound_type : public type bool is_bool () const FINAL OVERRIDE { return false; } type *is_pointer () FINAL OVERRIDE { return NULL; } type *is_array () FINAL OVERRIDE { return NULL; } + bool is_signed () const FINAL OVERRIDE { return false; } bool has_known_size () const FINAL OVERRIDE { return m_fields != NULL; } @@ -951,6 +1038,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 +1194,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 +1219,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 @@ -1360,6 +1465,7 @@ class global : public lvalue m_name (name) { m_initializer = NULL; + m_initializer_value = NULL; m_initializer_num_bytes = 0; } ~global () @@ -1386,6 +1492,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 +1512,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 +1580,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 +1619,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 +1738,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 +1796,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 +2069,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 +2099,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..e03817f371b0d 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,209 @@ 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::get_size method, in + jit-recording.c. */ + +ssize_t +gcc_jit_type_get_size (gcc_jit_type *type) +{ + RETURN_VAL_IF_FAIL (type->is_int (), -1, NULL, NULL, "only getting the size of an int type is supported for now"); + return type->get_size (); +} + +/* 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::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 (); + if (!func_ptr_type) { + return NULL; + } + + 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 +958,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 +1270,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 +1443,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 +1701,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 @@ -1454,7 +1878,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt, RETURN_NULL_IF_FAIL (a, ctxt, loc, "NULL a"); RETURN_NULL_IF_FAIL (b, ctxt, loc, "NULL b"); RETURN_NULL_IF_FAIL_PRINTF4 ( - a->get_type ()->unqualified () == b->get_type ()->unqualified (), + compatible_types (a->get_type (), b->get_type ()), ctxt, loc, "mismatching types for binary op:" " a: %s (type: %s) b: %s (type: %s)", @@ -1740,6 +2164,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 +2405,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..8c737f1704e38 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, @@ -593,6 +612,10 @@ gcc_jit_type_get_const (gcc_jit_type *type); extern gcc_jit_type * gcc_jit_type_get_volatile (gcc_jit_type *type); +/* Given type "T", get its size. */ +extern ssize_t +gcc_jit_type_get_size (gcc_jit_type *type); + /* Given type "T", get type "T[N]" (for a constant N). */ extern gcc_jit_type * gcc_jit_context_new_array_type (gcc_jit_context *ctxt, @@ -654,6 +677,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 +754,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 +852,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 +918,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 +1095,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 +1150,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 +1728,78 @@ 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); + +/* 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..53b42468de424 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_type_get_size; +} 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);