Table Of Contents

Previous topic

Types

Next topic

Creating and using functions

This Page

Expressions

Rvalues

A :c:type:`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 :c:type:`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 :c:type:`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 :c:type:`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 :c:data:`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.

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 available unary operations are:

Unary Operation C equivalent
:c:macro:`GCC_JIT_UNARY_OP_MINUS` -(EXPR)
:c:macro:`GCC_JIT_UNARY_OP_BITWISE_NEGATE` ~(EXPR)
:c:macro:`GCC_JIT_UNARY_OP_LOGICAL_NEGATE` !(EXPR)
:c:macro:`GCC_JIT_UNARY_OP_ABS` abs (EXPR)

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 available binary operations are:

Binary Operation C equivalent
:c:macro:`GCC_JIT_BINARY_OP_PLUS` x + y
:c:macro:`GCC_JIT_BINARY_OP_MINUS` x - y
:c:macro:`GCC_JIT_BINARY_OP_MULT` x * y
:c:macro:`GCC_JIT_BINARY_OP_DIVIDE` x / y
:c:macro:`GCC_JIT_BINARY_OP_MODULO` x % y
:c:macro:`GCC_JIT_BINARY_OP_BITWISE_AND` x & y
:c:macro:`GCC_JIT_BINARY_OP_BITWISE_XOR` x ^ y
:c:macro:`GCC_JIT_BINARY_OP_BITWISE_OR` x | y
:c:macro:`GCC_JIT_BINARY_OP_LOGICAL_AND` x && y
:c:macro:`GCC_JIT_BINARY_OP_LOGICAL_OR` x || y
:c:macro:`GCC_JIT_BINARY_OP_LSHIFT` x << y
:c:macro:`GCC_JIT_BINARY_OP_RSHIFT` x >> y

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.
Comparison C equivalent
:c:macro:`GCC_JIT_COMPARISON_EQ` x == y
:c:macro:`GCC_JIT_COMPARISON_NE` x != y
:c:macro:`GCC_JIT_COMPARISON_LT` x < y
:c:macro:`GCC_JIT_COMPARISON_LE` x <= y
:c:macro:`GCC_JIT_COMPARISON_GT` x > y
:c:macro:`GCC_JIT_COMPARISON_GE` 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

:c:func:`gcc_jit_context_new_call` merely builds a :c:type:`gcc_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), use :c:func:`gcc_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, 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 :c:func:`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 :c:type:`gcc_jit_rvalue *` for a call created through :c:func:`gcc_jit_context_new_call` or :c:func:`gcc_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

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

Lvalues

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.

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 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 :c:type:`gcc_jit_result`:

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 type T. 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 of index corresponds to sizeof(T) bytes. Analogous to:

PTR[INDEX]

in C (or, indeed, to PTR + INDEX).