Example #1
0
static void* concurrent_jit_run(void *info)
{
    gcc_jit_context *ctx;
    ctx = gcc_jit_context_acquire ();
    if (ctx == NULL)
    {
        fprintf(stderr, "acquired JIT context is NULL");
        return NULL;
    }

    gcc_jit_context_set_int_option(ctx, GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2);

#if EXTRAE_SUPPORT
    Extrae_event(JIT_EVENT_TYPE, JIT_CODE_GENERATION);
#endif

    generate_code_regexp(ctx, regexp);

#if EXTRAE_SUPPORT
    Extrae_event(JIT_EVENT_TYPE, 0);

    Extrae_event(JIT_EVENT_TYPE, JIT_COMPILATION);
#endif
    gcc_jit_result *result = gcc_jit_context_compile(ctx);
#if EXTRAE_SUPPORT
    Extrae_event(JIT_EVENT_TYPE, 0);
#endif
    if (result == NULL)
    {
        fprintf(stderr, "compilation failed");
        return NULL;
    }

#if EXTRAE_SUPPORT
    Extrae_event(JIT_EVENT_TYPE, JIT_GET_CODE);
#endif

    match_fun_t function_addr = (match_fun_t)gcc_jit_result_get_code(result, "match");

#if EXTRAE_SUPPORT
    Extrae_event(JIT_EVENT_TYPE, 0);
#endif

#if EXTRAE_SUPPORT
    if (function_addr == NULL)
    {
        fprintf(stderr, "error getting 'match'");
        return NULL;
    }
#endif

    atomic_store(&match_fun, function_addr);

    return NULL;
}
Example #2
0
int
main (int argc, char **argv)
{
  gcc_jit_context *ctxt = NULL;
  gcc_jit_result *result = NULL;

  /* Get a "context" object for working with the library.  */
  ctxt = gcc_jit_context_acquire ();
  if (!ctxt)
    {
      fprintf (stderr, "NULL ctxt");
      goto error;
    }

  /* Set some options on the context.
     Let's see the code being generated, in assembler form.  */
  gcc_jit_context_set_bool_option (
    ctxt,
    GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
    0);

  /* Populate the context.  */
  create_code (ctxt);

  /* Compile the code.  */
  result = gcc_jit_context_compile (ctxt);
  if (!result)
    {
      fprintf (stderr, "NULL result");
      goto error;
    }

  /* We're done with the context; we can release it: */
  gcc_jit_context_release (ctxt);
  ctxt = NULL;

  /* Extract the generated code from "result".  */
  void *fn_ptr = gcc_jit_result_get_code (result, "square");
  if (!fn_ptr)
     {
       fprintf (stderr, "NULL fn_ptr");
       goto error;
     }

  typedef int (*fn_type) (int);
  fn_type square = (fn_type)fn_ptr;
  printf ("result: %d\n", square (5));

 error:
  if (ctxt)
    gcc_jit_context_release (ctxt);
  if (result)
    gcc_jit_result_release (result);
  return 0;
}
Example #3
0
int
main (int argc, char **argv)
{
  gcc_jit_context *ctxt = NULL;
  gcc_jit_result *result = NULL;

  /* Get a "context" object for working with the library.  */
  ctxt = gcc_jit_context_acquire ();
  if (!ctxt)
    {
      fprintf (stderr, "NULL ctxt");
      goto error;
    }

  /* Set some options on the context.
     Let's see the code being generated, in assembler form.  */
  gcc_jit_context_set_bool_option (
    ctxt,
    GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
    0);

  /* Populate the context.  */
  create_code (ctxt);

  /* Compile the code.  */
  result = gcc_jit_context_compile (ctxt);
  if (!result)
    {
      fprintf (stderr, "NULL result");
      goto error;
    }

  /* Extract the generated code from "result".  */
  typedef int (*loop_test_fn_type) (int);
  loop_test_fn_type loop_test =
    (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
  if (!loop_test)
    {
      fprintf (stderr, "NULL loop_test");
      goto error;
    }

  /* Run the generated code.  */
  int val = loop_test (10);
  printf("loop_test returned: %d\n", val);

 error:
  gcc_jit_context_release (ctxt);
  gcc_jit_result_release (result);
  return 0;
}
Example #4
0
int
main (int argc, char **argv)
{
  gcc_jit_context *ctxt;
  gcc_jit_result *result;

  /* Get a "context" object for working with the library.  */
  ctxt = gcc_jit_context_acquire ();
  if (!ctxt)
    {
      fprintf (stderr, "NULL ctxt");
      exit (1);
    }

  /* Set some options on the context.
     Let's see the code being generated, in assembler form.  */
  gcc_jit_context_set_bool_option (
    ctxt,
    GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
    0);

  /* Populate the context.  */
  create_code (ctxt);

  /* Compile the code.  */
  result = gcc_jit_context_compile (ctxt);
  if (!result)
    {
      fprintf (stderr, "NULL result");
      exit (1);
    }

  /* Extract the generated code from "result".  */
  typedef void (*fn_type) (const char *);
  fn_type greet =
    (fn_type)gcc_jit_result_get_code (result, "greet");
  if (!greet)
    {
      fprintf (stderr, "NULL greet");
      exit (1);
    }

  /* Now call the generated function: */
  greet ("world");
  fflush (stdout);

  gcc_jit_context_release (ctxt);
  gcc_jit_result_release (result);
  return 0;
}
Example #5
0
ravi_gcc_context_t *ravi_jit_new_context(void) {
  ravi_gcc_context_t *ravi = NULL;
  gcc_jit_context *gcc_ctx = gcc_jit_context_acquire();
  if (!gcc_ctx) {
    fprintf(stderr, "failed to allocate a GCC JIT context\n");
    goto on_error;
  }

  ravi = (ravi_gcc_context_t *)calloc(1, sizeof(ravi_gcc_context_t));
  if (!ravi) {
    fprintf(stderr, "failed to allocate a Ravi JIT context\n");
    goto on_error;
  }
  ravi->context = gcc_ctx;
  ravi->auto_ = false;
  ravi->enabled_ = true;
  ravi->min_code_size_ = 150;
  ravi->min_exec_count_ = 50;
  ravi->opt_level_ = 3;
  ravi->size_level_ = 0;

  if (!ravi_setup_lua_types(ravi)) {
    fprintf(stderr, "failed to setup types\n");
    goto on_error;
  }

  ravi->parent_result_ = gcc_jit_context_compile(ravi->context);
  if (gcc_jit_context_get_first_error(ravi->context)) {
    fprintf(stderr, "aborting due to JIT error: %s\n",
            gcc_jit_context_get_first_error(ravi->context));
    abort();
  }

  return ravi;
on_error:
  if (ravi) {
    ravi_jit_context_free(ravi);
  } else if (gcc_ctx) {
    gcc_jit_context_release(gcc_ctx);
  }
  return NULL;
}
Example #6
0
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;
}
Example #7
0
int
main (int argc, char **argv)
{
  int i, j, k;
  const int NUM_TOP_ITERATIONS = 2;
  const int NUM_MIDDLE_ITERATIONS = 2;
  const int NUM_BOTTOM_ITERATIONS = 2;

  /* We do the whole thing multiple times to shake out state-management
     issues in the underlying code.  */

  for (i = 1; i <= NUM_TOP_ITERATIONS; i++)
    {
      /* Create the top-level context.  */
      snprintf (test, sizeof (test),
		"%s iteration %d of %d of top level",
		extract_progname (argv[0]),
		i, NUM_TOP_ITERATIONS);

      struct top_level top_level;
      memset (&top_level, 0, sizeof (top_level));

      top_level.ctxt = gcc_jit_context_acquire ();
      set_options (top_level.ctxt, argv[0]);

      make_types (&top_level);
      make_sqrt (&top_level);

      /* No errors should have occurred.  */
      CHECK_VALUE (gcc_jit_context_get_first_error (top_level.ctxt), NULL);

      gcc_jit_context_dump_to_file (top_level.ctxt,
				    "dump-of-test-nested-contexts-top.c",
				    1);

      for (j = 1; j <= NUM_MIDDLE_ITERATIONS; j++)
	{
	  /* Create and populate the middle-level context, using
	     objects from the top-level context.  */
	  snprintf (test, sizeof (test),
		    ("%s iteration %d of %d of top level;"
		     " %d of %d of middle level"),
		    extract_progname (argv[0]),
		    i, NUM_TOP_ITERATIONS,
		    j, NUM_MIDDLE_ITERATIONS);

	  struct middle_level middle_level;
	  memset (&middle_level, 0, sizeof (middle_level));

	  middle_level.ctxt =
	    gcc_jit_context_new_child_context (top_level.ctxt);
	  make_calc_discriminant (&top_level,
				  &middle_level);

	  /* No errors should have occurred.  */
	  CHECK_VALUE (gcc_jit_context_get_first_error (middle_level.ctxt),
		       NULL);

	  gcc_jit_context_dump_to_file (middle_level.ctxt,
					"dump-of-test-nested-contexts-middle.c",
					1);

	  gcc_jit_result *middle_result =
	    gcc_jit_context_compile (middle_level.ctxt);
	  CHECK_NON_NULL (middle_result);

	  verify_middle_code (middle_level.ctxt, middle_result);

	  for (k = 1; k <= NUM_BOTTOM_ITERATIONS; k++)
	    {
	      /* Create and populate the innermost context, using
		 objects from the top-level and middle-level contexts.  */
	      snprintf (test, sizeof (test),
			("%s iteration %d of %d of top level;"
			 " %d of %d of middle level;"
			 " %d of %d of bottom level"),
			extract_progname (argv[0]),
			i, NUM_TOP_ITERATIONS,
			j, NUM_MIDDLE_ITERATIONS,
			k, NUM_BOTTOM_ITERATIONS);

	      struct bottom_level bottom_level;
	      memset (&bottom_level, 0, sizeof (bottom_level));

	      bottom_level.ctxt =
		gcc_jit_context_new_child_context (middle_level.ctxt);
	      make_test_quadratic (&top_level,
				   &middle_level,
				   &bottom_level);

	      /* No errors should have occurred.  */
	      CHECK_VALUE (gcc_jit_context_get_first_error (bottom_level.ctxt),
			   NULL);

	      gcc_jit_context_dump_to_file (bottom_level.ctxt,
					    "dump-of-test-nested-contexts-bottom.c",
					    1);

	      gcc_jit_result *bottom_result =
		gcc_jit_context_compile (bottom_level.ctxt);
	      verify_bottom_code (bottom_level.ctxt, bottom_result);
	      gcc_jit_result_release (bottom_result);
	      gcc_jit_context_release (bottom_level.ctxt);

	    }

	  gcc_jit_result_release (middle_result);
	  gcc_jit_context_release (middle_level.ctxt);

	}

      gcc_jit_context_release (top_level.ctxt);
   }

  totals ();

  return 0;
}