From f2a67694bd87b5c2f564b07edfe962047f95f8b9 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 15 May 2021 10:54:36 -0400 Subject: [PATCH 01/17] Add function to set the initial value of a global variable [PR96089] 2021-05-20 Antoni Boucher gcc/jit/ PR target/96089 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_19): New ABI tag. * docs/topics/expressions.rst: Add documentation for the function gcc_jit_global_set_initializer_value. * jit-playback.c: New function (new_global_with_value). * jit-playback.h: New function (new_global_with_value). * jit-recording.c: Add support for setting a value to a global variable. * jit-recording.h: New function (set_initializer_value) and new field m_initializer_value. * libgccjit.c: New macro RETURN_IF_FAIL_PRINTF5 and new function (gcc_jit_global_set_initializer_value). * libgccjit.h: New function (gcc_jit_global_set_initializer_value). * libgccjit.map (LIBGCCJIT_ABI_19): New ABI tag. gcc/testsuite/ PR target/96089 * jit.dg/test-global-set-initializer.c: Add test for the new function (gcc_jit_global_set_initializer_value). Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/compatibility.rst | 9 ++++ gcc/jit/docs/topics/expressions.rst | 14 ++++++ gcc/jit/jit-playback.c | 18 ++++++++ gcc/jit/jit-playback.h | 7 +++ gcc/jit/jit-recording.c | 34 ++++++++++++--- gcc/jit/jit-recording.h | 8 ++++ gcc/jit/libgccjit.c | 43 +++++++++++++++++++ gcc/jit/libgccjit.h | 13 ++++++ gcc/jit/libgccjit.map | 5 +++ .../jit.dg/test-global-set-initializer.c | 15 +++++++ 10 files changed, 160 insertions(+), 6 deletions(-) diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 239b6aa1a9283..666eb3a1c518c 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -243,3 +243,12 @@ 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_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..f638cb68fddf6 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -603,6 +603,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/jit-playback.c b/gcc/jit/jit-playback.c index c613630124304..d86701a8ae696 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -664,6 +664,24 @@ 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); +} + /* Implementation of the various gcc::jit::playback::context::new_rvalue_from_const methods. diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 825a3e172e92d..958284df539eb 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -120,6 +120,13 @@ 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); + template rvalue * new_rvalue_from_const (type *type, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 117ff70114ca3..a26e49280844e 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -4547,20 +4547,34 @@ 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 * obj; + if (m_initializer) + { + obj = 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) + { + obj = 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 + { + obj = r->new_global (playback_location (r, m_loc), m_kind, m_type->playback_type (), - playback_string (m_name))); + playback_string (m_name)); + } + set_playback_obj (obj); } /* Override the default implementation of @@ -4675,6 +4689,14 @@ recording::global::write_reproducer (reproducer &r) r.get_identifier_as_type (get_type ()), m_name->get_debug_string ()); + 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 ()) { diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 03fa1160cf088..61de2e1dcd437 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1360,6 +1360,7 @@ class global : public lvalue m_name (name) { m_initializer = NULL; + m_initializer_value = NULL; m_initializer_num_bytes = 0; } ~global () @@ -1386,6 +1387,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,6 +1407,7 @@ 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; }; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 7fa948007ad8f..b7fd4d9bebbfd 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -269,6 +269,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. */ @@ -1161,6 +1172,38 @@ 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) +{ + 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 ()); + + reinterpret_cast (global) + ->set_initializer_value (value); +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, this calls the trivial diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 5c722c2c57fff..98762d0527172 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -810,6 +810,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); diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 337ea6c7fe4b6..69b3e79578b19 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -205,3 +205,8 @@ LIBGCCJIT_ABI_15 { gcc_jit_extended_asm_add_clobber; gcc_jit_context_add_top_level_asm; } LIBGCCJIT_ABI_14; + +LIBGCCJIT_ABI_19 { + global: + gcc_jit_global_set_initializer_value; +} LIBGCCJIT_ABI_18; 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); } From 117ae9fc358d8bb1e951aab82fccacaf13b2aae9 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 12 May 2021 07:57:54 -0400 Subject: [PATCH 02/17] Add support for setting the link section of global variables [PR100688] 2021-05-19 Antoni Boucher gcc/jit/ PR target/100688 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_18): New ABI tag. * docs/topics/expressions.rst: Add documentation for the function gcc_jit_lvalue_set_link_section. * jit-playback.h: New function (set_link_section) and rvalue::m_inner protected. * jit-recording.c: New function (set_link_section) and support for setting the link section. * jit-recording.h: New function (set_link_section) and new field m_link_section. * libgccjit.c: New function (gcc_jit_lvalue_set_link_section). * libgccjit.h: New function (gcc_jit_lvalue_set_link_section). * libgccjit.map (LIBGCCJIT_ABI_18): New ABI tag. gcc/testsuite/ PR target/100688 * jit.dg/all-non-failing-tests.h: Add test-link-section.c. * jit.dg/test-link_section.c: New test. Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/compatibility.rst | 9 +++++++ gcc/jit/docs/topics/expressions.rst | 12 +++++++++ gcc/jit/jit-playback.h | 8 ++++++ gcc/jit/jit-recording.c | 27 ++++++++++++++++---- gcc/jit/jit-recording.h | 7 ++++- gcc/jit/libgccjit.c | 12 +++++++++ gcc/jit/libgccjit.h | 13 ++++++++++ gcc/jit/libgccjit.map | 5 ++++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 +++++ gcc/testsuite/jit.dg/test-link-section.c | 25 ++++++++++++++++++ 10 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-link-section.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 666eb3a1c518c..4a91baac437f0 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -244,6 +244,15 @@ embedding assembler instructions: * :func:`gcc_jit_extended_asm_add_clobber` * :func:`gcc_jit_context_add_top_level_asm` +.. _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`` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index f638cb68fddf6..1c01629b57d29 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -539,6 +539,18 @@ 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. + Global variables **************** diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 958284df539eb..b7807e513fc3b 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -657,6 +657,8 @@ class rvalue : public wrapper private: context *m_ctxt; + +protected: tree m_inner; }; @@ -677,6 +679,12 @@ class lvalue : public rvalue rvalue * get_address (location *loc); + void + set_link_section (const char* name) + { + set_decl_section_name (m_inner, name); + } + private: bool mark_addressable (location *loc); }; diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index a26e49280844e..d207e91e3ae87 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -3713,6 +3713,11 @@ recording::lvalue::get_address (recording::location *loc) return result; } +void recording::lvalue::set_link_section (const char *name) +{ + m_link_section = new_string (name); +} + /* The implementation of class gcc::jit::recording::param. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -4547,10 +4552,10 @@ recording::block::dump_edges_to_dot (pretty_printer *pp) void recording::global::replay_into (replayer *r) { - playback::lvalue * obj; + playback::lvalue *global; if (m_initializer) { - obj = r->new_global_initialized (playback_location (r, m_loc), + global = r->new_global_initialized (playback_location (r, m_loc), m_kind, m_type->playback_type (), m_type->dereference ()->get_size (), @@ -4561,7 +4566,7 @@ recording::global::replay_into (replayer *r) } else if (m_initializer_value) { - obj = r->new_global_with_value (playback_location (r, m_loc), + global = r->new_global_with_value (playback_location (r, m_loc), m_kind, m_type->playback_type (), m_initializer_value->playback_rvalue (), @@ -4569,12 +4574,16 @@ recording::global::replay_into (replayer *r) } else { - obj = r->new_global (playback_location (r, m_loc), + global = r->new_global (playback_location (r, m_loc), m_kind, m_type->playback_type (), playback_string (m_name)); } - set_playback_obj (obj); + if (m_link_section != NULL) + { + global->set_link_section (m_link_section->c_str ()); + } + set_playback_obj (global); } /* Override the default implementation of @@ -4697,6 +4706,14 @@ recording::global::write_reproducer (reproducer &r) r.get_identifier_as_rvalue (m_initializer_value)); } + 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_initializer) switch (m_type->dereference ()->get_size ()) { diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 61de2e1dcd437..a995fd344877e 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1105,7 +1105,8 @@ class lvalue : public rvalue lvalue (context *ctxt, location *loc, type *type_) - : rvalue (ctxt, loc, type_) + : rvalue (ctxt, loc, type_), + m_link_section (NULL) {} playback::lvalue * @@ -1127,6 +1128,10 @@ 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); + +protected: + string *m_link_section; }; class param : public lvalue diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index b7fd4d9bebbfd..9e39ca6e52cb2 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -1996,6 +1996,18 @@ 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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 98762d0527172..626738f9ccfc2 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1085,6 +1085,19 @@ 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); + extern gcc_jit_lvalue * gcc_jit_function_new_local (gcc_jit_function *func, gcc_jit_location *loc, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 69b3e79578b19..494e105ca2993 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -206,6 +206,11 @@ LIBGCCJIT_ABI_15 { gcc_jit_context_add_top_level_asm; } LIBGCCJIT_ABI_14; +LIBGCCJIT_ABI_18 { + global: + gcc_jit_lvalue_set_link_section; +} LIBGCCJIT_ABI_17; + LIBGCCJIT_ABI_19 { global: gcc_jit_global_set_initializer_value; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 4202eb7798b70..7e3b59dee0d55 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -181,6 +181,13 @@ #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-hello-world.c */ #define create_code create_code_hello_world #define verify_code verify_code_hello_world 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) +{ +} From d8f75a8fab72545f4bdba5dd608e113fbcee25b2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 10 May 2021 19:43:02 -0400 Subject: [PATCH 03/17] Add support for sized integer types, including 128-bit integers [PR95325] 2021-05-18 Antoni Boucher gcc/jit/ PR target/95325 * docs/topics/types.rst: Add documentation for the new types 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. * jit-playback.c: Add support for the sized integer types. * jit-recording.c: Add support for the sized integer types. * libgccjit.h (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): New enum variants for gcc_jit_types. gcc/testsuite/ PR target/95325 * jit.dg/test-types.c: Add tests for sized integer types. Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/types.rst | 10 +++ gcc/jit/jit-playback.c | 21 ++++++ gcc/jit/jit-recording.c | 73 ++++++++++++++++++++ gcc/jit/libgccjit.h | 11 +++ gcc/testsuite/jit.dg/test-types.c | 111 ++++++++++++++++++++++++++++++ 5 files changed, 226 insertions(+) diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index 831f11b679a85..68accacca45c3 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` diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index d86701a8ae696..b87d6603f6710 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -193,6 +193,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: diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index d207e91e3ae87..0dfe329147df6 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -2247,6 +2247,18 @@ recording::memento_of_get_type::get_size () case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: size = LONG_LONG_TYPE_SIZE; break; + case GCC_JIT_TYPE_UINT8_T: + case GCC_JIT_TYPE_UINT16_T: + case GCC_JIT_TYPE_UINT32_T: + case GCC_JIT_TYPE_UINT64_T: + case GCC_JIT_TYPE_UINT128_T: + case GCC_JIT_TYPE_INT8_T: + case GCC_JIT_TYPE_INT16_T: + case GCC_JIT_TYPE_INT32_T: + case GCC_JIT_TYPE_INT64_T: + case GCC_JIT_TYPE_INT128_T: + size = 128; + break; case GCC_JIT_TYPE_FLOAT: size = FLOAT_TYPE_SIZE; break; @@ -2295,6 +2307,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 +2369,16 @@ recording::memento_of_get_type::is_int () const case GCC_JIT_TYPE_UNSIGNED_LONG: case GCC_JIT_TYPE_LONG_LONG: case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + case GCC_JIT_TYPE_UINT8_T: + case GCC_JIT_TYPE_UINT16_T: + case GCC_JIT_TYPE_UINT32_T: + case GCC_JIT_TYPE_UINT64_T: + case GCC_JIT_TYPE_UINT128_T: + case GCC_JIT_TYPE_INT8_T: + case GCC_JIT_TYPE_INT16_T: + case GCC_JIT_TYPE_INT32_T: + case GCC_JIT_TYPE_INT64_T: + case GCC_JIT_TYPE_INT128_T: return true; case GCC_JIT_TYPE_FLOAT: @@ -2400,6 +2432,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 +2495,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 +2563,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 +2614,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", diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 626738f9ccfc2..fece1f64e5ee1 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -548,6 +548,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, 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); From 3d32e36bf00046ed7a00768285de719dc379b728 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 11 May 2021 19:23:54 -0400 Subject: [PATCH 04/17] Add support for TLS variable [PR95415] 2021-05-18 Antoni Boucher gcc/jit/ PR target/95415 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_17): New ABI tag. * docs/topics/expressions.rst: Add document for the function gcc_jit_lvalue_set_tls_model. * jit-playback.h: New function (set_tls_model) and make rvalue::m_inner public. * jit-recording.c: New function (set_tls_model), new variables (tls_models and tls_model_enum_strings) and support for setting the tls model. * jit-recording.h: New function (set_tls_model) and new field m_tls_model. * libgccjit.c: New function (gcc_jit_lvalue_set_tls_model). * libgccjit.h: New function (gcc_jit_lvalue_set_tls_model) and new enum (gcc_jit_tls_model). * libgccjit.map (LIBGCCJIT_ABI_17): New ABI tag. gcc/testsuite/ PR target/95415 * jit.dg/all-non-failing-tests.h: Add test-tls.c. * jit.dg/test-tls.c: New test. Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/compatibility.rst | 9 +++++ gcc/jit/docs/topics/expressions.rst | 28 +++++++++++++++ gcc/jit/jit-playback.h | 6 ++++ gcc/jit/jit-recording.c | 36 ++++++++++++++++++++ gcc/jit/jit-recording.h | 5 ++- gcc/jit/libgccjit.c | 18 ++++++++++ gcc/jit/libgccjit.h | 21 ++++++++++++ gcc/jit/libgccjit.map | 5 +++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 ++++ gcc/testsuite/jit.dg/test-tls.c | 29 ++++++++++++++++ 10 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/jit.dg/test-tls.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 4a91baac437f0..3ba3c4c0a29c8 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -244,6 +244,15 @@ embedding assembler instructions: * :func:`gcc_jit_extended_asm_add_clobber` * :func:`gcc_jit_context_add_top_level_asm` +.. _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`` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index 1c01629b57d29..c681feb303a18 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -551,6 +551,34 @@ where the rvalue is computed by reading from the storage area. 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 **************** diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index b7807e513fc3b..83e443ca9e773 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -685,6 +685,12 @@ class lvalue : public rvalue set_decl_section_name (m_inner, name); } + void + set_tls_model (enum tls_model tls_model) + { + set_decl_tls_model (m_inner, tls_model); + } + private: bool mark_addressable (location *loc); }; diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 0dfe329147df6..3e7828c9a3e36 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -3791,6 +3791,12 @@ 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; +} + /* The implementation of class gcc::jit::recording::param. */ /* Implementation of pure virtual hook recording::memento::replay_into @@ -4617,6 +4623,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 @@ -4656,6 +4671,11 @@ recording::global::replay_into (replayer *r) { 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); } @@ -4754,6 +4774,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) { @@ -4787,6 +4815,14 @@ recording::global::write_reproducer (reproducer &r) 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) switch (m_type->dereference ()->get_size ()) { diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index a995fd344877e..6faff0add3e1d 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1106,7 +1106,8 @@ class lvalue : public rvalue location *loc, type *type_) : rvalue (ctxt, loc, type_), - m_link_section (NULL) + m_link_section (NULL), + m_tls_model (GCC_JIT_TLS_MODEL_DEFAULT) {} playback::lvalue * @@ -1129,9 +1130,11 @@ class lvalue : public rvalue 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); protected: string *m_link_section; + enum gcc_jit_tls_model m_tls_model; }; class param : public lvalue diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 9e39ca6e52cb2..56cc8207cbd26 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -2008,6 +2008,24 @@ gcc_jit_lvalue_set_link_section (gcc_jit_lvalue *lvalue, 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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index fece1f64e5ee1..b42541889a2e1 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -733,6 +733,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, @@ -1109,6 +1119,17 @@ 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); + extern gcc_jit_lvalue * gcc_jit_function_new_local (gcc_jit_function *func, gcc_jit_location *loc, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 494e105ca2993..f3b4fbbe43568 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -206,6 +206,11 @@ LIBGCCJIT_ABI_15 { gcc_jit_context_add_top_level_asm; } LIBGCCJIT_ABI_14; +LIBGCCJIT_ABI_17 { + global: + gcc_jit_lvalue_set_tls_model; +} LIBGCCJIT_ABI_16; + LIBGCCJIT_ABI_18 { global: gcc_jit_lvalue_set_link_section; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 7e3b59dee0d55..96ca457421ddd 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -188,6 +188,13 @@ #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-hello-world.c */ #define create_code create_code_hello_world #define verify_code verify_code_hello_world 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) +{ +} From 597ceb5cb4124e13271d35c127dd32114f16e44f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 9 May 2021 20:14:37 -0400 Subject: [PATCH 05/17] Add support for types used by atomic builtins [PR96066] [PR96067] 2021-05-17 Antoni Boucher gcc/jit/ PR target/PR96066 PR target/PR96067 * jit-builtins.c: Implement missing types for builtins. * jit-recording.c:: Allow sending a volatile const void * as argument. gcc/testsuite/ PR target/PR96066 PR target/PR96067 * jit.dg/all-non-failing-tests.h: Add test-builtin-types.c. * jit.dg/test-builtin-types.c Signed-off-by: Antoni Boucher --- gcc/jit/jit-builtins.c | 10 ++--- gcc/jit/jit-recording.c | 14 ++++++- gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 ++++ gcc/testsuite/jit.dg/test-builtin-types.c | 41 ++++++++++++++++++++ 4 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-builtin-types.c diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c index 1ea96f4e0253f..c279dd858f9cd 100644 --- a/gcc/jit/jit-builtins.c +++ b/gcc/jit/jit-builtins.c @@ -541,11 +541,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-recording.c b/gcc/jit/jit-recording.c index 3e7828c9a3e36..60ba2d30353e9 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -2671,8 +2671,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 diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 96ca457421ddd..c93eb5d37a930 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -195,6 +195,13 @@ #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 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); +} From c5f4ff2796db829cdf1434dcb4e153c9611f6fea Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Aug 2020 17:52:17 -0400 Subject: [PATCH 06/17] This patch add some reflection functions in the jit C api [PR96889] 2020-09-1 Antoni Boucher gcc/jit/ PR target/96889 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag. * docs/topics/functions.rst: Add documentation for the functions gcc_jit_function_get_return_type and gcc_jit_function_get_param_count * docs/topics/types.rst: Add documentation for the functions 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, and gcc_jit_struct_get_field_count * libgccjit.c: (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): New functions. (struct gcc_jit_function_type, struct gcc_jit_vector_type): New types. * libgccjit.h: (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): New function declarations. (struct gcc_jit_function_type, struct gcc_jit_vector_type): New types. * jit-recording.h: New functions (is_struct and is_vector) * libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag. gcc/testsuite/ PR target/96889 * jit.dg/all-non-failing-tests.h: Add test-reflection.c. * jit.dg/test-reflection.c: New test. Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/compatibility.rst | 43 +++- gcc/jit/docs/topics/functions.rst | 26 ++ gcc/jit/docs/topics/types.rst | 122 +++++++++ gcc/jit/jit-recording.h | 7 + gcc/jit/libgccjit.c | 256 +++++++++++++++++++ gcc/jit/libgccjit.h | 89 +++++++ gcc/jit/libgccjit.map | 21 ++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 + gcc/testsuite/jit.dg/test-reflection.c | 95 +++++++ 9 files changed, 668 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/jit.dg/test-reflection.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 3ba3c4c0a29c8..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: @@ -244,6 +244,47 @@ embedding assembler instructions: * :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`` 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 68accacca45c3..8c569f8f5ae23 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -355,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-recording.h b/gcc/jit/jit-recording.h index 6faff0add3e1d..1a7e1afe512bd 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -546,7 +546,9 @@ class type : public memento virtual bool is_bool () const = 0; virtual type *is_pointer () = 0; virtual type *is_array () = 0; + virtual struct_ *is_struct () { return NULL; } virtual bool is_void () const { return false; } + virtual vector_type *is_vector () { return NULL; } virtual bool has_known_size () const { return true; } bool is_numeric () const @@ -663,6 +665,7 @@ class decorated_type : public type bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); } type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); } type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); } + struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); } protected: type *m_other_type; @@ -745,6 +748,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; @@ -951,6 +956,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; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 56cc8207cbd26..44e3d1822ee99 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 { }; @@ -526,6 +534,194 @@ gcc_jit_type_get_volatile (gcc_jit_type *type) return (gcc_jit_type *)type->get_volatile (); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_array method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_type_is_array (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + + return (gcc_jit_type *)type->is_array (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_bool method, in + jit-recording.c. */ + +int +gcc_jit_type_is_bool (gcc_jit_type *type) +{ + RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type"); + + return type->is_bool (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_pointer method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_type_is_pointer (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + + return (gcc_jit_type *)type->is_pointer (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_int method, in + jit-recording.c. */ + +int +gcc_jit_type_is_integral (gcc_jit_type *type) +{ + RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type"); + + return type->is_int (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_vector method, in + jit-recording.c. */ + +gcc_jit_vector_type * +gcc_jit_type_is_vector (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + gcc::jit::recording::vector_type *vector_type = type->is_vector (); + return (gcc_jit_vector_type *)vector_type; +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::is_struct method, in + jit-recording.c. */ + +gcc_jit_struct * +gcc_jit_type_is_struct (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + gcc::jit::recording::struct_ *struct_type = type->is_struct (); + return (gcc_jit_struct *)struct_type; +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::vector_type::get_num_units method, in + jit-recording.c. */ + +ssize_t +gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type) +{ + RETURN_VAL_IF_FAIL (vector_type, -1, NULL, NULL, "NULL vector_type"); + return vector_type->get_num_units (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::vector_type::get_element_type method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type) +{ + RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type"); + return (gcc_jit_type *)vector_type->get_element_type (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::unqualified method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_type_unqualified (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + + return (gcc_jit_type *)type->unqualified (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::type::dyn_cast_function_type method, in + jit-recording.c. */ + +gcc_jit_function_type * +gcc_jit_type_is_function_ptr_type (gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); + gcc::jit::recording::type *func_ptr_type = type->dereference (); + RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type"); + + return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::function_type::get_return_type method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type) +{ + RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type"); + return (gcc_jit_type *)function_type->get_return_type (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::function_type::get_param_types method, in + jit-recording.c. */ + +ssize_t +gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type) +{ + RETURN_VAL_IF_FAIL (function_type, -1, NULL, NULL, "NULL function_type"); + return function_type->get_param_types ().length (); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::function_type::get_param_types method, in + jit-recording.c. */ + +gcc_jit_type * +gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type, + size_t index) +{ + RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type"); + size_t num_params = function_type->get_param_types ().length (); + gcc::jit::recording::context *ctxt = function_type->m_ctxt; + RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params, + ctxt, NULL, + "index of %ld is too large (%s has %ld params)", + index, + function_type->get_debug_string (), + num_params); + return (gcc_jit_type *)function_type->get_param_types ()[index]; +} + /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the @@ -747,6 +943,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 @@ -1028,6 +1255,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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index b42541889a2e1..ef71387de0640 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. */ @@ -665,6 +673,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type, int num_fields, gcc_jit_field **fields); +/* Get a field by index. */ +extern gcc_jit_field * +gcc_jit_struct_get_field (gcc_jit_struct *struct_type, + size_t index); + +/* Get the number of fields. */ +extern ssize_t +gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type); + /* Unions work similarly to structs. */ extern gcc_jit_type * gcc_jit_context_new_union_type (gcc_jit_context *ctxt, @@ -1679,6 +1696,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 f3b4fbbe43568..5031f305c57ae 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -206,6 +206,27 @@ LIBGCCJIT_ABI_15 { 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; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index c93eb5d37a930..37c20ee0267cc 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -279,6 +279,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 @@ -445,6 +452,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-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); +} + From 6dcd98e25015c3f699017bdab7776e4fd9949045 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 5 Jul 2020 19:07:30 -0400 Subject: [PATCH 07/17] This patch handles truncation and extension for casts in jit. 2020-07-12 Antoni Boucher gcc/jit/ PR target/95498 * jit-playback.c: Add support to handle truncation and extension in the convert function. gcc/testsuite/ PR target/95498 * jit.dg/all-non-failing-tests.h: New test. * jit.dg/test-cast.c: New test. Signed-off-by: Antoni Boucher --- gcc/jit/jit-playback.c | 39 ++++++++---- gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++ gcc/testsuite/jit.dg/test-cast.c | 66 ++++++++++++++++++++ 3 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-cast.c diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index b87d6603f6710..8081a8b6dd286 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 { diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 37c20ee0267cc..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 @@ -389,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}, 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); +} From c54e069e6f619e6851874da6069af130efd2c0fc Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 31 May 2021 09:38:14 -0400 Subject: [PATCH 08/17] Build and upload artifact on GitHub Actions --- .github/workflows/main.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/main.yml 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 From 73d4b8bb3403d80a8e03d3a85401ed8b633a8aa3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 2 Jun 2021 19:28:39 -0400 Subject: [PATCH 09/17] Revert "Add support for sized integer types, including 128-bit integers [PR95325]" This reverts commit d8f75a8fab72545f4bdba5dd608e113fbcee25b2. --- gcc/jit/docs/topics/types.rst | 10 --- gcc/jit/jit-playback.c | 21 ------ gcc/jit/jit-recording.c | 73 -------------------- gcc/jit/libgccjit.h | 11 --- gcc/testsuite/jit.dg/test-types.c | 111 ------------------------------ 5 files changed, 226 deletions(-) diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index 8c569f8f5ae23..73cdca11c3bcd 100644 --- a/gcc/jit/docs/topics/types.rst +++ b/gcc/jit/docs/topics/types.rst @@ -76,16 +76,6 @@ 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` diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 8081a8b6dd286..84fb638536953 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -210,27 +210,6 @@ 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: diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 60ba2d30353e9..95892f70c660e 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -2247,18 +2247,6 @@ recording::memento_of_get_type::get_size () case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: size = LONG_LONG_TYPE_SIZE; break; - case GCC_JIT_TYPE_UINT8_T: - case GCC_JIT_TYPE_UINT16_T: - case GCC_JIT_TYPE_UINT32_T: - case GCC_JIT_TYPE_UINT64_T: - case GCC_JIT_TYPE_UINT128_T: - case GCC_JIT_TYPE_INT8_T: - case GCC_JIT_TYPE_INT16_T: - case GCC_JIT_TYPE_INT32_T: - case GCC_JIT_TYPE_INT64_T: - case GCC_JIT_TYPE_INT128_T: - size = 128; - break; case GCC_JIT_TYPE_FLOAT: size = FLOAT_TYPE_SIZE; break; @@ -2307,16 +2295,6 @@ 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: @@ -2369,16 +2347,6 @@ 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: @@ -2432,16 +2400,6 @@ 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: @@ -2495,16 +2453,6 @@ 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: @@ -2563,17 +2511,6 @@ 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 */ @@ -2614,16 +2551,6 @@ 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", diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index ef71387de0640..b377d72a03ecd 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -556,17 +556,6 @@ 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, diff --git a/gcc/testsuite/jit.dg/test-types.c b/gcc/testsuite/jit.dg/test-types.c index 9c66284f193eb..8debcd7eb82c8 100644 --- a/gcc/testsuite/jit.dg/test-types.c +++ b/gcc/testsuite/jit.dg/test-types.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -30,18 +29,6 @@ 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; @@ -114,28 +101,6 @@ 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); @@ -182,18 +147,6 @@ 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, @@ -313,58 +266,6 @@ 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, @@ -446,18 +347,6 @@ 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); From eb6441e76a6f5b51ec6dd3159cfc3a20bf51224c Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 10 May 2021 19:43:02 -0400 Subject: [PATCH 10/17] Add support for sized integer types, including 128-bit integers [PR95325] 2021-05-18 Antoni Boucher gcc/jit/ PR target/95325 * docs/topics/types.rst: Add documentation for the new types 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. * jit-builtins.c: Add support for BT_UINT128. * jit-playback.c: Add support for the sized integer types. * jit-recording.c: Add support for the sized integer types. * libgccjit.h (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): New enum variants for gcc_jit_types. gcc/testsuite/ PR target/95325 * jit.dg/test-types.c: Add tests for sized integer types. Signed-off-by: Antoni Boucher --- gcc/jit/docs/topics/types.rst | 10 +++ gcc/jit/jit-builtins.c | 1 + gcc/jit/jit-playback.c | 21 ++++++ gcc/jit/jit-recording.c | 77 +++++++++++++++++++++ gcc/jit/libgccjit.h | 11 +++ gcc/testsuite/jit.dg/test-types.c | 111 ++++++++++++++++++++++++++++++ 6 files changed, 231 insertions(+) diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst index 73cdca11c3bcd..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` diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c index c279dd858f9cd..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); diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 84fb638536953..8081a8b6dd286 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -210,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: diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 95892f70c660e..442756dfcafc3 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -822,6 +822,10 @@ recording::context::get_int_type (int num_bytes, int is_signed) return get_type (is_signed ? GCC_JIT_TYPE_LONG_LONG : GCC_JIT_TYPE_UNSIGNED_LONG_LONG); + if (num_bits == 128) + return get_type (is_signed + ? GCC_JIT_TYPE_INT128_T + : GCC_JIT_TYPE_UINT128_T); /* Some other size, not corresponding to the C int types. */ /* To be written: support arbitrary other sizes, sharing by @@ -2247,6 +2251,18 @@ recording::memento_of_get_type::get_size () case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: size = LONG_LONG_TYPE_SIZE; break; + case GCC_JIT_TYPE_UINT8_T: + case GCC_JIT_TYPE_UINT16_T: + case GCC_JIT_TYPE_UINT32_T: + case GCC_JIT_TYPE_UINT64_T: + case GCC_JIT_TYPE_UINT128_T: + case GCC_JIT_TYPE_INT8_T: + case GCC_JIT_TYPE_INT16_T: + case GCC_JIT_TYPE_INT32_T: + case GCC_JIT_TYPE_INT64_T: + case GCC_JIT_TYPE_INT128_T: + size = 128; + break; case GCC_JIT_TYPE_FLOAT: size = FLOAT_TYPE_SIZE; break; @@ -2295,6 +2311,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 +2373,16 @@ recording::memento_of_get_type::is_int () const case GCC_JIT_TYPE_UNSIGNED_LONG: case GCC_JIT_TYPE_LONG_LONG: case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: + case GCC_JIT_TYPE_UINT8_T: + case GCC_JIT_TYPE_UINT16_T: + case GCC_JIT_TYPE_UINT32_T: + case GCC_JIT_TYPE_UINT64_T: + case GCC_JIT_TYPE_UINT128_T: + case GCC_JIT_TYPE_INT8_T: + case GCC_JIT_TYPE_INT16_T: + case GCC_JIT_TYPE_INT32_T: + case GCC_JIT_TYPE_INT64_T: + case GCC_JIT_TYPE_INT128_T: return true; case GCC_JIT_TYPE_FLOAT: @@ -2400,6 +2436,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 +2499,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 +2567,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 +2618,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", diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index b377d72a03ecd..ef71387de0640 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -556,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, 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); From cc8b57d0786558db90a6c2cd735ca60dc97e6039 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 9 Jun 2021 18:29:14 -0400 Subject: [PATCH 11/17] Implement bitcast --- gcc/jit/jit-playback.c | 14 +++++++++ gcc/jit/jit-playback.h | 5 ++++ gcc/jit/jit-recording.c | 66 +++++++++++++++++++++++++++++++++++++++++ gcc/jit/jit-recording.h | 32 ++++++++++++++++++++ gcc/jit/libgccjit.c | 28 +++++++++++++++++ gcc/jit/libgccjit.h | 9 ++++++ gcc/jit/libgccjit.map | 4 +++ 7 files changed, 158 insertions(+) diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 8081a8b6dd286..e9a46d51059fa 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -1255,6 +1255,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 83e443ca9e773..4841d0bdb2734 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -174,6 +174,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, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 442756dfcafc3..e6693dacda615 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -1168,6 +1168,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. @@ -5565,6 +5581,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. */ diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 1a7e1afe512bd..44258444d772f 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -194,6 +194,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, @@ -1620,6 +1625,33 @@ class cast : public rvalue 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; + +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 base_call : public rvalue { public: diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 44e3d1822ee99..5811846e3a5de 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -2039,6 +2039,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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index ef71387de0640..417b31e68076e 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1077,6 +1077,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, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 5031f305c57ae..99bbe7db3873f 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -241,3 +241,7 @@ LIBGCCJIT_ABI_19 { global: gcc_jit_global_set_initializer_value; } LIBGCCJIT_ABI_18; + +LIBGCCJIT_ABI_20 { + gcc_jit_context_new_bitcast; +} LIBGCCJIT_ABI_19; From 18d948aa4de76bac8c9650c144bd286ac0ac2ce4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 29 Aug 2021 10:54:55 -0400 Subject: [PATCH 12/17] Add support for register variable --- gcc/jit/jit-playback.h | 9 +++++++++ gcc/jit/jit-recording.c | 15 ++++++++++++--- gcc/jit/jit-recording.h | 3 +++ gcc/jit/libgccjit.c | 13 +++++++++++++ gcc/jit/libgccjit.h | 5 +++++ gcc/jit/libgccjit.map | 5 +++++ 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 4841d0bdb2734..c7e167c1fe0b0 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" @@ -696,6 +697,14 @@ class lvalue : public rvalue 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 e6693dacda615..96de3b522b7b9 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -3827,6 +3827,11 @@ 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 @@ -6234,11 +6239,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 44258444d772f..a5a1925b2edcc 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1119,6 +1119,7 @@ class lvalue : public rvalue type *type_) : rvalue (ctxt, loc, type_), m_link_section (NULL), + m_reg_name (NULL), m_tls_model (GCC_JIT_TLS_MODEL_DEFAULT) {} @@ -1143,9 +1144,11 @@ class lvalue : public rvalue 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); protected: string *m_link_section; + string *m_reg_name; enum gcc_jit_tls_model m_tls_model; }; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 5811846e3a5de..0a4294ba285e6 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -2310,6 +2310,19 @@ gcc_jit_lvalue_set_tls_model (gcc_jit_lvalue *lvalue, 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 417b31e68076e..44818b03b62e2 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1156,6 +1156,11 @@ 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, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 99bbe7db3873f..82be9dace36a8 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -245,3 +245,8 @@ LIBGCCJIT_ABI_19 { LIBGCCJIT_ABI_20 { gcc_jit_context_new_bitcast; } LIBGCCJIT_ABI_19; + +LIBGCCJIT_ABI_21 { + global: + gcc_jit_lvalue_set_register_name; +} LIBGCCJIT_ABI_20; From 6cce3df75cefbe7a1eaddc9ae21bb2f23f81a7c8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 25 Sep 2021 16:22:40 -0400 Subject: [PATCH 13/17] Revert "Add function to set the initial value of a global variable [PR96089]" This reverts commit f2a67694bd87b5c2f564b07edfe962047f95f8b9. --- gcc/jit/docs/topics/compatibility.rst | 9 ---- gcc/jit/docs/topics/expressions.rst | 14 ------ gcc/jit/jit-playback.c | 18 -------- gcc/jit/jit-playback.h | 7 --- gcc/jit/jit-recording.c | 16 ------- gcc/jit/jit-recording.h | 8 ---- gcc/jit/libgccjit.c | 43 ------------------- gcc/jit/libgccjit.h | 13 ------ gcc/jit/libgccjit.map | 9 +--- .../jit.dg/test-global-set-initializer.c | 15 ------- 10 files changed, 2 insertions(+), 150 deletions(-) diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 66612d9729ee5..73ec0d6a52072 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -302,12 +302,3 @@ thread-local storage model of a variable: 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 c681feb303a18..734ce441287b0 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -643,20 +643,6 @@ 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/jit-playback.c b/gcc/jit/jit-playback.c index e9a46d51059fa..e69c0f22349ff 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -702,24 +702,6 @@ 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); -} - /* Implementation of the various gcc::jit::playback::context::new_rvalue_from_const methods. diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index c7e167c1fe0b0..41c2199da5ecd 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -121,13 +121,6 @@ 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); - template rvalue * new_rvalue_from_const (type *type, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 96de3b522b7b9..cd5831727f6ae 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -4687,14 +4687,6 @@ recording::global::replay_into (replayer *r) m_initializer, 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), @@ -4834,14 +4826,6 @@ recording::global::write_reproducer (reproducer &r) r.get_identifier_as_type (get_type ()), m_name->get_debug_string ()); - 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_link_section != NULL) { r.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n" diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index a5a1925b2edcc..adb7ffa66e0e9 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -1383,7 +1383,6 @@ class global : public lvalue m_name (name) { m_initializer = NULL; - m_initializer_value = NULL; m_initializer_num_bytes = 0; } ~global () @@ -1410,12 +1409,6 @@ 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 @@ -1430,7 +1423,6 @@ 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; }; diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 0a4294ba285e6..a8157dcc96103 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -277,17 +277,6 @@ 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. */ @@ -1428,38 +1417,6 @@ 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) -{ - 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 ()); - - reinterpret_cast (global) - ->set_initializer_value (value); -} - /* Public entrypoint. See description in libgccjit.h. After error-checking, this calls the trivial diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 44818b03b62e2..23893c8fb71b6 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -848,19 +848,6 @@ 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); diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 82be9dace36a8..497166c8ba946 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -238,15 +238,10 @@ LIBGCCJIT_ABI_18 { } LIBGCCJIT_ABI_17; LIBGCCJIT_ABI_19 { - global: - gcc_jit_global_set_initializer_value; + gcc_jit_context_new_bitcast; } LIBGCCJIT_ABI_18; LIBGCCJIT_ABI_20 { - gcc_jit_context_new_bitcast; -} LIBGCCJIT_ABI_19; - -LIBGCCJIT_ABI_21 { global: gcc_jit_lvalue_set_register_name; -} LIBGCCJIT_ABI_20; +} LIBGCCJIT_ABI_19; diff --git a/gcc/testsuite/jit.dg/test-global-set-initializer.c b/gcc/testsuite/jit.dg/test-global-set-initializer.c index 418ed7dcf3fef..d38aba7d73f5b 100644 --- a/gcc/testsuite/jit.dg/test-global-set-initializer.c +++ b/gcc/testsuite/jit.dg/test-global-set-initializer.c @@ -21,7 +21,6 @@ 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); @@ -57,16 +56,6 @@ 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 @@ -86,8 +75,4 @@ 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); } From 919b622dec9fb8a68ca42ea69bd91521d86da52b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 25 Sep 2021 16:37:47 -0400 Subject: [PATCH 14/17] Add function to set the initial value of a global variable [PR96089] TODO: fail if global kind is imported TODO: doc 2021-05-20 Antoni Boucher gcc/jit/ PR target/96089 * docs/topics/compatibility.rst (LIBGCCJIT_ABI_19): New ABI tag. * docs/topics/expressions.rst: Add documentation for the function gcc_jit_global_set_initializer_value. * jit-playback.c: New functions (new_global_with_value, set_global_initial_value, new_rvalue_from_struct, new_rvalue_from_array). * jit-playback.h: New functions (new_global_with_value, set_global_initial_value, new_rvalue_from_struct, new_rvalue_from_array). * jit-recording.c: Add support for setting a value to a global variable and new methods (global_initializer::write_reproducer, global_initializer::make_debug_string, global_initializer::write_to_dump, global_initializer::replay_into, context::new_global_value_initializer, memento_of_new_rvalue_from_struct::write_reproducer, memento_of_new_rvalue_from_struct::make_debug_string, memento_of_new_rvalue_from_struct::visit_children, memento_of_new_rvalue_from_struct::replay_into, memento_of_new_rvalue_from_struct:: memento_of_new_rvalue_from_struct, context::new_rvalue_from_struct, memento_of_new_rvalue_from_array::write_reproducer, memento_of_new_rvalue_from_array::make_debug_string, memento_of_new_rvalue_from_array::visit_children, memento_of_new_rvalue_from_array::replay_into, memento_of_new_rvalue_from_array:: memento_of_new_rvalue_from_array, new_rvalue_from_array). * jit-recording.h: New functions (set_initializer_value, new_global_value_initializer, new_rvalue_from_struct, new_rvalue_from_array), new field m_initializer_value and new classes (global_initializer, memento_of_new_rvalue_from_struct, memento_of_new_rvalue_from_array). * libgccjit.c: New macro RETURN_IF_FAIL_PRINTF5 and new functions (gcc_jit_global_set_initializer_value, gcc_jit_context_new_rvalue_from_struct, gcc_jit_context_new_rvalue_from_array). * libgccjit.h: New functions (gcc_jit_global_set_initializer_value, gcc_jit_context_new_rvalue_from_struct, gcc_jit_context_new_rvalue_from_array). * libgccjit.map (LIBGCCJIT_ABI_19): New ABI tag. gcc/testsuite/ PR target/96089 * jit.dg/test-global-set-initializer.c: Add test for the new function (gcc_jit_global_set_initializer_value). --- gcc/jit/docs/topics/compatibility.rst | 9 + gcc/jit/docs/topics/expressions.rst | 14 + gcc/jit/jit-common.h | 1 + gcc/jit/jit-playback.c | 73 +++++ gcc/jit/jit-playback.h | 21 ++ gcc/jit/jit-recording.c | 250 ++++++++++++++++++ gcc/jit/jit-recording.h | 142 ++++++++++ gcc/jit/libgccjit.c | 153 +++++++++++ gcc/jit/libgccjit.h | 27 ++ gcc/jit/libgccjit.map | 7 + .../jit.dg/test-global-set-initializer.c | 15 ++ 11 files changed, 712 insertions(+) diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 73ec0d6a52072..66612d9729ee5 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -302,3 +302,12 @@ thread-local storage model of a variable: 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 734ce441287b0..c681feb303a18 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -643,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/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 e69c0f22349ff..f721e5ce9ae96 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -702,6 +702,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. @@ -852,6 +885,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 diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 41c2199da5ecd..b5d71aab5f8da 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -121,6 +121,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, @@ -134,6 +145,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, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index cd5831727f6ae..0aa535e0d8be8 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -1066,6 +1066,21 @@ recording::context::new_global (recording::location *loc, return result; } +/* Create a memento instance to initialize a global variable and add it to this + * context's list of mementos. + + Implements the post-error-checking part of + gcc_jit_global_set_initializer_value. */ + +void +recording::context::new_global_value_initializer (recording::lvalue *global, + recording::rvalue *value) +{ + recording::global_initializer *result = + new recording::global_initializer (global, value); + record (result); +} + /* Create a recording::memento_of_new_string_literal instance and add it to this context's list of mementos. @@ -1081,6 +1096,40 @@ recording::context::new_string_literal (const char *value) return result; } +/* Create a recording::memento_of_new_rvalue_from_struct instance and add it + to this context's list of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_rvalue_from_struct. */ + +recording::rvalue * +recording::context::new_rvalue_from_struct (location *loc, + struct_ *type, + rvalue **fields) +{ + recording::rvalue *result = + new memento_of_new_rvalue_from_struct (this, loc, type, fields); + record (result); + return result; +} + +/* Create a recording::memento_of_new_rvalue_from_array instance and add it + to this context's list of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_rvalue_from_array. */ + +recording::rvalue * +recording::context::new_rvalue_from_array (location *loc, + array_type *type, + rvalue **elements) +{ + recording::rvalue *result = + new memento_of_new_rvalue_from_array (this, loc, type, elements); + record (result); + return result; +} + /* Create a recording::memento_of_new_rvalue_from_vector instance and add it to this context's list of mementos. @@ -4687,6 +4736,14 @@ recording::global::replay_into (replayer *r) m_initializer, 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), @@ -4842,6 +4899,14 @@ recording::global::write_reproducer (reproducer &r) 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 ()) { @@ -4864,6 +4929,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 . */ @@ -5237,6 +5345,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 diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index adb7ffa66e0e9..36c8fba3cd5b5 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, @@ -527,6 +541,7 @@ class type : public memento virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; } virtual struct_ *dyn_cast_struct () { return NULL; } virtual vector_type *dyn_cast_vector_type () { return NULL; } + virtual array_type *dyn_cast_array_type () { return NULL; } /* Is it typesafe to copy to this type from rtype? */ virtual bool accepts_writes_from (type *rtype) @@ -778,6 +793,8 @@ class array_type : public type type *dereference () FINAL OVERRIDE; + array_type *dyn_cast_array_type () FINAL OVERRIDE { return this; } + bool is_int () const FINAL OVERRIDE { return false; } bool is_float () const FINAL OVERRIDE { return false; } bool is_bool () const FINAL OVERRIDE { return false; } @@ -1146,6 +1163,11 @@ class lvalue : public rvalue 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; @@ -1383,6 +1405,7 @@ class global : public lvalue m_name (name) { m_initializer = NULL; + m_initializer_value = NULL; m_initializer_num_bytes = 0; } ~global () @@ -1409,6 +1432,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 @@ -1423,9 +1452,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 { @@ -1470,6 +1520,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; @@ -1507,6 +1559,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: @@ -1554,6 +1678,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; @@ -1608,6 +1736,10 @@ 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; @@ -1635,6 +1767,10 @@ class bitcast : 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; @@ -1873,6 +2009,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; @@ -1899,6 +2039,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 a8157dcc96103..47838031385eb 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -277,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. */ @@ -1417,6 +1428,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 @@ -1639,6 +1686,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 diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 23893c8fb71b6..e4ec6cfb80410 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -848,6 +848,19 @@ gcc_jit_global_set_initializer (gcc_jit_lvalue *global, const void *blob, size_t num_bytes); +#define LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value + +/* Set an initial value for a global, which must be a constant. + + This API entrypoint was added in LIBGCCJIT_ABI_19; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer_value +*/ + +extern void +gcc_jit_global_set_initializer_value (gcc_jit_lvalue *global, + gcc_jit_rvalue *value); + /* Upcasting. */ extern gcc_jit_object * gcc_jit_lvalue_as_object (gcc_jit_lvalue *lvalue); @@ -901,6 +914,20 @@ extern gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, const char *value); +extern gcc_jit_rvalue * +gcc_jit_context_new_rvalue_from_struct (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_struct *struct_type, + size_t num_elements, + gcc_jit_rvalue **fields); + +extern gcc_jit_rvalue * +gcc_jit_context_new_rvalue_from_array (gcc_jit_context *ctxt, + gcc_jit_location *loc, + gcc_jit_type *type, + size_t num_elements, + gcc_jit_rvalue **elements); + enum gcc_jit_unary_op { /* Negate an arithmetic value; analogous to: diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 497166c8ba946..a30cca5761560 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -245,3 +245,10 @@ 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; 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); } From b80bd6a20a1ae8a15ca0cab065caaff594a1d6c3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 27 Sep 2021 18:34:37 -0400 Subject: [PATCH 15/17] fixup! This patch add some reflection functions in the jit C api [PR96889] --- gcc/jit/libgccjit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 47838031385eb..3758400e17a6a 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -669,7 +669,9 @@ gcc_jit_type_is_function_ptr_type (gcc_jit_type *type) { RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type"); gcc::jit::recording::type *func_ptr_type = type->dereference (); - RETURN_NULL_IF_FAIL (func_ptr_type, NULL, NULL, "NULL type"); + if (!func_ptr_type) { + return NULL; + } return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type (); } From 81ce652876c2d3e1b84dffc03b560f1df1630d03 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 10 Oct 2021 16:25:15 -0400 Subject: [PATCH 16/17] Support integers of any size --- gcc/jit/jit-recording.c | 67 ++++++++++++++++++++++++++++++++++++++--- gcc/jit/jit-recording.h | 43 ++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 0aa535e0d8be8..1a412b5238396 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) { @@ -827,10 +831,47 @@ recording::context::get_int_type (int num_bytes, int is_signed) ? GCC_JIT_TYPE_INT128_T : GCC_JIT_TYPE_UINT128_T); - /* Some other size, not corresponding to the C int types. */ - /* To be written: support arbitrary other sizes, sharing by - memoizing at the recording::context level? */ - gcc_unreachable (); + // TODO: check in num_bits > 0? + tree int_type; + if (is_signed) + { + if (tree type = m_signed_int_types[num_bits]) + { + int_type = type; + } + else + { + 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; + } + } + + recording::type *result = new memento_of_make_type (this, int_type, 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 @@ -2714,6 +2755,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 (this); +} + +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 diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 36c8fba3cd5b5..c06874e1e9e5f 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -368,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 @@ -638,6 +641,46 @@ 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, + tree int_type, + size_t num_bits) + : type (ctxt), + m_type (int_type), + 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; } + +public: + void replay_into (replayer *r) FINAL OVERRIDE; + +private: + string * make_debug_string () FINAL OVERRIDE; + void write_reproducer (reproducer &r) FINAL OVERRIDE; + +private: + tree m_type; + size_t m_num_bits; +}; + + /* Result of "gcc_jit_type_get_pointer". */ class memento_of_get_pointer : public type { From 4c3b8a933465d57f8d47ff81a53499089c72f5c8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 20 Oct 2021 08:55:12 -0400 Subject: [PATCH 17/17] Make sized integer types compatible with normal integer types --- gcc/jit/jit-playback.c | 19 +++++++ gcc/jit/jit-playback.h | 3 ++ gcc/jit/jit-recording.c | 115 +++++++++++++++++++++++++++++++++------- gcc/jit/jit-recording.h | 27 ++++++++-- gcc/jit/libgccjit.c | 15 +++++- gcc/jit/libgccjit.h | 4 ++ gcc/jit/libgccjit.map | 5 ++ 7 files changed, 162 insertions(+), 26 deletions(-) diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index f721e5ce9ae96..096c89902f7bd 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -282,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. */ diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index b5d71aab5f8da..25e0d5cf2f305 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -66,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, diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 1a412b5238396..5ea23208f057e 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -564,8 +564,8 @@ recording::context::context (context *parent_ctxt) m_compound_types (), m_globals (), m_functions (), - m_signed_int_types(), - m_unsigned_int_types(), + /*m_signed_int_types(), + m_unsigned_int_types(),*/ m_FILE_type (NULL), m_builtins_manager(NULL) { @@ -796,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) { @@ -805,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 @@ -832,33 +836,38 @@ recording::context::get_int_type (int num_bytes, int is_signed) : GCC_JIT_TYPE_UINT128_T); // TODO: check in num_bits > 0? - tree int_type; + /*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]) + /*if (tree type = m_signed_int_types[num_bits]) { int_type = type; } else - { - int_type = make_signed_type(num_bits); - m_signed_int_types[num_bits] = int_type; - } + {*/ + // 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]) + /*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; - } + {*/ + /*int_type = make_unsigned_type(num_bits);*/ + /*m_unsigned_int_types[num_bits] = int_type; + }*/ } - recording::type *result = new memento_of_make_type (this, int_type, num_bits); + recording::type *result = new memento_of_make_type (this, is_signed, num_bits); record (result); return result; } @@ -2358,14 +2367,22 @@ recording::memento_of_get_type::get_size () size = LONG_LONG_TYPE_SIZE; break; case GCC_JIT_TYPE_UINT8_T: - case GCC_JIT_TYPE_UINT16_T: - case GCC_JIT_TYPE_UINT32_T: - case GCC_JIT_TYPE_UINT64_T: - case GCC_JIT_TYPE_UINT128_T: case GCC_JIT_TYPE_INT8_T: + 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; @@ -2378,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 @@ -2512,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. */ @@ -2761,7 +2836,7 @@ recording::memento_of_get_type::write_reproducer (reproducer &r) void recording::memento_of_make_type::replay_into (replayer *r) { - set_playback_obj (this); + set_playback_obj (r->make_type(m_is_signed, m_num_bits)); } recording::string * diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index c06874e1e9e5f..343cd6c3ac41b 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -369,8 +369,8 @@ class context : public log_user 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]; + /*tree m_signed_int_types[128]; + tree m_unsigned_int_types[128];*/ type *m_FILE_type; builtins_manager *m_builtins_manager; // lazily created @@ -573,6 +573,7 @@ class type : public memento 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 { @@ -613,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); } @@ -629,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; @@ -646,10 +655,10 @@ class memento_of_make_type : public type { public: memento_of_make_type (context *ctxt, - tree int_type, + bool is_signed, size_t num_bits) : type (ctxt), - m_type (int_type), + m_is_signed (is_signed), m_num_bits (num_bits) {} type *dereference () FINAL OVERRIDE { return NULL; }; @@ -667,6 +676,7 @@ class memento_of_make_type : public type 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; @@ -676,7 +686,7 @@ class memento_of_make_type : public type void write_reproducer (reproducer &r) FINAL OVERRIDE; private: - tree m_type; + bool m_is_signed; size_t m_num_bits; }; @@ -702,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; @@ -723,12 +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; @@ -844,6 +858,7 @@ class array_type : public type 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; @@ -877,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; @@ -990,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; } diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index 3758400e17a6a..e03817f371b0d 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -534,6 +534,19 @@ 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 @@ -1865,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)", diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index e4ec6cfb80410..8c737f1704e38 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -612,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, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index a30cca5761560..53b42468de424 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -252,3 +252,8 @@ LIBGCCJIT_ABI_21 { 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;