Table Of Contents

Previous topic

Expressions

Next topic

Source Locations

This Page

Creating and using functions

Params

gcc_jit_param *\
gcc_jit_context_new_param (gcc_jit_context *ctxt,\
gcc_jit_location *loc,\
gcc_jit_type *type,\
const char *name)

In preparation for creating a function, create a new parameter of the given type and name.

The parameter name must be non-NULL. The call takes a copy of the underlying string, so it is valid to pass in a pointer to an on-stack buffer.

Parameters are lvalues, and thus are also rvalues (and objects), so the following upcasts are available:

gcc_jit_lvalue *\
gcc_jit_param_as_lvalue(gcc_jit_param *param)
Upcasting from param to lvalue.
gcc_jit_rvalue *\
gcc_jit_param_as_rvalue(gcc_jit_param *param)
Upcasting from param to rvalue.
gcc_jit_object *\
gcc_jit_param_as_object(gcc_jit_param *param)
Upcasting from param to object.

Functions

gcc_jit_function *\
gcc_jit_context_new_function (gcc_jit_context *ctxt,\
gcc_jit_location *loc,\
enum gcc_jit_function_kind kind,\
gcc_jit_type *return_type,\
const char *name,\
int num_params,\
gcc_jit_param **params,\
int is_variadic)

Create a gcc_jit_function with the given name and parameters.

This enum controls the kind of function created, and has the following values:

The parameter name must be non-NULL. The call takes a copy of the underlying string, so it is valid to pass in a pointer to an on-stack buffer.

gcc_jit_function *\
gcc_jit_context_get_builtin_function (gcc_jit_context *ctxt,\
const char *name)
gcc_jit_object *\
gcc_jit_function_as_object(gcc_jit_function *func)
Upcasting from function to object.
gcc_jit_param *\
gcc_jit_function_get_param(gcc_jit_function *func, int index)
Get the param of the given index (0-based).
void \
gcc_jit_function_dump_to_dot (gcc_jit_function *func,\
const char *path)
Emit the function in graphviz format to the given path.
gcc_jit_lvalue *\
gcc_jit_function_new_local (gcc_jit_function *func,\
gcc_jit_location *loc,\
gcc_jit_type *type,\
const char *name)

Create a new local variable within the function, of the given type and name.

The parameter name must be non-NULL. The call takes a copy of the underlying string, so it is valid to pass in a pointer to an on-stack buffer.

Blocks

gcc_jit_block *\
gcc_jit_function_new_block (gcc_jit_function *func,\
const char *name)

Create a basic block of the given name. The name may be NULL, but providing meaningful names is often helpful when debugging: it may show up in dumps of the internal representation, and in error messages. It is copied, so the input buffer does not need to outlive the call; you can pass in a pointer to an on-stack buffer, e.g.:

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);
 }
gcc_jit_object *\
gcc_jit_block_as_object(gcc_jit_block *block)
Upcast from block to object.
gcc_jit_function *\
gcc_jit_block_get_function(gcc_jit_block *block)
Which function is this block within?

Statements

void\
gcc_jit_block_add_eval (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_rvalue *rvalue)

Add evaluation of an rvalue, discarding the result (e.g. a function call that “returns” void).

This is equivalent to this C code:

(void)expression;
void\
gcc_jit_block_add_assignment (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_lvalue *lvalue,\
gcc_jit_rvalue *rvalue)

Add evaluation of an rvalue, assigning the result to the given lvalue.

This is roughly equivalent to this C code:

lvalue = rvalue;
void\
gcc_jit_block_add_assignment_op (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_lvalue *lvalue,\
enum gcc_jit_binary_op op,\
gcc_jit_rvalue *rvalue)

Add evaluation of an rvalue, using the result to modify an lvalue.

This is analogous to “+=” and friends:

lvalue += rvalue;
lvalue *= rvalue;
lvalue /= rvalue;

etc. For example:

/* "i++" */
gcc_jit_block_add_assignment_op (
  loop_body, NULL,
  i,
  GCC_JIT_BINARY_OP_PLUS,
  gcc_jit_context_one (ctxt, int_type));
void\
gcc_jit_block_add_comment (gcc_jit_block *block,\
gcc_jit_location *loc,\
const char *text)

Add a no-op textual comment to the internal representation of the code. It will be optimized away, but will be visible in the dumps seen via :macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE` and :macro:`GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE`, and thus may be of use when debugging how your project’s internal representation gets converted to the libgccjit IR.

The parameter text must be non-NULL. It is copied, so the input buffer does not need to outlive the call. For example:

char buf[100];
snprintf (buf, sizeof (buf),
          "op%i: %s",
          pc, opcode_names[op->op_opcode]);
gcc_jit_block_add_comment (block, loc, buf);
void\
gcc_jit_block_end_with_conditional (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_rvalue *boolval,\
gcc_jit_block *on_true,\
gcc_jit_block *on_false)

Terminate a block by adding evaluation of an rvalue, branching on the result to the appropriate successor block.

This is roughly equivalent to this C code:

if (boolval)
  goto on_true;
else
  goto on_false;

block, boolval, on_true, and on_false must be non-NULL.

void\
gcc_jit_block_end_with_jump (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_block *target)

Terminate a block by adding a jump to the given target block.

This is roughly equivalent to this C code:

goto target;
void\
gcc_jit_block_end_with_return (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_rvalue *rvalue)

Terminate a block by adding evaluation of an rvalue, returning the value.

This is roughly equivalent to this C code:

return expression;
void\
gcc_jit_block_end_with_void_return (gcc_jit_block *block,\
gcc_jit_location *loc)

Terminate a block by adding a valueless return, for use within a function with “void” return type.

This is equivalent to this C code:

return;
void\
gcc_jit_block_end_with_switch (gcc_jit_block *block,\
gcc_jit_location *loc,\
gcc_jit_rvalue *expr,\
gcc_jit_block *default_block,\
int num_cases,\
gcc_jit_case **cases)

Terminate a block by adding evalation of an rvalue, then performing a multiway branch.

This is roughly equivalent to this C code:

switch (expr)
  {
  default:
    goto default_block;

  case C0.min_value ... C0.max_value:
    goto C0.dest_block;

  case C1.min_value ... C1.max_value:
    goto C1.dest_block;

  ...etc...

  case C[N - 1].min_value ... C[N - 1].max_value:
    goto C[N - 1].dest_block;
}

block, expr, default_block and cases must all be non-NULL.

expr must be of the same integer type as all of the min_value and max_value within the cases.

num_cases must be >= 0.

The ranges of the cases must not overlap (or have duplicate values).

The API entrypoints relating to switch statements and cases:

were added in LIBGCCJIT_ABI_3; you can test for their presence using

#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS

A gcc_jit_case represents a case within a switch statement, and is created within a particular :c:type:`gcc_jit_context` using :c:func:`gcc_jit_context_new_case`.

Each case expresses a multivalued range of integer values. You can express single-valued cases by passing in the same value for both min_value and max_value.

gcc_jit_case *\
gcc_jit_context_new_case (gcc_jit_context *ctxt,\
gcc_jit_rvalue *min_value,\
gcc_jit_rvalue *max_value,\
gcc_jit_block *dest_block)

Create a new gcc_jit_case instance for use in a switch statement. min_value and max_value must be constants of an integer type, which must match that of the expression of the switch statement.

dest_block must be within the same function as the switch statement.

gcc_jit_object *\
gcc_jit_case_as_object(gcc_jit_case *case_)
Upcast from a case to an object.

Here’s an example of creating a switch statement:

void
create_code (gcc_jit_context *ctxt, void *user_data)
{
  /* Let's try to inject the equivalent of:
      int
      test_switch (int x)
      {
	switch (x)
	  {
	  case 0 ... 5:
	     return 3;

	  case 25 ... 27:
	     return 4;

	  case -42 ... -17:
	     return 83;

	  case 40:
	     return 8;

	  default:
	     return 10;
	  }
      }
   */
  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");
  gcc_jit_block *b_case_0_5 =
    gcc_jit_function_new_block (func, "case_0_5");
  gcc_jit_block *b_case_25_27 =
    gcc_jit_function_new_block (func, "case_25_27");
  gcc_jit_block *b_case_m42_m17 =
    gcc_jit_function_new_block (func, "case_m42_m17");
  gcc_jit_block *b_case_40 =
    gcc_jit_function_new_block (func, "case_40");

  gcc_jit_case *cases[4] = {
    gcc_jit_context_new_case (
      ctxt,
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 0),
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 5),
      b_case_0_5),
    gcc_jit_context_new_case (
      ctxt,
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 25),
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 27),
      b_case_25_27),
    gcc_jit_context_new_case (
      ctxt,
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -42),
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, -17),
      b_case_m42_m17),
    gcc_jit_context_new_case (
      ctxt,
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
      gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 40),
      b_case_40)
  };
  gcc_jit_block_end_with_switch (
    b_initial, NULL,
    gcc_jit_param_as_rvalue (x),
    b_default,
    4, cases);

  gcc_jit_block_end_with_return (
    b_case_0_5, NULL,
    gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 3));
  gcc_jit_block_end_with_return (
    b_case_25_27, NULL,
    gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 4));
  gcc_jit_block_end_with_return (
    b_case_m42_m17, NULL,
    gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 83));
  gcc_jit_block_end_with_return (
    b_case_40, NULL,
    gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 8));
  gcc_jit_block_end_with_return (
    b_default, NULL,
    gcc_jit_context_new_rvalue_from_int (ctxt, t_int, 10));
}