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, ¶m_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