void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: void hello_world (const char *name) { // a test comment printf ("hello from %s\n", name); } */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR); gcc_jit_param *param_name = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name"); gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "hello_world", 1, ¶m_name, 0); gcc_jit_param *param_format = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format"); gcc_jit_function *printf_func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, gcc_jit_context_get_type ( ctxt, GCC_JIT_TYPE_INT), "printf", 1, ¶m_format, 1); gcc_jit_rvalue *args[2]; args[0] = gcc_jit_context_new_string_literal (ctxt, "hello from %s\n"); args[1] = gcc_jit_param_as_rvalue (param_name); gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); gcc_jit_block_add_comment ( block, NULL, "a test comment"); gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call (ctxt, NULL, printf_func, 2, args)); gcc_jit_block_end_with_void_return (block, NULL); }
static void create_test_of_builtin_strcmp (gcc_jit_context *ctxt) { /* Let's try to inject the equivalent of: int test_of_builtin_strcmp (const char *a, const char *b) { return __builtin_strcmp (a, b); } */ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR); /* Get the built-in function. */ gcc_jit_function *builtin_fn = gcc_jit_context_get_builtin_function (ctxt, "strcmp"); CHECK_STRING_VALUE ( gcc_jit_object_get_debug_string (gcc_jit_function_as_object (builtin_fn)), "strcmp"); /* Build the test_fn. */ gcc_jit_param *param_a = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "a"); gcc_jit_param *param_b = gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "b"); gcc_jit_param *params[2] = {param_a, param_b}; gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, int_type, "test_of_builtin_strcmp", 2, params, 0); gcc_jit_rvalue *args[2] = {gcc_jit_param_as_rvalue (param_a), gcc_jit_param_as_rvalue (param_b)}; gcc_jit_rvalue *call = gcc_jit_context_new_call (ctxt, NULL, builtin_fn, 2, args); CHECK_STRING_VALUE ( gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (call)), "strcmp (a, b)"); gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial"); gcc_jit_block_end_with_return (initial, NULL, call); }
void create_code (gcc_jit_context *ctxt) { /* Let's try to inject the equivalent of: int square (int i) { return i * i; } */ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_param *param_i = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, int_type, "square", 1, ¶m_i, 0); gcc_jit_block *block = gcc_jit_function_new_block (func, NULL); gcc_jit_rvalue *expr = gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, int_type, gcc_jit_param_as_rvalue (param_i), gcc_jit_param_as_rvalue (param_i)); gcc_jit_block_end_with_return (block, NULL, expr); }
void create_code (gcc_jit_context *ctxt, void *user_data) { gcc_jit_type *t_int = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *return_type = t_int; gcc_jit_param *x = gcc_jit_context_new_param (ctxt, NULL, t_int, "x"); gcc_jit_param *params[1] = {x}; gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, return_type, "test_switch", 1, params, 0); gcc_jit_block *b_initial = gcc_jit_function_new_block (func, "initial"); gcc_jit_block *b_default = gcc_jit_function_new_block (func, "default"); /* Erroneous NULL case. */ gcc_jit_case *cases[1] = { NULL }; gcc_jit_block_end_with_switch ( b_initial, NULL, gcc_jit_param_as_rvalue (x), b_default, 1, cases); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Verify that we get an error (rather than a crash) if the client code reuses a gcc_jit_param * within a function. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Create a param. */ gcc_jit_param *param = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); /* Try to use it twice when creating "fn". */ gcc_jit_param *params[2]; params[0] = param; params[1] = param; gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, void_type, "fn", 2, params, 0); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Verify that we get an error (rather than a crash) if the client code reuses a gcc_jit_param * for two different functions. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Create a param. */ gcc_jit_param *param = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); /* Try to use it for two different functions. */ gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "fn_one", 1, ¶m, 0); gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "fn_two", 1, ¶m, 0); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: struct foo; extern void called_function (struct foo *ptr); void test_fn () { struct foo f; called_function (f); } and verify that we get a type error (foo * vs foo). */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_struct *struct_foo = gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 0, NULL); gcc_jit_type *foo_ptr = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_foo)); gcc_jit_param *param = gcc_jit_context_new_param (ctxt, NULL, foo_ptr, "ptr"); gcc_jit_function *called_function = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, void_type, "called_function", 1, ¶m, 0); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_fn", 0, NULL, 0); gcc_jit_lvalue *f = gcc_jit_function_new_local ( test_fn, NULL, gcc_jit_struct_as_type (struct_foo), "f"); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (f); gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call ( ctxt, NULL, called_function, 1, &arg)); gcc_jit_block_end_with_void_return (block, NULL); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: void fn_one (int i) { } int fn_two () { return i * 2; } and verify that the API complains about the use of the param from the other function. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_param *param = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "fn_one", 1, ¶m, 0); gcc_jit_function *fn_two = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, int_type, "fn_two", 0, NULL, 0); gcc_jit_block *block = gcc_jit_function_new_block (fn_two, NULL); /* "return i * 2;", using param i from the wrong function. */ gcc_jit_block_end_with_return ( block, NULL, gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, int_type, gcc_jit_param_as_rvalue (param), gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 2))); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: void test_fn (void (*some_fn_ptr) (void *)) { some_fn_ptr (42); } and verify that the API complains about the mismatching argument type ("int" vs "void *"). */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *void_ptr_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID_PTR); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Build the function ptr type. */ gcc_jit_type *fn_ptr_type = gcc_jit_context_new_function_ptr_type (ctxt, NULL, void_type, 1, &void_ptr_type, 0); /* Build the test_fn. */ gcc_jit_param *param_fn_ptr = gcc_jit_context_new_param (ctxt, NULL, fn_ptr_type, "some_fn_ptr"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_fn", 1, ¶m_fn_ptr, 0); /* some_fn_ptr (42); */ gcc_jit_rvalue *arg = gcc_jit_context_new_rvalue_from_int (ctxt, int_type, 42); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call_through_ptr ( ctxt, NULL, gcc_jit_param_as_rvalue (param_fn_ptr), 1, &arg)); /* the above has the wrong type for argument 1. */ gcc_jit_block_end_with_void_return (block, NULL); }
static void make_sqrt (struct top_level *top_level) { gcc_jit_param *param_x = gcc_jit_context_new_param (top_level->ctxt, NULL, top_level->numeric_type, "x"); top_level->sqrt = gcc_jit_context_new_function (top_level->ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, top_level->numeric_type, "sqrt", 1, ¶m_x, 0); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: extern void called_function (int p); void test_caller () { called_function (); // missing arg } and verify that the API complains about the missing argument. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Declare the imported function. */ gcc_jit_param *param_p = gcc_jit_context_new_param (ctxt, NULL, int_type, "p"); gcc_jit_function *called_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, void_type, "called_function", 1, ¶m_p, 0); /* Build the test_fn. */ gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_caller", 0, NULL, 0); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); /* called_function (); */ gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call (ctxt, NULL, called_fn, 0, NULL)); /* the above has the wrong arg count. */ gcc_jit_block_end_with_void_return (block, NULL); }
static void create_use_of_void_return (gcc_jit_context *ctxt) { /* Let's try to inject the equivalent of: void test_of_void_return (int *out) { *out = 1; return; } */ gcc_jit_type *void_t = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_t = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *int_ptr_t = gcc_jit_type_get_pointer (int_t); /* Build the test_fn. */ gcc_jit_param *param_out = gcc_jit_context_new_param (ctxt, NULL, int_ptr_t, "out"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_t, "test_of_void_return", 1, ¶m_out, 0); gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial"); gcc_jit_block_add_assignment ( initial, NULL, /* "*out = ..." */ gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (param_out), NULL), gcc_jit_context_one (ctxt, int_t)); gcc_jit_block_end_with_void_return (initial, NULL); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: void int test_bogus_dereference_read (int i) { return *i; } i.e. where i is *not* a pointer. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Build the test function. */ gcc_jit_param *param_i = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_bogus_dereference_read", 1, ¶m_i, 0); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); /* Erroneous: "return *i;" */ gcc_jit_block_end_with_return ( block, NULL, gcc_jit_lvalue_as_rvalue ( gcc_jit_rvalue_dereference ( gcc_jit_param_as_rvalue (param_i), NULL))); }
static void create_test_of_builtin_trig (gcc_jit_context *ctxt) { /* Let's try to inject the equivalent of: int test_of_builtin_trig (double theta) { return 2 * sin (theta) * cos (theta); } (in theory, optimizable to sin (2 * theta)) */ gcc_jit_context_enable_dump (ctxt, "tree-sincos", &trig_sincos_dump); gcc_jit_context_enable_dump (ctxt, "statistics", &trig_statistics_dump); gcc_jit_type *double_t = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); /* Get the built-in functions. */ gcc_jit_function *builtin_sin = gcc_jit_context_get_builtin_function (ctxt, "sin"); gcc_jit_function *builtin_cos = gcc_jit_context_get_builtin_function (ctxt, "cos"); /* Build the test_fn. */ gcc_jit_param *param_theta = gcc_jit_context_new_param (ctxt, NULL, double_t, "theta"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, double_t, "test_of_builtin_trig", 1, ¶m_theta, 0); gcc_jit_rvalue *args[1] = {gcc_jit_param_as_rvalue (param_theta)}; gcc_jit_rvalue *two = gcc_jit_context_new_rvalue_from_int (ctxt, double_t, 2); gcc_jit_rvalue *ret = gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, double_t, two, gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, double_t, gcc_jit_context_new_call (ctxt, NULL, builtin_sin, 1, args), gcc_jit_context_new_call (ctxt, NULL, builtin_cos, 1, args))); CHECK_STRING_VALUE ( gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (ret)), "(double)2 * sin (theta) * cos (theta)"); gcc_jit_block *initial = gcc_jit_function_new_block (test_fn, "initial"); gcc_jit_block_end_with_return (initial, NULL, ret); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: void test_bogus_access (struct foo f) { f.x = f.p; } i.e. using the wrong struct for the RHS. */ gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Map "struct foo". */ gcc_jit_field *x = gcc_jit_context_new_field (ctxt, NULL, int_type, "x"); gcc_jit_field *y = gcc_jit_context_new_field (ctxt, NULL, int_type, "y"); gcc_jit_field *foo_fields[] = {x, y}; gcc_jit_struct *struct_foo = gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, foo_fields); /* Map "struct bar". */ gcc_jit_field *p = gcc_jit_context_new_field (ctxt, NULL, int_type, "p"); gcc_jit_field *q = gcc_jit_context_new_field (ctxt, NULL, int_type, "q"); /* We don't actually need a gcc_jit_type for "struct bar" for the test. */ gcc_jit_field *bar_fields[] = {p, q}; (void)gcc_jit_context_new_struct_type (ctxt, NULL, "foo", 2, bar_fields); /* Build the test function. */ gcc_jit_param *param_f = gcc_jit_context_new_param (ctxt, NULL, gcc_jit_struct_as_type (struct_foo), "f"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_bogus_access", 1, ¶m_f, 0); /* OK: f.x = ... */ gcc_jit_lvalue *lvalue = gcc_jit_lvalue_access_field ( gcc_jit_param_as_lvalue (param_f), NULL, x); /* Erroneous: ... = f.p; */ gcc_jit_rvalue *rvalue = gcc_jit_rvalue_access_field ( gcc_jit_param_as_rvalue (param_f), NULL, p); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); gcc_jit_block_add_assignment ( block, NULL, lvalue, rvalue); gcc_jit_block_end_with_void_return (block, NULL); }
static toyvm_compiled_function * toyvm_function_compile (toyvm_function *fn) { compilation_state state; int pc; char *funcname; memset (&state, 0, sizeof (state)); funcname = get_function_name (fn->fn_filename); state.ctxt = gcc_jit_context_acquire (); gcc_jit_context_set_bool_option (state.ctxt, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 0); gcc_jit_context_set_bool_option (state.ctxt, GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 0); gcc_jit_context_set_int_option (state.ctxt, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3); gcc_jit_context_set_bool_option (state.ctxt, GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 0); gcc_jit_context_set_bool_option (state.ctxt, GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 0); gcc_jit_context_set_bool_option (state.ctxt, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); /* Create types. */ state.int_type = gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_INT); state.bool_type = gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_BOOL); state.stack_type = gcc_jit_context_new_array_type (state.ctxt, NULL, state.int_type, MAX_STACK_DEPTH); /* The constant value 1. */ state.const_one = gcc_jit_context_one (state.ctxt, state.int_type); /* Create locations. */ for (pc = 0; pc < fn->fn_num_ops; pc++) { toyvm_op *op = &fn->fn_ops[pc]; state.op_locs[pc] = gcc_jit_context_new_location (state.ctxt, fn->fn_filename, op->op_linenum, 0); /* column */ } /* Creating the function. */ state.param_arg = gcc_jit_context_new_param (state.ctxt, state.op_locs[0], state.int_type, "arg"); state.fn = gcc_jit_context_new_function (state.ctxt, state.op_locs[0], GCC_JIT_FUNCTION_EXPORTED, state.int_type, funcname, 1, &state.param_arg, 0); /* Create stack lvalues. */ state.stack = gcc_jit_function_new_local (state.fn, NULL, state.stack_type, "stack"); state.stack_depth = gcc_jit_function_new_local (state.fn, NULL, state.int_type, "stack_depth"); state.x = gcc_jit_function_new_local (state.fn, NULL, state.int_type, "x"); state.y = gcc_jit_function_new_local (state.fn, NULL, state.int_type, "y"); /* 1st pass: create blocks, one per opcode. */ /* We need an entry block to do one-time initialization, so create that first. */ state.initial_block = gcc_jit_function_new_block (state.fn, "initial"); /* Create a block per operation. */ for (pc = 0; pc < fn->fn_num_ops; pc++) { char buf[16]; sprintf (buf, "instr%i", pc); state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf); } /* Populate the initial block. */ /* "stack_depth = 0;". */ gcc_jit_block_add_assignment ( state.initial_block, state.op_locs[0], state.stack_depth, gcc_jit_context_zero (state.ctxt, state.int_type)); /* "PUSH (arg);". */ add_push (&state, state.initial_block, gcc_jit_param_as_rvalue (state.param_arg), state.op_locs[0]); /* ...and jump to insn 0. */ gcc_jit_block_end_with_jump (state.initial_block, state.op_locs[0], state.op_blocks[0]); /* 2nd pass: fill in instructions. */ for (pc = 0; pc < fn->fn_num_ops; pc++) { gcc_jit_location *loc = state.op_locs[pc]; gcc_jit_block *block = state.op_blocks[pc]; gcc_jit_block *next_block = (pc < fn->fn_num_ops ? state.op_blocks[pc + 1] : NULL); toyvm_op *op; op = &fn->fn_ops[pc]; /* Helper macros. */ #define X_EQUALS_POP()\ add_pop (&state, block, state.x, loc) #define Y_EQUALS_POP()\ add_pop (&state, block, state.y, loc) #define PUSH_RVALUE(RVALUE)\ add_push (&state, block, (RVALUE), loc) #define PUSH_X()\ PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.x)) #define PUSH_Y() \ PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.y)) gcc_jit_block_add_comment (block, loc, opcode_names[op->op_opcode]); /* Handle the individual opcodes. */ switch (op->op_opcode) { case DUP: X_EQUALS_POP (); PUSH_X (); PUSH_X (); break; case ROT: Y_EQUALS_POP (); X_EQUALS_POP (); PUSH_Y (); PUSH_X (); break; case BINARY_ADD: Y_EQUALS_POP (); X_EQUALS_POP (); PUSH_RVALUE ( gcc_jit_context_new_binary_op ( state.ctxt, loc, GCC_JIT_BINARY_OP_PLUS, state.int_type, gcc_jit_lvalue_as_rvalue (state.x), gcc_jit_lvalue_as_rvalue (state.y))); break; case BINARY_SUBTRACT: Y_EQUALS_POP (); X_EQUALS_POP (); PUSH_RVALUE ( gcc_jit_context_new_binary_op ( state.ctxt, loc, GCC_JIT_BINARY_OP_MINUS, state.int_type, gcc_jit_lvalue_as_rvalue (state.x), gcc_jit_lvalue_as_rvalue (state.y))); break; case BINARY_MULT: Y_EQUALS_POP (); X_EQUALS_POP (); PUSH_RVALUE ( gcc_jit_context_new_binary_op ( state.ctxt, loc, GCC_JIT_BINARY_OP_MULT, state.int_type, gcc_jit_lvalue_as_rvalue (state.x), gcc_jit_lvalue_as_rvalue (state.y))); break; case BINARY_COMPARE_LT: Y_EQUALS_POP (); X_EQUALS_POP (); PUSH_RVALUE ( /* cast of bool to int */ gcc_jit_context_new_cast ( state.ctxt, loc, /* (x < y) as a bool */ gcc_jit_context_new_comparison ( state.ctxt, loc, GCC_JIT_COMPARISON_LT, gcc_jit_lvalue_as_rvalue (state.x), gcc_jit_lvalue_as_rvalue (state.y)), state.int_type)); break; case RECURSE: { X_EQUALS_POP (); gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (state.x); PUSH_RVALUE ( gcc_jit_context_new_call ( state.ctxt, loc, state.fn, 1, &arg)); break; } case RETURN: X_EQUALS_POP (); gcc_jit_block_end_with_return ( block, loc, gcc_jit_lvalue_as_rvalue (state.x)); break; /* Ops taking an operand. */ case PUSH_CONST: PUSH_RVALUE ( gcc_jit_context_new_rvalue_from_int ( state.ctxt, state.int_type, op->op_operand)); break; case JUMP_ABS_IF_TRUE: X_EQUALS_POP (); gcc_jit_block_end_with_conditional ( block, loc, /* "(bool)x". */ gcc_jit_context_new_cast ( state.ctxt, loc, gcc_jit_lvalue_as_rvalue (state.x), state.bool_type), state.op_blocks[op->op_operand], /* on_true */ next_block); /* on_false */ break; default: assert(0); } /* end of switch on opcode */ /* Go to the next block. */ if (op->op_opcode != JUMP_ABS_IF_TRUE && op->op_opcode != RETURN) gcc_jit_block_end_with_jump ( block, loc, next_block); } /* end of loop on PC locations. */ /* We've now finished populating the context. Compile it. */ gcc_jit_result *jit_result = gcc_jit_context_compile (state.ctxt); gcc_jit_context_release (state.ctxt); toyvm_compiled_function *toyvm_result = (toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function)); if (!toyvm_result) { fprintf (stderr, "out of memory allocating toyvm_compiled_function\n"); gcc_jit_result_release (jit_result); return NULL; } toyvm_result->cf_jit_result = jit_result; toyvm_result->cf_code = (toyvm_compiled_code)gcc_jit_result_get_code (jit_result, funcname); free (funcname); return toyvm_result; }
static void create_overflow_fn (gcc_jit_context *ctxt, gcc_jit_type *type, const char *funcname, const char *builtin_name) { /* Create the equivalent of this C: int test_overflow_T_OP (T x, T y, int *ovf) { T result; result = x OP y; *ovf = ...; // did overflow happen? return result; } */ gcc_jit_type *t_bool = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL); gcc_jit_type *t_bool_star = gcc_jit_type_get_pointer (t_bool); gcc_jit_param *x = gcc_jit_context_new_param ( ctxt, NULL, type, "x"); gcc_jit_param *y = gcc_jit_context_new_param ( ctxt, NULL, type, "y"); gcc_jit_param *ovf = gcc_jit_context_new_param ( ctxt, NULL, t_bool_star, "ovf"); gcc_jit_param *params[3] = {x, y, ovf}; gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, type, funcname, 3, params, 0); gcc_jit_lvalue *result = gcc_jit_function_new_local (func, NULL, type, "result"); gcc_jit_block *b_initial = gcc_jit_function_new_block (func, "initial"); /* The builtins are listed in builtins.def as being variadic, but the have these signatures: bool __builtin_add_overflow (type1 a, type2 b, type3 *res); bool __builtin_sub_overflow (type1 a, type2 b, type3 *res); bool __builtin_mul_overflow (type1 a, type2 b, type3 *res); */ gcc_jit_function *builtin_fn = gcc_jit_context_get_builtin_function (ctxt, builtin_name); /* Construct a call of the form: (returns bool) __builtin_add_overflow (x, y, &result). */ gcc_jit_rvalue *args[3] = {gcc_jit_param_as_rvalue (x), gcc_jit_param_as_rvalue (y), gcc_jit_lvalue_get_address (result, NULL)}; gcc_jit_rvalue *call = gcc_jit_context_new_call (ctxt, NULL, builtin_fn, 3, args); /* "*ovf = BUILTIN_CALL ();" */ gcc_jit_block_add_assignment ( b_initial, NULL, gcc_jit_rvalue_dereference (gcc_jit_param_as_rvalue (ovf), NULL), call); /* "return result;" */ gcc_jit_block_end_with_return ( b_initial, NULL, gcc_jit_lvalue_as_rvalue (result)); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: extern void called_function (int i, int j, int k); void test_caller (int a) { called_function (a * 3, a * 4, a * 5); } */ int i; gcc_jit_type *void_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); /* Declare the imported function. */ gcc_jit_param *params[3]; params[0] = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); params[1] = gcc_jit_context_new_param (ctxt, NULL, int_type, "j"); params[2] = gcc_jit_context_new_param (ctxt, NULL, int_type, "k"); gcc_jit_function *called_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_IMPORTED, void_type, "called_function", 3, params, 0); /* Build the test_fn. */ gcc_jit_param *param_a = gcc_jit_context_new_param (ctxt, NULL, int_type, "a"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "test_caller", 1, ¶m_a, 0); /* "a * 3, a * 4, a * 5" */ gcc_jit_rvalue *args[3]; for (i = 0; i < 3; i++) args[i] = gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, int_type, gcc_jit_param_as_rvalue (param_a), gcc_jit_context_new_rvalue_from_int ( ctxt, int_type, (i + 3) )); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call (ctxt, NULL, called_fn, 3, args)); gcc_jit_block_end_with_void_return (block, NULL); }
static gcc_jit_function *generate_code_matchhere(gcc_jit_context *ctx, const char* regexp, const char* function_name) { gcc_jit_type *int_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT); gcc_jit_type *char_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR); gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR); gcc_jit_param *param_text = gcc_jit_context_new_param(ctx, /* loc */ NULL, const_char_ptr_type, "text"); gcc_jit_rvalue *rval_text = gcc_jit_param_as_rvalue(param_text); // matchhere gcc_jit_param* params[] = { param_text }; gcc_jit_function *matchhere = gcc_jit_context_new_function(ctx, /* loc */ NULL, GCC_JIT_FUNCTION_INTERNAL, int_type, function_name, 1, params, /* is_variadic */ 0); gcc_jit_block* current_block = gcc_jit_function_new_block(matchhere, new_block_name()); gcc_jit_rvalue* text_plus_one = gcc_jit_context_new_cast( ctx, /* loc */ NULL, gcc_jit_lvalue_get_address( gcc_jit_context_new_array_access( ctx, /* loc */ NULL, rval_text, gcc_jit_context_one(ctx, int_type)), /* loc */ NULL), const_char_ptr_type); gcc_jit_block* return_zero = NULL; gcc_jit_block* return_one = gcc_jit_function_new_block(matchhere, new_block_name()); gcc_jit_block_end_with_return( return_one, /* loc */ NULL, gcc_jit_context_one(ctx, int_type)); // Now go creating for (;;) { if (regexp[0] == '\0') { gcc_jit_block_end_with_jump( current_block, /* loc */ NULL, return_one); break; // We are done } else if (regexp[1] == '*') { // Generate code for the remaining regular expression gcc_jit_function *remaining_regexp_match = generate_code_matchhere(ctx, regexp + 2, new_function_name()); gcc_jit_block* loop_body = gcc_jit_function_new_block(matchhere, new_block_name()); gcc_jit_block* loop_check = gcc_jit_function_new_block(matchhere, new_block_name()); gcc_jit_block_end_with_jump(current_block, /* loc */ NULL, loop_body); gcc_jit_rvalue* args[] = { rval_text }; gcc_jit_rvalue* match_remainder = gcc_jit_context_new_comparison( ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, gcc_jit_context_new_call(ctx, /* loc */ NULL, remaining_regexp_match, 1, args), gcc_jit_context_zero(ctx, int_type)); gcc_jit_block_end_with_conditional(loop_body, /* loc */ NULL, match_remainder, return_one, loop_check); gcc_jit_lvalue* tmp = gcc_jit_function_new_local(matchhere, /* loc */ NULL, char_type, new_local_name()); gcc_jit_block_add_assignment( loop_check, /* loc */ NULL, tmp, gcc_jit_lvalue_as_rvalue( gcc_jit_rvalue_dereference(rval_text, /* loc */ NULL))); gcc_jit_rvalue* check_expr; if (regexp[0] == '.') { check_expr = gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, gcc_jit_lvalue_as_rvalue(tmp), gcc_jit_context_zero(ctx, char_type)); } else { check_expr = gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_EQ, gcc_jit_lvalue_as_rvalue(tmp), gcc_jit_context_new_rvalue_from_int(ctx, char_type, regexp[0])); } generate_return_zero(ctx, matchhere, &return_zero); gcc_jit_block_add_assignment(loop_check, /* loc */ NULL, gcc_jit_param_as_lvalue(param_text), text_plus_one); gcc_jit_block_end_with_conditional(loop_check, /* loc */ NULL, check_expr, loop_body, return_zero); break; // We are done } else if (regexp[0] == '$' && regexp[1] == '\0') { gcc_jit_block_end_with_return( current_block, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_EQ, gcc_jit_lvalue_as_rvalue( gcc_jit_rvalue_dereference(rval_text, /* loc */ NULL) ), gcc_jit_context_zero(ctx, char_type))); regexp++; } else if (regexp[0] == '.') { generate_return_zero(ctx, matchhere, &return_zero); gcc_jit_block* next_block = gcc_jit_function_new_block(matchhere, new_block_name()); // if (*text == '\0') // return 0; gcc_jit_block_end_with_conditional( current_block, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_EQ, gcc_jit_lvalue_as_rvalue( gcc_jit_rvalue_dereference(rval_text, /* loc */ NULL) ), gcc_jit_context_zero(ctx, char_type)), return_zero, next_block); // text = &text[1]; // pointer arithmetic gcc_jit_block_add_assignment(next_block, /* loc */ NULL, gcc_jit_param_as_lvalue(param_text), text_plus_one); // Chain the code current_block = next_block; // Done with the current letter regexp++; } else { generate_return_zero(ctx, matchhere, &return_zero); gcc_jit_block* next_block = gcc_jit_function_new_block(matchhere, new_block_name()); // if (*text != regexp[0]) // return 0; gcc_jit_block_end_with_conditional( current_block, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, gcc_jit_lvalue_as_rvalue( gcc_jit_rvalue_dereference(rval_text, /* loc */ NULL) ), gcc_jit_context_new_rvalue_from_int(ctx, char_type, regexp[0])), return_zero, next_block); // text = &text[1]; // pointer arithmetic gcc_jit_block_add_assignment(next_block, /* loc */ NULL, gcc_jit_param_as_lvalue(param_text), text_plus_one); // Chain the code current_block = next_block; // Done with the current letter regexp++; } } // char c[64]; // snprintf(c, 63, "%s.dot", function_name); // c[63] = '\0'; // gcc_jit_function_dump_to_dot(matchhere, c); return matchhere; }
void generate_code_regexp(gcc_jit_context *ctx, const char* regexp) { const char* matchhere_regexp = regexp; if (regexp[0] == '^') { matchhere_regexp++; } gcc_jit_function* matchhere = generate_code_matchhere(ctx, matchhere_regexp, "matchhere"); // match function gcc_jit_type *int_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT); gcc_jit_type *char_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR); gcc_jit_type *const_char_ptr_type = gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR); gcc_jit_param *param_text = gcc_jit_context_new_param(ctx, /* loc */ NULL, const_char_ptr_type, "text"); gcc_jit_param *param_regex = gcc_jit_context_new_param(ctx, /* loc */ NULL, const_char_ptr_type, "_regex"); gcc_jit_rvalue *rval_text = gcc_jit_param_as_rvalue(param_text); gcc_jit_param* params[] = { param_regex, param_text }; gcc_jit_function *match = gcc_jit_context_new_function(ctx, /* loc */ NULL, GCC_JIT_FUNCTION_EXPORTED, int_type, "match", 2, params, /* is_variadic */ 0); gcc_jit_rvalue* args[] = { rval_text }; gcc_jit_rvalue* call_to_matchhere = gcc_jit_context_new_call(ctx, /* loc */ NULL, matchhere, 1, args); if (regexp[0] == '^') { gcc_jit_block* block = gcc_jit_function_new_block(match, new_block_name()); gcc_jit_block_end_with_return( block, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, call_to_matchhere, gcc_jit_context_zero(ctx, int_type))); } else { gcc_jit_block* loop_body = gcc_jit_function_new_block(match, new_block_name()); gcc_jit_block* return_one = gcc_jit_function_new_block(match, new_block_name()); gcc_jit_block* condition_check = gcc_jit_function_new_block(match, new_block_name()); gcc_jit_block* return_zero = gcc_jit_function_new_block(match, new_block_name()); gcc_jit_block_end_with_conditional( loop_body, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, call_to_matchhere, gcc_jit_context_zero(ctx, int_type)), return_one, condition_check); gcc_jit_block_end_with_return( return_one, /* loc */ NULL, gcc_jit_context_one(ctx, int_type)); gcc_jit_lvalue* tmp = gcc_jit_function_new_local(match, /* loc */ NULL, char_type, new_local_name()); gcc_jit_block_add_assignment( condition_check, /* loc */ NULL, tmp, gcc_jit_lvalue_as_rvalue( gcc_jit_rvalue_dereference(rval_text, /* loc */ NULL))); gcc_jit_block_add_assignment( condition_check, /* loc */ NULL, gcc_jit_param_as_lvalue(param_text), gcc_jit_context_new_cast( ctx, /* loc */ NULL, gcc_jit_lvalue_get_address( gcc_jit_context_new_array_access( ctx, /* loc */ NULL, rval_text, gcc_jit_context_one(ctx, int_type)), /* loc */ NULL), const_char_ptr_type)); gcc_jit_block_end_with_conditional( condition_check, /* loc */ NULL, gcc_jit_context_new_comparison(ctx, /* loc */ NULL, GCC_JIT_COMPARISON_NE, gcc_jit_lvalue_as_rvalue(tmp), gcc_jit_context_zero(ctx, char_type)), loop_body, return_zero); gcc_jit_block_end_with_return( return_zero, /* loc */ NULL, gcc_jit_context_zero(ctx, int_type)); } // gcc_jit_function_dump_to_dot(match, "match.dot"); // gcc_jit_context_dump_to_file(ctx, "generated-regex.dump", /* update-locations */ 1); // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1); }
void create_code (gcc_jit_context *ctxt, void *user_data) { /* Let's try to inject the equivalent of: double test_nested_loops (int n, double *a, double *b) { double result = 0.; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) result += a[i] * b[j]; return result } */ gcc_jit_type *val_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); gcc_jit_type *ptr_type = gcc_jit_type_get_pointer (val_type); gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *return_type = val_type; gcc_jit_param *param_n = gcc_jit_context_new_param (ctxt, NULL, int_type, "n"); gcc_jit_param *param_a = gcc_jit_context_new_param (ctxt, NULL, ptr_type, "a"); gcc_jit_param *param_b = gcc_jit_context_new_param (ctxt, NULL, ptr_type, "b"); gcc_jit_param *params[3] = {param_n, param_a, param_b}; gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, return_type, "test_nested_loops", 3, params, 0); /* Create locals. */ gcc_jit_lvalue *result = gcc_jit_function_new_local (func, NULL, val_type, "result"); gcc_jit_lvalue *i = gcc_jit_function_new_local (func, NULL, int_type, "i"); gcc_jit_lvalue *j = gcc_jit_function_new_local (func, NULL, int_type, "j"); /* Create basic blocks. */ gcc_jit_block *b_entry = gcc_jit_function_new_block (func, "b_entry"); gcc_jit_block *b_outer_loop_cond = gcc_jit_function_new_block (func, "b_outer_loop_cond"); gcc_jit_block *b_outer_loop_head = gcc_jit_function_new_block (func, "b_outer_loop_head"); gcc_jit_block *b_outer_loop_tail = gcc_jit_function_new_block (func, "b_outer_loop_tail"); gcc_jit_block *b_inner_loop_cond = gcc_jit_function_new_block (func, "b_inner_loop_cond"); gcc_jit_block *b_inner_loop_body = gcc_jit_function_new_block (func, "b_inner_loop_body"); gcc_jit_block *b_exit = gcc_jit_function_new_block (func, "b_exit"); /* Populate b_entry. */ /* "result = 0.;" */ gcc_jit_block_add_assignment ( b_entry, NULL, result, gcc_jit_context_zero (ctxt, val_type)); /* "i = 0;" */ gcc_jit_block_add_assignment ( b_entry, NULL, i, gcc_jit_context_zero (ctxt, int_type)); gcc_jit_block_end_with_jump (b_entry, NULL, b_outer_loop_cond); /* Populate b_outer_loop_cond. */ gcc_jit_block_end_with_conditional ( b_outer_loop_cond, NULL, /* (i < n) */ gcc_jit_context_new_comparison ( ctxt, NULL, GCC_JIT_COMPARISON_LT, gcc_jit_lvalue_as_rvalue (i), gcc_jit_param_as_rvalue (param_n)), b_outer_loop_head, b_exit); /* Populate b_outer_loop_head. */ /* j = 0; */ gcc_jit_block_add_assignment ( b_outer_loop_head, NULL, j, gcc_jit_context_zero (ctxt, int_type)); gcc_jit_block_end_with_jump (b_outer_loop_head, NULL, b_inner_loop_cond); /* Populate b_inner_loop_cond. */ gcc_jit_block_end_with_conditional ( b_inner_loop_cond, NULL, /* (j < n) */ gcc_jit_context_new_comparison ( ctxt, NULL, GCC_JIT_COMPARISON_LT, gcc_jit_lvalue_as_rvalue (j), gcc_jit_param_as_rvalue (param_n)), b_inner_loop_body, b_outer_loop_tail); /* Populate b_inner_loop_body. */ /* "result += a[i] * b[j];" */ gcc_jit_block_add_assignment_op ( b_inner_loop_body, NULL, result, GCC_JIT_BINARY_OP_PLUS, gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, val_type, gcc_jit_lvalue_as_rvalue ( gcc_jit_context_new_array_access( ctxt, NULL, gcc_jit_param_as_rvalue (param_a), gcc_jit_lvalue_as_rvalue (i))), gcc_jit_lvalue_as_rvalue ( gcc_jit_context_new_array_access( ctxt, NULL, gcc_jit_param_as_rvalue (param_b), gcc_jit_lvalue_as_rvalue (j))))); /* "j++" */ gcc_jit_block_add_assignment_op ( b_inner_loop_body, NULL, j, GCC_JIT_BINARY_OP_PLUS, gcc_jit_context_one (ctxt, int_type)); gcc_jit_block_end_with_jump (b_inner_loop_body, NULL, b_inner_loop_cond); /* Populate b_outer_loop_tail. */ /* "i++" */ gcc_jit_block_add_assignment_op ( b_outer_loop_tail, NULL, i, GCC_JIT_BINARY_OP_PLUS, gcc_jit_context_one (ctxt, int_type)); gcc_jit_block_end_with_jump (b_outer_loop_tail, NULL, b_outer_loop_cond); /* Populate b_exit. */ /* "return result;" */ gcc_jit_block_end_with_return ( b_exit, NULL, gcc_jit_lvalue_as_rvalue (result)); }
static void make_test_quadratic (struct top_level *top_level, struct middle_level *middle_level, struct bottom_level *bottom_level) { gcc_jit_param *a = gcc_jit_context_new_param (bottom_level->ctxt, NULL, top_level->numeric_type, "a"); gcc_jit_param *b = gcc_jit_context_new_param (bottom_level->ctxt, NULL, top_level->numeric_type, "b"); gcc_jit_param *c = gcc_jit_context_new_param (bottom_level->ctxt, NULL, top_level->numeric_type, "c"); gcc_jit_param *r1 = gcc_jit_context_new_param (bottom_level->ctxt, NULL, top_level->numeric_type_ptr, "r1"); gcc_jit_param *r2 = gcc_jit_context_new_param (bottom_level->ctxt, NULL, top_level->numeric_type_ptr, "r2"); gcc_jit_param *params[] = {a, b, c, r1, r2}; gcc_jit_function *test_quadratic = gcc_jit_context_new_function (bottom_level->ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, top_level->int_type, "test_quadratic", 5, params, 0); /* struct quadratic q; */ gcc_jit_lvalue *q = gcc_jit_function_new_local ( test_quadratic, NULL, top_level->struct_quadratic, "q"); gcc_jit_block *initial = gcc_jit_function_new_block (test_quadratic, "initial"); gcc_jit_block *on_positive_discriminant = gcc_jit_function_new_block (test_quadratic, "positive_discriminant"); gcc_jit_block *on_nonpositive_discriminant = gcc_jit_function_new_block (test_quadratic, "nonpositive_discriminant"); gcc_jit_block *on_zero_discriminant = gcc_jit_function_new_block (test_quadratic, "zero_discriminant"); gcc_jit_block *on_negative_discriminant = gcc_jit_function_new_block (test_quadratic, "negative_discriminant"); /* Initial block. */ /* q.a = a; */ gcc_jit_block_add_assignment ( initial, NULL, gcc_jit_lvalue_access_field (q, NULL, top_level->a), gcc_jit_param_as_rvalue (a)); /* q.b = b; */ gcc_jit_block_add_assignment ( initial, NULL, gcc_jit_lvalue_access_field (q, NULL, top_level->b), gcc_jit_param_as_rvalue (b)); /* q.c = c; */ gcc_jit_block_add_assignment ( initial, NULL, gcc_jit_lvalue_access_field (q, NULL, top_level->c), gcc_jit_param_as_rvalue (c)); /* calc_discriminant (&q); */ gcc_jit_rvalue *address_of_q = gcc_jit_lvalue_get_address (q, NULL); gcc_jit_block_add_eval ( initial, NULL, gcc_jit_context_new_call ( bottom_level->ctxt, NULL, middle_level->calc_discriminant, 1, &address_of_q)); gcc_jit_block_add_comment ( initial, NULL, "if (q.discriminant > 0)"); gcc_jit_block_end_with_conditional ( initial, NULL, gcc_jit_context_new_comparison ( bottom_level->ctxt, NULL, GCC_JIT_COMPARISON_GT, gcc_jit_rvalue_access_field ( gcc_jit_lvalue_as_rvalue (q), NULL, top_level->discriminant), top_level->zero), on_positive_discriminant, on_nonpositive_discriminant); /* Block: "on_positive_discriminant" */ /* double s = sqrt (q.discriminant); */ gcc_jit_lvalue *s = gcc_jit_function_new_local ( test_quadratic, NULL, top_level->numeric_type, "s"); gcc_jit_rvalue *discriminant_of_q = gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q), NULL, top_level->discriminant); gcc_jit_block_add_assignment ( on_positive_discriminant, NULL, s, gcc_jit_context_new_call ( bottom_level->ctxt, NULL, top_level->sqrt, 1, &discriminant_of_q)); gcc_jit_rvalue *minus_b = gcc_jit_context_new_unary_op ( bottom_level->ctxt, NULL, GCC_JIT_UNARY_OP_MINUS, top_level->numeric_type, gcc_jit_param_as_rvalue (b)); gcc_jit_rvalue *two_a = gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_MULT, top_level->numeric_type, gcc_jit_context_new_rvalue_from_int ( bottom_level->ctxt, top_level->numeric_type, 2), gcc_jit_param_as_rvalue (a)); gcc_jit_block_add_comment ( on_positive_discriminant, NULL, "*r1 = (-b + s) / (2 * a);"); gcc_jit_block_add_assignment ( on_positive_discriminant, NULL, /* "*r1 = ..." */ gcc_jit_rvalue_dereference ( gcc_jit_param_as_rvalue (r1), NULL), /* (-b + s) / (2 * a) */ gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_DIVIDE, top_level->numeric_type, gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_PLUS, top_level->numeric_type, minus_b, gcc_jit_lvalue_as_rvalue (s)), two_a)); gcc_jit_block_add_comment ( on_positive_discriminant, NULL, "*r2 = (-b - s) / (2 * a)"); gcc_jit_block_add_assignment ( on_positive_discriminant, NULL, /* "*r2 = ..." */ gcc_jit_rvalue_dereference ( gcc_jit_param_as_rvalue (r2), NULL), /* (-b - s) / (2 * a) */ gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_DIVIDE, top_level->numeric_type, gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_MINUS, top_level->numeric_type, minus_b, gcc_jit_lvalue_as_rvalue (s)), two_a)); /* "return 2;" */ gcc_jit_block_end_with_return ( on_positive_discriminant, NULL, gcc_jit_context_new_rvalue_from_int ( bottom_level->ctxt, top_level->int_type, 2)); /* Block: "on_nonpositive_discriminant" */ gcc_jit_block_add_comment ( on_nonpositive_discriminant, NULL, "else if (q.discriminant == 0)"); gcc_jit_block_end_with_conditional ( on_nonpositive_discriminant, NULL, gcc_jit_context_new_comparison ( bottom_level->ctxt, NULL, GCC_JIT_COMPARISON_EQ, gcc_jit_rvalue_access_field ( gcc_jit_lvalue_as_rvalue (q), NULL, top_level->discriminant), top_level->zero), on_zero_discriminant, on_negative_discriminant); /* Block: "on_zero_discriminant" */ gcc_jit_block_add_comment ( on_zero_discriminant, NULL, "*r1 = -b / (2 * a);"); gcc_jit_block_add_assignment ( on_zero_discriminant, NULL, /* "*r1 = ..." */ gcc_jit_rvalue_dereference ( gcc_jit_param_as_rvalue (r1), NULL), /* -b / (2 * a) */ gcc_jit_context_new_binary_op ( bottom_level->ctxt, NULL, GCC_JIT_BINARY_OP_DIVIDE, top_level->numeric_type, minus_b, two_a)); /* "return 1;" */ gcc_jit_block_end_with_return ( on_zero_discriminant, NULL, gcc_jit_context_one (bottom_level->ctxt, top_level->int_type)); /* Block: "on_negative_discriminant" */ gcc_jit_block_end_with_return ( /* else return 0; */ on_negative_discriminant, NULL, gcc_jit_context_zero (bottom_level->ctxt, top_level->int_type)); }
void create_code (gcc_jit_context *ctxt) { /* Simple sum-of-squares, to test conditionals and looping int loop_test (int n) { int i; int sum = 0; for (i = 0; i < n ; i ++) { sum += i * i; } return sum; */ gcc_jit_type *the_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *return_type = the_type; gcc_jit_param *n = gcc_jit_context_new_param (ctxt, NULL, the_type, "n"); gcc_jit_param *params[1] = {n}; gcc_jit_function *func = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, return_type, "loop_test", 1, params, 0); /* Build locals: */ gcc_jit_lvalue *i = gcc_jit_function_new_local (func, NULL, the_type, "i"); gcc_jit_lvalue *sum = gcc_jit_function_new_local (func, NULL, the_type, "sum"); gcc_jit_block *b_initial = gcc_jit_function_new_block (func, "initial"); gcc_jit_block *b_loop_cond = gcc_jit_function_new_block (func, "loop_cond"); gcc_jit_block *b_loop_body = gcc_jit_function_new_block (func, "loop_body"); gcc_jit_block *b_after_loop = gcc_jit_function_new_block (func, "after_loop"); /* sum = 0; */ gcc_jit_block_add_assignment ( b_initial, NULL, sum, gcc_jit_context_zero (ctxt, the_type)); /* i = 0; */ gcc_jit_block_add_assignment ( b_initial, NULL, i, gcc_jit_context_zero (ctxt, the_type)); gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond); /* if (i >= n) */ gcc_jit_block_end_with_conditional ( b_loop_cond, NULL, gcc_jit_context_new_comparison ( ctxt, NULL, GCC_JIT_COMPARISON_GE, gcc_jit_lvalue_as_rvalue (i), gcc_jit_param_as_rvalue (n)), b_after_loop, b_loop_body); /* sum += i * i */ gcc_jit_block_add_assignment_op ( b_loop_body, NULL, sum, GCC_JIT_BINARY_OP_PLUS, gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, the_type, gcc_jit_lvalue_as_rvalue (i), gcc_jit_lvalue_as_rvalue (i))); /* i++ */ gcc_jit_block_add_assignment_op ( b_loop_body, NULL, i, GCC_JIT_BINARY_OP_PLUS, gcc_jit_context_one (ctxt, the_type)); gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond); /* return sum */ gcc_jit_block_end_with_return ( b_after_loop, NULL, gcc_jit_lvalue_as_rvalue (sum)); }
void create_code (gcc_jit_context *ctxt, void * user_data) { gcc_jit_type *type_void = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); gcc_jit_type *type_int = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *type_unsigned_char = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR); gcc_jit_type *type_void_ptr = gcc_jit_type_get_pointer (type_void); gcc_jit_type *type_void_ptr_ptr = gcc_jit_type_get_pointer (type_void_ptr); gcc_jit_type *type_unsigned_char__ = gcc_jit_type_get_pointer (type_unsigned_char); gcc_jit_field *field_x = gcc_jit_context_new_field (ctxt, NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type, */ "x"); /* const char *name */ gcc_jit_field *field_y = gcc_jit_context_new_field (ctxt, NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type, */ "y"); /* const char *name */ gcc_jit_struct *struct_struct_ip_coord = gcc_jit_context_new_opaque_struct (ctxt, NULL, /* gcc_jit_location *loc */ "ip_coord"); /* const char *name */ gcc_jit_field *fields_fields_0x18dc9d0[2] = { field_x, field_y, }; gcc_jit_struct_set_fields (struct_struct_ip_coord, /* gcc_jit_struct *struct_type */ NULL, /* gcc_jit_location *loc */ 2, /* int num_fields */ fields_fields_0x18dc9d0); /* gcc_jit_field **fields */ gcc_jit_field *field_size = gcc_jit_context_new_field (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_struct_as_type (struct_struct_ip_coord), /* gcc_jit_type *type, */ "size"); /* const char *name */ gcc_jit_field *field_imrow = gcc_jit_context_new_field (ctxt, NULL, /* gcc_jit_location *loc */ type_void_ptr_ptr, /* gcc_jit_type *type, */ "imrow"); /* const char *name */ gcc_jit_struct *struct_struct_ip_image = gcc_jit_context_new_opaque_struct (ctxt, NULL, /* gcc_jit_location *loc */ "ip_image"); /* const char *name */ gcc_jit_field *fields_fields_0x18dd310[] = { field_size, field_imrow }; gcc_jit_struct_set_fields (struct_struct_ip_image, /* gcc_jit_struct *struct_type */ NULL, /* gcc_jit_location *loc */ 2, /* int num_fields */ fields_fields_0x18dd310); /* gcc_jit_field **fields */ gcc_jit_type *type_struct_ip_image__ = gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_struct_ip_image)); gcc_jit_param *param_dest = gcc_jit_context_new_param (ctxt, NULL, /* gcc_jit_location *loc */ type_struct_ip_image__, /*gcc_jit_type *type */ "dest"); /* const char *name */ gcc_jit_param *param_src = gcc_jit_context_new_param (ctxt, NULL, /* gcc_jit_location *loc */ type_struct_ip_image__, /*gcc_jit_type *type */ "src"); /* const char *name */ gcc_jit_param *params_for_func_ip_jit_im_add_clip_UBYTE[2] = { param_dest, param_src, }; gcc_jit_function *func_ip_jit_im_add_clip_UBYTE = gcc_jit_context_new_function (ctxt, /* gcc_jit_context *ctxt */ NULL, /* gcc_jit_location *loc */ GCC_JIT_FUNCTION_EXPORTED, /* enum gcc_jit_function_kind kind */ type_void, /* gcc_jit_type *return_type */ "ip_jit_im_add_clip_UBYTE", /* const char *name */ 2, /* int num_params */ params_for_func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_param **params */ 0); /* int is_variadic */ gcc_jit_lvalue *local_rowlen = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type */ "rowlen"); /* const char *name */ gcc_jit_lvalue *local_numrows = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type */ "numrows"); /* const char *name */ gcc_jit_lvalue *local_j = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type */ "j"); /* const char *name */ gcc_jit_lvalue *local_dptr = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_unsigned_char__, /* gcc_jit_type *type */ "dptr"); /* const char *name */ gcc_jit_lvalue *local_sptr = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_unsigned_char__, /* gcc_jit_type *type */ "sptr"); /* const char *name */ gcc_jit_lvalue *local_i = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type */ "i"); /* const char *name */ gcc_jit_block *block_F1 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "F1"); gcc_jit_block *block_C1 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "C1"); gcc_jit_block *block_L1 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "L1"); gcc_jit_block *block_C2 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "C2"); gcc_jit_block *block_L2 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "L2"); gcc_jit_block *block_A2 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "A2"); gcc_jit_block *block_A1 = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "A1"); gcc_jit_lvalue *lvalue_dest__size= gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest), /* gcc_jit_rvalue *ptr */ NULL, /* gcc_jit_location *loc */ field_size); /* gcc_jit_field *field */ gcc_jit_rvalue *rvalue_dest__size_x = gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size), /*gcc_jit_rvalue *struct_or_union */ NULL, /*gcc_jit_location *loc */ field_x); gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_rowlen, /* gcc_jit_lvalue *lvalue */ rvalue_dest__size_x); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue_dest__size_y = gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (lvalue_dest__size), /*gcc_jit_rvalue *struct_or_union */ NULL, /*gcc_jit_location *loc */ field_y); gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_numrows, /* gcc_jit_lvalue *lvalue */ rvalue_dest__size_y); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_0 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 0); /* int value */ gcc_jit_block_add_assignment (block_F1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_j, /* gcc_jit_lvalue *lvalue */ rvalue__int_0); /* gcc_jit_rvalue *rvalue */ gcc_jit_block_end_with_jump (block_F1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ block_C1); /* gcc_jit_block *target */ gcc_jit_rvalue *rvalue_j___numrows = gcc_jit_context_new_comparison (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */ gcc_jit_lvalue_as_rvalue (local_j), /* gcc_jit_rvalue *a */ gcc_jit_lvalue_as_rvalue (local_numrows)); /* gcc_jit_rvalue *b */ gcc_jit_block_end_with_conditional (block_C1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ rvalue_j___numrows, /* gcc_jit_rvalue *boolval */ block_L1, /* gcc_jit_block *on_true */ block_A1); /* gcc_jit_block *on_false */ gcc_jit_lvalue *lvalue_dest__imrow= gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_dest), /* gcc_jit_rvalue *ptr */ NULL, /* gcc_jit_location *loc */ field_imrow); /* gcc_jit_field *field */ gcc_jit_lvalue *lvalue_dest__imrow_j_ = gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */ NULL, /*gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow), /* gcc_jit_rvalue *ptr */ gcc_jit_lvalue_as_rvalue (local_j)); /* gcc_jit_rvalue *index */ gcc_jit_rvalue *rvalue__unsigned_char___dest__imrow_j_ = gcc_jit_context_new_cast (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (lvalue_dest__imrow_j_), /* gcc_jit_rvalue *rvalue */ type_unsigned_char__); /* gcc_jit_type *type */ gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_dptr, /* gcc_jit_lvalue *lvalue */ rvalue__unsigned_char___dest__imrow_j_); /* gcc_jit_rvalue *rvalue */ gcc_jit_lvalue *lvalue_src__imrow= gcc_jit_rvalue_dereference_field (gcc_jit_param_as_rvalue (param_src), /* gcc_jit_rvalue *ptr */ NULL, /* gcc_jit_location *loc */ field_imrow); /* gcc_jit_field *field */ gcc_jit_lvalue *lvalue_src__imrow_j_ = gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */ NULL, /*gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (lvalue_src__imrow), /* gcc_jit_rvalue *ptr */ gcc_jit_lvalue_as_rvalue (local_j)); /* gcc_jit_rvalue *index */ gcc_jit_rvalue *rvalue__unsigned_char___src__imrow_j_ = gcc_jit_context_new_cast (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (lvalue_src__imrow_j_), /* gcc_jit_rvalue *rvalue */ type_unsigned_char__); /* gcc_jit_type *type */ gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_sptr, /* gcc_jit_lvalue *lvalue */ rvalue__unsigned_char___src__imrow_j_); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_0_0x18dd890 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 0); /* int value */ gcc_jit_block_add_assignment (block_L1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_i, /* gcc_jit_lvalue *lvalue */ rvalue__int_0_0x18dd890); /* gcc_jit_rvalue *rvalue */ gcc_jit_block_end_with_jump (block_L1, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ block_C2); /* gcc_jit_block *target */ gcc_jit_rvalue *rvalue_i___rowlen = gcc_jit_context_new_comparison (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_COMPARISON_LT, /* enum gcc_jit_comparison op */ gcc_jit_lvalue_as_rvalue (local_i), /* gcc_jit_rvalue *a */ gcc_jit_lvalue_as_rvalue (local_rowlen)); /* gcc_jit_rvalue *b */ gcc_jit_block_end_with_conditional (block_C2, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ rvalue_i___rowlen, /* gcc_jit_rvalue *boolval */ block_L2, /* gcc_jit_block *on_true */ block_A2); /* gcc_jit_block *on_false */ gcc_jit_lvalue *dereference__dptr = gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *rvalue */ NULL); /* gcc_jit_location *loc */ gcc_jit_lvalue *dereference__sptr = gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_sptr), /* gcc_jit_rvalue *rvalue */ NULL); /* gcc_jit_location *loc */ gcc_jit_block *block_p_C1_true = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "p_C1_true"); gcc_jit_block *block_p_C1_end = gcc_jit_function_new_block (func_ip_jit_im_add_clip_UBYTE, "p_C1_end"); gcc_jit_lvalue *local_ival = gcc_jit_function_new_local (func_ip_jit_im_add_clip_UBYTE, /* gcc_jit_function *func */ NULL, /* gcc_jit_location *loc */ type_int, /* gcc_jit_type *type */ "ival"); /* const char *name */ gcc_jit_rvalue *rvalue__int__dptr = gcc_jit_context_new_cast (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (dereference__dptr), /* gcc_jit_rvalue *rvalue */ type_int); /* gcc_jit_type *type */ gcc_jit_rvalue *rvalue__int__sptr = gcc_jit_context_new_cast (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (dereference__sptr), /* gcc_jit_rvalue *rvalue */ type_int); /* gcc_jit_type *type */ gcc_jit_rvalue *rvalue__int__dptr____int__sptr = gcc_jit_context_new_binary_op (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */ type_int, /* gcc_jit_type *result_type */ rvalue__int__dptr, /* gcc_jit_rvalue *a */ rvalue__int__sptr); /* gcc_jit_rvalue *b */ gcc_jit_block_add_assignment (block_L2, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_ival, /* gcc_jit_lvalue *lvalue */ rvalue__int__dptr____int__sptr); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_255 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 255); /* int value */ gcc_jit_rvalue *rvalue_ival____int_255 = gcc_jit_context_new_comparison (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_COMPARISON_GT, /* enum gcc_jit_comparison op */ gcc_jit_lvalue_as_rvalue (local_ival), /* gcc_jit_rvalue *a */ rvalue__int_255); /* gcc_jit_rvalue *b */ gcc_jit_block_end_with_conditional (block_L2, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ rvalue_ival____int_255, /* gcc_jit_rvalue *boolval */ block_p_C1_true, /* gcc_jit_block *on_true */ block_p_C1_end); /* gcc_jit_block *on_false */ gcc_jit_block_add_assignment (block_p_C1_true, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_ival, /* gcc_jit_lvalue *lvalue */ rvalue__int_255); /* gcc_jit_rvalue *rvalue */ gcc_jit_block_end_with_jump (block_p_C1_true, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ block_p_C1_end); /* gcc_jit_block *target */ gcc_jit_rvalue *rvalue__unsigned_char_ival = gcc_jit_context_new_cast (ctxt, NULL, /* gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (local_ival), /* gcc_jit_rvalue *rvalue */ type_unsigned_char); /* gcc_jit_type *type */ gcc_jit_lvalue *dereference__dptr_0x18df2e0 = gcc_jit_rvalue_dereference (gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *rvalue */ NULL); /* gcc_jit_location *loc */ gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ dereference__dptr_0x18df2e0, /* gcc_jit_lvalue *lvalue */ rvalue__unsigned_char_ival); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_1 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 1); /* int value */ gcc_jit_lvalue *lvalue_dptr__int_1_ = gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */ NULL, /*gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (local_dptr), /* gcc_jit_rvalue *ptr */ rvalue__int_1); /* gcc_jit_rvalue *index */ gcc_jit_rvalue *address_of__dptr__int_1_ = gcc_jit_lvalue_get_address (lvalue_dptr__int_1_, /* gcc_jit_lvalue *lvalue */ NULL); /* gcc_jit_location *loc */ gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_dptr, /* gcc_jit_lvalue *lvalue */ address_of__dptr__int_1_); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_1_0x18df500 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 1); /* int value */ gcc_jit_lvalue *lvalue_sptr__int_1_ = gcc_jit_context_new_array_access (ctxt, /* gcc_jit_context *ctxt */ NULL, /*gcc_jit_location *loc */ gcc_jit_lvalue_as_rvalue (local_sptr), /* gcc_jit_rvalue *ptr */ rvalue__int_1_0x18df500); /* gcc_jit_rvalue *index */ gcc_jit_rvalue *address_of__sptr__int_1_ = gcc_jit_lvalue_get_address (lvalue_sptr__int_1_, /* gcc_jit_lvalue *lvalue */ NULL); /* gcc_jit_location *loc */ gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_sptr, /* gcc_jit_lvalue *lvalue */ address_of__sptr__int_1_); /* gcc_jit_rvalue *rvalue */ gcc_jit_rvalue *rvalue__int_1_0x18df650 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 1); /* int value */ gcc_jit_rvalue *rvalue_i____int_1 = gcc_jit_context_new_binary_op (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */ type_int, /* gcc_jit_type *result_type */ gcc_jit_lvalue_as_rvalue (local_i), /* gcc_jit_rvalue *a */ rvalue__int_1_0x18df650); /* gcc_jit_rvalue *b */ gcc_jit_block_add_assignment (block_p_C1_end, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_i, /* gcc_jit_lvalue *lvalue */ rvalue_i____int_1); /* gcc_jit_rvalue *rvalue */ gcc_jit_block_end_with_jump (block_p_C1_end, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ block_C2); /* gcc_jit_block *target */ gcc_jit_rvalue *rvalue__int_1_0x18df7e0 = gcc_jit_context_new_rvalue_from_int (ctxt, /* gcc_jit_context *ctxt */ type_int, /* gcc_jit_type *numeric_type */ 1); /* int value */ gcc_jit_rvalue *rvalue_j____int_1 = gcc_jit_context_new_binary_op (ctxt, NULL, /* gcc_jit_location *loc */ GCC_JIT_BINARY_OP_PLUS, /* enum gcc_jit_binary_op op */ type_int, /* gcc_jit_type *result_type */ gcc_jit_lvalue_as_rvalue (local_j), /* gcc_jit_rvalue *a */ rvalue__int_1_0x18df7e0); /* gcc_jit_rvalue *b */ gcc_jit_block_add_assignment (block_A2, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ local_j, /* gcc_jit_lvalue *lvalue */ rvalue_j____int_1); /* gcc_jit_rvalue *rvalue */ gcc_jit_block_end_with_jump (block_A2, /*gcc_jit_block *block */ NULL, /* gcc_jit_location *loc */ block_C1); /* gcc_jit_block *target */ gcc_jit_block_end_with_void_return (block_A1, /*gcc_jit_block *block */ NULL); /* gcc_jit_location *loc */ }
/********************************************************************** GCC_JIT_FUNCTION_ALWAYS_INLINE and GCC_JIT_FUNCTION_INTERNAL **********************************************************************/ static void create_test_of_hidden_function (gcc_jit_context *ctxt, enum gcc_jit_function_kind hidden_kind, const char *hidden_func_name, const char *visible_func_name) { /* Let's try to inject the equivalent of: static double hidden_mult (double a, double b) { return x * x; } double my_square (double x) { return my_mult (x, x); } where hidden_mult can potentially be inline __attribute__((always_inline)). */ gcc_jit_type *double_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE); /* Create "my_mult" */ gcc_jit_param *param_a = gcc_jit_context_new_param (ctxt, NULL, double_type, "a"); gcc_jit_param *param_b = gcc_jit_context_new_param (ctxt, NULL, double_type, "b"); gcc_jit_param *params[2] = {param_a, param_b}; gcc_jit_function *my_mult = gcc_jit_context_new_function (ctxt, NULL, hidden_kind, double_type, hidden_func_name, 2, params, 0); gcc_jit_block *body_of_my_mult = gcc_jit_function_new_block (my_mult, NULL); gcc_jit_block_end_with_return ( body_of_my_mult, NULL, gcc_jit_context_new_binary_op ( ctxt, NULL, GCC_JIT_BINARY_OP_MULT, double_type, gcc_jit_param_as_rvalue (param_a), gcc_jit_param_as_rvalue (param_b))); /* Create "my_square" */ gcc_jit_param *param_x = gcc_jit_context_new_param (ctxt, NULL, double_type, "x"); gcc_jit_function *my_square = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, double_type, visible_func_name, 1, ¶m_x, 0); gcc_jit_block *body_of_my_square = gcc_jit_function_new_block (my_square, NULL); gcc_jit_rvalue *args[2] = {gcc_jit_param_as_rvalue (param_x), gcc_jit_param_as_rvalue (param_x)}; gcc_jit_block_end_with_return ( body_of_my_square, NULL, gcc_jit_context_new_call ( ctxt, NULL, my_mult, 2, args)); }
void create_code (gcc_jit_context *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; } */ gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT); gcc_jit_type *float_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT); gcc_jit_field *as_int = gcc_jit_context_new_field (ctxt, NULL, int_type, "as_int"); gcc_jit_field *as_float = gcc_jit_context_new_field (ctxt, NULL, float_type, "as_float"); gcc_jit_field *fields[] = {as_int, as_float}; gcc_jit_type *union_type = gcc_jit_context_new_union_type (ctxt, NULL, "int_or_float", 2, fields); /* Build the test function. */ gcc_jit_param *param_i = gcc_jit_context_new_param (ctxt, NULL, int_type, "i"); gcc_jit_function *test_fn = gcc_jit_context_new_function (ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, float_type, "test_union", 1, ¶m_i, 0); gcc_jit_lvalue *u = gcc_jit_function_new_local (test_fn, NULL, union_type, "u"); gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); /* u.as_int = i; */ gcc_jit_block_add_assignment ( block, NULL, /* "u.as_int = ..." */ gcc_jit_lvalue_access_field (u, NULL, as_int), gcc_jit_param_as_rvalue (param_i)); /* return u.as_float; */ gcc_jit_block_end_with_return ( block, NULL, gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (u), NULL, as_float)); }
static void make_calc_discriminant (struct top_level *top_level, struct middle_level *middle_level) { /* Build "calc_discriminant". */ gcc_jit_param *param_q = gcc_jit_context_new_param (middle_level->ctxt, NULL, top_level->quadratic_ptr, "q"); middle_level->calc_discriminant = gcc_jit_context_new_function (middle_level->ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, top_level->void_type, "calc_discriminant", 1, ¶m_q, 0); gcc_jit_block *blk = gcc_jit_function_new_block (middle_level->calc_discriminant, NULL); gcc_jit_block_add_comment ( blk, NULL, "(b^2 - 4ac)"); gcc_jit_rvalue *q_a = gcc_jit_lvalue_as_rvalue ( gcc_jit_rvalue_dereference_field ( gcc_jit_param_as_rvalue (param_q), NULL, top_level->a)); gcc_jit_rvalue *q_b = gcc_jit_lvalue_as_rvalue ( gcc_jit_rvalue_dereference_field ( gcc_jit_param_as_rvalue (param_q), NULL, top_level->b)); gcc_jit_rvalue *q_c = gcc_jit_lvalue_as_rvalue ( gcc_jit_rvalue_dereference_field ( gcc_jit_param_as_rvalue (param_q), NULL, top_level->c)); gcc_jit_block_add_assignment ( blk, NULL, /* q->discriminant =... */ gcc_jit_rvalue_dereference_field ( gcc_jit_param_as_rvalue (param_q), NULL, top_level->discriminant), /* (q->b * q->b) - (4 * q->a * q->c) */ gcc_jit_context_new_binary_op ( middle_level->ctxt, NULL, GCC_JIT_BINARY_OP_MINUS, top_level->numeric_type, /* (q->b * q->b) */ gcc_jit_context_new_binary_op ( middle_level->ctxt, NULL, GCC_JIT_BINARY_OP_MULT, top_level->numeric_type, q_b, q_b), /* (4 * (q->a * q->c)) */ gcc_jit_context_new_binary_op ( middle_level->ctxt, NULL, GCC_JIT_BINARY_OP_MULT, top_level->numeric_type, /* 4.0 */ gcc_jit_context_new_rvalue_from_int ( middle_level->ctxt, top_level->numeric_type, 4), /* (q->a * q->c) */ gcc_jit_context_new_binary_op ( middle_level->ctxt, NULL, GCC_JIT_BINARY_OP_MULT, top_level->numeric_type, q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */ gcc_jit_block_end_with_void_return (blk, NULL); }