Expressions#
Rvalues#
-
type gcc_jit_rvalue#
A gcc_jit_rvalue
is an expression that can be computed.
It can be simple, e.g.:
an integer value e.g. 0 or 42
a string literal e.g. “Hello world”
a variable e.g. i. These are also lvalues (see below).
or compound e.g.:
a unary expression e.g. !cond
a binary expression e.g. (a + b)
a function call e.g. get_distance (&player_ship, &target)
etc.
Every rvalue has an associated type, and the API will check to ensure that types match up correctly (otherwise the context will emit an error).
-
gcc_jit_type *gcc_jit_rvalue_get_type(gcc_jit_rvalue *rvalue)#
Get the type of this rvalue.
-
gcc_jit_object *gcc_jit_rvalue_as_object(gcc_jit_rvalue *rvalue)#
Upcast the given rvalue to be an object.
Simple expressions#
-
gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_int(gcc_jit_context *ctxt, gcc_jit_type *numeric_type, int value)#
Given a numeric type (integer or floating point), build an rvalue for the given constant int value.
-
gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_long(gcc_jit_context *ctxt, gcc_jit_type *numeric_type, long value)#
Given a numeric type (integer or floating point), build an rvalue for the given constant long value.
-
gcc_jit_rvalue *gcc_jit_context_zero(gcc_jit_context *ctxt, gcc_jit_type *numeric_type)#
Given a numeric type (integer or floating point), get the rvalue for zero. Essentially this is just a shortcut for:
gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0)
-
gcc_jit_rvalue *gcc_jit_context_one(gcc_jit_context *ctxt, gcc_jit_type *numeric_type)#
Given a numeric type (integer or floating point), get the rvalue for one. Essentially this is just a shortcut for:
gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1)
-
gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_double(gcc_jit_context *ctxt, gcc_jit_type *numeric_type, double value)#
Given a numeric type (integer or floating point), build an rvalue for the given constant double value.
-
gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_ptr(gcc_jit_context *ctxt, gcc_jit_type *pointer_type, void *value)#
Given a pointer type, build an rvalue for the given address.
-
gcc_jit_rvalue *gcc_jit_context_null(gcc_jit_context *ctxt, gcc_jit_type *pointer_type)#
Given a pointer type, build an rvalue for
NULL
. Essentially this is just a shortcut for:gcc_jit_context_new_rvalue_from_ptr (ctxt, pointer_type, NULL)
-
gcc_jit_rvalue *gcc_jit_context_new_string_literal(gcc_jit_context *ctxt, const char *value)#
Generate an rvalue for the given NIL-terminated string, of type
GCC_JIT_TYPE_CONST_CHAR_PTR
.The parameter
value
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.
Constructor expressions#
The following functions make constructors for array, struct and union types.
The constructor rvalue can be used for assignment to locals. It can be used to initialize global variables with
gcc_jit_global_set_initializer_rvalue()
. It can also be used as a temporary value for function calls and return values, but its address can’t be taken.Note that arrays in libgccjit do not collapse to pointers like in C. I.e. if an array constructor is used as e.g. a return value, the whole array would be returned by value - array constructors can be assigned to array variables.
The constructor can contain nested constructors.
Note that a string literal rvalue can’t be used to construct a char array; the latter needs one rvalue for each char.
These entrypoints were added in LIBGCCJIT_ABI_19; you can test for their presence using:
#ifdef LIBGCCJIT_HAVE_CTORS
-
gcc_jit_rvalue *gcc_jit_context_new_array_constructor(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type, size_t num_values, gcc_jit_rvalue **values)#
Create a constructor for an array as an rvalue.
Returns NULL on error.
values
are copied and do not have to outlive the context.type
specifies what the constructor will build and has to be an array.num_values
specifies the number of elements invalues
and it can’t have more elements than the array type.Each value in
values
sets the corresponding value in the array. If the array type itself has more elements thanvalues
, the left-over elements will be zeroed.Each value in
values
need to be the same unqualified type as the array type’s element type.If
num_values
is 0, thevalues
parameter will be ignored and zero initialization will be used.This entrypoint was added in LIBGCCJIT_ABI_19; you can test for its presence using:
#ifdef LIBGCCJIT_HAVE_CTORS
-
gcc_jit_rvalue *gcc_jit_context_new_struct_constructor(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type, size_t num_values, gcc_jit_field **fields, gcc_jit_rvalue **values)#
Create a constructor for a struct as an rvalue.
Returns NULL on error. The two parameter arrays are copied and do not have to outlive the context.
type
specifies what the constructor will build and has to be a struct.num_values
specifies the number of elements invalues
.fields
need to have the same length asvalues
, or be NULL.If
fields
is null, the values are applied in definition order.Otherwise, each field in
fields
specifies which field in the struct to set to the corresponding value invalues
.fields
andvalues
are paired by index.The fields in
fields
have to be in definition order, but there can be gaps. Any field in the struct that is not specified infields
will be zeroed.The fields in
fields
need to be the same objects that were used to create the struct.Each value has to have have the same unqualified type as the field it is applied to.
A NULL value element in
values
is a shorthand for zero initialization of the corresponding field.If
num_values
is 0, the array parameters will be ignored and zero initialization will be used.This entrypoint was added in LIBGCCJIT_ABI_19; you can test for its presence using:
#ifdef LIBGCCJIT_HAVE_CTORS
-
gcc_jit_rvalue *gcc_jit_context_new_union_constructor(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *type, gcc_jit_field *field, gcc_jit_rvalue *value)#
Create a constructor for a union as an rvalue.
Returns NULL on error.
type
specifies what the constructor will build and has to be an union.field
specifies which field to set. If it is NULL, the first field in the union will be set.``field`` need to be the same object that were used to create the union.value
specifies what value to set the corresponding field to. Ifvalue
is NULL, zero initialization will be used.Each value has to have have the same unqualified type as the field it is applied to.
This entrypoint was added in LIBGCCJIT_ABI_19; you can test for its presence using:
#ifdef LIBGCCJIT_HAVE_CTORS
Vector expressions#
-
gcc_jit_rvalue *gcc_jit_context_new_rvalue_from_vector(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_type *vec_type, size_t num_elements, gcc_jit_rvalue **elements)#
Build a vector rvalue from an array of elements.
“vec_type” should be a vector type, created using
gcc_jit_type_get_vector()
.“num_elements” should match that of the vector type.
This entrypoint was added in LIBGCCJIT_ABI_10; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector
Unary Operations#
-
gcc_jit_rvalue *gcc_jit_context_new_unary_op(gcc_jit_context *ctxt, gcc_jit_location *loc, enum gcc_jit_unary_op op, gcc_jit_type *result_type, gcc_jit_rvalue *rvalue)#
Build a unary operation out of an input rvalue.
The parameter
result_type
must be a numeric type.
-
enum gcc_jit_unary_op#
The available unary operations are:
Unary Operation |
C equivalent |
---|---|
-(EXPR) |
|
~(EXPR) |
|
!(EXPR) |
|
abs (EXPR) |
-
GCC_JIT_UNARY_OP_MINUS#
Negate an arithmetic value; analogous to:
-(EXPR)
in C.
-
GCC_JIT_UNARY_OP_BITWISE_NEGATE#
Bitwise negation of an integer value (one’s complement); analogous to:
~(EXPR)
in C.
-
GCC_JIT_UNARY_OP_LOGICAL_NEGATE#
Logical negation of an arithmetic or pointer value; analogous to:
!(EXPR)
in C.
-
GCC_JIT_UNARY_OP_ABS#
Absolute value of an arithmetic expression; analogous to:
abs (EXPR)
in C.
Binary Operations#
-
gcc_jit_rvalue *gcc_jit_context_new_binary_op(gcc_jit_context *ctxt, gcc_jit_location *loc, enum gcc_jit_binary_op op, gcc_jit_type *result_type, gcc_jit_rvalue *a, gcc_jit_rvalue *b)#
Build a binary operation out of two constituent rvalues.
The parameter
result_type
must be a numeric type.
-
enum gcc_jit_binary_op#
The available binary operations are:
Binary Operation |
C equivalent |
---|---|
x + y |
|
x - y |
|
x * y |
|
x / y |
|
x % y |
|
x & y |
|
x ^ y |
|
x | y |
|
x && y |
|
x || y |
|
x << y |
|
x >> y |
-
GCC_JIT_BINARY_OP_PLUS#
Addition of arithmetic values; analogous to:
(EXPR_A) + (EXPR_B)
in C.
For pointer addition, use
gcc_jit_context_new_array_access()
.
-
GCC_JIT_BINARY_OP_MINUS#
Subtraction of arithmetic values; analogous to:
(EXPR_A) - (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_MULT#
Multiplication of a pair of arithmetic values; analogous to:
(EXPR_A) * (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_DIVIDE#
Quotient of division of arithmetic values; analogous to:
(EXPR_A) / (EXPR_B)
in C.
The result type affects the kind of division: if the result type is integer-based, then the result is truncated towards zero, whereas a floating-point result type indicates floating-point division.
-
GCC_JIT_BINARY_OP_MODULO#
Remainder of division of arithmetic values; analogous to:
(EXPR_A) % (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_BITWISE_AND#
Bitwise AND; analogous to:
(EXPR_A) & (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_BITWISE_XOR#
Bitwise exclusive OR; analogous to:
(EXPR_A) ^ (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_BITWISE_OR#
Bitwise inclusive OR; analogous to:
(EXPR_A) | (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_LOGICAL_AND#
Logical AND; analogous to:
(EXPR_A) && (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_LOGICAL_OR#
Logical OR; analogous to:
(EXPR_A) || (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_LSHIFT#
Left shift; analogous to:
(EXPR_A) << (EXPR_B)
in C.
-
GCC_JIT_BINARY_OP_RSHIFT#
Right shift; analogous to:
(EXPR_A) >> (EXPR_B)
in C.
Comparisons#
-
gcc_jit_rvalue *gcc_jit_context_new_comparison(gcc_jit_context *ctxt, gcc_jit_location *loc, enum gcc_jit_comparison op, gcc_jit_rvalue *a, gcc_jit_rvalue *b)#
Build a boolean rvalue out of the comparison of two other rvalues.
-
enum gcc_jit_comparison#
Comparison |
C equivalent |
---|---|
|
x == y |
|
x != y |
|
x < y |
|
x <= y |
|
x > y |
|
x >= y |
Function calls#
-
gcc_jit_rvalue *gcc_jit_context_new_call(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_function *func, int numargs, gcc_jit_rvalue **args)#
Given a function and the given table of argument rvalues, construct a call to the function, with the result as an rvalue.
Note
gcc_jit_context_new_call()
merely builds agcc_jit_rvalue
i.e. an expression that can be evaluated, perhaps as part of a more complicated expression. The call won’t happen unless you add a statement to a function that evaluates the expression.For example, if you want to call a function and discard the result (or to call a function with
void
return type), usegcc_jit_block_add_eval()
:/* Add "(void)printf (arg0, arg1);". */ gcc_jit_block_add_eval ( block, NULL, gcc_jit_context_new_call ( ctxt, NULL, printf_func, 2, args));
-
gcc_jit_rvalue *gcc_jit_context_new_call_through_ptr(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *fn_ptr, int numargs, gcc_jit_rvalue **args)#
Given an rvalue of function pointer type (e.g. from
gcc_jit_context_new_function_ptr_type()
), and the given table of argument rvalues, construct a call to the function pointer, with the result as an rvalue.Note
The same caveat as for
gcc_jit_context_new_call()
applies.
-
void gcc_jit_rvalue_set_bool_require_tail_call(gcc_jit_rvalue *call, int require_tail_call)#
Given an
gcc_jit_rvalue
for a call created throughgcc_jit_context_new_call()
orgcc_jit_context_new_call_through_ptr()
, mark/clear the call as needing tail-call optimization. The optimizer will attempt to optimize the call into a jump instruction; if it is unable to do do, an error will be emitted.This may be useful when implementing functions that use the continuation-passing style (e.g. for functional programming languages), in which every function “returns” by calling a “continuation” function pointer. This call must be guaranteed to be implemented as a jump, otherwise the program could consume an arbitrary amount of stack space as it executed.
This entrypoint was added in LIBGCCJIT_ABI_6; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call
Function pointers#
Function pointers can be obtained:
from a
gcc_jit_function
usinggcc_jit_function_get_address()
, orfrom an existing function using
gcc_jit_context_new_rvalue_from_ptr()
, using a function pointer type obtained usinggcc_jit_context_new_function_ptr_type()
.
Type-coercion#
-
gcc_jit_rvalue *gcc_jit_context_new_cast(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *rvalue, gcc_jit_type *type)#
Given an rvalue of T, construct another rvalue of another type.
Currently only a limited set of conversions are possible:
int <-> float
int <-> bool
P* <-> Q*, for pointer types P and Q
-
gcc_jit_rvalue *gcc_jit_context_new_bitcast(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *rvalue, gcc_jit_type *type)#
Given an rvalue of T, bitcast it to another type, meaning that this will generate a new rvalue by interpreting the bits of
rvalue
to the layout oftype
.The type of rvalue must be the same size as the size of
type
.This entrypoint was added in LIBGCCJIT_ABI_21; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast
Lvalues#
-
type gcc_jit_lvalue#
An lvalue is something that can of the left-hand side of an assignment: a storage area (such as a variable). It is also usable as an rvalue, where the rvalue is computed by reading from the storage area.
-
gcc_jit_object *gcc_jit_lvalue_as_object(gcc_jit_lvalue *lvalue)#
Upcast an lvalue to be an object.
-
gcc_jit_rvalue *gcc_jit_lvalue_as_rvalue(gcc_jit_lvalue *lvalue)#
Upcast an lvalue to be an rvalue.
-
gcc_jit_rvalue *gcc_jit_lvalue_get_address(gcc_jit_lvalue *lvalue, gcc_jit_location *loc)#
Take the address of an lvalue; analogous to:
&(EXPR)
in C.
-
void gcc_jit_lvalue_set_tls_model(gcc_jit_lvalue *lvalue, enum gcc_jit_tls_model model)#
Make a variable a thread-local variable.
The “model” parameter determines the thread-local storage model of the “lvalue”:
-
enum gcc_jit_tls_model#
-
GCC_JIT_TLS_MODEL_NONE#
Don’t set the TLS model.
-
GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC#
-
GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC#
-
GCC_JIT_TLS_MODEL_INITIAL_EXEC#
-
GCC_JIT_TLS_MODEL_LOCAL_EXEC#
This is analogous to:
_Thread_local int foo __attribute__ ((tls_model("MODEL")));
in C.
This entrypoint was added in LIBGCCJIT_ABI_17; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model
-
enum gcc_jit_tls_model#
-
void gcc_jit_lvalue_set_link_section(gcc_jit_lvalue *lvalue, const char *section_name)#
Set the link section of a variable. The parameter
section_name
must be non-NULL and must contain the leading dot. Analogous to:int variable __attribute__((section(".section")));
in C.
This entrypoint was added in LIBGCCJIT_ABI_18; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_link_section
-
void gcc_jit_lvalue_set_register_name(gcc_jit_lvalue *lvalue, const char *reg_name);#
Set the register name of a variable. The parameter
reg_name
must be non-NULL. Analogous to:register int variable asm ("r12");
in C.
This entrypoint was added in LIBGCCJIT_ABI_22; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_register_name
-
void gcc_jit_lvalue_set_alignment(gcc_jit_lvalue *lvalue, unsigned bytes)#
Set the alignment of a variable, in bytes. Analogous to:
int variable __attribute__((aligned (16)));
in C.
This entrypoint was added in LIBGCCJIT_ABI_24; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_ALIGNMENT
-
unsigned gcc_jit_lvalue_get_alignment(gcc_jit_lvalue *lvalue)#
Return the alignment of a variable set by
gcc_jit_lvalue_set_alignment
. Return 0 if the alignment was not set. Analogous to:_Alignof (variable)
in C.
This entrypoint was added in LIBGCCJIT_ABI_24; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_ALIGNMENT
Global variables#
-
gcc_jit_lvalue *gcc_jit_context_new_global(gcc_jit_context *ctxt, gcc_jit_location *loc, enum gcc_jit_global_kind kind, gcc_jit_type *type, const char *name)#
Add a new global variable of the given type and name to the context.
The parameter
type
must be non-void.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.The “kind” parameter determines the visibility of the “global” outside of the
gcc_jit_result
:-
enum gcc_jit_global_kind#
-
GCC_JIT_GLOBAL_EXPORTED#
Global is defined by the client code and is visible by name outside of this JIT context via
gcc_jit_result_get_global()
(and this value is required for the global to be accessible via that entrypoint).
-
GCC_JIT_GLOBAL_INTERNAL#
Global is defined by the client code, but is invisible outside of it. Analogous to a “static” global within a .c file. Specifically, the variable will only be visible within this context and within child contexts.
-
GCC_JIT_GLOBAL_IMPORTED#
Global is not defined by the client code; we’re merely referring to it. Analogous to using an “extern” global from a header file.
-
enum gcc_jit_global_kind#
-
gcc_jit_lvalue *gcc_jit_global_set_initializer(gcc_jit_lvalue *global, const void *blob, size_t num_bytes)#
Set an initializer for
global
using the memory content pointed byblob
fornum_bytes
.global
must be an array of an integral type. Return the global itself.The parameter
blob
must be non-NULL. The call copies the memory pointed byblob
fornum_bytes
bytes, so it is valid to pass in a pointer to an on-stack buffer. The content will be stored in the compilation unit and used as initialization value of the array.This entrypoint was added in LIBGCCJIT_ABI_14; you can test for its presence using
#ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer
-
gcc_jit_lvalue *gcc_jit_global_set_initializer_rvalue(gcc_jit_lvalue *global, gcc_jit_rvalue *init_value)#
Set the initial value of a global with an rvalue.
The rvalue needs to be a constant expression, e.g. no function calls.
The global can’t have the
kind
GCC_JIT_GLOBAL_IMPORTED
.As a non-comprehensive example it is OK to do the equivalent of:
int foo = 3 * 2; /* rvalue from gcc_jit_context_new_binary_op. */ int arr[] = {1,2,3,4}; /* rvalue from gcc_jit_context_new_constructor. */ int *bar = &arr[2] + 1; /* rvalue from nested "get address" of "array access". */ const int baz = 3; /* rvalue from gcc_jit_context_rvalue_from_int. */ int boz = baz; /* rvalue from gcc_jit_lvalue_as_rvalue. */
Use together with
gcc_jit_context_new_struct_constructor()
,gcc_jit_context_new_union_constructor()
,gcc_jit_context_new_array_constructor()
to initialize structs, unions and arrays.On success, returns the
global
parameter unchanged. Otherwise,NULL
.This entrypoint was added in LIBGCCJIT_ABI_19; you can test for its presence using:
#ifdef LIBGCCJIT_HAVE_CTORS
Working with pointers, structs and unions#
-
gcc_jit_lvalue *gcc_jit_rvalue_dereference(gcc_jit_rvalue *rvalue, gcc_jit_location *loc)#
Given an rvalue of pointer type
T *
, dereferencing the pointer, getting an lvalue of typeT
. Analogous to:*(EXPR)
in C.
Field access is provided separately for both lvalues and rvalues.
-
gcc_jit_lvalue *gcc_jit_lvalue_access_field(gcc_jit_lvalue *struct_, gcc_jit_location *loc, gcc_jit_field *field)#
Given an lvalue of struct or union type, access the given field, getting an lvalue of the field’s type. Analogous to:
(EXPR).field = ...;
in C.
-
gcc_jit_rvalue *gcc_jit_rvalue_access_field(gcc_jit_rvalue *struct_, gcc_jit_location *loc, gcc_jit_field *field)#
Given an rvalue of struct or union type, access the given field as an rvalue. Analogous to:
(EXPR).field
in C.
-
gcc_jit_lvalue *gcc_jit_rvalue_dereference_field(gcc_jit_rvalue *ptr, gcc_jit_location *loc, gcc_jit_field *field)#
Given an rvalue of pointer type
T *
where T is of struct or union type, access the given field as an lvalue. Analogous to:(EXPR)->field
in C, itself equivalent to
(*EXPR).FIELD
.
-
gcc_jit_lvalue *gcc_jit_context_new_array_access(gcc_jit_context *ctxt, gcc_jit_location *loc, gcc_jit_rvalue *ptr, gcc_jit_rvalue *index)#
Given an rvalue of pointer type
T *
, get at the element T at the given index, using standard C array indexing rules i.e. each increment ofindex
corresponds tosizeof(T)
bytes. Analogous to:PTR[INDEX]
in C (or, indeed, to
PTR + INDEX
).