* [PATCH 1/2] jit: structs/unions: bring the C++ API more on par with C @ 2022-01-31 16:34 Marc Nieper-Wisskirchen 2022-01-31 16:34 ` [PATCH 2/2] jit: function pointers: " Marc Nieper-Wisskirchen 0 siblings, 1 reply; 2+ messages in thread From: Marc Nieper-Wisskirchen @ 2022-01-31 16:34 UTC (permalink / raw) To: gcc-patches, jit; +Cc: Marc Nieper-Wisskirchen This patch adds yet missing C++ API entry points to create union types and to set the fields of structs previously defined as opaque. A missing convenience method returning NULL pointer values is also added and used in one of the two provided tests. gcc/jit/ChangeLog: * docs/cp/topics/expressions.rst: Update doc. * docs/cp/topics/types.rst: Update doc. * libgccjit++.h (context::new_union_type): New method. (context::null): New method. (type::null): New method. (struct_::set_fields): New method. gcc/testsuite/ChangeLog: * jit.dg/test-accessing-union.cc: New test. * jit.dg/test-linked-list.cc: New test. --- gcc/jit/docs/cp/topics/expressions.rst | 10 ++ gcc/jit/docs/cp/topics/types.rst | 27 +++- gcc/jit/libgccjit++.h | 61 ++++++++- gcc/testsuite/jit.dg/test-accessing-union.cc | 86 +++++++++++++ gcc/testsuite/jit.dg/test-linked-list.cc | 128 +++++++++++++++++++ 5 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-accessing-union.cc create mode 100644 gcc/testsuite/jit.dg/test-linked-list.cc diff --git a/gcc/jit/docs/cp/topics/expressions.rst b/gcc/jit/docs/cp/topics/expressions.rst index 239e004371e..3e9534790a3 100644 --- a/gcc/jit/docs/cp/topics/expressions.rst +++ b/gcc/jit/docs/cp/topics/expressions.rst @@ -86,6 +86,16 @@ Simple expressions ctxt.new_rvalue (numeric_type, 1) +.. function:: gccjit::rvalue \ + gccjit::context::null (gccjit::type pointer_type) const + + Given a pointer type, get the rvalue for the null pointer. + Essentially this is just a shortcut for: + + .. code-block:: c++ + + ctxt.new_rvalue (pointer_type, (void *) 0) + .. function:: gccjit::rvalue \ gccjit::context::new_rvalue (gccjit::type numeric_type, \ double value) const diff --git a/gcc/jit/docs/cp/topics/types.rst b/gcc/jit/docs/cp/topics/types.rst index c695ceb3098..f41f504da6a 100644 --- a/gcc/jit/docs/cp/topics/types.rst +++ b/gcc/jit/docs/cp/topics/types.rst @@ -179,8 +179,6 @@ You can model C `struct` types by creating :class:`gccjit::struct_` and fields.push_back (field_next); node.set_fields (fields); -.. FIXME: the above API doesn't seem to exist yet - .. function:: gccjit::field \ gccjit::context::new_field (gccjit::type type,\ const char *name, \ @@ -196,10 +194,25 @@ You can model C `struct` types by creating :class:`gccjit::struct_` and Construct a new struct type, with the given name and fields. .. function:: gccjit::struct_ \ - gccjit::context::new_opaque_struct (const std::string &name, \ - gccjit::location loc) + gccjit::context::new_opaque_struct (const std::string &name, \ + gccjit::location loc) Construct a new struct type, with the given name, but without - specifying the fields. The fields can be omitted (in which case the - size of the struct is not known), or later specified using - :c:func:`gcc_jit_struct_set_fields`. + specifying the fields. The fields can be omitted (in which case + the size of the struct is not known), or later specified using + :func:`set_fields`. + +.. function:: void \ + gccjit::struct_::set_fields (std::vector <field> &fields, \ + gccjit::location loc) + + Populate the fields of a formerly-opaque struct type. + + This can only be called once on a given struct type. + +.. function:: gccjit::type \ + gccjit::context::new_union_type (const std::string &name, \ + std::vector<field> &fields,\ + gccjit::location loc) + + Construct a new union type, with the given name and fields. diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 4b88e877bc9..17b10bc55c3 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -165,6 +165,10 @@ namespace gccjit struct_ new_opaque_struct_type (const std::string &name, location loc = location ()); + type new_union_type (const std::string &name, + std::vector <field> &fields, + location loc = location ()); + param new_param (type type_, const std::string &name, location loc = location ()); @@ -189,6 +193,7 @@ namespace gccjit long value) const; rvalue zero (type numeric_type) const; rvalue one (type numeric_type) const; + rvalue null (type pointer_type) const; rvalue new_rvalue (type numeric_type, double value) const; rvalue new_rvalue (type pointer_type, @@ -361,9 +366,10 @@ namespace gccjit type get_aligned (size_t alignment_in_bytes); type get_vector (size_t num_units); - // Shortcuts for getting values of numeric types: + // Shortcuts for getting values of numeric and pointer types: rvalue zero (); rvalue one (); + rvalue null (); }; class struct_ : public type @@ -373,6 +379,9 @@ namespace gccjit struct_ (gcc_jit_struct *inner); gcc_jit_struct *get_inner_struct () const; + + void set_fields (std::vector <field> &fields, + location loc = location ()); }; class function : public object @@ -864,6 +873,26 @@ context::new_opaque_struct_type (const std::string &name, name.c_str ())); } +inline type +context::new_union_type (const std::string &name, + std::vector<field> &fields, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + field *as_array_of_wrappers = &fields[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_field **as_array_of_ptrs = + reinterpret_cast<gcc_jit_field **> (as_array_of_wrappers); + + return type (gcc_jit_context_new_union_type (m_inner_ctxt, + loc.get_inner_location (), + name.c_str (), + fields.size (), + as_array_of_ptrs)); +} + inline param context::new_param (type type_, const std::string &name, @@ -955,6 +984,13 @@ context::one (type numeric_type) const numeric_type.get_inner_type ())); } +inline rvalue +context::null (type pointer_type) const +{ + return rvalue (gcc_jit_context_null (m_inner_ctxt, + pointer_type.get_inner_type ())); +} + inline rvalue context::new_rvalue (type numeric_type, double value) const @@ -1442,6 +1478,12 @@ type::one () return get_context ().new_rvalue (*this, 1); } +inline rvalue +type::null () +{ + return get_context ().null (*this); +} + // class struct_ inline struct_::struct_ () : type (NULL) {} inline struct_::struct_ (gcc_jit_struct *inner) : @@ -1456,6 +1498,23 @@ struct_::get_inner_struct () const return reinterpret_cast<gcc_jit_struct *> (get_inner_object ()); } +inline void +struct_::set_fields (std::vector <field> &fields, location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + field *as_array_of_wrappers = &fields[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_field **as_array_of_ptrs = + reinterpret_cast<gcc_jit_field **> (as_array_of_wrappers); + + gcc_jit_struct_set_fields (get_inner_struct (), + loc.get_inner_location (), + fields.size (), + as_array_of_ptrs); +} + // class function inline function::function () : object () {} inline function::function (gcc_jit_function *inner) diff --git a/gcc/testsuite/jit.dg/test-accessing-union.cc b/gcc/testsuite/jit.dg/test-accessing-union.cc new file mode 100644 index 00000000000..8fa03fd209c --- /dev/null +++ b/gcc/testsuite/jit.dg/test-accessing-union.cc @@ -0,0 +1,86 @@ +#include <cstdlib> +#include <cstdio> +#include <vector> + +#include "libgccjit++.h" + +#include "harness.h" + +union int_or_float +{ + int as_int; + float as_float; +}; + +void +create_code (gcc_jit_context* c_ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + float + test_union (int i) + { + union int_or_float u; + u.as_int = i; + return u.as_float; + } + */ + gccjit::context ctxt (c_ctxt); + gccjit::type int_type = + ctxt.get_type (GCC_JIT_TYPE_INT); + gccjit::type float_type = + ctxt.get_type (GCC_JIT_TYPE_FLOAT); + gccjit::field as_int = + ctxt.new_field (int_type, "as_int"); + gccjit::field as_float = + ctxt.new_field (float_type, "as_float"); + std::vector <gccjit::field> fields; + fields.push_back (as_int); + fields.push_back (as_float); + gccjit::type union_type = + ctxt.new_union_type ("int_or_float", fields); + + /* Build the test function. */ + gccjit::param param_i = + ctxt.new_param (int_type, "i"); + std::vector <gccjit::param> params; + params.push_back (param_i); + gccjit::function test_fn = + ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, + float_type, + "test_union", + params, + 0); + + gccjit::lvalue u = + test_fn.new_local (union_type, "u"); + + gccjit::block block = test_fn.new_block (); + + /* u.as_int = i; */ + block.add_assignment ( + /* "u.as_int = ..." */ + u.access_field (as_int), + param_i); + + /* return u.as_float; */ + block.end_with_return (u.access_field (as_float)); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef float (*fn_type) (int i); + CHECK_NON_NULL (result); + + fn_type test_union = + (fn_type)gcc_jit_result_get_code (result, "test_union"); + CHECK_NON_NULL (test_union); + + /* Call the JIT-generated function. */ + float f_result = test_union (42); + + union int_or_float u; + u.as_float = f_result; + + CHECK_VALUE (u.as_int, 42); +} diff --git a/gcc/testsuite/jit.dg/test-linked-list.cc b/gcc/testsuite/jit.dg/test-linked-list.cc new file mode 100644 index 00000000000..933ab706b00 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-linked-list.cc @@ -0,0 +1,128 @@ +#include <cstdlib> +#include <cstdio> +#include <vector> + +#include "libgccjit++.h" + +#include "harness.h" + +/* A doubly-linked list, to ensure that the JIT API can cope with + self-referential types. */ +struct node +{ + struct node *prev; + struct node *next; + int value; +}; + +void +create_code (gcc_jit_context *c_ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + int + test_linked_list (struct node *n) + { + int total = 0; + while (n) + { + total += n->value; + n = n->next; + } + return total; + } + */ + gccjit::context ctxt (c_ctxt); + gccjit::type t_int = + ctxt.get_type (GCC_JIT_TYPE_INT); + gccjit::struct_ t_node = + ctxt.new_opaque_struct_type ("node"); + gccjit::type t_node_ptr = + t_node.get_pointer (); + + gccjit::field f_prev = + ctxt.new_field (t_node_ptr, "prev"); + gccjit::field f_next = + ctxt.new_field (t_node_ptr, "next"); + gccjit::field f_value = + ctxt.new_field (t_int, "value"); + std::vector <gccjit::field> fields; + fields.push_back (f_prev); + fields.push_back (f_next); + fields.push_back (f_value); + t_node.set_fields (fields); + + /* Build the test function. */ + gccjit::param param_n = + ctxt.new_param (t_node_ptr, "n"); + std::vector <gccjit::param> params; + params.push_back (param_n); + gccjit::function fn = + ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, + t_int, + "test_linked_list", + params, + 0); + /* int total; */ + gccjit::lvalue total = + fn.new_local (t_int, "total"); + + gccjit::block initial = fn.new_block ("initial"); + gccjit::block loop_test = fn.new_block ("loop_test"); + gccjit::block loop_body = fn.new_block ("loop_body"); + gccjit::block final = fn.new_block ("final"); + + /* total = 0; */ + initial.add_assignment ( + total, + ctxt.zero (t_int)); + initial.end_with_jump (loop_test); + + /* while (n) */ + loop_test.end_with_conditional (param_n != t_node_ptr.null (), + loop_body, + final); + + /* total += n->value; */ + loop_body.add_assignment_op (total, + GCC_JIT_BINARY_OP_PLUS, + param_n.dereference_field (f_value)); + + /* n = n->next; */ + loop_body.add_assignment (param_n, + param_n.dereference_field (f_next)); + + loop_body.end_with_jump (loop_test); + + /* return total; */ + final.end_with_return (total); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + struct node a, b, c; + typedef int (*fn_type) (struct node *n); + CHECK_NON_NULL (result); + + fn_type test_linked_list = + (fn_type)gcc_jit_result_get_code (result, "test_linked_list"); + CHECK_NON_NULL (test_linked_list); + + /* Construct a simple linked-list on the stack: a->b->c: */ + a.prev = NULL; + a.next = &b; + a.value = 5; + + b.prev = &a; + b.next = &c; + b.value = 3; + + c.prev = &b; + c.next = NULL; + c.value = 7; + + CHECK_VALUE (test_linked_list (NULL), 0); + CHECK_VALUE (test_linked_list (&a), 15); + CHECK_VALUE (test_linked_list (&b), 10); + CHECK_VALUE (test_linked_list (&c), 7); +} -- 2.32.0 ^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH 2/2] jit: function pointers: bring the C++ API more on par with C 2022-01-31 16:34 [PATCH 1/2] jit: structs/unions: bring the C++ API more on par with C Marc Nieper-Wisskirchen @ 2022-01-31 16:34 ` Marc Nieper-Wisskirchen 0 siblings, 0 replies; 2+ messages in thread From: Marc Nieper-Wisskirchen @ 2022-01-31 16:34 UTC (permalink / raw) To: gcc-patches, jit; +Cc: Marc Nieper-Wisskirchen This patch adds yet missing support for creating function pointer types and to call functions through functions pointers in the C++ API of libgccjit. The method gccjit::context::new_call is overloaded so that it accepts an rvalue instead of a function argument. Instead of creating ad-hoc specializations for 0 to 6 arguments, another overload taking an initializer list instead of a vector is added. gcc/jit/ChangeLog: * docs/cp/topics/expressions.rst: Updated. * docs/cp/topics/types.rst: Updated. * libgccjit++.h (context::new_function_ptr_type): New method. (context::new_call): New method overloads. gcc/testsuite/ChangeLog: * jit.dg/test-calling-function-ptr.cc: New test. --- gcc/jit/docs/cp/topics/expressions.rst | 34 +++++-- gcc/jit/docs/cp/topics/types.rst | 16 ++++ gcc/jit/libgccjit++.h | 70 ++++++++++++++ .../jit.dg/test-calling-function-ptr.cc | 93 +++++++++++++++++++ 4 files changed, 204 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-calling-function-ptr.cc diff --git a/gcc/jit/docs/cp/topics/expressions.rst b/gcc/jit/docs/cp/topics/expressions.rst index 3e9534790a3..d6c8f0de156 100644 --- a/gcc/jit/docs/cp/topics/expressions.rst +++ b/gcc/jit/docs/cp/topics/expressions.rst @@ -119,8 +119,8 @@ Vector expressions ****************** .. function:: gccjit::rvalue \ - gccjit::context::new_rvalue (gccjit::type vector_type, \ - std::vector<gccjit::rvalue> elements) const + gccjit::context::new_rvalue (gccjit::type vector_type, \ + std::vector<gccjit::rvalue> elements) const Given a vector type, and a vector of scalar rvalue elements, generate a vector rvalue. @@ -454,13 +454,13 @@ The most concise way to spell them is with overloaded operators: Function calls ************** -.. function:: gcc_jit_rvalue *\ - gcc_jit_context_new_call (gcc_jit_context *ctxt,\ - gcc_jit_location *loc,\ - gcc_jit_function *func,\ - int numargs , gcc_jit_rvalue **args) - Given a function and the given table of argument rvalues, construct a +.. function:: gccjit::rvalue \ + gccjit::context::new_call (gccjit::function func, \ + std::vector <gccjit::rvalue> &args, \ + gccjit::location loc) + + Given a function and the given vector of argument rvalues, construct a call to the function, with the result as an rvalue. .. note:: @@ -480,11 +480,27 @@ Function calls /* Add "(void)printf (arg0, arg1);". */ block.add_eval (ctxt.new_call (printf_func, arg0, arg1)); +.. function:: gccjit::rvalue \ + gccjit::context::new_call (gccjit::rvalue fn_ptr, \ + std::vector <gccjit::rvalue> &args, \ + gccjit::location loc) + + Given a function and the given vector of argument rvalues, construct a + call to the function, with the result as an rvalue. + +.. function:: gccjit::rvalue \ + gccjit::context::new_call (gccjit::rvalue fn_ptr, \ + std::initializer_list <gccjit::rvalue> args, \ + gccjit::location loc) + + Given a function and the given list of argument rvalues, construct a + call to the function, with the result as an rvalue. + Function pointers ***************** .. function:: gccjit::rvalue \ - gccjit::function::get_address (gccjit::location loc) + gccjit::function::get_address (gccjit::location loc) Get the address of a function as an rvalue, of function pointer type. diff --git a/gcc/jit/docs/cp/topics/types.rst b/gcc/jit/docs/cp/topics/types.rst index f41f504da6a..8c677d74834 100644 --- a/gcc/jit/docs/cp/topics/types.rst +++ b/gcc/jit/docs/cp/topics/types.rst @@ -216,3 +216,19 @@ You can model C `struct` types by creating :class:`gccjit::struct_` and gccjit::location loc) Construct a new union type, with the given name and fields. + + +Function pointer types +---------------------- + +.. function:: gccjit::type \ + gccjit::context::new_function_ptr_type (gccjit::type return_type, \ + std::vector <type> ¶m_types, \ + int is_variadic, \ + gccjit::location loc) + + Generate a :class:`type` for a function pointer with the given + return type and parameters. + + Each of `param_types` must be non-`void`; `return_type` may be + `void`. diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index 17b10bc55c3..fa06c9cc4e1 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -169,6 +169,11 @@ namespace gccjit std::vector <field> &fields, location loc = location ()); + type new_function_ptr_type (type return_type, + std::vector <type> ¶m_types, + int is_variadic, + location loc = location ()); + param new_param (type type_, const std::string &name, location loc = location ()); @@ -324,6 +329,11 @@ namespace gccjit rvalue arg3, rvalue arg4, rvalue arg5, location loc = location ()); + rvalue new_call (rvalue fn_ptr, std::vector <rvalue> &args, + location loc = location ()); + rvalue new_call (rvalue fn_ptr, std::initializer_list <rvalue> args, + location loc = location ()); + rvalue new_cast (rvalue expr, type type_, location loc = location ()); @@ -893,6 +903,29 @@ context::new_union_type (const std::string &name, as_array_of_ptrs)); } +inline type +context::new_function_ptr_type (type return_type, + std::vector <type> ¶m_types, + int is_variadic, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + type *as_array_of_wrappers = ¶m_types[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_type **as_array_of_ptrs = + reinterpret_cast<gcc_jit_type **> (as_array_of_wrappers); + + return type + (gcc_jit_context_new_function_ptr_type (m_inner_ctxt, + loc.get_inner_location (), + return_type.get_inner_type (), + param_types.size (), + as_array_of_ptrs, + is_variadic)); +} + inline param context::new_param (type type_, const std::string &name, @@ -1241,6 +1274,7 @@ context::new_call (function func, args.size (), as_array_of_ptrs); } + inline rvalue context::new_call (function func, location loc) @@ -1322,6 +1356,42 @@ context::new_call (function func, return new_call (func, args, loc); } +inline rvalue +context::new_call (rvalue fn_ptr, std::vector <rvalue> &args, + location loc) +{ + /* Treat std::vector as an array, relying on it not being resized: */ + rvalue *as_array_of_wrappers = &args[0]; + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_rvalue **as_array_of_ptrs = + reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers); + return gcc_jit_context_new_call_through_ptr (m_inner_ctxt, + loc.get_inner_location (), + fn_ptr.get_inner_rvalue (), + args.size (), + as_array_of_ptrs); +} + +inline rvalue +context::new_call (rvalue fn_ptr, std::initializer_list <rvalue> args, + location loc) +{ + /* We rely on the underlying C API not modifying the values. */ + rvalue *as_array_of_wrappers = const_cast <rvalue *> (args.begin ()); + + /* Treat the array as being of the underlying pointers, relying on + the wrapper type being such a pointer internally. */ + gcc_jit_rvalue **as_array_of_ptrs = + reinterpret_cast<gcc_jit_rvalue **> (as_array_of_wrappers); + return gcc_jit_context_new_call_through_ptr (m_inner_ctxt, + loc.get_inner_location (), + fn_ptr.get_inner_rvalue (), + args.size (), + as_array_of_ptrs); +} + inline rvalue context::new_cast (rvalue expr, type type_, diff --git a/gcc/testsuite/jit.dg/test-calling-function-ptr.cc b/gcc/testsuite/jit.dg/test-calling-function-ptr.cc new file mode 100644 index 00000000000..f83b08b8869 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-calling-function-ptr.cc @@ -0,0 +1,93 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit++.h" + +#include "harness.h" + +void +create_code (gcc_jit_context *c_ctxt, void *user_data) +{ + /* Let's try to inject the equivalent of: + + void + test_calling_function_ptr (void (*fn_ptr) (int, int, int) fn_ptr, + int a) + { + fn_ptr (a * 3, a * 4, a * 5); + } + */ + + gccjit::context ctxt (c_ctxt); + + int i; + gccjit::type void_type = + ctxt.get_type (GCC_JIT_TYPE_VOID); + gccjit::type int_type = + ctxt.get_type (GCC_JIT_TYPE_INT); + + /* Build the function ptr type. */ + std::vector param_types { + int_type, + int_type, + int_type + }; + gccjit::type fn_ptr_type = + ctxt.new_function_ptr_type (void_type, param_types, 0); + + /* Build the test_fn. */ + gccjit::param param_fn_ptr = + ctxt.new_param (fn_ptr_type, "fn_ptr"); + gccjit::param param_a = + ctxt.new_param (int_type, "a"); + + std::vector params {param_fn_ptr, param_a}; + gccjit::function test_fn = + ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED, + void_type, + "test_calling_function_ptr", + params, + 0); + /* "a * 3, a * 4, a * 5" */ + gccjit::rvalue args[3]; + for (i = 0; i < 3; i++) + args[i] = param_a * ctxt.new_rvalue (int_type, i + 3); + gccjit::block block = test_fn.new_block (); + block.add_eval (ctxt.new_call (param_fn_ptr, + {args[0], args[1], args[2]})); + block.end_with_return (); +} + +static int called_through_ptr_with[3]; + +static void +function_called_through_fn_ptr (int i, int j, int k) +{ + called_through_ptr_with[0] = i; + called_through_ptr_with[1] = j; + called_through_ptr_with[2] = k; +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + typedef void (*fn_type) (void (*fn_ptr) (int, int, int), + int); + CHECK_NON_NULL (result); + + fn_type test_caller = + (fn_type)gcc_jit_result_get_code (result, "test_calling_function_ptr"); + CHECK_NON_NULL (test_caller); + + called_through_ptr_with[0] = 0; + called_through_ptr_with[1] = 0; + called_through_ptr_with[2] = 0; + + /* Call the JIT-generated function. */ + test_caller (function_called_through_fn_ptr, 5); + + /* Verify that it correctly called "function_called_through_fn_ptr". */ + CHECK_VALUE (called_through_ptr_with[0], 15); + CHECK_VALUE (called_through_ptr_with[1], 20); + CHECK_VALUE (called_through_ptr_with[2], 25); +} -- 2.32.0 ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-01-31 16:35 UTC | newest] Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-01-31 16:34 [PATCH 1/2] jit: structs/unions: bring the C++ API more on par with C Marc Nieper-Wisskirchen 2022-01-31 16:34 ` [PATCH 2/2] jit: function pointers: " Marc Nieper-Wisskirchen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).