jit: handle equality of function pointer types
[official-gcc.git] / gcc / testsuite / jit.dg / test-fuzzer.c
blob6943d3ed232d6b1d9e7466e8e49deb8a31c9eb1e
1 /* Fuzz-testing of libgccjit API.
2 Currently this triggers internal compiler errors, typically due to type
3 mismatches. */
4 #include <limits.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <assert.h>
9 #include "libgccjit.h"
11 #define TEST_PROVIDES_MAIN
12 #include "harness.h"
14 typedef struct fuzzer
16 gcc_jit_context *ctxt;
18 unsigned int seed;
20 int num_types;
21 gcc_jit_type **types;
23 int num_globals;
24 gcc_jit_lvalue **globals;
26 int num_funcs;
27 gcc_jit_function **funcs;
29 } fuzzer;
31 static void
32 fuzzer_init (fuzzer *f, gcc_jit_context *ctxt, unsigned int seed);
34 static int
35 fuzzer_randrange (fuzzer *f, int min, int max);
37 static gcc_jit_location *
38 get_random_location (fuzzer *f);
40 static gcc_jit_type *
41 get_random_type (fuzzer *f);
43 static gcc_jit_type *
44 make_random_type (fuzzer *f);
46 static gcc_jit_lvalue *
47 make_random_global (fuzzer *f);
49 static gcc_jit_function *
50 make_random_function (fuzzer *f);
52 typedef struct function_fuzzer
54 fuzzer *f;
56 int num_params;
57 gcc_jit_param **params;
59 gcc_jit_function *fn;
61 int num_locals;
62 gcc_jit_lvalue **locals;
64 gcc_jit_block *block;
66 } function_fuzzer;
68 static void
69 function_fuzzer_add_stmt (function_fuzzer *ff);
71 static gcc_jit_lvalue *
72 get_random_lvalue (function_fuzzer *ff, int max_depth);
74 static gcc_jit_rvalue *
75 get_random_rvalue (function_fuzzer *ff, int max_depth);
77 /* fuzzer defns. */
79 static void
80 fuzzer_init (fuzzer *f, gcc_jit_context *ctxt, unsigned int seed)
82 int i;
83 memset (f, 0, sizeof (*f));
84 f->ctxt = ctxt;
85 f->seed = seed;
87 int num_types = fuzzer_randrange (f, 5, 10);
88 f->types = malloc (num_types * sizeof (gcc_jit_type *));
90 int num_funcs = fuzzer_randrange (f, 3, 5);
91 f->funcs = malloc (num_funcs * sizeof (gcc_jit_function *));
93 int num_globals = fuzzer_randrange (f, 5, 10);
94 f->globals = malloc (num_globals * sizeof (gcc_jit_lvalue *));
96 for (i = 0; i < num_types; i++)
98 gcc_jit_type *type = make_random_type (f);
99 assert (type);
100 f->types[f->num_types++] = type;
103 for (i = 0; i < num_globals; i++)
104 f->globals[f->num_globals++] = make_random_global (f);
106 for (i = 0; i < num_funcs; i++)
107 f->funcs[f->num_funcs++] = make_random_function (f);
109 /* Now clean out f. */
110 free (f->types);
111 free (f->funcs);
112 free (f->globals);
115 /* Get random int in inclusive range [min, max]. */
117 static int fuzzer_randrange (fuzzer *f, int min, int max)
119 assert (min <= max);
120 int i = rand_r (&f->seed);
121 int result = (i % (max + 1 - min)) + min;
122 assert (result >= min);
123 assert (result <= max);
124 return result;
127 static gcc_jit_location *
128 get_random_location (fuzzer *f)
130 const char *filename = NULL;
132 if (fuzzer_randrange (f, 0, 1))
133 return NULL;
135 switch (fuzzer_randrange (f, 1, 2))
137 case 1:
138 filename = "foo.c";
139 break;
140 case 2:
141 filename = "bar.c";
142 break;
145 return gcc_jit_context_new_location (f->ctxt,
146 filename,
147 fuzzer_randrange (f, 1, 1000),
148 fuzzer_randrange (f, 1, 1000));
151 const enum gcc_jit_types types[] = {
152 GCC_JIT_TYPE_VOID,
154 GCC_JIT_TYPE_VOID_PTR,
156 GCC_JIT_TYPE_CHAR,
157 GCC_JIT_TYPE_SIGNED_CHAR,
158 GCC_JIT_TYPE_UNSIGNED_CHAR,
160 GCC_JIT_TYPE_SHORT,
161 GCC_JIT_TYPE_UNSIGNED_SHORT,
163 GCC_JIT_TYPE_INT,
164 GCC_JIT_TYPE_UNSIGNED_INT,
166 GCC_JIT_TYPE_LONG,
167 GCC_JIT_TYPE_UNSIGNED_LONG,
169 GCC_JIT_TYPE_LONG_LONG,
170 GCC_JIT_TYPE_UNSIGNED_LONG_LONG,
172 GCC_JIT_TYPE_FLOAT,
173 GCC_JIT_TYPE_DOUBLE,
174 GCC_JIT_TYPE_LONG_DOUBLE,
176 GCC_JIT_TYPE_CONST_CHAR_PTR,
178 GCC_JIT_TYPE_SIZE_T,
180 GCC_JIT_TYPE_FILE_PTR
182 #define NUM_TYPES (sizeof(types)/sizeof(types[0]))
184 static gcc_jit_type *
185 get_random_type (fuzzer *f)
187 int i = fuzzer_randrange (f, 0, (NUM_TYPES - 1) + f->num_types);
188 if (i < NUM_TYPES)
189 return gcc_jit_context_get_type (f->ctxt, types[i]);
190 assert ((i - NUM_TYPES) < f->num_types);
191 assert (f->types[i - NUM_TYPES]);
192 return f->types[i - NUM_TYPES];
195 static gcc_jit_type *
196 make_random_type (fuzzer *f)
198 switch (fuzzer_randrange (f, 0, 5))
200 case 0:
201 return gcc_jit_type_get_pointer (get_random_type (f));
202 case 1:
203 return gcc_jit_type_get_const (get_random_type (f));
204 default:
206 /* Create a struct. */
207 int num_fields = fuzzer_randrange (f, 0, 10);
208 gcc_jit_field **fields = \
209 malloc (num_fields * sizeof (gcc_jit_field *));
210 int i;
211 for (i = 0; i < num_fields ; i++)
213 char field_name[256];
214 sprintf (field_name, "field%i", i);
215 fields[i] = gcc_jit_context_new_field (f->ctxt,
216 get_random_location (f),
217 get_random_type (f),
218 field_name);
220 char struct_name[256];
221 sprintf (struct_name, "s%i", f->num_types);
222 gcc_jit_struct *struct_ = \
223 gcc_jit_context_new_struct_type (f->ctxt,
224 get_random_location (f),
225 struct_name,
226 num_fields,
227 fields);
228 free (fields);
229 return gcc_jit_struct_as_type (struct_);
234 static gcc_jit_lvalue *
235 make_random_global (fuzzer *f)
237 char global_name[256];
238 sprintf (global_name, "g%i", f->num_globals);
239 return gcc_jit_context_new_global (f->ctxt,
240 get_random_location (f),
241 GCC_JIT_GLOBAL_EXPORTED,
242 get_random_type (f),
243 global_name);
246 static gcc_jit_function *
247 make_random_function (fuzzer *f)
249 char func_name[256];
250 sprintf (func_name, "fn%i", f->num_funcs);
252 function_fuzzer *ff = malloc (sizeof (function_fuzzer));
253 memset (ff, 0, sizeof (*ff));
255 ff->f = f;
257 ff->num_params = fuzzer_randrange (f, 0, 10);
258 ff->params = malloc (ff->num_params * sizeof (gcc_jit_param *));
259 int i;
260 for (i = 0; i < ff->num_params; i++)
262 char param_name[256];
263 sprintf (param_name, "param%i", i);
264 ff->params[i] = \
265 gcc_jit_context_new_param (f->ctxt,
266 get_random_location (f),
267 get_random_type (f),
268 param_name);
271 enum gcc_jit_function_kind kind =
272 ((enum gcc_jit_function_kind)
273 fuzzer_randrange (f, 0, GCC_JIT_FUNCTION_IMPORTED));
275 ff->fn = \
276 gcc_jit_context_new_function (
277 f->ctxt,
278 get_random_location (f),
279 kind,
280 get_random_type (f),
281 func_name,
282 ff->num_params,
283 ff->params,
284 fuzzer_randrange (f, 0, 1));
285 ff->block = gcc_jit_function_new_block (ff->fn, NULL);
287 /* Create locals. */
288 if (kind != GCC_JIT_FUNCTION_IMPORTED)
290 ff->num_locals = fuzzer_randrange (f, 0, 10);
291 ff->locals = malloc (ff->num_locals * sizeof (gcc_jit_lvalue *));
292 for (i = 0; i < ff->num_locals; i++)
294 char local_name[256];
295 sprintf (local_name, "local%i", i);
296 ff->locals[i] =
297 gcc_jit_function_new_local (ff->fn,
298 get_random_location (f),
299 get_random_type (f),
300 local_name);
303 /* TODO: use locals. */
305 if (kind != GCC_JIT_FUNCTION_IMPORTED)
307 /* TODO: create body */
308 int num_stmts = fuzzer_randrange (f, 0, 10);
309 for (i = 0; i < num_stmts; i++)
310 function_fuzzer_add_stmt (ff);
313 gcc_jit_block_end_with_return (ff->block, NULL, get_random_rvalue (ff, 3));
316 gcc_jit_function *result = ff->fn;
318 free (ff->locals);
319 free (ff->params);
320 free (ff);
322 return result;
325 /* function_fuzzer defns. */
327 static void function_fuzzer_add_stmt (function_fuzzer *ff)
329 gcc_jit_block_add_eval (ff->block,
330 get_random_location (ff->f),
331 get_random_rvalue (ff, 4));
332 gcc_jit_block_add_assignment (ff->block,
333 get_random_location (ff->f),
334 get_random_lvalue (ff, 4),
335 get_random_rvalue (ff, 4));
336 /* TODO: place more kinds of statement */
337 /* TODO: labels */
340 static gcc_jit_lvalue *get_random_lvalue (function_fuzzer *ff, int max_depth)
342 int choice = fuzzer_randrange (ff->f, 0,
343 ff->num_params
344 + ff->num_locals
345 + ff->f->num_globals - 1);
346 if (choice < ff->num_params)
347 return gcc_jit_param_as_lvalue (ff->params[choice]);
348 choice -= ff->num_params;
350 if (choice < ff->num_locals)
351 return ff->locals[choice];
352 choice -= ff->num_locals;
354 assert (choice < ff->f->num_globals);
355 return ff->f->globals[choice];
358 static gcc_jit_rvalue *get_random_rvalue (function_fuzzer *ff, int max_depth)
360 int use_lvalue = fuzzer_randrange (ff->f, 0, 1);
361 if (use_lvalue)
362 return gcc_jit_lvalue_as_rvalue (get_random_lvalue (ff, max_depth));
364 int choice = fuzzer_randrange (ff->f, 0, 1);
366 /* Compound op: */
367 switch (choice)
369 case 0:
370 return gcc_jit_context_new_string_literal (ff->f->ctxt, "hello");
371 case 1:
372 return gcc_jit_context_new_rvalue_from_int (
373 ff->f->ctxt,
374 get_random_type (ff->f),
375 fuzzer_randrange (ff->f, 0, INT_MAX));
376 case 2:
377 return gcc_jit_context_new_rvalue_from_double (
378 ff->f->ctxt,
379 get_random_type (ff->f),
380 ((double)fuzzer_randrange (ff->f, 0, INT_MAX))
381 / (double)fuzzer_randrange (ff->f, 0, INT_MAX));
382 case 3:
383 return gcc_jit_context_new_unary_op (
384 ff->f->ctxt,
385 get_random_location (ff->f),
386 ((enum gcc_jit_unary_op)
387 fuzzer_randrange (ff->f, 0, GCC_JIT_UNARY_OP_LOGICAL_NEGATE)),
388 get_random_type (ff->f),
389 get_random_rvalue (ff, max_depth - 1));
390 case 4:
391 return gcc_jit_context_new_binary_op (
392 ff->f->ctxt,
393 get_random_location (ff->f),
394 ((enum gcc_jit_binary_op)
395 fuzzer_randrange (ff->f, 0, GCC_JIT_BINARY_OP_LOGICAL_OR)),
396 get_random_type (ff->f),
397 get_random_rvalue (ff, max_depth - 1),
398 get_random_rvalue (ff, max_depth - 1));
399 case 5:
400 return gcc_jit_lvalue_get_address (
401 get_random_lvalue (ff, max_depth - 1),
402 get_random_location (ff->f));
404 /* TODO:
405 - comparisons
406 - calls
407 - array lookup
408 - fields
409 - dereferencing */
411 return NULL;
415 /* Top-level defns for use by harness. */
416 void
417 create_code (gcc_jit_context *ctxt, void *user_data)
419 fuzzer f;
420 int seed = *(int*)user_data;
422 fuzzer_init (&f, ctxt, seed);
425 static int num_completed_compilations = 0;
427 void
428 verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
430 /* We can make no guarantees about whether we built something
431 valid or not, and the result might have an infinite loop,
432 so we can't execute it.
434 If we survive to reach here, note the fact for DejaGnu. */
435 pass ("%s: survived compilation", test);
436 if (result)
437 num_completed_compilations++;
440 static void
441 test_fuzzer (const char *argv0, int seed)
443 test_jit (argv0, &seed);
447 main (int argc, char **argv)
449 int i, seed;
450 const int NUM_ITERATIONS = 2;
451 const int NUM_SEEDS = 100;
452 for (i = 1; i <= NUM_ITERATIONS; i++)
454 for (seed = 0; seed < NUM_SEEDS ; seed++)
456 snprintf (test, sizeof (test),
457 "%s iteration %d of %d; seed %d of %d",
458 extract_progname (argv[0]),
459 i, NUM_ITERATIONS, seed, NUM_SEEDS);
460 test_fuzzer (argv[0], seed);
463 pass ("%s: survived running all tests", extract_progname (argv[0]));
464 note ("%s: num completed compilations: %d", extract_progname (argv[0]),
465 num_completed_compilations);
466 totals ();
468 return 0;