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
create_code(gcc_jit_context * ctxt,void * user_data)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
internally_called_function(int i,int j,int k)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
verify_code(gcc_jit_context * ctxt,gcc_jit_result * result)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 }
163