From 12d8e57ca2313002da42672dc86b167baf812ff3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 4 Apr 2024 18:57:07 -0400 Subject: [PATCH] libgccjit: Add ability to get the alignment of a type gcc/jit/ChangeLog: * docs/topics/compatibility.rst (LIBGCCJIT_ABI_28): New ABI tag. * docs/topics/expressions.rst: Document gcc_jit_context_new_alignof. * jit-playback.cc (new_alignof): New method. * jit-playback.h: New method. * jit-recording.cc (recording::context::new_alignof): New method. (recording::memento_of_sizeof::replay_into, recording::memento_of_typeinfo::replay_into, recording::memento_of_sizeof::make_debug_string, recording::memento_of_typeinfo::make_debug_string, recording::memento_of_sizeof::write_reproducer, recording::memento_of_typeinfo::write_reproducer): Rename. * jit-recording.h (enum type_info_type): New enum. (class memento_of_sizeof class memento_of_typeinfo): Rename. * libgccjit.cc (gcc_jit_context_new_alignof): New function. * libgccjit.h (gcc_jit_context_new_alignof): New function. * libgccjit.map: New function. gcc/testsuite/ChangeLog: * jit.dg/all-non-failing-tests.h: New test. * jit.dg/test-alignof.c: New test. --- gcc/jit/docs/topics/compatibility.rst | 7 ++ gcc/jit/docs/topics/expressions.rst | 14 ++++ gcc/jit/jit-playback.cc | 11 ++++ gcc/jit/jit-playback.h | 3 + gcc/jit/jit-recording.cc | 67 +++++++++++++++---- gcc/jit/jit-recording.h | 19 ++++-- gcc/jit/libgccjit.cc | 18 +++++ gcc/jit/libgccjit.h | 13 ++++ gcc/jit/libgccjit.map | 5 ++ gcc/testsuite/jit.dg/all-non-failing-tests.h | 10 +++ gcc/testsuite/jit.dg/test-alignof.c | 69 ++++++++++++++++++++ 11 files changed, 221 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-alignof.c diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 9cfb054f653..92c3ed24c89 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -397,3 +397,10 @@ on functions and variables: -------------------- ``LIBGCCJIT_ABI_27`` covers the addition of :func:`gcc_jit_context_new_sizeof` + +.. _LIBGCCJIT_ABI_28: + +``LIBGCCJIT_ABI_28`` +-------------------- +``LIBGCCJIT_ABI_28`` covers the addition of +:func:`gcc_jit_context_new_alignof` diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index c3f4f61eb06..299d3d229df 100644 --- a/gcc/jit/docs/topics/expressions.rst +++ b/gcc/jit/docs/topics/expressions.rst @@ -140,6 +140,20 @@ Simple expressions sizeof (type) +.. function:: gcc_jit_rvalue *\ + gcc_jit_context_new_alignof (gcc_jit_context *ctxt, \ + gcc_jit_type *type) + + Generate an rvalue that is equal to the alignment of ``type``. + + The parameter ``type`` must be non-NULL. + + This is equivalent to this C code: + + .. code-block:: c + + _Alignof (type) + Constructor expressions *********************** diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc index 6baa838af10..b3f54da24ab 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -1120,6 +1120,17 @@ new_sizeof (type *type) /* Construct a playback::rvalue instance (wrapping a tree). */ +playback::rvalue * +playback::context:: +new_alignof (type *type) +{ + int alignment = TYPE_ALIGN (type->as_tree ()) / BITS_PER_UNIT; + tree inner = build_int_cst (integer_type_node, alignment); + return new rvalue (this, inner); +} + +/* Construct a playback::rvalue instance (wrapping a tree). */ + playback::rvalue * playback::context:: new_string_literal (const char *value) diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index aa6a086613c..6e97b389cbb 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -165,6 +165,9 @@ public: rvalue * new_sizeof (type *type); + rvalue * + new_alignof (type *type); + rvalue * new_string_literal (const char *value); diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 68a2e860c1f..1121f5e00a8 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -1077,7 +1077,7 @@ recording::context::new_global_init_rvalue (lvalue *variable, gbl->set_rvalue_init (init); /* Needed by the global for write dump. */ } -/* Create a recording::memento_of_sizeof instance and add it +/* Create a recording::memento_of_typeinfo instance and add it to this context's list of mementos. Implements the post-error-checking part of @@ -1087,7 +1087,22 @@ recording::rvalue * recording::context::new_sizeof (recording::type *type) { recording::rvalue *result = - new memento_of_sizeof (this, NULL, type); + new memento_of_typeinfo (this, NULL, type, TYPE_INFO_SIZE_OF); + record (result); + return result; +} + +/* Create a recording::memento_of_typeinfo instance and add it + to this context's list of mementos. + + Implements the post-error-checking part of + gcc_jit_context_new_alignof. */ + +recording::rvalue * +recording::context::new_alignof (recording::type *type) +{ + recording::rvalue *result = + new memento_of_typeinfo (this, NULL, type, TYPE_INFO_ALIGN_OF); record (result); return result; } @@ -5472,25 +5487,44 @@ memento_of_new_rvalue_from_const ::write_reproducer (reproducer &r) } // namespace recording -/* The implementation of class gcc::jit::recording::memento_of_sizeof. */ +/* The implementation of class gcc::jit::recording::memento_of_typeinfo. */ /* Implementation of pure virtual hook recording::memento::replay_into - for recording::memento_of_sizeof. */ + for recording::memento_of_typeinfo. */ void -recording::memento_of_sizeof::replay_into (replayer *r) +recording::memento_of_typeinfo::replay_into (replayer *r) { - set_playback_obj (r->new_sizeof (m_type->playback_type ())); + switch (m_info_type) + { + case TYPE_INFO_ALIGN_OF: + set_playback_obj (r->new_alignof (m_type->playback_type ())); + break; + case TYPE_INFO_SIZE_OF: + set_playback_obj (r->new_sizeof (m_type->playback_type ())); + break; + } } /* Implementation of recording::memento::make_debug_string for sizeof expressions. */ recording::string * -recording::memento_of_sizeof::make_debug_string () +recording::memento_of_typeinfo::make_debug_string () { + const char* ident; + switch (m_info_type) + { + case TYPE_INFO_ALIGN_OF: + ident = "_Alignof"; + break; + case TYPE_INFO_SIZE_OF: + ident = "sizeof"; + break; + } return string::from_printf (m_ctxt, - "sizeof (%s)", + "%s (%s)", + ident, m_type->get_debug_string ()); } @@ -5498,13 +5532,24 @@ recording::memento_of_sizeof::make_debug_string () expressions. */ void -recording::memento_of_sizeof::write_reproducer (reproducer &r) +recording::memento_of_typeinfo::write_reproducer (reproducer &r) { + const char* type; + switch (m_info_type) + { + case TYPE_INFO_ALIGN_OF: + type = "align"; + break; + case TYPE_INFO_SIZE_OF: + type = "size"; + break; + } const char *id = r.make_identifier (this, "rvalue"); r.write (" gcc_jit_rvalue *%s =\n" - " gcc_jit_context_new_sizeof (%s, /* gcc_jit_context *ctxt */\n" - " %s); /* gcc_jit_type *type */\n", + " gcc_jit_context_new_%sof (%s, /* gcc_jit_context *ctxt */\n" + " (gcc_jit_type *) %s); /* gcc_jit_type *type */\n", id, + type, r.get_identifier (get_context ()), r.get_identifier (m_type)); } diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index d8d16f4fe29..cce25f1fc07 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -47,6 +47,11 @@ class reproducer; namespace recording { +enum type_info_type { + TYPE_INFO_ALIGN_OF, + TYPE_INFO_SIZE_OF, +}; + playback::location * playback_location (replayer *r, location *loc); @@ -172,6 +177,9 @@ public: rvalue * new_sizeof (type *type); + rvalue * + new_alignof (type *type); + rvalue * new_string_literal (const char *value); @@ -1608,14 +1616,16 @@ private: HOST_TYPE m_value; }; -class memento_of_sizeof : public rvalue +class memento_of_typeinfo : public rvalue { public: - memento_of_sizeof (context *ctxt, + memento_of_typeinfo (context *ctxt, location *loc, - type *type) + type *type, + type_info_type type_info) : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_INT)), - m_type (type) {} + m_type (type), + m_info_type (type_info) {} void replay_into (replayer *r) final override; @@ -1631,6 +1641,7 @@ private: private: type *m_type; + type_info_type m_info_type; }; class memento_of_new_string_literal : public rvalue diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 445c0d0e0e3..eb38da91df1 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -2091,6 +2091,24 @@ gcc_jit_context_new_sizeof (gcc_jit_context *ctxt, ->new_sizeof (type)); } +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the + gcc::jit::recording::context::new_alignof method in + jit-recording.cc. */ + +gcc_jit_rvalue * +gcc_jit_context_new_alignof (gcc_jit_context *ctxt, + gcc_jit_type *type) +{ + RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + RETURN_NULL_IF_FAIL (type, ctxt, NULL, "NULL type"); + JIT_LOG_FUNC (ctxt->get_logger ()); + + return ((gcc_jit_rvalue *)ctxt + ->new_alignof (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 74e847b2dec..c82a4be792e 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1105,6 +1105,19 @@ extern gcc_jit_rvalue * gcc_jit_context_new_sizeof (gcc_jit_context *ctxt, gcc_jit_type *type); +#define LIBGCCJIT_HAVE_gcc_jit_context_new_alignof + +/* Generates an rvalue that is equal to the alignment of type. + + This API entrypoint was added in LIBGCCJIT_ABI_38; you can test for its + presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_alignof */ + +extern gcc_jit_rvalue * +gcc_jit_context_new_alignof (gcc_jit_context *ctxt, + gcc_jit_type *type); + + /* String literals. */ extern gcc_jit_rvalue * gcc_jit_context_new_string_literal (gcc_jit_context *ctxt, diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index 99aa5970be1..b02783ebfb2 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -289,3 +289,8 @@ LIBGCCJIT_ABI_27 { global: gcc_jit_context_new_sizeof; } LIBGCCJIT_ABI_26; + +LIBGCCJIT_ABI_28 { + global: + gcc_jit_context_new_alignof; +} LIBGCCJIT_ABI_27; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 14a0a321550..63b4e78c8ce 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -42,6 +42,13 @@ #undef create_code #undef verify_code +/* test-alignof.c */ +#define create_code create_code_alignof +#define verify_code verify_code_alignof +#include "test-alignof.c" +#undef create_code +#undef verify_code + /* test-always_inline-attribute.c: This can't be in the testcases array as it needs the `-O0` flag. */ @@ -449,6 +456,9 @@ const struct testcase testcases[] = { {"accessing_union", create_code_accessing_union, verify_code_accessing_union}, + {"alignof", + create_code_alignof, + verify_code_alignof}, {"alignment", create_code_alignment, verify_code_alignment}, diff --git a/gcc/testsuite/jit.dg/test-alignof.c b/gcc/testsuite/jit.dg/test-alignof.c new file mode 100644 index 00000000000..af288a82f47 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-alignof.c @@ -0,0 +1,69 @@ +#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: +int +my_alignof () +{ + return _Alignof(int32_t); +} + */ + gcc_jit_type *int32 = + gcc_jit_context_get_int_type (ctxt, 4, 1); + gcc_jit_type *int64 = + gcc_jit_context_get_int_type (ctxt, 8, 1); + 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, + int_type, + "my_alignof", + 0, NULL, 0); + + gcc_jit_block *initial = + gcc_jit_function_new_block (func, "initial"); + + gcc_jit_field *field1 = + gcc_jit_context_new_field (ctxt, NULL, int32, "int32"); + gcc_jit_field *field2 = + gcc_jit_context_new_field (ctxt, NULL, int64, "int64"); + + gcc_jit_field *fields[] = { + field1, + field2, + }; + + gcc_jit_struct *struct_type = + gcc_jit_context_new_struct_type ( + ctxt, + NULL, + "ints", + 2, fields); + + gcc_jit_block_end_with_return(initial, NULL, + gcc_jit_context_new_alignof(ctxt, gcc_jit_struct_as_type (struct_type))); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef int (*my_alignof_type) (); + CHECK_NON_NULL (result); + my_alignof_type my_alignof = + (my_alignof_type)gcc_jit_result_get_code (result, "my_alignof"); + CHECK_NON_NULL (my_alignof); + int val = my_alignof (); + CHECK_VALUE (val, 8); +} -- 2.44.0