Compiling a context

Once populated, a gcc_jit_context * can be compiled to machine code, either in-memory via gcc_jit_context_compile() or to disk via gcc_jit_context_compile_to_file().

You can compile a context multiple times (using either form of compilation), although any errors that occur on the context will prevent any future compilation of that context.

In-memory compilation

gcc_jit_result * gcc_jit_context_compile(gcc_jit_context *ctxt)

This calls into GCC and builds the code, returning a gcc_jit_result *.

If the result is non-NULL, the caller becomes responsible for calling gcc_jit_result_release() on it once they’re done with it.

gcc_jit_result

A gcc_jit_result encapsulates the result of compiling a context in-memory, and the lifetimes of any machine code functions or globals that are within the result.

void * gcc_jit_result_get_code(gcc_jit_result *result, const char *funcname)

Locate a given function within the built machine code.

Functions are looked up by name. For this to succeed, a function with a name matching funcname must have been created on result’s context (or a parent context) via a call to gcc_jit_context_new_function() with kind GCC_JIT_FUNCTION_EXPORTED:

gcc_jit_context_new_function (ctxt,
                              any_location, /* or NULL */
                              /* Required for func to be visible to
                                 gcc_jit_result_get_code: */
                              GCC_JIT_FUNCTION_EXPORTED,
                              any_return_type,
                              /* Must string-compare equal: */
                              funcname,
                              /* etc */);

If such a function is not found (or result or funcname are NULL), an error message will be emitted on stderr and NULL will be returned.

If the function is found, the result will need to be cast to a function pointer of the correct type before it can be called.

Note that the resulting machine code becomes invalid after gcc_jit_result_release() is called on the gcc_jit_result *; attempting to call it after that may lead to a segmentation fault.

void * gcc_jit_result_get_global(gcc_jit_result *result, const char *name)

Locate a given global within the built machine code.

Globals are looked up by name. For this to succeed, a global with a name matching name must have been created on result’s context (or a parent context) via a call to gcc_jit_context_new_global() with kind GCC_JIT_GLOBAL_EXPORTED.

If the global is found, the result will need to be cast to a pointer of the correct type before it can be called.

This is a pointer to the global, so e.g. for an int this is an int *.

For example, given an int foo; created this way:

gcc_jit_lvalue *exported_global =
  gcc_jit_context_new_global (ctxt,
  any_location, /* or NULL */
  GCC_JIT_GLOBAL_EXPORTED,
  int_type,
  "foo");

we can access it like this:

int *ptr_to_foo =
  (int *)gcc_jit_result_get_global (result, "foo");

If such a global is not found (or result or name are NULL), an error message will be emitted on stderr and NULL will be returned.

Note that the resulting address becomes invalid after gcc_jit_result_release() is called on the gcc_jit_result *; attempting to use it after that may lead to a segmentation fault.

void gcc_jit_result_release(gcc_jit_result *result)

Once we’re done with the code, this unloads the built .so file. This cleans up the result; after calling this, it’s no longer valid to use the result, or any code or globals that were obtained by calling gcc_jit_result_get_code() or gcc_jit_result_get_global() on it.

Ahead-of-time compilation

Although libgccjit is primarily aimed at just-in-time compilation, it can also be used for implementing more traditional ahead-of-time compilers, via the gcc_jit_context_compile_to_file() API entrypoint.

void gcc_jit_context_compile_to_file(gcc_jit_context *ctxt, enum gcc_jit_output_kind output_kind, const char *output_path)

Compile the gcc_jit_context * to a file of the given kind.

gcc_jit_context_compile_to_file() ignores the suffix of output_path, and insteads uses the given enum gcc_jit_output_kind to decide what to do.

Note

This is different from the gcc program, which does make use of the suffix of the output file when determining what to do.

enum gcc_jit_output_kind

The available kinds of output are:

Output kind

Typical suffix

GCC_JIT_OUTPUT_KIND_ASSEMBLER

.s

GCC_JIT_OUTPUT_KIND_OBJECT_FILE

.o

GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY

.so or .dll

GCC_JIT_OUTPUT_KIND_EXECUTABLE

None, or .exe

GCC_JIT_OUTPUT_KIND_ASSEMBLER

Compile the context to an assembler file.

GCC_JIT_OUTPUT_KIND_OBJECT_FILE

Compile the context to an object file.

GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY

Compile the context to a dynamic library.

There is currently no support for specifying other libraries to link against.

GCC_JIT_OUTPUT_KIND_EXECUTABLE

Compile the context to an executable.

There is currently no support for specifying libraries to link against.