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 parameter
typemust be non-void.The parameter
namemust 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 a
gcc_jit_resultviagcc_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 with
inlineand 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 parameter
namemust be non-NULL. The call takes a copy of theunderlying string, so it is valid to pass in a pointer to an on-stackbuffer.- enumgcc_jit_function_kind¶
- gcc_jit_function*gcc_jit_context_get_builtin_function(gcc_jit_context*ctxt,constchar*name)¶
Get the
gcc_jit_functionfor 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 the
gcc_jit_functionfor 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 parameter
typemust be non-void.The parameter
namemust 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 to
gcc_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 parameter
typemust 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¶
- typegcc_jit_case¶
- void gcc_jit_function_add_attribute(gcc_jit_function*func,
- enumgcc_jit_fn_attributeattribute)
Add an attribute
attributeto 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 attribute
attributewith valuevalueto 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 attribute
attributewithlengthinteger valuesvalueto 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 via
GCC_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 parameter
textmust 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_blockandcasesmust all benon-NULL.exprmust be of the same integer type as all of themin_valueandmax_valuewithin the cases.num_casesmust 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 particular
gcc_jit_contextusinggcc_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));}
- typegcc_jit_case¶
See alsogcc_jit_extended_asm for entrypoints for adding inlineassembler statements to a function.