From 8e8688799729a98d8bdfaf28532de163c0be8c69 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 4 Apr 2024 19:17:46 -0400 Subject: [PATCH] libgccjit: Add ability to get the alignment of a type gcc/jit/ChangeLog: * 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/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 ++++++++++++++++++++ 10 files changed, 214 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-alignof.c diff --git a/gcc/jit/docs/topics/expressions.rst b/gcc/jit/docs/topics/expressions.rst index c3f4f61eb061f..299d3d229dfd5 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 cde058879a986..e98cd596fae92 100644 --- a/gcc/jit/jit-playback.cc +++ b/gcc/jit/jit-playback.cc @@ -1148,6 +1148,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 171fb1e3d56f5..7e29d2329a2d1 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -173,6 +173,9 @@ class context : public log_user 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 f0aae5c6d4d8c..ea6379a0bc61f 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -1134,7 +1134,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 @@ -1144,7 +1144,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; } @@ -5805,25 +5820,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 ()); } @@ -5831,13 +5865,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 07db75b24916d..80da2b2aafb52 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -52,6 +52,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); @@ -181,6 +186,9 @@ class context : public log_user rvalue * new_sizeof (type *type); + rvalue * + new_alignof (type *type); + rvalue * new_string_literal (const char *value); @@ -1814,14 +1822,16 @@ class memento_of_new_rvalue_from_const : public rvalue 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; @@ -1837,6 +1847,7 @@ class memento_of_sizeof : public rvalue 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 a2cdc01a3a469..bccbefbf7d347 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -2158,6 +2158,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 d55a034f14aee..c31938f21aa62 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -1122,6 +1122,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 181ca135941fb..e6facb1f0ec0e 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -347,3 +347,8 @@ LIBGCCJIT_ABI_37 { gcc_jit_function_set_location; gcc_jit_rvalue_set_location; } LIBGCCJIT_ABI_36; + +LIBGCCJIT_ABI_38 { + global: + gcc_jit_context_new_alignof; +} LIBGCCJIT_ABI_37; diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 469f94c076878..1e230a65de186 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. */ @@ -455,6 +462,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 0000000000000..af288a82f474c --- /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); +}