Compilation contexts

class gccjit::context

The top-level of the C++ API is the gccjit::context type.

A gccjit::context instance encapsulates the state of a compilation.

You can set up options on it, and add types, functions and code. Invoking gccjit::context::compile() on it gives you a gcc_jit_result *.

It is a thin wrapper around the C API’s gcc_jit_context *.

Lifetime-management

Contexts are the unit of lifetime-management within the API: objects have their lifetime bounded by the context they are created within, and cleanup of such objects is done for you when the context is released.

gccjit::context gccjit::context::acquire()

This function acquires a new gccjit::context instance, which is independent of any others that may be present within this process.

void gccjit::context::release()

This function releases all resources associated with the given context. Both the context itself and all of its gccjit::object * instances are cleaned up. It should be called exactly once on a given context.

It is invalid to use the context or any of its “contextual” objects after calling this.

ctxt.release ();
gccjit::context gccjit::context::new_child_context()

Given an existing JIT context, create a child context.

The child inherits a copy of all option-settings from the parent.

The child can reference objects created within the parent, but not vice-versa.

The lifetime of the child context must be bounded by that of the parent: you should release a child context before releasing the parent context.

If you use a function from a parent context within a child context, you have to compile the parent context before you can compile the child context, and the gccjit::result of the parent context must outlive the gccjit::result of the child context.

This allows caching of shared initializations. For example, you could create types and declarations of global functions in a parent context once within a process, and then create child contexts whenever a function or loop becomes hot. Each such child context can be used for JIT-compiling just one function or loop, but can reference types and helper functions created within the parent context.

Contexts can be arbitrarily nested, provided the above rules are followed, but it’s probably not worth going above 2 or 3 levels, and there will likely be a performance hit for such nesting.

Thread-safety

Instances of gccjit::context created via gccjit::context::acquire() are independent from each other: only one thread may use a given context at once, but multiple threads could each have their own contexts without needing locks.

Contexts created via gccjit::context::new_child_context() are related to their parent context. They can be partitioned by their ultimate ancestor into independent “family trees”. Only one thread within a process may use a given “family tree” of such contexts at once, and if you’re using multiple threads you should provide your own locking around entire such context partitions.

Error-handling

You can only compile and get code from a context if no errors occur.

In general, if an error occurs when using an API entrypoint, it returns NULL. You don’t have to check everywhere for NULL results, since the API gracefully handles a NULL being passed in for any argument.

Errors are printed on stderr and can be queried using gccjit::context::get_first_error().

const char *gccjit::context::get_first_error(gccjit::context *ctxt)

Returns the first error message that occurred on the context.

The returned string is valid for the rest of the lifetime of the context.

If no errors occurred, this will be NULL.

Debugging

void gccjit::context::dump_to_file(const std::string &path, int update_locations)

To help with debugging: dump a C-like representation to the given path, describing what’s been set up on the context.

If “update_locations” is true, then also set up gccjit::location information throughout the context, pointing at the dump file as if it were a source file. This may be of use in conjunction with GCCJIT::BOOL_OPTION_DEBUGINFO to allow stepping through the code in a debugger.

void gccjit::context::dump_reproducer_to_file(gcc_jit_context *ctxt, const char *path)

This is a thin wrapper around the C API gcc_jit_context_dump_reproducer_to_file(), and hence works the same way.

Note that the generated source is C code, not C++; this might be of use for seeing what the C++ bindings are doing at the C level.

Options

String Options

void gccjit::context::set_str_option(enum gcc_jit_str_option, const char *value)

Set a string option of the context.

This is a thin wrapper around the C API gcc_jit_context_set_str_option(); the options have the same meaning.

Boolean options

void gccjit::context::set_bool_option(enum gcc_jit_bool_option, int value)

Set a boolean option of the context.

This is a thin wrapper around the C API gcc_jit_context_set_bool_option(); the options have the same meaning.

void gccjit::context::set_bool_allow_unreachable_blocks(int bool_value)

By default, libgccjit will issue an error about unreachable blocks within a function.

This entrypoint can be used to disable that error; it is a thin wrapper around the C API gcc_jit_context_set_bool_allow_unreachable_blocks().

This entrypoint was added in LIBGCCJIT_ABI_2; you can test for its presence using

#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks
void gccjit::context::set_bool_use_external_driver(int bool_value)

libgccjit internally generates assembler, and uses “driver” code for converting it to other formats (e.g. shared libraries).

By default, libgccjit will use an embedded copy of the driver code.

This option can be used to instead invoke an external driver executable as a subprocess; it is a thin wrapper around the C API gcc_jit_context_set_bool_use_external_driver().

This entrypoint was added in LIBGCCJIT_ABI_5; you can test for its presence using

#ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver

Integer options

void gccjit::context::set_int_option(enum gcc_jit_int_option, int value)

Set an integer option of the context.

This is a thin wrapper around the C API gcc_jit_context_set_int_option(); the options have the same meaning.

Additional command-line options

void gccjit::context::add_command_line_option(const char *optname)

Add an arbitrary gcc command-line option to the context for use when compiling.

This is a thin wrapper around the C API gcc_jit_context_add_command_line_option().

This entrypoint was added in LIBGCCJIT_ABI_1; you can test for its presence using

#ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option