Creating and using functions

Params

typegcc_jit_param

Agcc_jit_param represents a parameter to a function.

gcc_jit_param*gcc_jit_context_new_param(gcc_jit_context*ctxt,gcc_jit_location*loc,gcc_jit_type*type,constchar*name)

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

The parametertype must be non-void.

The parametername must be non-NULL. The call takes a copy of theunderlying string, so it is valid to pass in a pointer to an on-stackbuffer.

Parameters are lvalues, and thus are also rvalues (and objects), so thefollowing 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

typegcc_jit_function

Agcc_jit_function represents a function - either one that we’recreating ourselves, or one that we’re referencing.

gcc_jit_function*gcc_jit_context_new_function(gcc_jit_context*ctxt,gcc_jit_location*loc,enumgcc_jit_function_kindkind,gcc_jit_type*return_type,constchar*name,intnum_params,gcc_jit_param**params,intis_variadic)

Create a gcc_jit_function with the given name and parameters.

enumgcc_jit_function_kind

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

GCC_JIT_FUNCTION_EXPORTED

Function is defined by the client code and visibleby name outside of the JIT.

This value is required if you want to extract machine codefor this function from agcc_jit_result viagcc_jit_result_get_code().

GCC_JIT_FUNCTION_INTERNAL

Function is defined by the client code, but is invisibleoutside of the JIT. Analogous to a “static” function.

GCC_JIT_FUNCTION_IMPORTED

Function is not defined by the client code; we’re merelyreferring to it. Analogous to using an “extern” function from aheader file.

GCC_JIT_FUNCTION_ALWAYS_INLINE

Function is only ever inlined into other functions, and isinvisible outside of the JIT.

Analogous to prefixing withinline and adding__attribute__((always_inline))

Inlining will only occur when the optimization level isabove 0; when optimization is off, this is essentially thesame as GCC_JIT_FUNCTION_INTERNAL.

The parametername must be non-NULL. The call takes a copy of theunderlying string, so it is valid to pass in a pointer to an on-stackbuffer.

gcc_jit_function*gcc_jit_context_get_builtin_function(gcc_jit_context*ctxt,constchar*name)

Get thegcc_jit_function for the built-in function with thegiven name. For example:

gcc_jit_function*fn=gcc_jit_context_get_builtin_function(ctxt,"__builtin_memcpy");

Note

Due to technical limitations with how libgccjit interacts withthe insides of GCC, not all built-in functions are supported. Moreprecisely, not all types are supported for parameters of built-infunctions from libgccjit. Attempts to get a built-in function thatuses such a parameter will lead to an error being emitted withinthe context.

gcc_jit_function*gcc_jit_context_get_target_builtin_function(gcc_jit_context*ctxt,constchar*name)

Get thegcc_jit_function for the built-in function (sometimes calledintrinsic functions) with the given name. For example:

gcc_jit_function*fn=gcc_jit_context_get_target_builtin_function(ctxt,"__builtin_ia32_pmuldq512_mask");

Note

Due to technical limitations with how libgccjit interacts withthe insides of GCC, not all built-in functions are supported. Moreprecisely, not all types are supported for parameters of built-infunctions from libgccjit. Attempts to get a built-in function thatuses such a parameter will lead to an error being emitted withinthe context.

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,intindex)

Get the param of the given index (0-based).

voidgcc_jit_function_dump_to_dot(gcc_jit_function*func,constchar*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,constchar*name)

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

The parametertype must be non-void.

The parametername must be non-NULL. The call takes a copy of theunderlying string, so it is valid to pass in a pointer to an on-stackbuffer.

gcc_jit_lvalue*gcc_jit_function_new_temp(gcc_jit_function*func,gcc_jit_location*loc,gcc_jit_type*type)

Create a new local variable within the function, of the given type.This function is similar togcc_jit_function_new_local(), butit is to be used for compiler-generated variables (as opposed touser-defined variables in the language to be compiled) and thesevariables won’t show up in the debug info.

The parametertype must be non-void.

This entrypoint was added inLIBGCCJIT_ABI_33; you can testfor its presence using

#ifdef LIBGCCJIT_HAVE_gcc_jit_function_new_temp
size_tgcc_jit_function_get_param_count(gcc_jit_function*func)

Get the number of parameters of the function.

gcc_jit_type*gcc_jit_function_get_return_type(gcc_jit_function*func)

Get the return type of the function.

The API entrypoints relating to getting info about parameters and returntypes:

were added inLIBGCCJIT_ABI_16; you can test for their presenceusing

#ifdef LIBGCCJIT_HAVE_REFLECTION
typegcc_jit_case
void            gcc_jit_function_add_attribute(gcc_jit_function*func,
enumgcc_jit_fn_attributeattribute)

Add an attributeattribute to a functionfunc.

This is equivalent to the following code:

 __attribute__((always_inline))This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test forits presence using.. code-block:: c   #ifdef LIBGCCJIT_HAVE_ATTRIBUTES
void            gcc_jit_function_add_string_attribute(gcc_jit_function*func,
enumgcc_jit_fn_attributeattribute,
constchar*value)

Add a string attributeattribute with valuevalue to a functionfunc.

This is equivalent to the following code:

 __attribute__ ((alias ("xxx")))This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test forits presence using.. code-block:: c   #ifdef LIBGCCJIT_HAVE_ATTRIBUTES
void            gcc_jit_function_add_integer_array_attribute(gcc_jit_function*func,
enumgcc_jit_fn_attributeattribute,
constint*value,
size_tlength)

Add an attributeattribute withlength integer valuesvalue to afunctionfunc. The integer values must be the same as you would writethem in a C code.

This is equivalent to the following code:

 __attribute__ ((nonnull (1, 2)))This entrypoint was added in :ref:`LIBGCCJIT_ABI_26`; you can test forits presence using.. code-block:: c   #ifdef LIBGCCJIT_HAVE_ATTRIBUTES

Blocks

typegcc_jit_block

Agcc_jit_block represents a basic block within a function i.e. asequence of statements with a single entry point and a single exitpoint.

The first basic block that you create within a function willbe the entrypoint.

Each basic block that you create within a function must beterminated, either with a conditional, a jump, a return, or aswitch.

It’s legal to have multiple basic blocks that return withinone function.

gcc_jit_block*gcc_jit_function_new_block(gcc_jit_function*func,constchar*name)

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

for(pc=0;pc<fn->fn_num_ops;pc++){charbuf[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

voidgcc_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;
voidgcc_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 givenlvalue.

This is roughly equivalent to this C code:

lvalue=rvalue;
voidgcc_jit_block_add_assignment_op(gcc_jit_block*block,gcc_jit_location*loc,gcc_jit_lvalue*lvalue,enumgcc_jit_binary_opop,gcc_jit_rvalue*rvalue)

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

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));
voidgcc_jit_block_add_comment(gcc_jit_block*block,gcc_jit_location*loc,constchar*text)

Add a no-op textual comment to the internal representation of thecode. It will be optimized away, but will be visible in the dumpsseen viaGCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREEandGCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,and thus may be of use when debugging how your project’s internalrepresentation gets converted to the libgccjit IR.

The parametertext must be non-NULL. It is copied, so the inputbuffer does not need to outlive the call. For example:

charbuf[100];snprintf(buf,sizeof(buf),"op%i: %s",pc,opcode_names[op->op_opcode]);gcc_jit_block_add_comment(block,loc,buf);
voidgcc_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 theresult to the appropriate successor block.

This is roughly equivalent to this C code:

if(boolval)gotoon_true;elsegotoon_false;

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

voidgcc_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:

gototarget;
voidgcc_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:

returnexpression;
voidgcc_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 functionwith “void” return type.

This is equivalent to this C code:

return;
voidgcc_jit_block_end_with_switch(gcc_jit_block*block,gcc_jit_location*loc,gcc_jit_rvalue*expr,gcc_jit_block*default_block,intnum_cases,gcc_jit_case**cases)

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

This is roughly equivalent to this C code:

switch(expr){default:gotodefault_block;caseC0.min_value...C0.max_value:gotoC0.dest_block;caseC1.min_value...C1.max_value:gotoC1.dest_block;...etc...caseC[N-1].min_value...C[N-1].max_value:gotoC[N-1].dest_block;}

block,expr,default_block andcases must all benon-NULL.

expr must be of the same integer type as all of themin_valueandmax_value within the cases.

num_cases must be >= 0.

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

The API entrypoints relating to switch statements and cases:

were added inLIBGCCJIT_ABI_3; you can test for their presenceusing

#ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS
typegcc_jit_case

Agcc_jit_case represents a case within a switch statement, andis created within a particulargcc_jit_context usinggcc_jit_context_new_case().

Each case expresses a multivalued range of integer values. Youcan express single-valued cases by passing in the same value forbothmin_value andmax_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 andmax_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 switchstatement.

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:

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

See alsogcc_jit_extended_asm for entrypoints for adding inlineassembler statements to a function.