(root)/
gcc-13.2.0/
gcc/
testsuite/
jit.dg/
test-returning-function-ptr.c
       1  #include <stdlib.h>
       2  #include <stdio.h>
       3  
       4  #include "libgccjit.h"
       5  
       6  #include "harness.h"
       7  
       8  #ifdef __cplusplus
       9  extern "C" {
      10  #endif
      11  
      12    extern void
      13    internally_called_function (int i, int j, int k);
      14  
      15  #ifdef __cplusplus
      16  }
      17  #endif
      18  
      19  void
      20  create_code (gcc_jit_context *ctxt, void *user_data)
      21  {
      22    /* Let's try to inject the equivalent of:
      23       extern void internally_called_function (int i, int j, int k);
      24  
      25       static void
      26       internal_test_caller (int a)
      27       {
      28          internally_called_function (a * 3, a * 4, a * 5);
      29       }
      30  
      31       typedef void (*fn_ptr_type) (int);
      32  
      33       fn_ptr_type
      34       get_test_caller (void)
      35       {
      36         // Verify that we can assign function pointers to variables
      37         fn_ptr_type p;
      38         p = internal_test_caller;
      39         return p;
      40       }
      41    */
      42    int i;
      43    gcc_jit_type *void_type =
      44      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
      45    gcc_jit_type *int_type =
      46      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
      47  
      48    /* Declare the imported function.  */
      49    gcc_jit_param *params[3];
      50    params[0] =
      51      gcc_jit_context_new_param (ctxt, NULL, int_type, "i");
      52    params[1] =
      53      gcc_jit_context_new_param (ctxt, NULL, int_type, "j");
      54    params[2] =
      55      gcc_jit_context_new_param (ctxt, NULL, int_type, "k");
      56    gcc_jit_function *called_fn =
      57      gcc_jit_context_new_function (ctxt, NULL,
      58  				  GCC_JIT_FUNCTION_IMPORTED,
      59  				  void_type,
      60  				  "internally_called_function",
      61  				  3, params,
      62  				  0);
      63  
      64    /* Build the test_caller fn.  */
      65    gcc_jit_param *param_a =
      66      gcc_jit_context_new_param (ctxt, NULL, int_type, "a");
      67    gcc_jit_function *test_caller =
      68      gcc_jit_context_new_function (ctxt, NULL,
      69  				  GCC_JIT_FUNCTION_EXPORTED,
      70  				  void_type,
      71  				  "internal_test_caller",
      72  				  1, &param_a,
      73  				  0);
      74    /* "a * 3, a * 4, a * 5"  */
      75    gcc_jit_rvalue *args[3];
      76    for (i = 0; i < 3; i++)
      77      args[i]
      78        = gcc_jit_context_new_binary_op
      79  	  (ctxt, NULL,
      80  	   GCC_JIT_BINARY_OP_MULT,
      81  	   int_type,
      82  	   gcc_jit_param_as_rvalue (param_a),
      83  	   gcc_jit_context_new_rvalue_from_int (ctxt,
      84  						int_type,
      85  						(i + 3) ));
      86    gcc_jit_block *block = gcc_jit_function_new_block (test_caller, NULL);
      87    gcc_jit_block_add_eval (
      88      block, NULL,
      89      gcc_jit_context_new_call (ctxt,
      90  			      NULL,
      91  			      called_fn,
      92  			      3, args));
      93    gcc_jit_block_end_with_void_return (block, NULL);
      94  
      95    gcc_jit_type *fn_ptr_type
      96      = gcc_jit_context_new_function_ptr_type (ctxt, NULL,
      97  					     void_type,
      98  					     1, &int_type,
      99  					     0);
     100  
     101    /* Build the get_test_caller fn.  */
     102    gcc_jit_function *get_test_caller =
     103      gcc_jit_context_new_function (ctxt, NULL,
     104  				  GCC_JIT_FUNCTION_EXPORTED,
     105  				  fn_ptr_type,
     106  				  "get_test_caller",
     107  				  0, NULL,
     108  				  0);
     109    block = gcc_jit_function_new_block (get_test_caller, NULL);
     110  
     111    /* fn_ptr_type p; */
     112    gcc_jit_lvalue *local_p
     113      = gcc_jit_function_new_local (get_test_caller, NULL,
     114  				  fn_ptr_type, "p");
     115  
     116    /* p = internal_test_caller; */
     117    gcc_jit_block_add_assignment (block, NULL,
     118  				local_p,
     119  				gcc_jit_function_get_address (test_caller,
     120  							      NULL));
     121  
     122    /* return p; */
     123    gcc_jit_block_end_with_return (block, NULL,
     124  				 gcc_jit_lvalue_as_rvalue (local_p));
     125  }
     126  
     127  static int called_with[3];
     128  
     129  extern void
     130  internally_called_function (int i, int j, int k)
     131  {
     132    called_with[0] = i;
     133    called_with[1] = j;
     134    called_with[2] = k;
     135  }
     136  
     137  void
     138  verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
     139  {
     140    typedef void (*test_caller_type) (int);
     141    typedef test_caller_type (*get_test_caller_type) (void);
     142    CHECK_NON_NULL (result);
     143  
     144    get_test_caller_type get_test_caller =
     145      (get_test_caller_type)gcc_jit_result_get_code (result, "get_test_caller");
     146    CHECK_NON_NULL (get_test_caller);
     147  
     148    test_caller_type test_caller = (test_caller_type)get_test_caller ();
     149    CHECK_NON_NULL (test_caller);
     150  
     151    called_with[0] = 0;
     152    called_with[1] = 0;
     153    called_with[2] = 0;
     154  
     155    /* Call the JIT-generated function.  */
     156    test_caller (5);
     157  
     158    /* Verify that it correctly called "internally_called_function".  */
     159    CHECK_VALUE (called_with[0], 15);
     160    CHECK_VALUE (called_with[1], 20);
     161    CHECK_VALUE (called_with[2], 25);
     162  }