Message ID | 20241110213805.107824-1-i@zhuyi.fan |
---|---|
State | New |
Headers | show |
Series | [v3,GCCJIT] support dynamic alloca stub | expand |
Hi and thanks for the patch. I would rather avoid having to hard-code the types of built-in functions, especially since we can already access them via the function gcc_jit_context_get_target_builtin_function that is available in this patch: https://gcc.gnu.org/pipermail/jit/2023q4/001725.html I'll soon address the review in this patch and we'll hopefully have it merged soon. Le 2024-11-10 à 16 h 40, Schrodinger ZHU Yifan a écrit : > 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`. > > This is the third roll of the patch: > > - Fix wrong test cases mistakenly introduced in V2. > - Undo the removal of `gcc_assert` inside get_attrs_tree for non-stub builtin > functions. > > gcc/jit/ChangeLog: > > * jit-builtins.cc (builtins_manager::make_builtin_function): Add stub type handling. > (builtins_manager::make_type_for_stub): Add stub type handling. > (builtins_manager::get_type_for_stub): Add stub type handling. > (builtins_manager::get_attrs_tree): Add stub attribute hand > ling. > (builtins_manager::get_attrs_tree_for_stub): Add stub attribute handling. > * jit-builtins.h: Add new functions for stubs. > * jit-playback.cc (postprocess): Always set supercontext. > > 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 | 68 +++++++++- > 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(+), 2 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..5f61775beb7 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 (bui > ltin_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,10 +709,26 @@ 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: > + retu > rn 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) > 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 e3 > 2e837f2fe..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..358adba708a > --- /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_ca > ll (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..4e6ca5391ae > --- /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_all > oca_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); > +}
diff --git a/gcc/jit/jit-builtins.cc b/gcc/jit/jit-builtins.cc index 0c13c8db586..5f61775beb7 100644 --- a/gcc/jit/jit-builtins.cc 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 e3 2e837f2fe..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..358adba708a --- /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_ca ll (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..4e6ca5391ae --- /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_all oca_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");