sorry, just noticed that the check_value was wrongly written on the last line 
of this patch. Other parts should be good. Should I correct it now in a new 
revision? Or is it okay to wait for further reviews for now?
On Sun, Nov 10, 2024 at 13:17, Schrodinger ZHU Yifan <i...@zhuyi.fan> 
wrote:  This patch adds dynamic alloca stubs support to GCCJIT.



DEF_BUILTIN_STUB only defines the enum for builtins instead of

providing the type. Therefore, builtins with stub will lead to

ICE before this patch. This applies to `alloca_with_align`,

`stack_save` and `stack_restore`.



This patch adds special handling for builtins defined by

DEF_BUILTIN_STUB.



Additionally, it fixes that supercontext is not

set for blocks emitted by gccjit. This triggers a SEGV error inside

`fold_builtin_with_align`.

gcc/jit/ChangeLog:



 * jit-builtins.cc (builtins_manager::make_builtin_function):

 (builtins_manager::make_type_for_stub):

 (builtins_manager::get_type_for_stub):

 (builtins_manager::get_attrs_tree):

 (builtins_manager::get_attrs_tree_for_stub):

 * jit-builtins.h:

 * jit-playback.cc (postprocess):



gcc/testsuite/ChangeLog:



 * jit.dg/test-aligned-alloca.c: New test.

 * jit.dg/test-stack-save-restore.c: New test.



---

 gcc/jit/jit-builtins.cc | 69 +++++++++-

 gcc/jit/jit-builtins.h | 7 +

 gcc/jit/jit-playback.cc | 1 +

 gcc/testsuite/jit.dg/test-aligned-alloca.c | 121 ++++++++++++++++++

 .../jit.dg/test-stack-save-restore.c | 114 +++++++++++++++++

 5 files changed, 309 insertions(+), 3 deletions(-)

 create mode 100644 gcc/testsuite/jit.dg/test-aligned-alloca.c

 create mode 100644 gcc/testsuite/jit.dg/test-stack-save-restore.c



diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc

index 0c13c8db586..06affd66634 100644

--- a/gcc/jit/jit-builtins.cc

+++ b/gcc/jit/jit-builtins.cc

@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see

 #include "target.h"

 #include "jit-playback.h"

 #include "stringpool.h"

+#include "tree-core.h"

 
 #include "jit-builtins.h"

 
@@ -185,7 +186,8 @@ builtins_manager::make_builtin_function (enum 
built_in_function builtin_id)

 {

 const struct builtin_data& bd = builtin_data[builtin_id];

 enum jit_builtin_type type_id = bd.type;

- recording::type *t = get_type (type_id);

+ recording::type *t = type_id == BT_LAST ? get_type_for_stub (builtin_id)

+ : get_type (type_id);

 if (!t)

 return NULL;

 recording::function_type *func_type = t->as_a_function_type ();

@@ -333,6 +335,52 @@ builtins_manager::get_type (enum jit_builtin_type type_id)

 return m_types[type_id];

 }

 
+/* Create the recording::type for special builtins whose types are not defined

+ in builtin-types.def. */

+

+recording::type *

+builtins_manager::make_type_for_stub (enum built_in_function builtin_id)

+{

+ switch (builtin_id)

+ {

+ default:

+ return reinterpret_cast<recording::type *> (-1);

+ case BUILT_IN_ALLOCA_WITH_ALIGN:

+ {

+ recording::type *p = m_ctxt->get_type (GCC_JIT_TYPE_SIZE_T);

+ recording::type *r = m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR);

+ recording::type *params[2] = { p, p };

+ return m_ctxt->new_function_type (r, 2, params, false);

+ }

+ case BUILT_IN_STACK_SAVE:

+ {

+ recording::type *r = m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR);

+ return m_ctxt->new_function_type (r, 0, nullptr, false);

+ }

+ case BUILT_IN_STACK_RESTORE:

+ {

+ recording::type *p = m_ctxt->get_type (GCC_JIT_TYPE_VOID_PTR);

+ recording::type *r = m_ctxt->get_type (GCC_JIT_TYPE_VOID);

+ recording::type *params[1] = { p };

+ return m_ctxt->new_function_type (r, 1, params, false);

+ }

+ }

+}

+

+/* Get the recording::type for a given type of builtin function,

+ by ID, creating it if it doesn't already exist. */

+

+recording::type *

+builtins_manager::get_type_for_stub (enum built_in_function type_id)

+{

+ if (m_types[type_id] == nullptr)

+ m_types[type_id] = make_type_for_stub (type_id);

+ recording::type *t = m_types[type_id];

+ if (reinterpret_cast<intptr_t> (t) == -1)

+ return nullptr;

+ return t;

+}

+

 /* Create the recording::type for a given type of builtin function. */

 
 recording::type *

@@ -661,15 +709,30 @@ tree

 builtins_manager::get_attrs_tree (enum built_in_function builtin_id)

 {

 enum built_in_attribute attr = builtin_data[builtin_id].attr;

+ if (attr == ATTR_LAST)

+ return get_attrs_tree_for_stub (builtin_id);

 return get_attrs_tree (attr);

 }

 
-/* As above, but for an enum built_in_attribute. */

+/* Get attributes for builtin stubs. */

+

+tree

+builtins_manager::get_attrs_tree_for_stub (enum built_in_function builtin_id)

+{

+ switch (builtin_id)

+ {

+ default:

+ return NULL_TREE;

+ case BUILT_IN_ALLOCA_WITH_ALIGN:

+ return get_attrs_tree (BUILT_IN_ALLOCA);

+ }

+}

+

+/* As get_attrs_tree, but for an enum built_in_attribute. */

 
 tree

 builtins_manager::get_attrs_tree (enum built_in_attribute attr)

 {

- gcc_assert (attr < ATTR_LAST);

 if (!m_attributes [attr])

 m_attributes [attr] = make_attrs_tree (attr);

 return m_attributes [attr];

diff --git a/gcc/jit/jit-builtins.h b/gcc/jit/jit-builtins.h

index 17e118481d6..f4de3707201 100644

--- a/gcc/jit/jit-builtins.h

+++ b/gcc/jit/jit-builtins.h

@@ -124,6 +124,9 @@ public:

 tree

 get_attrs_tree (enum built_in_function builtin_id);

 
+ tree

+ get_attrs_tree_for_stub (enum built_in_function builtin_id);

+

 tree

 get_attrs_tree (enum built_in_attribute attr);

 
@@ -146,6 +149,10 @@ private:

 recording::type *

 make_type (enum jit_builtin_type type_id);

 
+ recording::type *get_type_for_stub (enum built_in_function type_id);

+

+ recording::type *make_type_for_stub (enum built_in_function type_id);

+

 recording::type*

 make_primitive_type (enum jit_builtin_type type_id);

 
diff --git a/gcc/jit/jit-playback.cc b/gcc/jit/jit-playback.cc

index e32e837f2fe..acdb25c7d09 100644

--- a/gcc/jit/jit-playback.cc

+++ b/gcc/jit/jit-playback.cc

@@ -2118,6 +2118,7 @@ postprocess ()

 /* Seem to need this in gimple-low.cc: */

 gcc_assert (m_inner_block);

 DECL_INITIAL (m_inner_fndecl) = m_inner_block;

+ BLOCK_SUPERCONTEXT (m_inner_block) = m_inner_fndecl;

 
 /* how to add to function? the following appears to be how to

 set the body of a m_inner_fndecl: */

diff --git a/gcc/testsuite/jit.dg/test-aligned-alloca.c 
b/gcc/testsuite/jit.dg/test-aligned-alloca.c

new file mode 100644

index 00000000000..9d4174c3cd0

--- /dev/null

+++ b/gcc/testsuite/jit.dg/test-aligned-alloca.c

@@ -0,0 +1,121 @@

+#define __need_size_t

+#include <stddef.h>

+#include <stdio.h>

+#include <stdlib.h>

+

+#include "libgccjit.h"

+

+#include "harness.h"

+

+void

+fill (void *ptr)

+{

+ for (int i = 0; i < 100; i++)

+ ((int *)ptr)[i] = i;

+}

+

+void

+sum (void *ptr, int *sum)

+{

+ *sum = 0;

+ for (int i = 0; i < 100; i++)

+ *sum += ((int *)ptr)[i];

+}

+

+void

+create_code (gcc_jit_context *ctxt, void *user_data)

+{

+ /*

+ size_t test_aligned_alloca (typeof(fill) *fill, typeof(sum) *sum, int* sum_p)

+ {

+ void *p;

+ p = __builtin_alloca_with_align (sizeof (int) * 100, 128);

+ fill (p);

+ sum (p, sum_p);

+ return )size_t)p;

+ }

+ */

+

+ /* Types */

+ gcc_jit_type *size_t_type

+ = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIZE_T);

+ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

+ gcc_jit_type *int_ptr_type = gcc_jit_type_get_pointer (int_type);

+ gcc_jit_type *void_ptr_type

+ = 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 *fill_ptr_type = gcc_jit_context_new_function_ptr_type (

+ ctxt, NULL, void_type, 1, &void_ptr_type, 0);

+ gcc_jit_type *sum_params[] = { void_ptr_type, int_ptr_type };

+ gcc_jit_type *sum_ptr_type = gcc_jit_context_new_function_ptr_type (

+ ctxt, NULL, void_type, 2, sum_params, 0);

+

+ /* Function */

+ gcc_jit_param *fill_param

+ = gcc_jit_context_new_param (ctxt, NULL, fill_ptr_type, "fill");

+ gcc_jit_rvalue *rv_fill = gcc_jit_param_as_rvalue (fill_param);

+ gcc_jit_param *sum_param

+ = gcc_jit_context_new_param (ctxt, NULL, sum_ptr_type, "sum");

+ gcc_jit_rvalue *rv_sum = gcc_jit_param_as_rvalue (sum_param);

+ gcc_jit_param *sum_p_param

+ = gcc_jit_context_new_param (ctxt, NULL, int_ptr_type, "sum_p");

+ gcc_jit_rvalue *rv_sum_p = gcc_jit_param_as_rvalue (sum_p_param);

+ gcc_jit_param *params[] = { fill_param, sum_param, sum_p_param };

+ gcc_jit_function *test_aligned_alloca = gcc_jit_context_new_function (

+ ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, size_t_type,

+ "test_aligned_alloca", 3, params, 0);

+

+ /* Variables */

+ gcc_jit_lvalue *p = gcc_jit_function_new_local (test_aligned_alloca, NULL,

+ void_ptr_type, "p");

+ gcc_jit_rvalue *rv_p = gcc_jit_lvalue_as_rvalue (p);

+

+ /* Blocks */

+ gcc_jit_block *block

+ = gcc_jit_function_new_block (test_aligned_alloca, NULL);

+

+ /* p = __builtin_alloca_with_align (sizeof (int) * 100, 128); */

+ gcc_jit_rvalue *sizeof_int = gcc_jit_context_new_sizeof (ctxt, int_type);

+ gcc_jit_rvalue *c100

+ = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 100);

+ gcc_jit_rvalue *size = gcc_jit_context_new_binary_op (

+ ctxt, NULL, GCC_JIT_BINARY_OP_MULT, size_t_type, sizeof_int, c100);

+ gcc_jit_rvalue *c128x8

+ = gcc_jit_context_new_rvalue_from_long (ctxt, size_t_type, 128 * 8);

+ gcc_jit_function *alloca_with_align = gcc_jit_context_get_builtin_function (

+ ctxt, "__builtin_alloca_with_align");

+ gcc_jit_rvalue *args[] = { size, c128x8 };

+ gcc_jit_rvalue *alloca_with_align_call

+ = gcc_jit_context_new_call (ctxt, NULL, alloca_with_align, 2, args);

+ gcc_jit_block_add_assignment (block, NULL, p, alloca_with_align_call);

+

+ /* fill (p); */

+ gcc_jit_rvalue *call_fill

+ = gcc_jit_context_new_call_through_ptr (ctxt, NULL, rv_fill, 1, &rv_p);

+ gcc_jit_block_add_eval (block, NULL, call_fill);

+

+ /* sum (p, sum_p); */

+ gcc_jit_rvalue *sum_args[] = { rv_p, rv_sum_p };

+ gcc_jit_rvalue *call_sum

+ = gcc_jit_context_new_call_through_ptr (ctxt, NULL, rv_sum, 2, sum_args);

+ gcc_jit_block_add_eval (block, NULL, call_sum);

+

+ /* return (size_t)p; */

+ gcc_jit_rvalue *cast_p

+ = gcc_jit_context_new_bitcast (ctxt, NULL, rv_p, size_t_type);

+ gcc_jit_block_end_with_return (block, NULL, cast_p);

+}

+

+void

+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)

+{

+ typedef size_t (*fn_type) (typeof (fill) *, typeof (sum) *, int *);

+ CHECK_NON_NULL (result);

+ fn_type test_aligned_alloca

+ = (fn_type)gcc_jit_result_get_code (result, "test_aligned_alloca");

+ CHECK_NON_NULL (test_aligned_alloca);

+ int value;

+ size_t addr = test_aligned_alloca (fill, sum, &value);

+ CHECK_VALUE (addr % 128, 0);

+ CHECK_VALUE (value, 4950);

+}

diff --git a/gcc/testsuite/jit.dg/test-stack-save-restore.c 
b/gcc/testsuite/jit.dg/test-stack-save-restore.c

new file mode 100644

index 00000000000..e3119749c47

--- /dev/null

+++ b/gcc/testsuite/jit.dg/test-stack-save-restore.c

@@ -0,0 +1,114 @@

+#include <stddef.h>

+#include <stdio.h>

+#include <stdlib.h>

+

+#include "libgccjit.h"

+

+#include "harness.h"

+

+void

+create_code (gcc_jit_context *ctxt, void *user_data)

+{

+ /*

+ size_t test_stack_save_restore() {

+ void *p;

+ size_t a, b;

+ p = __builtin_stack_save();

+ a = (size_t)__builtin_alloca(1024);

+ __builtin_stack_restore(p);

+

+ p = __builtin_stack_save();

+ b = (size_t)__builtin_alloca(512);

+ __builtin_stack_restore(p);

+

+ return b - a;

+ }

+ */

+

+ /* Types */

+ gcc_jit_type *size_t_type

+ = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_SIZE_T);

+ gcc_jit_type *void_ptr_type

+ = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR);

+

+ /* Function */

+ gcc_jit_function *test_stack_save_restore = gcc_jit_context_new_function (

+ ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, size_t_type,

+ "test_stack_save_restore", 0, NULL, 0);

+

+ /* Variables */

+ gcc_jit_lvalue *p = gcc_jit_function_new_local (test_stack_save_restore,

+ NULL, void_ptr_type, "p");

+ gcc_jit_lvalue *a = gcc_jit_function_new_local (test_stack_save_restore,

+ NULL, size_t_type, "a");

+ gcc_jit_lvalue *b = gcc_jit_function_new_local (test_stack_save_restore,

+ NULL, size_t_type, "b");

+ gcc_jit_rvalue *rv_p = gcc_jit_lvalue_as_rvalue (p);

+ gcc_jit_rvalue *rv_a = gcc_jit_lvalue_as_rvalue (a);

+ gcc_jit_rvalue *rv_b = gcc_jit_lvalue_as_rvalue (b);

+

+ /* Blocks */

+ gcc_jit_block *block

+ = gcc_jit_function_new_block (test_stack_save_restore, NULL);

+

+ /* Builtin functions */

+ gcc_jit_function *stack_save

+ = gcc_jit_context_get_builtin_function (ctxt, "__builtin_stack_save");

+ gcc_jit_function *stack_restore

+ = gcc_jit_context_get_builtin_function (ctxt, "__builtin_stack_restore");

+ gcc_jit_function *alloca

+ = gcc_jit_context_get_builtin_function (ctxt, "__builtin_alloca");

+

+ /* Common code */

+ gcc_jit_rvalue *call_stack_save

+ = gcc_jit_context_new_call (ctxt, NULL, stack_save, 0, NULL);

+ gcc_jit_rvalue *call_stack_restore

+ = gcc_jit_context_new_call (ctxt, NULL, stack_restore, 1, &rv_p);

+

+ /* p = __builtin_stack_save(); */

+ gcc_jit_block_add_assignment (block, NULL, p, call_stack_save);

+

+ /* a = (size_t)__builtin_alloca(1024); */

+ gcc_jit_rvalue *c1024

+ = gcc_jit_context_new_rvalue_from_int (ctxt, size_t_type, 1024);

+ gcc_jit_rvalue *call_alloca_1024

+ = gcc_jit_context_new_call (ctxt, NULL, alloca, 1, &c1024);

+ gcc_jit_rvalue *cast_alloca_1024 = gcc_jit_context_new_bitcast (

+ ctxt, NULL, call_alloca_1024, size_t_type);

+ gcc_jit_block_add_assignment (block, NULL, a, cast_alloca_1024);

+

+ /* __builtin_stack_restore(p); */

+ gcc_jit_block_add_eval (block, NULL, call_stack_restore);

+

+ /* p = __builtin_stack_save(); */

+ gcc_jit_block_add_assignment (block, NULL, p, call_stack_save);

+

+ /* b = (size_t)__builtin_alloca(512); */

+ gcc_jit_rvalue *c512

+ = gcc_jit_context_new_rvalue_from_int (ctxt, size_t_type, 512);

+ gcc_jit_rvalue *call_alloca_512

+ = gcc_jit_context_new_call (ctxt, NULL, alloca, 1, &c512);

+ gcc_jit_rvalue *cast_alloca_512

+ = gcc_jit_context_new_bitcast (ctxt, NULL, call_alloca_512, size_t_type);

+ gcc_jit_block_add_assignment (block, NULL, b, cast_alloca_512);

+

+ /* __builtin_stack_restore(p); */

+ gcc_jit_block_add_eval (block, NULL, call_stack_restore);

+

+ /* return b - a; */

+ gcc_jit_rvalue *sub = gcc_jit_context_new_binary_op (

+ ctxt, NULL, GCC_JIT_BINARY_OP_MINUS, size_t_type, rv_b, rv_a);

+ gcc_jit_block_end_with_return (block, NULL, sub);

+}

+

+void

+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)

+{

+ typedef size_t (*fn_type) (void);

+ CHECK_NON_NULL (result);

+ fn_type test_stack_save_restore

+ = (fn_type)gcc_jit_result_get_code (result, "test_stack_save_restore");

+ CHECK_NON_NULL (test_stack_save_restore);

+ size_t value = test_stack_save_restore ();

+ CHECK_VALUE (value, 512 - 1024);

+}

-- 
2.43.0

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to