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: 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); }