This is doc/libgccjit.info, produced by makeinfo version 4.8 from
/opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_lang_gcc9/gcc9/work/gcc-9.5.0/gcc/jit/docs/_build/texinfo/libgccjit.texi.

Generated by Sphinx 1.1.3.
INFO-DIR-SECTION Miscellaneous
START-INFO-DIR-ENTRY
* libgccjit: (libgccjit.info). One line description of project.
END-INFO-DIR-ENTRY

     libgccjit 8.0.0 (experimental 20171031), October 31, 2017

     David Malcolm

     Copyright (C) 2014-2019 Free Software Foundation, Inc.


File: libgccjit.info,  Node: Top,  Next: Tutorial,  Up: (dir)

libgccjit Documentation
***********************

     libgccjit 8.0.0 (experimental 20171031), October 31, 2017

     David Malcolm

     Copyright (C) 2014-2019 Free Software Foundation, Inc.

  This document describes libgccjit(1), an API for embedding GCC inside
programs and libraries.

  Note that libgccjit is currently of "Alpha" quality; the APIs are not
yet set in stone, and they shouldn't be used in production yet.

  There are actually two APIs for the library:

   * a pure C API: `libgccjit.h'

   * a C++ wrapper API: `libgccjit++.h'.  This is a collection of "thin"
     wrapper classes around the C API, to save typing.

  Contents:

* Menu:

* Tutorial::
* Topic Reference::
* C++ bindings for libgccjit::
* Internals::
* Indices and tables::
* Index::

 --- The Detailed Node Listing ---

Tutorial

* Tutorial part 1; "Hello world": Tutorial part 1 "Hello world".
* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function.
* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables.
* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter.
* Tutorial part 5; Implementing an Ahead-of-Time compiler: Tutorial part 5 Implementing an Ahead-of-Time compiler.

Tutorial part 2: Creating a trivial machine code function

* Error-handling::
* Options::
* Full example::

Tutorial part 3: Loops and variables

* Expressions; lvalues and rvalues: Expressions lvalues and rvalues.
* Control flow::
* Visualizing the control flow graph::
* Full example: Full example<2>.

Tutorial part 4: Adding JIT-compilation to a toy interpreter

* Our toy interpreter::
* Compiling to machine code::
* Setting things up::
* Populating the function::
* Verifying the control flow graph::
* Compiling the context::
* Single-stepping through the generated code::
* Examining the generated code::
* Putting it all together::
* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?.

Behind the curtain: How does our code get optimized?

* Optimizing away stack manipulation::
* Elimination of tail recursion::

Tutorial part 5: Implementing an Ahead-of-Time compiler

* The "brainf" language::
* Converting a brainf script to libgccjit IR::
* Compiling a context to a file::
* Other forms of ahead-of-time-compilation::

Topic Reference

* Compilation contexts::
* Objects::
* Types::
* Expressions::
* Creating and using functions::
* Function pointers: Function pointers<2>.
* Source Locations::
* Compiling a context::
* ABI and API compatibility::
* Performance::

Compilation contexts

* Lifetime-management::
* Thread-safety::
* Error-handling: Error-handling<2>.
* Debugging::
* Options: Options<2>.

Options

* String Options::
* Boolean options::
* Integer options::
* Additional command-line options::

Types

* Standard types::
* Pointers, const, and volatile: Pointers const and volatile.
* Vector types::
* Structures and unions::
* Function pointer types::

Expressions

* Rvalues::
* Lvalues::
* Working with pointers, structs and unions: Working with pointers structs and unions.

Rvalues

* Simple expressions::
* Vector expressions::
* Unary Operations::
* Binary Operations::
* Comparisons::
* Function calls::
* Function pointers::
* Type-coercion::

Lvalues

* Global variables::

Creating and using functions

* Params::
* Functions::
* Blocks::
* Statements::

Source Locations

* Faking it::

Compiling a context

* In-memory compilation::
* Ahead-of-time compilation::

ABI and API compatibility

* ABI symbol tags::

ABI symbol tags

* LIBGCCJIT_ABI_0::
* LIBGCCJIT_ABI_1::
* LIBGCCJIT_ABI_2::
* LIBGCCJIT_ABI_3::
* LIBGCCJIT_ABI_4::
* LIBGCCJIT_ABI_5::
* LIBGCCJIT_ABI_6::
* LIBGCCJIT_ABI_7::
* LIBGCCJIT_ABI_8::
* LIBGCCJIT_ABI_9::
* LIBGCCJIT_ABI_10::

Performance

* The timing API::

C++ bindings for libgccjit

* Tutorial: Tutorial<2>.
* Topic Reference: Topic Reference<2>.

Tutorial

* Tutorial part 1; "Hello world": Tutorial part 1 "Hello world"<2>.
* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>.
* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>.
* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>.

Tutorial part 2: Creating a trivial machine code function

* Options: Options<3>.
* Full example: Full example<3>.

Tutorial part 3: Loops and variables

* Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>.
* Control flow: Control flow<2>.
* Visualizing the control flow graph: Visualizing the control flow graph<2>.
* Full example: Full example<4>.

Tutorial part 4: Adding JIT-compilation to a toy interpreter

* Our toy interpreter: Our toy interpreter<2>.
* Compiling to machine code: Compiling to machine code<2>.
* Setting things up: Setting things up<2>.
* Populating the function: Populating the function<2>.
* Verifying the control flow graph: Verifying the control flow graph<2>.
* Compiling the context: Compiling the context<2>.
* Single-stepping through the generated code: Single-stepping through the generated code<2>.
* Examining the generated code: Examining the generated code<2>.
* Putting it all together: Putting it all together<2>.
* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>.

Behind the curtain: How does our code get optimized?

* Optimizing away stack manipulation: Optimizing away stack manipulation<2>.
* Elimination of tail recursion: Elimination of tail recursion<2>.

Topic Reference

* Compilation contexts: Compilation contexts<2>.
* Objects: Objects<2>.
* Types: Types<2>.
* Expressions: Expressions<2>.
* Creating and using functions: Creating and using functions<2>.
* Source Locations: Source Locations<2>.
* Compiling a context: Compiling a context<2>.

Compilation contexts

* Lifetime-management: Lifetime-management<2>.
* Thread-safety: Thread-safety<2>.
* Error-handling: Error-handling<3>.
* Debugging: Debugging<2>.
* Options: Options<4>.

Options

* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
* Additional command-line options: Additional command-line options<2>.

Types

* Standard types: Standard types<2>.
* Pointers, const, and volatile: Pointers const and volatile<2>.
* Vector types: Vector types<2>.
* Structures and unions: Structures and unions<2>.

Expressions

* Rvalues: Rvalues<2>.
* Lvalues: Lvalues<2>.
* Working with pointers, structs and unions: Working with pointers structs and unions<2>.

Rvalues

* Simple expressions: Simple expressions<2>.
* Vector expressions: Vector expressions<2>.
* Unary Operations: Unary Operations<2>.
* Binary Operations: Binary Operations<2>.
* Comparisons: Comparisons<2>.
* Function calls: Function calls<2>.
* Function pointers: Function pointers<3>.
* Type-coercion: Type-coercion<2>.

Lvalues

* Global variables: Global variables<2>.

Creating and using functions

* Params: Params<2>.
* Functions: Functions<2>.
* Blocks: Blocks<2>.
* Statements: Statements<2>.

Source Locations

* Faking it: Faking it<2>.

Compiling a context

* In-memory compilation: In-memory compilation<2>.
* Ahead-of-time compilation: Ahead-of-time compilation<2>.

Internals

* Working on the JIT library::
* Running the test suite::
* Environment variables::
* Packaging notes::
* Overview of code structure::
* Design notes::
* Submitting patches::

Running the test suite

* Running under valgrind::

  ---------- Footnotes ----------

  (1) http://gcc.gnu.org/wiki/JIT


File: libgccjit.info,  Node: Tutorial,  Next: Topic Reference,  Prev: Top,  Up: Top

1 Tutorial
**********

* Menu:

* Tutorial part 1; "Hello world": Tutorial part 1 "Hello world".
* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function.
* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables.
* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter.
* Tutorial part 5; Implementing an Ahead-of-Time compiler: Tutorial part 5 Implementing an Ahead-of-Time compiler.


File: libgccjit.info,  Node: Tutorial part 1 "Hello world",  Next: Tutorial part 2 Creating a trivial machine code function,  Up: Tutorial

1.1 Tutorial part 1: "Hello world"
==================================

Before we look at the details of the API, let's look at building and
running programs that use the library.

  Here's a toy "hello world" program that uses the library to synthesize
a call to `printf' and uses it to write a message to stdout.

  Don't worry about the content of the program for now; we'll cover the
details in later parts of this tutorial.

         /* Smoketest example for libgccjit.so
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit.h>

         #include <stdlib.h>
         #include <stdio.h>

         static void
         create_code (gcc_jit_context *ctxt)
         {
           /* Let's try to inject the equivalent of:
              void
              greet (const char *name)
              {
                 printf ("hello %s\n", name);
              }
           */
           gcc_jit_type *void_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
           gcc_jit_type *const_char_ptr_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CONST_CHAR_PTR);
           gcc_jit_param *param_name =
             gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "name");
           gcc_jit_function *func =
             gcc_jit_context_new_function (ctxt, NULL,
                                           GCC_JIT_FUNCTION_EXPORTED,
                                           void_type,
                                           "greet",
                                           1, &param_name,
                                           0);

           gcc_jit_param *param_format =
             gcc_jit_context_new_param (ctxt, NULL, const_char_ptr_type, "format");
           gcc_jit_function *printf_func =
             gcc_jit_context_new_function (ctxt, NULL,
         				  GCC_JIT_FUNCTION_IMPORTED,
         				  gcc_jit_context_get_type (
         				     ctxt, GCC_JIT_TYPE_INT),
         				  "printf",
         				  1, &param_format,
         				  1);
           gcc_jit_rvalue *args[2];
           args[0] = gcc_jit_context_new_string_literal (ctxt, "hello %s\n");
           args[1] = gcc_jit_param_as_rvalue (param_name);

           gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);

           gcc_jit_block_add_eval (
             block, NULL,
             gcc_jit_context_new_call (ctxt,
                                       NULL,
                                       printf_func,
                                       2, args));
           gcc_jit_block_end_with_void_return (block, NULL);
         }

         int
         main (int argc, char **argv)
         {
           gcc_jit_context *ctxt;
           gcc_jit_result *result;

           /* Get a "context" object for working with the library.  */
           ctxt = gcc_jit_context_acquire ();
           if (!ctxt)
             {
               fprintf (stderr, "NULL ctxt");
               exit (1);
             }

           /* Set some options on the context.
              Let's see the code being generated, in assembler form.  */
           gcc_jit_context_set_bool_option (
             ctxt,
             GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
             0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           result = gcc_jit_context_compile (ctxt);
           if (!result)
             {
               fprintf (stderr, "NULL result");
               exit (1);
             }

           /* Extract the generated code from "result".  */
           typedef void (*fn_type) (const char *);
           fn_type greet =
             (fn_type)gcc_jit_result_get_code (result, "greet");
           if (!greet)
             {
               fprintf (stderr, "NULL greet");
               exit (1);
             }

           /* Now call the generated function: */
           greet ("world");
           fflush (stdout);

           gcc_jit_context_release (ctxt);
           gcc_jit_result_release (result);
           return 0;
         }



  Copy the above to `tut01-hello-world.c'.

  Assuming you have the jit library installed, build the test program
using:

    $ gcc \
        tut01-hello-world.c \
        -o tut01-hello-world \
        -lgccjit

You should then be able to run the built program:

    $ ./tut01-hello-world
    hello world



File: libgccjit.info,  Node: Tutorial part 2 Creating a trivial machine code function,  Next: Tutorial part 3 Loops and variables,  Prev: Tutorial part 1 "Hello world",  Up: Tutorial

1.2 Tutorial part 2: Creating a trivial machine code function
=============================================================

Consider this C function:

    int square (int i)
    {
      return i * i;
    }

How can we construct this at run-time using libgccjit?

  First we need to include the relevant header:

    #include <libgccjit.h>

All state associated with compilation is associated with a *note
gcc_jit_context *: 8.

  Create one using *note gcc_jit_context_acquire(): 9.:

    gcc_jit_context *ctxt;
    ctxt = gcc_jit_context_acquire ();

The JIT library has a system of types.  It is statically-typed: every
expression is of a specific type, fixed at compile-time.  In our
example, all of the expressions are of the C `int' type, so let's
obtain this from the context, as a *note gcc_jit_type *: a, using *note
gcc_jit_context_get_type(): b.:

    gcc_jit_type *int_type =
      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

*note gcc_jit_type *: a. is an example of a "contextual" object: every
entity in the API is associated with a *note gcc_jit_context *: 8.

  Memory management is easy: all such "contextual" objects are
automatically cleaned up for you when the context is released, using
*note gcc_jit_context_release(): c.:

    gcc_jit_context_release (ctxt);

so you don't need to manually track and cleanup all objects, just the
contexts.

  Although the API is C-based, there is a form of class hierarchy, which
looks like this:

    +- gcc_jit_object
        +- gcc_jit_location
        +- gcc_jit_type
           +- gcc_jit_struct
        +- gcc_jit_field
        +- gcc_jit_function
        +- gcc_jit_block
        +- gcc_jit_rvalue
            +- gcc_jit_lvalue
               +- gcc_jit_param

There are casting methods for upcasting from subclasses to parent
classes.  For example, *note gcc_jit_type_as_object(): d.:

    gcc_jit_object *obj = gcc_jit_type_as_object (int_type);

One thing you can do with a *note gcc_jit_object *: e. is to ask it for
a human-readable description, using *note
gcc_jit_object_get_debug_string(): f.:

    printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj));

giving this text on stdout:

    obj: int

This is invaluable when debugging.

  Let's create the function.  To do so, we first need to construct its
single parameter, specifying its type and giving it a name, using *note
gcc_jit_context_new_param(): 10.:

    gcc_jit_param *param_i =
      gcc_jit_context_new_param (ctxt, NULL, int_type, "i");

Now we can create the function, using *note
gcc_jit_context_new_function(): 11.:

    gcc_jit_function *func =
      gcc_jit_context_new_function (ctxt, NULL,
                                    GCC_JIT_FUNCTION_EXPORTED,
                                    int_type,
                                    "square",
                                    1, &param_i,
                                    0);

To define the code within the function, we must create basic blocks
containing statements.

  Every basic block contains a list of statements, eventually terminated
by a statement that either returns, or jumps to another basic block.

  Our function has no control-flow, so we just need one basic block:

    gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);

Our basic block is relatively simple: it immediately terminates by
returning the value of an expression.

  We can build the expression using *note
gcc_jit_context_new_binary_op(): 12.:

    gcc_jit_rvalue *expr =
      gcc_jit_context_new_binary_op (
        ctxt, NULL,
        GCC_JIT_BINARY_OP_MULT, int_type,
        gcc_jit_param_as_rvalue (param_i),
        gcc_jit_param_as_rvalue (param_i));

A *note gcc_jit_rvalue *: 13. is another example of a *note
gcc_jit_object *: e. subclass.  We can upcast it using *note
gcc_jit_rvalue_as_object(): 14. and as before print it with *note
gcc_jit_object_get_debug_string(): f.

    printf ("expr: %s\n",
            gcc_jit_object_get_debug_string (
              gcc_jit_rvalue_as_object (expr)));

giving this output:

    expr: i * i

Creating the expression in itself doesn't do anything; we have to add
this expression to a statement within the block.  In this case, we use
it to build a return statement, which terminates the basic block:

    gcc_jit_block_end_with_return (block, NULL, expr);

OK, we've populated the context.  We can now compile it using *note
gcc_jit_context_compile(): 15.:

    gcc_jit_result *result;
    result = gcc_jit_context_compile (ctxt);

and get a *note gcc_jit_result *: 16.

  At this point we're done with the context; we can release it:

    gcc_jit_context_release (ctxt);

We can now use *note gcc_jit_result_get_code(): 17. to look up a
specific machine code routine within the result, in this case, the
function we created above.

    void *fn_ptr = gcc_jit_result_get_code (result, "square");
    if (!fn_ptr)
      {
        fprintf (stderr, "NULL fn_ptr");
        goto error;
      }

We can now cast the pointer to an appropriate function pointer type, and
then call it:

    typedef int (*fn_type) (int);
    fn_type square = (fn_type)fn_ptr;
    printf ("result: %d", square (5));


    result: 25

Once we're done with the code, we can release the result:

    gcc_jit_result_release (result);

We can't call `square' anymore once we've released `result'.

* Menu:

* Error-handling::
* Options::
* Full example::


File: libgccjit.info,  Node: Error-handling,  Next: Options,  Up: Tutorial part 2 Creating a trivial machine code function

1.2.1 Error-handling
--------------------

Various kinds of errors are possible when using the API, such as
mismatched types in an assignment.  You can only compile and get code
from a context if no errors occur.

  Errors are printed on stderr; they typically contain the name of the
API entrypoint where the error occurred, and pertinent information on
the problem:

    ./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *)

The API is designed to cope with errors without crashing, so you can get
away with having a single error-handling check in your code:

    void *fn_ptr = gcc_jit_result_get_code (result, "square");
    if (!fn_ptr)
      {
        fprintf (stderr, "NULL fn_ptr");
        goto error;
      }

For more information, see the *note error-handling guide: 19.  within
the Topic eference.


File: libgccjit.info,  Node: Options,  Next: Full example,  Prev: Error-handling,  Up: Tutorial part 2 Creating a trivial machine code function

1.2.2 Options
-------------

To get more information on what's going on, you can set debugging flags
on the context using *note gcc_jit_context_set_bool_option(): 1b.

  Setting *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: 1c. will dump a
C-like representation to stderr when you compile (GCC's "GIMPLE"
representation):

    gcc_jit_context_set_bool_option (
      ctxt,
      GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
      1);
    result = gcc_jit_context_compile (ctxt);


    square (signed int i)
    {
      signed int D.260;

      entry:
      D.260 = i * i;
      return D.260;
    }

We can see the generated machine code in assembler form (on stderr) by
setting *note GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE: 1d. on the
context before compiling:

    gcc_jit_context_set_bool_option (
      ctxt,
      GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
      1);
    result = gcc_jit_context_compile (ctxt);


          .file   "fake.c"
          .text
          .globl  square
          .type   square, @function
    square:
    .LFB6:
          .cfi_startproc
          pushq   %rbp
          .cfi_def_cfa_offset 16
          .cfi_offset 6, -16
          movq    %rsp, %rbp
          .cfi_def_cfa_register 6
          movl    %edi, -4(%rbp)
    .L14:
          movl    -4(%rbp), %eax
          imull   -4(%rbp), %eax
          popq    %rbp
          .cfi_def_cfa 7, 8
          ret
          .cfi_endproc
    .LFE6:
          .size   square, .-square
          .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)"
          .section       .note.GNU-stack,"",@progbits

By default, no optimizations are performed, the equivalent of GCC's
`-O0' option.  We can turn things up to e.g. `-O3' by calling *note
gcc_jit_context_set_int_option(): 1e. with *note
GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 1f.:

    gcc_jit_context_set_int_option (
      ctxt,
      GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
      3);


          .file   "fake.c"
          .text
          .p2align 4,,15
          .globl  square
          .type   square, @function
    square:
    .LFB7:
          .cfi_startproc
    .L16:
          movl    %edi, %eax
          imull   %edi, %eax
          ret
          .cfi_endproc
    .LFE7:
          .size   square, .-square
          .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)"
          .section        .note.GNU-stack,"",@progbits

Naturally this has only a small effect on such a trivial function.


File: libgccjit.info,  Node: Full example,  Prev: Options,  Up: Tutorial part 2 Creating a trivial machine code function

1.2.3 Full example
------------------

Here's what the above looks like as a complete program:

         /* Usage example for libgccjit.so
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit.h>

         #include <stdlib.h>
         #include <stdio.h>

         void
         create_code (gcc_jit_context *ctxt)
         {
           /* Let's try to inject the equivalent of:

               int square (int i)
               {
                 return i * i;
               }
           */
           gcc_jit_type *int_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
           gcc_jit_param *param_i =
             gcc_jit_context_new_param (ctxt, NULL, int_type, "i");
           gcc_jit_function *func =
             gcc_jit_context_new_function (ctxt, NULL,
                                           GCC_JIT_FUNCTION_EXPORTED,
                                           int_type,
                                           "square",
                                           1, &param_i,
                                           0);

           gcc_jit_block *block = gcc_jit_function_new_block (func, NULL);

           gcc_jit_rvalue *expr =
             gcc_jit_context_new_binary_op (
               ctxt, NULL,
               GCC_JIT_BINARY_OP_MULT, int_type,
               gcc_jit_param_as_rvalue (param_i),
               gcc_jit_param_as_rvalue (param_i));

            gcc_jit_block_end_with_return (block, NULL, expr);
         }

         int
         main (int argc, char **argv)
         {
           gcc_jit_context *ctxt = NULL;
           gcc_jit_result *result = NULL;

           /* Get a "context" object for working with the library.  */
           ctxt = gcc_jit_context_acquire ();
           if (!ctxt)
             {
               fprintf (stderr, "NULL ctxt");
               goto error;
             }

           /* Set some options on the context.
              Let's see the code being generated, in assembler form.  */
           gcc_jit_context_set_bool_option (
             ctxt,
             GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
             0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           result = gcc_jit_context_compile (ctxt);
           if (!result)
             {
               fprintf (stderr, "NULL result");
               goto error;
             }

           /* We're done with the context; we can release it: */
           gcc_jit_context_release (ctxt);
           ctxt = NULL;

           /* Extract the generated code from "result".  */
           void *fn_ptr = gcc_jit_result_get_code (result, "square");
           if (!fn_ptr)
              {
                fprintf (stderr, "NULL fn_ptr");
                goto error;
              }

           typedef int (*fn_type) (int);
           fn_type square = (fn_type)fn_ptr;
           printf ("result: %d\n", square (5));

          error:
           if (ctxt)
             gcc_jit_context_release (ctxt);
           if (result)
             gcc_jit_result_release (result);
           return 0;
         }



  Building and running it:

    $ gcc \
        tut02-square.c \
        -o tut02-square \
        -lgccjit

    # Run the built program:
    $ ./tut02-square
    result: 25



File: libgccjit.info,  Node: Tutorial part 3 Loops and variables,  Next: Tutorial part 4 Adding JIT-compilation to a toy interpreter,  Prev: Tutorial part 2 Creating a trivial machine code function,  Up: Tutorial

1.3 Tutorial part 3: Loops and variables
========================================

Consider this C function:

         int loop_test (int n)
         {
           int sum = 0;
           for (int i = 0; i < n; i++)
             sum += i * i;
           return sum;
         }



  This example demonstrates some more features of libgccjit, with local
variables and a loop.

  To break this down into libgccjit terms, it's usually easier to reword
the `for' loop as a `while' loop, giving:

         int loop_test (int n)
         {
           int sum = 0;
           int i = 0;
           while (i < n)
           {
             sum += i * i;
             i++;
           }
           return sum;
         }



  Here's what the final control flow graph will look like:

       Figure


  As before, we include the libgccjit header and make a *note
gcc_jit_context *: 8.

    #include <libgccjit.h>

    void test (void)
    {
      gcc_jit_context *ctxt;
      ctxt = gcc_jit_context_acquire ();

The function works with the C `int' type:

    gcc_jit_type *the_type =
      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
    gcc_jit_type *return_type = the_type;

though we could equally well make it work on, say, `double':

    gcc_jit_type *the_type =
      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);

Let's build the function:

    gcc_jit_param *n =
      gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
    gcc_jit_param *params[1] = {n};
    gcc_jit_function *func =
      gcc_jit_context_new_function (ctxt, NULL,
                                    GCC_JIT_FUNCTION_EXPORTED,
                                    return_type,
                                    "loop_test",
                                    1, params, 0);


* Menu:

* Expressions; lvalues and rvalues: Expressions lvalues and rvalues.
* Control flow::
* Visualizing the control flow graph::
* Full example: Full example<2>.


File: libgccjit.info,  Node: Expressions lvalues and rvalues,  Next: Control flow,  Up: Tutorial part 3 Loops and variables

1.3.1 Expressions: lvalues and rvalues
--------------------------------------

The base class of expression is the *note gcc_jit_rvalue *: 13,
representing an expression that can be on the _right_-hand side of an
assignment: a value that can be computed somehow, and assigned _to_ a
storage area (such as a variable).  It has a specific *note
gcc_jit_type *: a.

  Anothe important class is *note gcc_jit_lvalue *: 24.  A *note
gcc_jit_lvalue *: 24. is something that can of the _left_-hand side of
an assignment: a storage area (such as a variable).

  In other words, every assignment can be thought of as:

    LVALUE = RVALUE;

Note that *note gcc_jit_lvalue *: 24. is a subclass of *note
gcc_jit_rvalue *: 13, where in an assignment of the form:

    LVALUE_A = LVALUE_B;

the `LVALUE_B' implies reading the current value of that storage area,
assigning it into the `LVALUE_A'.

  So far the only expressions we've seen are `i * i':

    gcc_jit_rvalue *expr =
      gcc_jit_context_new_binary_op (
        ctxt, NULL,
        GCC_JIT_BINARY_OP_MULT, int_type,
        gcc_jit_param_as_rvalue (param_i),
        gcc_jit_param_as_rvalue (param_i));

which is a *note gcc_jit_rvalue *: 13, and the various function
parameters: `param_i' and `param_n', instances of *note gcc_jit_param
*: 25, which is a subclass of *note gcc_jit_lvalue *: 24. (and, in
turn, of *note gcc_jit_rvalue *: 13.): we can both read from and write
to function parameters within the body of a function.

  Our new example has a couple of local variables.  We create them by
calling *note gcc_jit_function_new_local(): 26, supplying a type and a
name:

    /* Build locals:  */
    gcc_jit_lvalue *i =
      gcc_jit_function_new_local (func, NULL, the_type, "i");
    gcc_jit_lvalue *sum =
      gcc_jit_function_new_local (func, NULL, the_type, "sum");

These are instances of *note gcc_jit_lvalue *: 24. - they can be read
from and written to.

  Note that there is no precanned way to create _and_ initialize a
variable like in C:

    int i = 0;

Instead, having added the local to the function, we have to separately
add an assignment of `0' to `local_i' at the beginning of the function.


File: libgccjit.info,  Node: Control flow,  Next: Visualizing the control flow graph,  Prev: Expressions lvalues and rvalues,  Up: Tutorial part 3 Loops and variables

1.3.2 Control flow
------------------

This function has a loop, so we need to build some basic blocks to
handle the control flow.  In this case, we need 4 blocks:

  1. before the loop (initializing the locals)

  2. the conditional at the top of the loop (comparing `i < n')

  3. the body of the loop

  4. after the loop terminates (`return sum')

  so we create these as *note gcc_jit_block *: 28. instances within the
*note gcc_jit_function *: 29.:

    gcc_jit_block *b_initial =
      gcc_jit_function_new_block (func, "initial");
    gcc_jit_block *b_loop_cond =
      gcc_jit_function_new_block (func, "loop_cond");
    gcc_jit_block *b_loop_body =
      gcc_jit_function_new_block (func, "loop_body");
    gcc_jit_block *b_after_loop =
      gcc_jit_function_new_block (func, "after_loop");

We now populate each block with statements.

  The entry block `b_initial' consists of initializations followed by a
jump to the conditional.  We assign `0' to `i' and to `sum', using
*note gcc_jit_block_add_assignment(): 2a. to add an assignment
statement, and using *note gcc_jit_context_zero(): 2b. to get the
constant value `0' for the relevant type for the right-hand side of the
assignment:

    /* sum = 0; */
    gcc_jit_block_add_assignment (
      b_initial, NULL,
      sum,
      gcc_jit_context_zero (ctxt, the_type));

    /* i = 0; */
    gcc_jit_block_add_assignment (
      b_initial, NULL,
      i,
      gcc_jit_context_zero (ctxt, the_type));

We can then terminate the entry block by jumping to the conditional:

    gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond);

The conditional block is equivalent to the line `while (i < n)' from our
C example. It contains a single statement: a conditional, which jumps to
one of two destination blocks depending on a boolean *note
gcc_jit_rvalue *: 13, in this case the comparison of `i' and `n'.  We
build the comparison using *note gcc_jit_context_new_comparison(): 2c.:

    /* (i >= n) */
     gcc_jit_rvalue *guard =
       gcc_jit_context_new_comparison (
         ctxt, NULL,
         GCC_JIT_COMPARISON_GE,
         gcc_jit_lvalue_as_rvalue (i),
         gcc_jit_param_as_rvalue (n));

and can then use this to add `b_loop_cond''s sole statement, via *note
gcc_jit_block_end_with_conditional(): 2d.:

    /* Equivalent to:
         if (guard)
           goto after_loop;
         else
           goto loop_body;  */
    gcc_jit_block_end_with_conditional (
      b_loop_cond, NULL,
      guard,
      b_after_loop, /* on_true */
      b_loop_body); /* on_false */

Next, we populate the body of the loop.

  The C statement `sum += i * i;' is an assignment operation, where an
lvalue is modified "in-place".  We use *note
gcc_jit_block_add_assignment_op(): 2e. to handle these operations:

    /* sum += i * i */
    gcc_jit_block_add_assignment_op (
      b_loop_body, NULL,
      sum,
      GCC_JIT_BINARY_OP_PLUS,
      gcc_jit_context_new_binary_op (
        ctxt, NULL,
        GCC_JIT_BINARY_OP_MULT, the_type,
        gcc_jit_lvalue_as_rvalue (i),
        gcc_jit_lvalue_as_rvalue (i)));

The `i++' can be thought of as `i += 1', and can thus be handled in a
similar way.  We use *note gcc_jit_context_one(): 2f. to get the
constant value `1' (for the relevant type) for the right-hand side of
the assignment.

    /* i++ */
    gcc_jit_block_add_assignment_op (
      b_loop_body, NULL,
      i,
      GCC_JIT_BINARY_OP_PLUS,
      gcc_jit_context_one (ctxt, the_type));


     Note: For numeric constants other than 0 or 1, we could use *note
     gcc_jit_context_new_rvalue_from_int(): 30. and *note
     gcc_jit_context_new_rvalue_from_double(): 31.

  The loop body completes by jumping back to the conditional:

    gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond);

Finally, we populate the `b_after_loop' block, reached when the loop
conditional is false.  We want to generate the equivalent of:

    return sum;

so the block is just one statement:

    /* return sum */
    gcc_jit_block_end_with_return (
      b_after_loop,
      NULL,
      gcc_jit_lvalue_as_rvalue (sum));


     Note: You can intermingle block creation with statement creation,
     but given that the terminator statements generally include
     references to other blocks, I find it's clearer to create all the
     blocks, _then_ all the statements.

  We've finished populating the function.  As before, we can now
compile it to machine code:

    gcc_jit_result *result;
    result = gcc_jit_context_compile (ctxt);

    typedef int (*loop_test_fn_type) (int);
    loop_test_fn_type loop_test =
     (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
    if (!loop_test)
      goto error;
    printf ("result: %d", loop_test (10));


    result: 285



File: libgccjit.info,  Node: Visualizing the control flow graph,  Next: Full example<2>,  Prev: Control flow,  Up: Tutorial part 3 Loops and variables

1.3.3 Visualizing the control flow graph
----------------------------------------

You can see the control flow graph of a function using *note
gcc_jit_function_dump_to_dot(): 33.:

    gcc_jit_function_dump_to_dot (func, "/tmp/sum-of-squares.dot");

giving a .dot file in GraphViz format.

  You can convert this to an image using `dot':

    $ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png

or use a viewer (my preferred one is xdot.py; see
<https://github.com/jrfonseca/xdot.py>; on Fedora you can install it
with `yum install python-xdot'):

       Figure



File: libgccjit.info,  Node: Full example<2>,  Prev: Visualizing the control flow graph,  Up: Tutorial part 3 Loops and variables

1.3.4 Full example
------------------

         /* Usage example for libgccjit.so
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit.h>

         #include <stdlib.h>
         #include <stdio.h>

         void
         create_code (gcc_jit_context *ctxt)
         {
           /*
             Simple sum-of-squares, to test conditionals and looping

             int loop_test (int n)
             {
               int i;
               int sum = 0;
               for (i = 0; i < n ; i ++)
               {
         	sum += i * i;
               }
               return sum;
            */
           gcc_jit_type *the_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
           gcc_jit_type *return_type = the_type;

           gcc_jit_param *n =
             gcc_jit_context_new_param (ctxt, NULL, the_type, "n");
           gcc_jit_param *params[1] = {n};
           gcc_jit_function *func =
             gcc_jit_context_new_function (ctxt, NULL,
         				  GCC_JIT_FUNCTION_EXPORTED,
         				  return_type,
         				  "loop_test",
         				  1, params, 0);

           /* Build locals:  */
           gcc_jit_lvalue *i =
             gcc_jit_function_new_local (func, NULL, the_type, "i");
           gcc_jit_lvalue *sum =
             gcc_jit_function_new_local (func, NULL, the_type, "sum");

           gcc_jit_block *b_initial =
             gcc_jit_function_new_block (func, "initial");
           gcc_jit_block *b_loop_cond =
             gcc_jit_function_new_block (func, "loop_cond");
           gcc_jit_block *b_loop_body =
             gcc_jit_function_new_block (func, "loop_body");
           gcc_jit_block *b_after_loop =
             gcc_jit_function_new_block (func, "after_loop");

           /* sum = 0; */
           gcc_jit_block_add_assignment (
             b_initial, NULL,
             sum,
             gcc_jit_context_zero (ctxt, the_type));

           /* i = 0; */
           gcc_jit_block_add_assignment (
             b_initial, NULL,
             i,
             gcc_jit_context_zero (ctxt, the_type));

           gcc_jit_block_end_with_jump (b_initial, NULL, b_loop_cond);

           /* if (i >= n) */
           gcc_jit_block_end_with_conditional (
             b_loop_cond, NULL,
             gcc_jit_context_new_comparison (
                ctxt, NULL,
                GCC_JIT_COMPARISON_GE,
                gcc_jit_lvalue_as_rvalue (i),
                gcc_jit_param_as_rvalue (n)),
             b_after_loop,
             b_loop_body);

           /* sum += i * i */
           gcc_jit_block_add_assignment_op (
             b_loop_body, NULL,
             sum,
             GCC_JIT_BINARY_OP_PLUS,
             gcc_jit_context_new_binary_op (
               ctxt, NULL,
               GCC_JIT_BINARY_OP_MULT, the_type,
               gcc_jit_lvalue_as_rvalue (i),
               gcc_jit_lvalue_as_rvalue (i)));

           /* i++ */
           gcc_jit_block_add_assignment_op (
             b_loop_body, NULL,
             i,
             GCC_JIT_BINARY_OP_PLUS,
             gcc_jit_context_one (ctxt, the_type));

           gcc_jit_block_end_with_jump (b_loop_body, NULL, b_loop_cond);

           /* return sum */
           gcc_jit_block_end_with_return (
             b_after_loop,
             NULL,
             gcc_jit_lvalue_as_rvalue (sum));
         }

         int
         main (int argc, char **argv)
         {
           gcc_jit_context *ctxt = NULL;
           gcc_jit_result *result = NULL;

           /* Get a "context" object for working with the library.  */
           ctxt = gcc_jit_context_acquire ();
           if (!ctxt)
             {
               fprintf (stderr, "NULL ctxt");
               goto error;
             }

           /* Set some options on the context.
              Let's see the code being generated, in assembler form.  */
           gcc_jit_context_set_bool_option (
             ctxt,
             GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
             0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           result = gcc_jit_context_compile (ctxt);
           if (!result)
             {
               fprintf (stderr, "NULL result");
               goto error;
             }

           /* Extract the generated code from "result".  */
           typedef int (*loop_test_fn_type) (int);
           loop_test_fn_type loop_test =
             (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
           if (!loop_test)
             {
               fprintf (stderr, "NULL loop_test");
               goto error;
             }

           /* Run the generated code.  */
           int val = loop_test (10);
           printf("loop_test returned: %d\n", val);

          error:
           gcc_jit_context_release (ctxt);
           gcc_jit_result_release (result);
           return 0;
         }



  Building and running it:

    $ gcc \
        tut03-sum-of-squares.c \
        -o tut03-sum-of-squares \
        -lgccjit

    # Run the built program:
    $ ./tut03-sum-of-squares
    loop_test returned: 285



File: libgccjit.info,  Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter,  Next: Tutorial part 5 Implementing an Ahead-of-Time compiler,  Prev: Tutorial part 3 Loops and variables,  Up: Tutorial

1.4 Tutorial part 4: Adding JIT-compilation to a toy interpreter
================================================================

In this example we construct a "toy" interpreter, and add
JIT-compilation to it.

* Menu:

* Our toy interpreter::
* Compiling to machine code::
* Setting things up::
* Populating the function::
* Verifying the control flow graph::
* Compiling the context::
* Single-stepping through the generated code::
* Examining the generated code::
* Putting it all together::
* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?.


File: libgccjit.info,  Node: Our toy interpreter,  Next: Compiling to machine code,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.1 Our toy interpreter
-------------------------

It's a stack-based interpreter, and is intended as a (very simple)
example of the kind of bytecode interpreter seen in dynamic languages
such as Python, Ruby etc.

  For the sake of simplicity, our toy virtual machine is very limited:

        * The only data type is `int'

        * It can only work on one function at a time (so that the only
          function call that can be made is to recurse).

        * Functions can only take one parameter.

        * Functions have a stack of `int' values.

        * We'll implement function call within the interpreter by
          calling a function in our implementation, rather than
          implementing our own frame stack.

        * The parser is only good enough to get the examples to work.

  Naturally, a real interpreter would be much more complicated that
this.

  The following operations are supported:

Operation                  Meaning                      Old Stack           New Stack
------------------------------------------------------------------------------------------------- 
DUP                        Duplicate top of stack.      `[..., x]'          `[..., x, x]'
ROT                        Swap top two elements of     `[..., x, y]'       `[..., y, x]'
                           stack.                                           
BINARY_ADD                 Add the top two elements on  `[..., x, y]'       `[..., (x+y)]'
                           the stack.                                       
BINARY_SUBTRACT            Likewise, but subtract.      `[..., x, y]'       `[..., (x-y)]'
BINARY_MULT                Likewise, but multiply.      `[..., x, y]'       `[..., (x*y)]'
BINARY_COMPARE_LT          Compare the top two          `[..., x, y]'       `[..., (x<y)]'
                           elements on the stack and                        
                           push a nonzero/zero if                           
                           (x<y).                                           
RECURSE                    Recurse, passing the top of  `[..., x]'          `[..., fn(x)]'
                           the stack, and popping the                       
                           result.                                          
RETURN                     Return the top of the stack. `[x]'               `[]'
PUSH_CONST `arg'           Push an int const.           `[...]'             `[..., arg]'
JUMP_ABS_IF_TRUE `arg'     Pop; if top of stack was     `[..., x]'          `[...]'
                           nonzero, jump to `arg'.                          

  Programs can be interpreted, disassembled, and compiled to machine
code.

  The interpreter reads `.toy' scripts.  Here's what a simple recursive
factorial program looks like, the script `factorial.toy'.  The parser
ignores lines beginning with a `#'.

         # Simple recursive factorial implementation, roughly equivalent to:
         #
         #  int factorial (int arg)
         #  {
         #     if (arg < 2)
         #       return arg
         #     return arg * factorial (arg - 1)
         #  }

         # Initial state:
         # stack: [arg]

         # 0:
         DUP
         # stack: [arg, arg]

         # 1:
         PUSH_CONST 2
         # stack: [arg, arg, 2]

         # 2:
         BINARY_COMPARE_LT
         # stack: [arg, (arg < 2)]

         # 3:
         JUMP_ABS_IF_TRUE 9
         # stack: [arg]

         # 4:
         DUP
         # stack: [arg, arg]

         # 5:
         PUSH_CONST 1
         # stack: [arg, arg, 1]

         # 6:
         BINARY_SUBTRACT
         # stack: [arg,  (arg - 1)

         # 7:
         RECURSE
         # stack: [arg, factorial(arg - 1)]

         # 8:
         BINARY_MULT
         # stack: [arg * factorial(arg - 1)]

         # 9:
         RETURN



  The interpreter is a simple infinite loop with a big `switch'
statement based on what the next opcode is:


         static int
         toyvm_function_interpret (toyvm_function *fn, int arg, FILE *trace)
         {
           toyvm_frame frame;
         #define PUSH(ARG) (toyvm_frame_push (&frame, (ARG)))
         #define POP(ARG) (toyvm_frame_pop (&frame))

           frame.frm_function = fn;
           frame.frm_pc = 0;
           frame.frm_cur_depth = 0;

           PUSH (arg);

           while (1)
             {
               toyvm_op *op;
               int x, y;
               assert (frame.frm_pc < fn->fn_num_ops);
               op = &fn->fn_ops[frame.frm_pc++];

               if (trace)
         	{
         	  toyvm_frame_dump_stack (&frame, trace);
         	  toyvm_function_disassemble_op (fn, op, frame.frm_pc, trace);
         	}

               switch (op->op_opcode)
         	{
         	  /* Ops taking no operand.  */
         	case DUP:
         	  x = POP ();
         	  PUSH (x);
         	  PUSH (x);
         	  break;

         	case ROT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (y);
         	  PUSH (x);
         	  break;

         	case BINARY_ADD:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x + y);
         	  break;

         	case BINARY_SUBTRACT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x - y);
         	  break;

         	case BINARY_MULT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x * y);
         	  break;

         	case BINARY_COMPARE_LT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x < y);
         	  break;

         	case RECURSE:
         	  x = POP ();
         	  x = toyvm_function_interpret (fn, x, trace);
         	  PUSH (x);
         	  break;

         	case RETURN:
         	  return POP ();

         	  /* Ops taking an operand.  */
         	case PUSH_CONST:
         	  PUSH (op->op_operand);
         	  break;

         	case JUMP_ABS_IF_TRUE:
         	  x = POP ();
         	  if (x)
         	    frame.frm_pc = op->op_operand;
         	  break;

         	default:
         	  assert (0); /* unknown opcode */

         	} /* end of switch on opcode */
             } /* end of while loop */

         #undef PUSH
         #undef POP
         }




File: libgccjit.info,  Node: Compiling to machine code,  Next: Setting things up,  Prev: Our toy interpreter,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.2 Compiling to machine code
-------------------------------

We want to generate machine code that can be cast to this type and then
directly executed in-process:

         typedef int (*toyvm_compiled_code) (int);



  The lifetime of the code is tied to that of a *note gcc_jit_result *:
16.  We'll handle this by bundling them up in a structure, so that we
can clean them up together by calling *note gcc_jit_result_release():
39.:


         struct toyvm_compiled_function
         {
           gcc_jit_result *cf_jit_result;
           toyvm_compiled_code cf_code;
         };



  Our compiler isn't very sophisticated; it takes the implementation of
each opcode above, and maps it directly to the operations supported by
the libgccjit API.

  How should we handle the stack?  In theory we could calculate what the
stack depth will be at each opcode, and optimize away the stack
manipulation "by hand".  We'll see below that libgccjit is able to do
this for us, so we'll implement stack manipulation in a direct way, by
creating a `stack' array and `stack_depth' variables, local within the
generated function, equivalent to this C code:

    int stack_depth;
    int stack[MAX_STACK_DEPTH];

We'll also have local variables `x' and `y' for use when implementing
the opcodes, equivalent to this:

    int x;
    int y;

This means our compiler has the following state:


         struct compilation_state
         {
           gcc_jit_context *ctxt;

           gcc_jit_type *int_type;
           gcc_jit_type *bool_type;
           gcc_jit_type *stack_type; /* int[MAX_STACK_DEPTH] */

           gcc_jit_rvalue *const_one;

           gcc_jit_function *fn;
           gcc_jit_param *param_arg;
           gcc_jit_lvalue *stack;
           gcc_jit_lvalue *stack_depth;
           gcc_jit_lvalue *x;
           gcc_jit_lvalue *y;

           gcc_jit_location *op_locs[MAX_OPS];
           gcc_jit_block *initial_block;
           gcc_jit_block *op_blocks[MAX_OPS];

         };




File: libgccjit.info,  Node: Setting things up,  Next: Populating the function,  Prev: Compiling to machine code,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.3 Setting things up
-----------------------

First we create our types:

           state.int_type =
             gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_INT);
           state.bool_type =
             gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_BOOL);
           state.stack_type =
             gcc_jit_context_new_array_type (state.ctxt, NULL,
         				    state.int_type, MAX_STACK_DEPTH);



  along with extracting a useful `int' constant:

           state.const_one = gcc_jit_context_one (state.ctxt, state.int_type);



  We'll implement push and pop in terms of the `stack' array and
`stack_depth'.  Here are helper functions for adding statements to a
block, implementing pushing and popping values:


         static void
         add_push (compilation_state *state,
         	  gcc_jit_block *block,
         	  gcc_jit_rvalue *rvalue,
         	  gcc_jit_location *loc)
         {
           /* stack[stack_depth] = RVALUE */
           gcc_jit_block_add_assignment (
             block,
             loc,
             /* stack[stack_depth] */
             gcc_jit_context_new_array_access (
               state->ctxt,
               loc,
               gcc_jit_lvalue_as_rvalue (state->stack),
               gcc_jit_lvalue_as_rvalue (state->stack_depth)),
             rvalue);

           /* "stack_depth++;".  */
           gcc_jit_block_add_assignment_op (
             block,
             loc,
             state->stack_depth,
             GCC_JIT_BINARY_OP_PLUS,
             state->const_one);
         }

         static void
         add_pop (compilation_state *state,
         	 gcc_jit_block *block,
         	 gcc_jit_lvalue *lvalue,
         	 gcc_jit_location *loc)
         {
           /* "--stack_depth;".  */
           gcc_jit_block_add_assignment_op (
             block,
             loc,
             state->stack_depth,
             GCC_JIT_BINARY_OP_MINUS,
             state->const_one);

           /* "LVALUE = stack[stack_depth];".  */
           gcc_jit_block_add_assignment (
             block,
             loc,
             lvalue,
             /* stack[stack_depth] */
             gcc_jit_lvalue_as_rvalue (
               gcc_jit_context_new_array_access (
         	state->ctxt,
         	loc,
         	gcc_jit_lvalue_as_rvalue (state->stack),
         	gcc_jit_lvalue_as_rvalue (state->stack_depth))));
         }



  We will support single-stepping through the generated code in the
debugger, so we need to create *note gcc_jit_location: 3b. instances,
one per operation in the source code.  These will reference the lines of
e.g. `factorial.toy'.

           for (pc = 0; pc < fn->fn_num_ops; pc++)
             {
               toyvm_op *op = &fn->fn_ops[pc];

               state.op_locs[pc] = gcc_jit_context_new_location (state.ctxt,
         							fn->fn_filename,
         							op->op_linenum,
         							0); /* column */
             }



  Let's create the function itself.  As usual, we create its parameter
first, then use the parameter to create the function:

           state.param_arg =
             gcc_jit_context_new_param (state.ctxt, state.op_locs[0],
         			       state.int_type, "arg");
           state.fn =
             gcc_jit_context_new_function (state.ctxt,
         				  state.op_locs[0],
         				  GCC_JIT_FUNCTION_EXPORTED,
         				  state.int_type,
         				  funcname,
         				  1, &state.param_arg, 0);



  We create the locals within the function.

           state.stack =
             gcc_jit_function_new_local (state.fn, NULL,
         				state.stack_type, "stack");
           state.stack_depth =
             gcc_jit_function_new_local (state.fn, NULL,
         				state.int_type, "stack_depth");
           state.x =
             gcc_jit_function_new_local (state.fn, NULL,
         				state.int_type, "x");
           state.y =
             gcc_jit_function_new_local (state.fn, NULL,
         				state.int_type, "y");




File: libgccjit.info,  Node: Populating the function,  Next: Verifying the control flow graph,  Prev: Setting things up,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.4 Populating the function
-----------------------------

There's some one-time initialization, and the API treats the first block
you create as the entrypoint of the function, so we need to create that
block first:

           state.initial_block = gcc_jit_function_new_block (state.fn, "initial");



  We can now create blocks for each of the operations.  Most of these
will be consolidated into larger blocks when the optimizer runs.

           for (pc = 0; pc < fn->fn_num_ops; pc++)
             {
               char buf[16];
               sprintf (buf, "instr%i", pc);
               state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf);
             }



  Now that we have a block it can jump to when it's done, we can
populate the initial block:


           /* "stack_depth = 0;".  */
           gcc_jit_block_add_assignment (
             state.initial_block,
             state.op_locs[0],
             state.stack_depth,
             gcc_jit_context_zero (state.ctxt, state.int_type));

           /* "PUSH (arg);".  */
           add_push (&state,
         	    state.initial_block,
         	    gcc_jit_param_as_rvalue (state.param_arg),
         	    state.op_locs[0]);

           /* ...and jump to insn 0.  */
           gcc_jit_block_end_with_jump (state.initial_block,
         			       state.op_locs[0],
         			       state.op_blocks[0]);



  We can now populate the blocks for the individual operations.  We loop
through them, adding instructions to their blocks:

           for (pc = 0; pc < fn->fn_num_ops; pc++)
             {
               gcc_jit_location *loc = state.op_locs[pc];

               gcc_jit_block *block = state.op_blocks[pc];
               gcc_jit_block *next_block = (pc < fn->fn_num_ops
         				   ? state.op_blocks[pc + 1]
         				   : NULL);

               toyvm_op *op;
               op = &fn->fn_ops[pc];



  We're going to have another big `switch' statement for implementing
the opcodes, this time for compiling them, rather than interpreting
them.  It's helpful to have macros for implementing push and pop, so
that we can make the `switch' statement that's coming up look as much as
possible like the one above within the interpreter:


    #define X_EQUALS_POP()\
          add_pop (&state, block, state.x, loc)
    #define Y_EQUALS_POP()\
          add_pop (&state, block, state.y, loc)
    #define PUSH_RVALUE(RVALUE)\
          add_push (&state, block, (RVALUE), loc)
    #define PUSH_X()\
          PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.x))
    #define PUSH_Y() \
          PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.y))


     Note: A particularly clever implementation would have an
     _identical_ `switch' statement shared by the interpreter and the
     compiler, with some preprocessor "magic".  We're not doing that
     here, for the sake of simplicity.

  When I first implemented this compiler, I accidentally missed an edit
when copying and pasting the `Y_EQUALS_POP' macro, so that popping the
stack into `y' instead erroneously assigned it to `x', leaving `y'
uninitialized.

  To track this kind of thing down, we can use *note
gcc_jit_block_add_comment(): 3d. to add descriptive comments to the
internal representation.  This is invaluable when looking through the
generated IR for, say `factorial':


               gcc_jit_block_add_comment (block, loc, opcode_names[op->op_opcode]);



  We can now write the big `switch' statement that implements the
individual opcodes, populating the relevant block with statements:


               switch (op->op_opcode)
         	{
         	case DUP:
         	  X_EQUALS_POP ();
         	  PUSH_X ();
         	  PUSH_X ();
         	  break;

         	case ROT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_Y ();
         	  PUSH_X ();
         	  break;

         	case BINARY_ADD:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	   gcc_jit_context_new_binary_op (
         	     state.ctxt,
         	     loc,
         	     GCC_JIT_BINARY_OP_PLUS,
         	     state.int_type,
         	     gcc_jit_lvalue_as_rvalue (state.x),
         	     gcc_jit_lvalue_as_rvalue (state.y)));
         	  break;

         	case BINARY_SUBTRACT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	   gcc_jit_context_new_binary_op (
         	     state.ctxt,
         	     loc,
         	     GCC_JIT_BINARY_OP_MINUS,
         	     state.int_type,
         	     gcc_jit_lvalue_as_rvalue (state.x),
         	     gcc_jit_lvalue_as_rvalue (state.y)));
         	  break;

         	case BINARY_MULT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	   gcc_jit_context_new_binary_op (
         	     state.ctxt,
         	     loc,
         	     GCC_JIT_BINARY_OP_MULT,
         	     state.int_type,
         	     gcc_jit_lvalue_as_rvalue (state.x),
         	     gcc_jit_lvalue_as_rvalue (state.y)));
         	  break;

         	case BINARY_COMPARE_LT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	     /* cast of bool to int */
         	     gcc_jit_context_new_cast (
         	       state.ctxt,
         	       loc,
         	       /* (x < y) as a bool */
         	       gcc_jit_context_new_comparison (
         		 state.ctxt,
         		 loc,
         		 GCC_JIT_COMPARISON_LT,
         		 gcc_jit_lvalue_as_rvalue (state.x),
         		 gcc_jit_lvalue_as_rvalue (state.y)),
         	       state.int_type));
         	  break;

         	case RECURSE:
         	  {
         	    X_EQUALS_POP ();
         	    gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (state.x);
         	    PUSH_RVALUE (
         	      gcc_jit_context_new_call (
         		state.ctxt,
         		loc,
         		state.fn,
         		1, &arg));
         	    break;
         	  }

         	case RETURN:
         	  X_EQUALS_POP ();
         	  gcc_jit_block_end_with_return (
         	    block,
         	    loc,
         	    gcc_jit_lvalue_as_rvalue (state.x));
         	  break;

         	  /* Ops taking an operand.  */
         	case PUSH_CONST:
         	  PUSH_RVALUE (
         	    gcc_jit_context_new_rvalue_from_int (
         	      state.ctxt,
         	      state.int_type,
         	      op->op_operand));
         	  break;

         	case JUMP_ABS_IF_TRUE:
         	  X_EQUALS_POP ();
         	  gcc_jit_block_end_with_conditional (
         	    block,
         	    loc,
         	    /* "(bool)x".  */
         	    gcc_jit_context_new_cast (
         	      state.ctxt,
         	      loc,
         	      gcc_jit_lvalue_as_rvalue (state.x),
         	      state.bool_type),
         	    state.op_blocks[op->op_operand], /* on_true */
         	    next_block); /* on_false */
         	  break;

         	default:
         	  assert(0);
         	} /* end of switch on opcode */



  Every block must be terminated, via a call to one of the
`gcc_jit_block_end_with_' entrypoints.  This has been done for two of
the opcodes, but we need to do it for the other ones, by jumping to the
next block.

               if (op->op_opcode != JUMP_ABS_IF_TRUE
         	  && op->op_opcode != RETURN)
         	gcc_jit_block_end_with_jump (
         	  block,
         	  loc,
         	  next_block);



  This is analogous to simply incrementing the program counter.


File: libgccjit.info,  Node: Verifying the control flow graph,  Next: Compiling the context,  Prev: Populating the function,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.5 Verifying the control flow graph
--------------------------------------

Having finished looping over the blocks, the context is complete.

  As before, we can verify that the control flow and statements are
sane by using *note gcc_jit_function_dump_to_dot(): 33.:

    gcc_jit_function_dump_to_dot (state.fn, "/tmp/factorial.dot");

and viewing the result.  Note how the label names, comments, and
variable names show up in the dump, to make it easier to spot errors in
our compiler.

       Figure



File: libgccjit.info,  Node: Compiling the context,  Next: Single-stepping through the generated code,  Prev: Verifying the control flow graph,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.6 Compiling the context
---------------------------

Having finished looping over the blocks and populating them with
statements, the context is complete.

  We can now compile it, and extract machine code from the result:

           gcc_jit_result *jit_result = gcc_jit_context_compile (state.ctxt);
           gcc_jit_context_release (state.ctxt);

           toyvm_compiled_function *toyvm_result =
             (toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function));
           if (!toyvm_result)
             {
               fprintf (stderr, "out of memory allocating toyvm_compiled_function\n");
               gcc_jit_result_release (jit_result);
               return NULL;
             }

           toyvm_result->cf_jit_result = jit_result;
           toyvm_result->cf_code =
             (toyvm_compiled_code)gcc_jit_result_get_code (jit_result,
         						  funcname);

           free (funcname);

           return toyvm_result;
         }

         char test[1024];

         #define CHECK_NON_NULL(PTR) \
           do {                                       \
             if ((PTR) != NULL)                       \
               {                                      \
         	pass ("%s: %s is non-null", test, #PTR); \
               }                                      \
             else                                     \
               {                                      \
         	fail ("%s: %s is NULL", test, #PTR); \
         	abort ();                            \
             }                                        \
           } while (0)

         #define CHECK_VALUE(ACTUAL, EXPECTED) \
           do {                                       \
             if ((ACTUAL) == (EXPECTED))              \
               {                                      \
         	pass ("%s: actual: %s == expected: %s", test, #ACTUAL, #EXPECTED); \
               }                                      \
             else                                     \
               {                                        \
         	fail ("%s: actual: %s != expected: %s", test, #ACTUAL, #EXPECTED); \
         	fprintf (stderr, "incorrect value\n"); \
         	abort ();                              \
             }                                        \
           } while (0)

         static void
         test_script (const char *scripts_dir, const char *script_name, int input,
         	     int expected_result)
         {
           char *script_path;
           toyvm_function *fn;
           int interpreted_result;
           toyvm_compiled_function *compiled_fn;
           toyvm_compiled_code code;
           int compiled_result;

           snprintf (test, sizeof (test), "toyvm.c: %s", script_name);

           script_path = (char *)malloc (strlen (scripts_dir)
         				+ strlen (script_name) + 1);
           CHECK_NON_NULL (script_path);
           sprintf (script_path, "%s%s", scripts_dir, script_name);

           fn = toyvm_function_parse (script_path, script_name);
           CHECK_NON_NULL (fn);

           interpreted_result = toyvm_function_interpret (fn, input, NULL);
           CHECK_VALUE (interpreted_result, expected_result);

           compiled_fn = toyvm_function_compile (fn);
           CHECK_NON_NULL (compiled_fn);

           code = (toyvm_compiled_code)compiled_fn->cf_code;
           CHECK_NON_NULL (code);

           compiled_result = code (input);
           CHECK_VALUE (compiled_result, expected_result);

           gcc_jit_result_release (compiled_fn->cf_jit_result);
           free (compiled_fn);
           free (fn);
           free (script_path);
         }

         #define PATH_TO_SCRIPTS  ("/jit/docs/examples/tut04-toyvm/")

         static void
         test_suite (void)
         {
           const char *srcdir;
           char *scripts_dir;

           snprintf (test, sizeof (test), "toyvm.c");

           /* We need to locate the test scripts.
              Rely on "srcdir" being set in the environment.  */

           srcdir = getenv ("srcdir");
           CHECK_NON_NULL (srcdir);

           scripts_dir = (char *)malloc (strlen (srcdir) + strlen(PATH_TO_SCRIPTS)
         				+ 1);
           CHECK_NON_NULL (scripts_dir);
           sprintf (scripts_dir, "%s%s", srcdir, PATH_TO_SCRIPTS);

           test_script (scripts_dir, "factorial.toy", 10, 3628800);
           test_script (scripts_dir, "fibonacci.toy", 10, 55);

           free (scripts_dir);
         }

         int
         main (int argc, char **argv)
         {
           const char *filename = NULL;
           toyvm_function *fn = NULL;

           /* If called with no args, assume we're being run by the test suite.  */
           if (argc < 3)
             {
               test_suite ();
               return 0;
             }

           if (argc != 3)
             {
               fprintf (stdout,
         	"%s FILENAME INPUT: Parse and run a .toy file\n",
         	argv[0]);
               exit (1);
             }

           filename = argv[1];
           fn = toyvm_function_parse (filename, filename);
           if (!fn)
             exit (1);

           if (0)
             toyvm_function_disassemble (fn, stdout);

           printf ("interpreter result: %d\n",
         	  toyvm_function_interpret (fn, atoi (argv[2]), NULL));

           /* JIT-compilation.  */
           toyvm_compiled_function *compiled_fn
             = toyvm_function_compile (fn);

           toyvm_compiled_code code = compiled_fn->cf_code;
           printf ("compiler result: %d\n",
         	  code (atoi (argv[2])));

           gcc_jit_result_release (compiled_fn->cf_jit_result);
           free (compiled_fn);

          return 0;
         }



  We can now run the result:

           toyvm_compiled_function *compiled_fn
             = toyvm_function_compile (fn);

           toyvm_compiled_code code = compiled_fn->cf_code;
           printf ("compiler result: %d\n",
         	  code (atoi (argv[2])));

           gcc_jit_result_release (compiled_fn->cf_jit_result);
           free (compiled_fn);




File: libgccjit.info,  Node: Single-stepping through the generated code,  Next: Examining the generated code,  Prev: Compiling the context,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.7 Single-stepping through the generated code
------------------------------------------------

It's possible to debug the generated code.  To do this we need to both:

        * Set up source code locations for our statements, so that we
          can meaningfully step through the code.  We did this above by
          calling *note gcc_jit_context_new_location(): 41. and using
          the results.

        * Enable the generation of debugging information, by setting
          *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the *note
          gcc_jit_context: 8. via *note
          gcc_jit_context_set_bool_option(): 1b.:

              gcc_jit_context_set_bool_option (
                ctxt,
                GCC_JIT_BOOL_OPTION_DEBUGINFO,
                1);



  Having done this, we can put a breakpoint on the generated function:

    $ gdb --args ./toyvm factorial.toy 10
    (gdb) break factorial
    Function "factorial" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y
    Breakpoint 1 (factorial) pending.
    (gdb) run
    Breakpoint 1, factorial (arg=10) at factorial.toy:14
    14    DUP

We've set up location information, which references `factorial.toy'.
This allows us to use e.g. `list' to see where we are in the script:

    (gdb) list
    9
    10    # Initial state:
    11    # stack: [arg]
    12
    13    # 0:
    14    DUP
    15    # stack: [arg, arg]
    16
    17    # 1:
    18    PUSH_CONST 2

and to step through the function, examining the data:

    (gdb) n
    18    PUSH_CONST 2
    (gdb) n
    22    BINARY_COMPARE_LT
    (gdb) print stack
    $5 = {10, 10, 2, 0, -7152, 32767, 0, 0}
    (gdb) print stack_depth
    $6 = 3

You'll see that the parts of the `stack' array that haven't been
touched yet are uninitialized.

     Note: Turning on optimizations may lead to unpredictable results
     when stepping through the generated code: the execution may appear
     to "jump around" the source code.  This is analogous to turning up
     the optimization level in a regular compiler.


File: libgccjit.info,  Node: Examining the generated code,  Next: Putting it all together,  Prev: Single-stepping through the generated code,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.8 Examining the generated code
----------------------------------

How good is the optimized code?

  We can turn up optimizations, by calling *note
gcc_jit_context_set_int_option(): 1e. with *note
GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 1f.:

    gcc_jit_context_set_int_option (
      ctxt,
      GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
      3);

One of GCC's internal representations is called "gimple".  A dump of the
initial gimple representation of the code can be seen by setting:

    gcc_jit_context_set_bool_option (ctxt,
                                     GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
                                     1);

With optimization on and source locations displayed, this gives:

    factorial (signed int arg)
    {
      <unnamed type> D.80;
      signed int D.81;
      signed int D.82;
      signed int D.83;
      signed int D.84;
      signed int D.85;
      signed int y;
      signed int x;
      signed int stack_depth;
      signed int stack[8];

      try
        {
          initial:
          stack_depth = 0;
          stack[stack_depth] = arg;
          stack_depth = stack_depth + 1;
          goto instr0;
          instr0:
          /* DUP */:
          stack_depth = stack_depth + -1;
          x = stack[stack_depth];
          stack[stack_depth] = x;
          stack_depth = stack_depth + 1;
          stack[stack_depth] = x;
          stack_depth = stack_depth + 1;
          goto instr1;
          instr1:
          /* PUSH_CONST */:
          stack[stack_depth] = 2;
          stack_depth = stack_depth + 1;
          goto instr2;

          /* etc */

You can see the generated machine code in assembly form via:

    gcc_jit_context_set_bool_option (
      ctxt,
      GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
      1);
    result = gcc_jit_context_compile (ctxt);

which shows that (on this x86_64 box) the compiler has unrolled the loop
and is using MMX instructions to perform several multiplications
simultaneously:

            .file   "fake.c"
            .text
    .Ltext0:
            .p2align 4,,15
            .globl  factorial
            .type   factorial, @function
    factorial:
    .LFB0:
            .file 1 "factorial.toy"
            .loc 1 14 0
            .cfi_startproc
    .LVL0:
    .L2:
            .loc 1 26 0
            cmpl    $1, %edi
            jle     .L13
            leal    -1(%rdi), %edx
            movl    %edx, %ecx
            shrl    $2, %ecx
            leal    0(,%rcx,4), %esi
            testl   %esi, %esi
            je      .L14
            cmpl    $9, %edx
            jbe     .L14
            leal    -2(%rdi), %eax
            movl    %eax, -16(%rsp)
            leal    -3(%rdi), %eax
            movd    -16(%rsp), %xmm0
            movl    %edi, -16(%rsp)
            movl    %eax, -12(%rsp)
            movd    -16(%rsp), %xmm1
            xorl    %eax, %eax
            movl    %edx, -16(%rsp)
            movd    -12(%rsp), %xmm4
            movd    -16(%rsp), %xmm6
            punpckldq       %xmm4, %xmm0
            movdqa  .LC1(%rip), %xmm4
            punpckldq       %xmm6, %xmm1
            punpcklqdq      %xmm0, %xmm1
            movdqa  .LC0(%rip), %xmm0
            jmp     .L5
            # etc - edited for brevity

This is clearly overkill for a function that will likely overflow the
`int' type before the vectorization is worthwhile - but then again, this
is a toy example.

  Turning down the optimization level to 2:

    gcc_jit_context_set_int_option (
      ctxt,
      GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
      3);

yields this code, which is simple enough to quote in its entirety:

            .file   "fake.c"
            .text
            .p2align 4,,15
            .globl  factorial
            .type   factorial, @function
    factorial:
    .LFB0:
            .cfi_startproc
    .L2:
            cmpl    $1, %edi
            jle     .L8
            movl    $1, %edx
            jmp     .L4
            .p2align 4,,10
            .p2align 3
    .L6:
            movl    %eax, %edi
    .L4:
    .L5:
            leal    -1(%rdi), %eax
            imull   %edi, %edx
            cmpl    $1, %eax
            jne     .L6
    .L3:
    .L7:
            imull   %edx, %eax
            ret
    .L8:
            movl    %edi, %eax
            movl    $1, %edx
            jmp     .L7
            .cfi_endproc
    .LFE0:
            .size   factorial, .-factorial
            .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%{gcc_release})"
            .section        .note.GNU-stack,"",@progbits

Note that the stack pushing and popping have been eliminated, as has the
recursive call (in favor of an iteration).


File: libgccjit.info,  Node: Putting it all together,  Next: Behind the curtain How does our code get optimized?,  Prev: Examining the generated code,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.9 Putting it all together
-----------------------------

The complete example can be seen in the source tree at
`gcc/jit/docs/examples/tut04-toyvm/toyvm.c'

  along with a Makefile and a couple of sample .toy scripts:

    $ ls -al
    drwxrwxr-x. 2 david david   4096 Sep 19 17:46 .
    drwxrwxr-x. 3 david david   4096 Sep 19 15:26 ..
    -rw-rw-r--. 1 david david    615 Sep 19 12:43 factorial.toy
    -rw-rw-r--. 1 david david    834 Sep 19 13:08 fibonacci.toy
    -rw-rw-r--. 1 david david    238 Sep 19 14:22 Makefile
    -rw-rw-r--. 1 david david  16457 Sep 19 17:07 toyvm.c

    $ make toyvm
    g++ -Wall -g -o toyvm toyvm.c -lgccjit

    $ ./toyvm factorial.toy 10
    interpreter result: 3628800
    compiler result: 3628800

    $ ./toyvm fibonacci.toy 10
    interpreter result: 55
    compiler result: 55



File: libgccjit.info,  Node: Behind the curtain How does our code get optimized?,  Prev: Putting it all together,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter

1.4.10 Behind the curtain: How does our code get optimized?
-----------------------------------------------------------

Our example is done, but you may be wondering about exactly how the
compiler turned what we gave it into the machine code seen above.

  We can examine what the compiler is doing in detail by setting:

    gcc_jit_context_set_bool_option (state.ctxt,
                                     GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
                                     1);
    gcc_jit_context_set_bool_option (state.ctxt,
                                     GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
                                     1);

This will dump detailed information about the compiler's state to a
directory under `/tmp', and keep it from being cleaned up.

  The precise names and their formats of these files is subject to
change.  Higher optimization levels lead to more files.  Here's what I
saw (edited for brevity; there were almost 200 files):

    intermediate files written to /tmp/libgccjit-KPQbGw
    $ ls /tmp/libgccjit-KPQbGw/
    fake.c.000i.cgraph
    fake.c.000i.type-inheritance
    fake.c.004t.gimple
    fake.c.007t.omplower
    fake.c.008t.lower
    fake.c.011t.eh
    fake.c.012t.cfg
    fake.c.014i.visibility
    fake.c.015i.early_local_cleanups
    fake.c.016t.ssa
    # etc

The gimple code is converted into Static Single Assignment form, with
annotations for use when generating the debuginfo:

    $ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;
      signed int _56;

    initial:
      stack_depth_3 = 0;
      # DEBUG stack_depth => stack_depth_3
      stack[stack_depth_3] = arg_5(D);
      stack_depth_7 = stack_depth_3 + 1;
      # DEBUG stack_depth => stack_depth_7
      # DEBUG instr0 => NULL
      # DEBUG /* DUP */ => NULL
      stack_depth_8 = stack_depth_7 + -1;
      # DEBUG stack_depth => stack_depth_8
      x_9 = stack[stack_depth_8];
      # DEBUG x => x_9
      stack[stack_depth_8] = x_9;
      stack_depth_11 = stack_depth_8 + 1;
      # DEBUG stack_depth => stack_depth_11
      stack[stack_depth_11] = x_9;
      stack_depth_13 = stack_depth_11 + 1;
      # DEBUG stack_depth => stack_depth_13
      # DEBUG instr1 => NULL
      # DEBUG /* PUSH_CONST */ => NULL
      stack[stack_depth_13] = 2;

      /* etc; edited for brevity */

We can perhaps better see the code by turning off *note
GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. to suppress all those `DEBUG'
statements, giving:

    $ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;
      signed int _56;

    initial:
      stack_depth_3 = 0;
      stack[stack_depth_3] = arg_5(D);
      stack_depth_7 = stack_depth_3 + 1;
      stack_depth_8 = stack_depth_7 + -1;
      x_9 = stack[stack_depth_8];
      stack[stack_depth_8] = x_9;
      stack_depth_11 = stack_depth_8 + 1;
      stack[stack_depth_11] = x_9;
      stack_depth_13 = stack_depth_11 + 1;
      stack[stack_depth_13] = 2;
      stack_depth_15 = stack_depth_13 + 1;
      stack_depth_16 = stack_depth_15 + -1;
      y_17 = stack[stack_depth_16];
      stack_depth_18 = stack_depth_16 + -1;
      x_19 = stack[stack_depth_18];
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack[stack_depth_18] = _21;
      stack_depth_23 = stack_depth_18 + 1;
      stack_depth_24 = stack_depth_23 + -1;
      x_25 = stack[stack_depth_24];
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      stack_depth_26 = stack_depth_24 + -1;
      x_27 = stack[stack_depth_26];
      stack[stack_depth_26] = x_27;
      stack_depth_29 = stack_depth_26 + 1;
      stack[stack_depth_29] = x_27;
      stack_depth_31 = stack_depth_29 + 1;
      stack[stack_depth_31] = 1;
      stack_depth_33 = stack_depth_31 + 1;
      stack_depth_34 = stack_depth_33 + -1;
      y_35 = stack[stack_depth_34];
      stack_depth_36 = stack_depth_34 + -1;
      x_37 = stack[stack_depth_36];
      _38 = x_37 - y_35;
      stack[stack_depth_36] = _38;
      stack_depth_40 = stack_depth_36 + 1;
      stack_depth_41 = stack_depth_40 + -1;
      x_42 = stack[stack_depth_41];
      _44 = factorial (x_42);
      stack[stack_depth_41] = _44;
      stack_depth_46 = stack_depth_41 + 1;
      stack_depth_47 = stack_depth_46 + -1;
      y_48 = stack[stack_depth_47];
      stack_depth_49 = stack_depth_47 + -1;
      x_50 = stack[stack_depth_49];
      _51 = x_50 * y_48;
      stack[stack_depth_49] = _51;
      stack_depth_53 = stack_depth_49 + 1;

      # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)>
    instr9:
    /* RETURN */:
      stack_depth_54 = stack_depth_1 + -1;
      x_55 = stack[stack_depth_54];
      _56 = x_55;
      stack ={v} {CLOBBER};
      return _56;

    }

Note in the above how all the *note gcc_jit_block: 28. instances we
created have been consolidated into just 3 blocks in GCC's internal
representation: `initial', `instr4' and `instr9'.

* Menu:

* Optimizing away stack manipulation::
* Elimination of tail recursion::


File: libgccjit.info,  Node: Optimizing away stack manipulation,  Next: Elimination of tail recursion,  Up: Behind the curtain How does our code get optimized?

1.4.10.1 Optimizing away stack manipulation
...........................................

Recall our simple implementation of stack operations.  Let's examine
how the stack operations are optimized away.

  After a pass of constant-propagation, the depth of the stack at each
opcode can be determined at compile-time:

    $ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack[0] = arg_5(D);
      x_9 = stack[0];
      stack[0] = x_9;
      stack[1] = x_9;
      stack[2] = 2;
      y_17 = stack[2];
      x_19 = stack[1];
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack[1] = _21;
      x_25 = stack[1];
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      x_27 = stack[0];
      stack[0] = x_27;
      stack[1] = x_27;
      stack[2] = 1;
      y_35 = stack[2];
      x_37 = stack[1];
      _38 = x_37 - y_35;
      stack[1] = _38;
      x_42 = stack[1];
      _44 = factorial (x_42);
      stack[1] = _44;
      y_48 = stack[1];
      x_50 = stack[0];
      _51 = x_50 * y_48;
      stack[0] = _51;

    instr9:
    /* RETURN */:
      x_55 = stack[0];
      x_56 = x_55;
      stack ={v} {CLOBBER};
      return x_56;

    }

Note how, in the above, all those `stack_depth' values are now just
constants: we're accessing specific stack locations at each opcode.

  The "esra" pass ("Early Scalar Replacement of Aggregates") breaks out
our "stack" array into individual elements:

    $ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    Created a replacement for stack offset: 0, size: 32: stack$0
    Created a replacement for stack offset: 32, size: 32: stack$1
    Created a replacement for stack offset: 64, size: 32: stack$2

    Symbols to be put in SSA form
    { D.89 D.90 D.91 }
    Incremental SSA update started at block: 0
    Number of blocks in CFG: 5
    Number of blocks to update: 4 ( 80%)


    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack$0_45 = arg_5(D);
      x_9 = stack$0_45;
      stack$0_39 = x_9;
      stack$1_32 = x_9;
      stack$2_30 = 2;
      y_17 = stack$2_30;
      x_19 = stack$1_32;
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack$1_28 = _21;
      x_25 = stack$1_28;
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      x_27 = stack$0_39;
      stack$0_22 = x_27;
      stack$1_14 = x_27;
      stack$2_12 = 1;
      y_35 = stack$2_12;
      x_37 = stack$1_14;
      _38 = x_37 - y_35;
      stack$1_10 = _38;
      x_42 = stack$1_10;
      _44 = factorial (x_42);
      stack$1_6 = _44;
      y_48 = stack$1_6;
      x_50 = stack$0_22;
      _51 = x_50 * y_48;
      stack$0_1 = _51;

      # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)>
    instr9:
    /* RETURN */:
      x_55 = stack$0_52;
      x_56 = x_55;
      stack ={v} {CLOBBER};
      return x_56;

    }

Hence at this point, all those pushes and pops of the stack are now
simply assignments to specific temporary variables.

  After some copy propagation, the stack manipulation has been
completely optimized away:

    $ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack$0_39 = arg_5(D);
      _20 = arg_5(D) <= 1;
      _21 = (signed int) _20;
      if (_21 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _38 = arg_5(D) + -1;
      _44 = factorial (_38);
      _51 = arg_5(D) * _44;
      stack$0_1 = _51;

      # stack$0_52 = PHI <arg_5(D)(2), _51(3)>
    instr9:
    /* RETURN */:
      stack ={v} {CLOBBER};
      return stack$0_52;

    }

Later on, another pass finally eliminated `stack_depth' local and the
unused parts of the `stack`' array altogether:

    $ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    Released 44 names, 314.29%, removed 44 holes
    factorial (signed int arg)
    {
      signed int stack$0;
      signed int mult_acc_1;
      <unnamed type> _5;
      signed int _6;
      signed int _7;
      signed int mul_tmp_10;
      signed int mult_acc_11;
      signed int mult_acc_13;

      # arg_9 = PHI <arg_8(D)(0)>
      # mult_acc_13 = PHI <1(0)>
    initial:

      <bb 5>:
      # arg_4 = PHI <arg_9(2), _7(3)>
      # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)>
      _5 = arg_4 <= 1;
      _6 = (signed int) _5;
      if (_6 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _7 = arg_4 + -1;
      mult_acc_11 = mult_acc_1 * arg_4;
      goto <bb 5>;

      # stack$0_12 = PHI <arg_4(5)>
    instr9:
    /* RETURN */:
      mul_tmp_10 = mult_acc_1 * stack$0_12;
      return mul_tmp_10;

    }



File: libgccjit.info,  Node: Elimination of tail recursion,  Prev: Optimizing away stack manipulation,  Up: Behind the curtain How does our code get optimized?

1.4.10.2 Elimination of tail recursion
......................................

Another significant optimization is the detection that the call to
`factorial' is tail recursion, which can be eliminated in favor of an
iteration:

    $ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)


    Symbols to be put in SSA form
    { D.88 }
    Incremental SSA update started at block: 0
    Number of blocks in CFG: 5
    Number of blocks to update: 4 ( 80%)


    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      signed int mult_acc_1;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int mul_tmp_44;
      signed int mult_acc_51;

      # arg_5 = PHI <arg_39(D)(0), _38(3)>
      # mult_acc_1 = PHI <1(0), mult_acc_51(3)>
    initial:
      _20 = arg_5 <= 1;
      _21 = (signed int) _20;
      if (_21 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _38 = arg_5 + -1;
      mult_acc_51 = mult_acc_1 * arg_5;
      goto <bb 2> (initial);

      # stack$0_52 = PHI <arg_5(2)>
    instr9:
    /* RETURN */:
      stack ={v} {CLOBBER};
      mul_tmp_44 = mult_acc_1 * stack$0_52;
      return mul_tmp_44;

    }



File: libgccjit.info,  Node: Tutorial part 5 Implementing an Ahead-of-Time compiler,  Prev: Tutorial part 4 Adding JIT-compilation to a toy interpreter,  Up: Tutorial

1.5 Tutorial part 5: Implementing an Ahead-of-Time compiler
===========================================================

If you have a pre-existing language frontend that's compatible with
libgccjit's license, it's possible to hook it up to libgccjit as a
backend.  In the previous example we showed how to do that for
in-memory JIT-compilation, but libgccjit can also compile code directly
to a file, allowing you to implement a more traditional ahead-of-time
compiler ("JIT" is something of a misnomer for this use-case).

  The essential difference is to compile the context using *note
gcc_jit_context_compile_to_file(): 4a. rather than *note
gcc_jit_context_compile(): 15.

* Menu:

* The "brainf" language::
* Converting a brainf script to libgccjit IR::
* Compiling a context to a file::
* Other forms of ahead-of-time-compilation::


File: libgccjit.info,  Node: The "brainf" language,  Next: Converting a brainf script to libgccjit IR,  Up: Tutorial part 5 Implementing an Ahead-of-Time compiler

1.5.1 The "brainf" language
---------------------------

In this example we use libgccjit to construct an ahead-of-time compiler
for an esoteric programming language that we shall refer to as "brainf".

  brainf scripts operate on an array of bytes, with a notional data
pointer within the array.

  brainf is hard for humans to read, but it's trivial to write a parser
for it, as there is no lexing; just a stream of bytes.  The operations
are:

Character                  Meaning
------------------------------------------------------------- 
`>'                        `idx += 1'
`<'                        `idx -= 1'
`+'                        `data[idx] += 1'
`-'                        `data[idx] -= 1'
`.'                        `output (data[idx])'
`,'                        `data[idx] = input ()'
`['                        loop until `data[idx] == 0'
`]'                        end of loop
Anything else              ignored

  Unlike the previous example, we'll implement an ahead-of-time
compiler, which reads `.bf' scripts and outputs executables (though it
would be trivial to have it run them JIT-compiled in-process).

  Here's what a simple `.bf' script looks like:

         [
           Emit the uppercase alphabet
         ]

         cell 0 = 26
         ++++++++++++++++++++++++++

         cell 1 = 65
         >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<

         while cell#0 != 0
         [
          >
          .      emit cell#1
          +      increment cell@1
          <-     decrement cell@0
         ]



     Note: This example makes use of whitespace and comments for
     legibility, but could have been written as:

         ++++++++++++++++++++++++++
         >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
         [>.+<-]

     It's not a particularly useful language, except for providing
     compiler-writers with a test case that's easy to parse.  The point
     is that you can use *note gcc_jit_context_compile_to_file(): 4a.
     to use libgccjit as a backend for a pre-existing language frontend
     (provided that the pre-existing frontend is compatible with
     libgccjit's license).


File: libgccjit.info,  Node: Converting a brainf script to libgccjit IR,  Next: Compiling a context to a file,  Prev: The "brainf" language,  Up: Tutorial part 5 Implementing an Ahead-of-Time compiler

1.5.2 Converting a brainf script to libgccjit IR
------------------------------------------------

As before we write simple code to populate a *note gcc_jit_context *: 8.


         typedef struct bf_compiler
         {
           const char *filename;
           int line;
           int column;

           gcc_jit_context *ctxt;

           gcc_jit_type *void_type;
           gcc_jit_type *int_type;
           gcc_jit_type *byte_type;
           gcc_jit_type *array_type;

           gcc_jit_function *func_getchar;
           gcc_jit_function *func_putchar;

           gcc_jit_function *func;
           gcc_jit_block *curblock;

           gcc_jit_rvalue *int_zero;
           gcc_jit_rvalue *int_one;
           gcc_jit_rvalue *byte_zero;
           gcc_jit_rvalue *byte_one;
           gcc_jit_lvalue *data_cells;
           gcc_jit_lvalue *idx;

           int num_open_parens;
           gcc_jit_block *paren_test[MAX_OPEN_PARENS];
           gcc_jit_block *paren_body[MAX_OPEN_PARENS];
           gcc_jit_block *paren_after[MAX_OPEN_PARENS];

         } bf_compiler;

         /* Bail out, with a message on stderr.  */

         static void
         fatal_error (bf_compiler *bfc, const char *msg)
         {
           fprintf (stderr,
         	   "%s:%i:%i: %s",
         	   bfc->filename, bfc->line, bfc->column, msg);
           abort ();
         }

         /* Get "data_cells[idx]" as an lvalue.  */

         static gcc_jit_lvalue *
         bf_get_current_data (bf_compiler *bfc, gcc_jit_location *loc)
         {
           return gcc_jit_context_new_array_access (
             bfc->ctxt,
             loc,
             gcc_jit_lvalue_as_rvalue (bfc->data_cells),
             gcc_jit_lvalue_as_rvalue (bfc->idx));
         }

         /* Get "data_cells[idx] == 0" as a boolean rvalue.  */

         static gcc_jit_rvalue *
         bf_current_data_is_zero (bf_compiler *bfc, gcc_jit_location *loc)
         {
           return gcc_jit_context_new_comparison (
             bfc->ctxt,
             loc,
             GCC_JIT_COMPARISON_EQ,
             gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)),
             bfc->byte_zero);
         }

         /* Compile one bf character.  */

         static void
         bf_compile_char (bf_compiler *bfc,
         		 unsigned char ch)
         {
           gcc_jit_location *loc =
             gcc_jit_context_new_location (bfc->ctxt,
         				  bfc->filename,
         				  bfc->line,
         				  bfc->column);

           /* Turn this on to trace execution, by injecting putchar ()
              of each source char. */
           if (0)
             {
               gcc_jit_rvalue *arg =
         	gcc_jit_context_new_rvalue_from_int (
         					     bfc->ctxt,
         					     bfc->int_type,
         					     ch);
               gcc_jit_rvalue *call =
         	gcc_jit_context_new_call (bfc->ctxt,
         				  loc,
         				  bfc->func_putchar,
         				  1, &arg);
               gcc_jit_block_add_eval (bfc->curblock,
         			      loc,
         			      call);
             }

           switch (ch)
             {
               case '>':
         	gcc_jit_block_add_comment (bfc->curblock,
         				   loc,
         				   "'>': idx += 1;");
         	gcc_jit_block_add_assignment_op (bfc->curblock,
         					 loc,
         					 bfc->idx,
         					 GCC_JIT_BINARY_OP_PLUS,
         					 bfc->int_one);
         	break;

               case '<':
         	gcc_jit_block_add_comment (bfc->curblock,
         				   loc,
         				   "'<': idx -= 1;");
         	gcc_jit_block_add_assignment_op (bfc->curblock,
         					 loc,
         					 bfc->idx,
         					 GCC_JIT_BINARY_OP_MINUS,
         					 bfc->int_one);
         	break;

               case '+':
         	gcc_jit_block_add_comment (bfc->curblock,
         				   loc,
         				   "'+': data[idx] += 1;");
         	gcc_jit_block_add_assignment_op (bfc->curblock,
         					 loc,
         					 bf_get_current_data (bfc, loc),
         					 GCC_JIT_BINARY_OP_PLUS,
         					 bfc->byte_one);
         	break;

               case '-':
         	gcc_jit_block_add_comment (bfc->curblock,
         				   loc,
         				   "'-': data[idx] -= 1;");
         	gcc_jit_block_add_assignment_op (bfc->curblock,
         					 loc,
         					 bf_get_current_data (bfc, loc),
         					 GCC_JIT_BINARY_OP_MINUS,
         					 bfc->byte_one);
         	break;

               case '.':
         	{
         	  gcc_jit_rvalue *arg =
         	    gcc_jit_context_new_cast (
         	      bfc->ctxt,
         	      loc,
         	      gcc_jit_lvalue_as_rvalue (bf_get_current_data (bfc, loc)),
         	      bfc->int_type);
         	  gcc_jit_rvalue *call =
         	    gcc_jit_context_new_call (bfc->ctxt,
         				      loc,
         				      bfc->func_putchar,
         				      1, &arg);
         	  gcc_jit_block_add_comment (bfc->curblock,
         				     loc,
         				     "'.': putchar ((int)data[idx]);");
         	  gcc_jit_block_add_eval (bfc->curblock,
         				  loc,
         				  call);
         	}
         	break;

               case ',':
         	{
         	  gcc_jit_rvalue *call =
         	    gcc_jit_context_new_call (bfc->ctxt,
         				      loc,
         				      bfc->func_getchar,
         				      0, NULL);
         	  gcc_jit_block_add_comment (
         	    bfc->curblock,
         	    loc,
         	    "',': data[idx] = (unsigned char)getchar ();");
         	  gcc_jit_block_add_assignment (bfc->curblock,
         					loc,
         					bf_get_current_data (bfc, loc),
         					gcc_jit_context_new_cast (
         					  bfc->ctxt,
         					  loc,
         					  call,
         					  bfc->byte_type));
         	}
         	break;

               case '[':
         	{
         	  gcc_jit_block *loop_test =
         	    gcc_jit_function_new_block (bfc->func, NULL);
         	  gcc_jit_block *on_zero =
         	    gcc_jit_function_new_block (bfc->func, NULL);
         	  gcc_jit_block *on_non_zero =
         	    gcc_jit_function_new_block (bfc->func, NULL);

         	  if (bfc->num_open_parens == MAX_OPEN_PARENS)
         	    fatal_error (bfc, "too many open parens");

         	  gcc_jit_block_end_with_jump (
         	    bfc->curblock,
         	    loc,
         	    loop_test);

         	  gcc_jit_block_add_comment (
         	    loop_test,
         	    loc,
         	    "'['");
         	  gcc_jit_block_end_with_conditional (
         	    loop_test,
         	    loc,
         	    bf_current_data_is_zero (bfc, loc),
         	    on_zero,
         	    on_non_zero);
         	  bfc->paren_test[bfc->num_open_parens] = loop_test;
         	  bfc->paren_body[bfc->num_open_parens] = on_non_zero;
         	  bfc->paren_after[bfc->num_open_parens] = on_zero;
         	  bfc->num_open_parens += 1;
         	  bfc->curblock = on_non_zero;
         	}
         	break;

               case ']':
         	{
         	  gcc_jit_block_add_comment (
         	    bfc->curblock,
         	    loc,
         	    "']'");

         	  if (bfc->num_open_parens == 0)
         	    fatal_error (bfc, "mismatching parens");
         	  bfc->num_open_parens -= 1;
         	  gcc_jit_block_end_with_jump (
         	    bfc->curblock,
         	    loc,
         	    bfc->paren_test[bfc->num_open_parens]);
         	  bfc->curblock = bfc->paren_after[bfc->num_open_parens];
         	}
         	break;

             case '\n':
               bfc->line +=1;
               bfc->column = 0;
               break;
             }

           if (ch != '\n')
             bfc->column += 1;
         }

         /* Compile the given .bf file into a gcc_jit_context, containing a
            single "main" function suitable for compiling into an executable.  */

         gcc_jit_context *
         bf_compile (const char *filename)
         {
           bf_compiler bfc;
           FILE *f_in;
           int ch;

           memset (&bfc, 0, sizeof (bfc));

           bfc.filename = filename;
           f_in = fopen (filename, "r");
           if (!f_in)
             fatal_error (&bfc, "unable to open file");
           bfc.line = 1;

           bfc.ctxt = gcc_jit_context_acquire ();

           gcc_jit_context_set_int_option (
             bfc.ctxt,
             GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
             3);
           gcc_jit_context_set_bool_option (
             bfc.ctxt,
             GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
             0);
           gcc_jit_context_set_bool_option (
             bfc.ctxt,
             GCC_JIT_BOOL_OPTION_DEBUGINFO,
             1);
           gcc_jit_context_set_bool_option (
             bfc.ctxt,
             GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
             0);
           gcc_jit_context_set_bool_option (
             bfc.ctxt,
             GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
             0);

           bfc.void_type =
             gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_VOID);
           bfc.int_type =
             gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_INT);
           bfc.byte_type =
             gcc_jit_context_get_type (bfc.ctxt, GCC_JIT_TYPE_UNSIGNED_CHAR);
           bfc.array_type =
             gcc_jit_context_new_array_type (bfc.ctxt,
         				    NULL,
         				    bfc.byte_type,
         				    30000);

           bfc.func_getchar =
             gcc_jit_context_new_function (bfc.ctxt, NULL,
         				  GCC_JIT_FUNCTION_IMPORTED,
         				  bfc.int_type,
         				  "getchar",
         				  0, NULL,
         				  0);

           gcc_jit_param *param_c =
             gcc_jit_context_new_param (bfc.ctxt, NULL, bfc.int_type, "c");
           bfc.func_putchar =
             gcc_jit_context_new_function (bfc.ctxt, NULL,
         				  GCC_JIT_FUNCTION_IMPORTED,
         				  bfc.void_type,
         				  "putchar",
         				  1, &param_c,
         				  0);

           bfc.func = make_main (bfc.ctxt);
            bfc.curblock =
             gcc_jit_function_new_block (bfc.func, "initial");
           bfc.int_zero = gcc_jit_context_zero (bfc.ctxt, bfc.int_type);
           bfc.int_one = gcc_jit_context_one (bfc.ctxt, bfc.int_type);
           bfc.byte_zero = gcc_jit_context_zero (bfc.ctxt, bfc.byte_type);
           bfc.byte_one = gcc_jit_context_one (bfc.ctxt, bfc.byte_type);

           bfc.data_cells =
             gcc_jit_context_new_global (bfc.ctxt, NULL,
         				 GCC_JIT_GLOBAL_INTERNAL,
         				 bfc.array_type,
         				 "data_cells");
           bfc.idx =
             gcc_jit_function_new_local (bfc.func, NULL,
         				bfc.int_type,
         				"idx");

           gcc_jit_block_add_comment (bfc.curblock,
         			     NULL,
         			     "idx = 0;");
           gcc_jit_block_add_assignment (bfc.curblock,
         				NULL,
         				bfc.idx,
         				bfc.int_zero);

           bfc.num_open_parens = 0;

           while ( EOF != (ch = fgetc (f_in)))
             bf_compile_char (&bfc, (unsigned char)ch);

           gcc_jit_block_end_with_return (bfc.curblock, NULL, bfc.int_zero);

           fclose (f_in);

           return bfc.ctxt;
         }




File: libgccjit.info,  Node: Compiling a context to a file,  Next: Other forms of ahead-of-time-compilation,  Prev: Converting a brainf script to libgccjit IR,  Up: Tutorial part 5 Implementing an Ahead-of-Time compiler

1.5.3 Compiling a context to a file
-----------------------------------

Unlike the previous tutorial, this time we'll compile the context
directly to an executable, using *note
gcc_jit_context_compile_to_file(): 4a.:

    gcc_jit_context_compile_to_file (ctxt,
                                     GCC_JIT_OUTPUT_KIND_EXECUTABLE,
                                     output_file);

Here's the top-level of the compiler, which is what actually calls into
*note gcc_jit_context_compile_to_file(): 4a.:


         int
         main (int argc, char **argv)
         {
           const char *input_file;
           const char *output_file;
           gcc_jit_context *ctxt;
           const char *err;

           if (argc != 3)
             {
               fprintf (stderr, "%s: INPUT_FILE OUTPUT_FILE\n", argv[0]);
               return 1;
             }

           input_file = argv[1];
           output_file = argv[2];
           ctxt = bf_compile (input_file);

           gcc_jit_context_compile_to_file (ctxt,
         				   GCC_JIT_OUTPUT_KIND_EXECUTABLE,
         				   output_file);

           err = gcc_jit_context_get_first_error (ctxt);

           if (err)
             {
               gcc_jit_context_release (ctxt);
               return 1;
             }

           gcc_jit_context_release (ctxt);
           return 0;
         }



  Note how once the context is populated you could trivially instead
compile it to memory using *note gcc_jit_context_compile(): 15. and run
it in-process as in the previous tutorial.

  To create an executable, we need to export a `main' function.  Here's
how to create one from the JIT API:


         /* Make "main" function:
              int
              main (int argc, char **argv)
              {
                ...
              }
         */
         static gcc_jit_function *
         make_main (gcc_jit_context *ctxt)
         {
           gcc_jit_type *int_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
           gcc_jit_param *param_argc =
             gcc_jit_context_new_param (ctxt, NULL, int_type, "argc");
           gcc_jit_type *char_ptr_ptr_type =
             gcc_jit_type_get_pointer (
               gcc_jit_type_get_pointer (
         	gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_CHAR)));
           gcc_jit_param *param_argv =
             gcc_jit_context_new_param (ctxt, NULL, char_ptr_ptr_type, "argv");
           gcc_jit_param *params[2] = {param_argc, param_argv};
           gcc_jit_function *func_main =
             gcc_jit_context_new_function (ctxt, NULL,
         				  GCC_JIT_FUNCTION_EXPORTED,
         				  int_type,
         				  "main",
         				  2, params,
         				  0);
           return func_main;
         }



     Note: The above implementation ignores `argc' and `argv', but you
     could make use of them by exposing `param_argc' and `param_argv'
     to the caller.

  Upon compiling this C code, we obtain a bf-to-machine-code compiler;
let's call it `bfc':

    $ gcc \
        tut05-bf.c \
        -o bfc \
        -lgccjit

We can now use `bfc' to compile .bf files into machine code executables:

    $ ./bfc \
         emit-alphabet.bf \
         a.out

which we can run directly:

    $ ./a.out
    ABCDEFGHIJKLMNOPQRSTUVWXYZ

Success!

  We can also inspect the generated executable using standard tools:

    $ objdump -d a.out |less

which shows that libgccjit has managed to optimize the function
somewhat (for example, the runs of 26 and 65 increment operations have
become integer constants 0x1a and 0x41):

    0000000000400620 <main>:
      400620:     80 3d 39 0a 20 00 00    cmpb   $0x0,0x200a39(%rip)        # 601060 <data
      400627:     74 07                   je     400630 <main
      400629:     eb fe                   jmp    400629 <main+0x9>
      40062b:     0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
      400630:     48 83 ec 08             sub    $0x8,%rsp
      400634:     0f b6 05 26 0a 20 00    movzbl 0x200a26(%rip),%eax        # 601061 <data_cells+0x1>
      40063b:     c6 05 1e 0a 20 00 1a    movb   $0x1a,0x200a1e(%rip)       # 601060 <data_cells>
      400642:     8d 78 41                lea    0x41(%rax),%edi
      400645:     40 88 3d 15 0a 20 00    mov    %dil,0x200a15(%rip)        # 601061 <data_cells+0x1>
      40064c:     0f 1f 40 00             nopl   0x0(%rax)
      400650:     40 0f b6 ff             movzbl %dil,%edi
      400654:     e8 87 fe ff ff          callq  4004e0 <putchar@plt>
      400659:     0f b6 05 01 0a 20 00    movzbl 0x200a01(%rip),%eax        # 601061 <data_cells+0x1>
      400660:     80 2d f9 09 20 00 01    subb   $0x1,0x2009f9(%rip)        # 601060 <data_cells>
      400667:     8d 78 01                lea    0x1(%rax),%edi
      40066a:     40 88 3d f0 09 20 00    mov    %dil,0x2009f0(%rip)        # 601061 <data_cells+0x1>
      400671:     75 dd                   jne    400650 <main+0x30>
      400673:     31 c0                   xor    %eax,%eax
      400675:     48 83 c4 08             add    $0x8,%rsp
      400679:     c3                      retq
      40067a:     66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

We also set up debugging information (via *note
gcc_jit_context_new_location(): 41. and *note
GCC_JIT_BOOL_OPTION_DEBUGINFO: 42.), so it's possible to use `gdb' to
singlestep through the generated binary and inspect the internal state
`idx' and `data_cells':

    (gdb) break main
    Breakpoint 1 at 0x400790
    (gdb) run
    Starting program: a.out

    Breakpoint 1, 0x0000000000400790 in main (argc=1, argv=0x7fffffffe448)
    (gdb) stepi
    0x0000000000400797 in main (argc=1, argv=0x7fffffffe448)
    (gdb) stepi
    0x00000000004007a0 in main (argc=1, argv=0x7fffffffe448)
    (gdb) stepi
    9     >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
    (gdb) list
    4
    5     cell 0 = 26
    6     ++++++++++++++++++++++++++
    7
    8     cell 1 = 65
    9     >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
    10
    11    while cell#0 != 0
    12    [
    13     >
    (gdb) n
    6     ++++++++++++++++++++++++++
    (gdb) n
    9     >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
    (gdb) p idx
    $1 = 1
    (gdb) p data_cells
    $2 = "\032", '\000' <repeats 29998 times>
    (gdb) p data_cells[0]
    $3 = 26 '\032'
    (gdb) p data_cells[1]
    $4 = 0 '\000'
    (gdb) list
    4
    5     cell 0 = 26
    6     ++++++++++++++++++++++++++
    7
    8     cell 1 = 65
    9     >+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
    10
    11    while cell#0 != 0
    12    [
    13     >



File: libgccjit.info,  Node: Other forms of ahead-of-time-compilation,  Prev: Compiling a context to a file,  Up: Tutorial part 5 Implementing an Ahead-of-Time compiler

1.5.4 Other forms of ahead-of-time-compilation
----------------------------------------------

The above demonstrates compiling a *note gcc_jit_context *: 8. directly
to an executable.  It's also possible to compile it to an object file,
and to a dynamic library.  See the documentation of *note
gcc_jit_context_compile_to_file(): 4a. for more information.


File: libgccjit.info,  Node: Topic Reference,  Next: C++ bindings for libgccjit,  Prev: Tutorial,  Up: Top

2 Topic Reference
*****************

* Menu:

* Compilation contexts::
* Objects::
* Types::
* Expressions::
* Creating and using functions::
* Function pointers: Function pointers<2>.
* Source Locations::
* Compiling a context::
* ABI and API compatibility::
* Performance::

Compilation contexts

* Lifetime-management::
* Thread-safety::
* Error-handling: Error-handling<2>.
* Debugging::
* Options: Options<2>.

Options

* String Options::
* Boolean options::
* Integer options::
* Additional command-line options::

Types

* Standard types::
* Pointers, const, and volatile: Pointers const and volatile.
* Vector types::
* Structures and unions::
* Function pointer types::

Expressions

* Rvalues::
* Lvalues::
* Working with pointers, structs and unions: Working with pointers structs and unions.

Rvalues

* Simple expressions::
* Vector expressions::
* Unary Operations::
* Binary Operations::
* Comparisons::
* Function calls::
* Function pointers::
* Type-coercion::

Lvalues

* Global variables::

Creating and using functions

* Params::
* Functions::
* Blocks::
* Statements::

Source Locations

* Faking it::

Compiling a context

* In-memory compilation::
* Ahead-of-time compilation::

ABI and API compatibility

* ABI symbol tags::

ABI symbol tags

* LIBGCCJIT_ABI_0::
* LIBGCCJIT_ABI_1::
* LIBGCCJIT_ABI_2::
* LIBGCCJIT_ABI_3::
* LIBGCCJIT_ABI_4::
* LIBGCCJIT_ABI_5::
* LIBGCCJIT_ABI_6::
* LIBGCCJIT_ABI_7::
* LIBGCCJIT_ABI_8::
* LIBGCCJIT_ABI_9::
* LIBGCCJIT_ABI_10::

Performance

* The timing API::


File: libgccjit.info,  Node: Compilation contexts,  Next: Objects,  Up: Topic Reference

2.1 Compilation contexts
========================

 -- C Type: gcc_jit_context

  The top-level of the API is the *note gcc_jit_context: 8. type.

  A *note gcc_jit_context: 8. instance encapsulates the state of a
compilation.

  You can set up options on it, and add types, functions and code.
Invoking *note gcc_jit_context_compile(): 15. on it gives you a *note
gcc_jit_result: 16.

* Menu:

* Lifetime-management::
* Thread-safety::
* Error-handling: Error-handling<2>.
* Debugging::
* Options: Options<2>.


File: libgccjit.info,  Node: Lifetime-management,  Next: Thread-safety,  Up: Compilation contexts

2.1.1 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.

 -- C Function: gcc_jit_context *gcc_jit_context_acquire (void)
     This function acquires a new *note gcc_jit_context *: 8. instance,
     which is independent of any others that may be present within this
     process.

 -- C Function: void gcc_jit_context_release (gcc_jit_context *ctxt)
     This function releases all resources associated with the given
     context.  Both the context itself and all of its *note
     gcc_jit_object *: e.  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.

         gcc_jit_context_release (ctxt);



 -- C Function: gcc_jit_context * gcc_jit_context_new_child_context
          (gcc_jit_context *parent_ctxt)
     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 gcc_jit_result of the parent context must
     outlive the gcc_jit_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.


File: libgccjit.info,  Node: Thread-safety,  Next: Error-handling<2>,  Prev: Lifetime-management,  Up: Compilation contexts

2.1.2 Thread-safety
-------------------

Instances of *note gcc_jit_context *: 8. created via *note
gcc_jit_context_acquire(): 9. 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 *note gcc_jit_context_new_child_context(): 54.
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.


File: libgccjit.info,  Node: Error-handling<2>,  Next: Debugging,  Prev: Thread-safety,  Up: Compilation contexts

2.1.3 Error-handling
--------------------

Various kinds of errors are possible when using the API, such as
mismatched types in an assignment.  You can only compile and get code
from a context if no errors occur.

  Errors are printed on stderr and can be queried using *note
gcc_jit_context_get_first_error(): 57.

  They typically contain the name of the API entrypoint where the error
occurred, and pertinent information on the problem:

    ./buggy-program: error: gcc_jit_block_add_assignment: mismatching types: assignment to i (type: int) from "hello world" (type: const char *)

In general, if an error occurs when using an API entrypoint, the
entrypoint returns NULL.  You don't have to check everywhere for NULL
results, since the API handles a NULL being passed in for any argument
by issuing another error.  This typically leads to a cascade of
followup error messages, but is safe (albeit verbose).  The first error
message is usually the one to pay attention to, since it is likely to
be responsible for all of the rest:

 -- C Function: const char * gcc_jit_context_get_first_error
          (gcc_jit_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.

  If you are wrapping the C API for a higher-level language that
supports exception-handling, you may instead be interested in the last
error that occurred on the context, so that you can embed this in an
exception:

 -- C Function: const char * gcc_jit_context_get_last_error
          (gcc_jit_context *ctxt)
     Returns the last error message that occurred on the context.

     If no errors occurred, this will be NULL.

     If non-NULL, the returned string is only guaranteed to be valid
     until the next call to libgccjit relating to this context.


File: libgccjit.info,  Node: Debugging,  Next: Options<2>,  Prev: Error-handling<2>,  Up: Compilation contexts

2.1.4 Debugging
---------------

 -- C Function: void gcc_jit_context_dump_to_file
          (gcc_jit_context *ctxt, const char *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 *note
     gcc_jit_location: 3b.  information throughout the context,
     pointing at the dump file as if it were a source file.  This may
     be of use in conjunction with *note GCC_JIT_BOOL_OPTION_DEBUGINFO:
     42. to allow stepping through the code in a debugger.

 -- C Function: void gcc_jit_context_set_logfile
          (gcc_jit_context *ctxt, FILE *logfile, int flags,
          int verbosity)
     To help with debugging; enable ongoing logging of the context's
     activity to the given file.

     For example, the following will enable logging to stderr.

         gcc_jit_context_set_logfile (ctxt, stderr, 0, 0);

     Examples of information logged include:

        * API calls

        * the various steps involved within compilation

        * activity on any *note gcc_jit_result: 16. instances created by
          the context

        * activity within any child contexts

     An example of a log can be seen *note here: 5c, though the precise
     format and kinds of information logged is subject to change.

     The caller remains responsible for closing `logfile', and it must
     not be closed until all users are released.  In particular, note
     that child contexts and *note gcc_jit_result: 16. instances
     created by the context will use the logfile.

     There may a performance cost for logging.

     You can turn off logging on `ctxt' by passing `NULL' for `logfile'.
     Doing so only affects the context; it does not affect child
     contexts or *note gcc_jit_result: 16. instances already created by
     the context.

     The parameters "flags" and "verbosity" are reserved for future
     expansion, and must be zero for now.

  To contrast the above: *note gcc_jit_context_dump_to_file(): 5a.
dumps the current state of a context to the given path, whereas *note
gcc_jit_context_set_logfile(): 5b. enables on-going logging of future
activies on a context to the given `FILE *'.

 -- C Function: void gcc_jit_context_dump_reproducer_to_file
          (gcc_jit_context *ctxt, const char *path)
     Write C source code into `path' that can be compiled into a
     self-contained executable (i.e. with libgccjit as the only
     dependency).  The generated code will attempt to replay the API
     calls that have been made into the given context.

     This may be useful when debugging the library or client code, for
     reducing a complicated recipe for reproducing a bug into a simpler
     form.  For example, consider client code that parses some source
     file into some internal representation, and then walks this IR,
     calling into libgccjit.  If this encounters a bug, a call to
     `gcc_jit_context_dump_reproducer_to_file' will write out C code for
     a much simpler executable that performs the equivalent calls into
     libgccjit, without needing the client code and its data.

     Typically you need to supply `-Wno-unused-variable' when compiling
     the generated file (since the result of each API call is assigned
     to a unique variable within the generated C source, and not all
     are necessarily then used).

 -- C Function: void gcc_jit_context_enable_dump
          (gcc_jit_context *ctxt, const char *dumpname, char **out_ptr)
     Enable the dumping of a specific set of internal state from the
     compilation, capturing the result in-memory as a buffer.

     Parameter "dumpname" corresponds to the equivalent gcc command-line
     option, without the "-fdump-" prefix.  For example, to get the
     equivalent of `-fdump-tree-vrp1', supply `"tree-vrp1"':

         static char *dump_vrp1;

         void
         create_code (gcc_jit_context *ctxt)
         {
            gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
            /* (other API calls omitted for brevity) */
         }

     The context directly stores the dumpname as a `(const char *)', so
     the passed string must outlive the context.

     *note gcc_jit_context_compile(): 15. will capture the dump as a
     dynamically-allocated buffer, writing it to `*out_ptr'.

     The caller becomes responsible for calling:

         free (*out_ptr)

     each time that *note gcc_jit_context_compile(): 15. is called.
     `*out_ptr' will be written to, either with the address of a buffer,
     or with `NULL' if an error occurred.

          Warning: This API entrypoint is likely to be less stable than
          the others.  In particular, both the precise dumpnames, and
          the format and content of the dumps are subject to change.

          It exists primarily for writing the library's own test suite.


File: libgccjit.info,  Node: Options<2>,  Prev: Debugging,  Up: Compilation contexts

2.1.5 Options
-------------

Options present in the initial release of libgccjit were handled using
enums, whereas those added subsequently have their own per-option API
entrypoints.

  Adding entrypoints for each new option means that client code that use
the new options can be identified directly from binary metadata, which
would not be possible if we instead extended the various `enum
gcc_jit_*_option'.

* Menu:

* String Options::
* Boolean options::
* Integer options::
* Additional command-line options::


File: libgccjit.info,  Node: String Options,  Next: Boolean options,  Up: Options<2>

2.1.5.1 String Options
......................

 -- C Function: void gcc_jit_context_set_str_option
          (gcc_jit_context *ctxt, enum gcc_jit_str_option opt, const
          char *value)
     Set a string option of the context.

      -- C Type: enum gcc_jit_str_option

     The parameter `value' can be NULL.   If 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.

     There is just one string option specified this way:

      -- C Macro: GCC_JIT_STR_OPTION_PROGNAME
          The name of the program, for use as a prefix when printing
          error messages to stderr.  If `NULL', or default,
          "libgccjit.so" is used.


File: libgccjit.info,  Node: Boolean options,  Next: Integer options,  Prev: String Options,  Up: Options<2>

2.1.5.2 Boolean options
.......................

 -- C Function: void gcc_jit_context_set_bool_option
          (gcc_jit_context *ctxt, enum gcc_jit_bool_option opt,
          int value)
     Set a boolean option of the context.  Zero is "false" (the
     default), non-zero is "true".

      -- C Type: enum gcc_jit_bool_option

      -- C Macro: GCC_JIT_BOOL_OPTION_DEBUGINFO
          If true, *note gcc_jit_context_compile(): 15. will attempt to
          do the right thing so that if you attach a debugger to the
          process, it will be able to inspect variables and step
          through your code.

          Note that you can't step through code unless you set up source
          location information for the code (by creating and passing in
          *note gcc_jit_location: 3b. instances).

      -- C Macro: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE
          If true, *note gcc_jit_context_compile(): 15. will dump its
          initial "tree" representation of your code to stderr (before
          any optimizations).

          Here's some sample output (from the `square' example):

              <statement_list 0x7f4875a62cc0
                 type <void_type 0x7f4875a64bd0 VOID
                     align 8 symtab 0 alias set -1 canonical type 0x7f4875a64bd0
                     pointer_to_this <pointer_type 0x7f4875a64c78>>
                 side-effects head 0x7f4875a761e0 tail 0x7f4875a761f8 stmts 0x7f4875a62d20 0x7f4875a62d00

                 stmt <label_expr 0x7f4875a62d20 type <void_type 0x7f4875a64bd0>
                     side-effects
                     arg 0 <label_decl 0x7f4875a79080 entry type <void_type 0x7f4875a64bd0>
                         VOID file (null) line 0 col 0
                         align 1 context <function_decl 0x7f4875a77500 square>>>
                 stmt <return_expr 0x7f4875a62d00
                     type <integer_type 0x7f4875a645e8 public SI
                         size <integer_cst 0x7f4875a623a0 constant 32>
                         unit size <integer_cst 0x7f4875a623c0 constant 4>
                         align 32 symtab 0 alias set -1 canonical type 0x7f4875a645e8 precision 32 min <integer_cst 0x7f4875a62340 -2147483648> max <integer_cst 0x7f4875a62360 2147483647>
                         pointer_to_this <pointer_type 0x7f4875a6b348>>
                     side-effects
                     arg 0 <modify_expr 0x7f4875a72a78 type <integer_type 0x7f4875a645e8>
                         side-effects arg 0 <result_decl 0x7f4875a7a000 D.54>
                         arg 1 <mult_expr 0x7f4875a72a50 type <integer_type 0x7f4875a645e8>
                             arg 0 <parm_decl 0x7f4875a79000 i> arg 1 <parm_decl 0x7f4875a79000 i>>>>>



      -- C Macro: GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE
          If true, *note gcc_jit_context_compile(): 15. will dump the
          "gimple" representation of your code to stderr, before any
          optimizations are performed.  The dump resembles C code:

              square (signed int i)
              {
                signed int D.56;

                entry:
                D.56 = i * i;
                return D.56;
              }



      -- C Macro: GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE
          If true, *note gcc_jit_context_compile(): 15. will dump the
          final generated code to stderr, in the form of assembly
          language:

                  .file    "fake.c"
                  .text
                  .globl    square
                  .type    square, @function
              square:
              .LFB0:
                  .cfi_startproc
                  pushq    %rbp
                  .cfi_def_cfa_offset 16
                  .cfi_offset 6, -16
                  movq    %rsp, %rbp
                  .cfi_def_cfa_register 6
                  movl    %edi, -4(%rbp)
              .L2:
                  movl    -4(%rbp), %eax
                  imull    -4(%rbp), %eax
                  popq    %rbp
                  .cfi_def_cfa 7, 8
                  ret
                  .cfi_endproc
              .LFE0:
                  .size    square, .-square
                  .ident    "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.1-%{gcc_release})"
                  .section    .note.GNU-stack,"",@progbits



      -- C Macro: GCC_JIT_BOOL_OPTION_DUMP_SUMMARY
          If true, *note gcc_jit_context_compile(): 15. will print
          information to stderr on the actions it is performing.

      -- C Macro: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING
          If true, *note gcc_jit_context_compile(): 15. will dump
          copious amount of information on what it's doing to various
          files within a temporary directory.  Use *note
          GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: 69. (see below) to
          see the results.  The files are intended to be human-readable,
          but the exact files and their formats are subject to change.

      -- C Macro: GCC_JIT_BOOL_OPTION_SELFCHECK_GC
          If true, libgccjit will aggressively run its garbage
          collector, to shake out bugs (greatly slowing down the
          compile).  This is likely to only be of interest to
          developers _of_ the library.  It is used when running the
          selftest suite.

      -- C Macro: GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES
          If true, the *note gcc_jit_context: 8. will not clean up
          intermediate files written to the filesystem, and will
          display their location on stderr.

 -- C Function: void gcc_jit_context_set_bool_allow_unreachable_blocks
          (gcc_jit_context *ctxt, 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.

     This entrypoint was added in *note LIBGCCJIT_ABI_2: 6c.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks



 -- C Function: void gcc_jit_context_set_bool_use_external_driver
          (gcc_jit_context *ctxt, 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.

     This entrypoint was added in *note LIBGCCJIT_ABI_5: 6e.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver




File: libgccjit.info,  Node: Integer options,  Next: Additional command-line options,  Prev: Boolean options,  Up: Options<2>

2.1.5.3 Integer options
.......................

 -- C Function: void gcc_jit_context_set_int_option
          (gcc_jit_context *ctxt, enum gcc_jit_int_option opt,
          int value)
     Set an integer option of the context.

      -- C Type: enum gcc_jit_int_option

     There is just one integer option specified this way:

      -- C Macro: GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL
          How much to optimize the code.

          Valid values are 0-3, corresponding to GCC's command-line
          options -O0 through -O3.

          The default value is 0 (unoptimized).


File: libgccjit.info,  Node: Additional command-line options,  Prev: Integer options,  Up: Options<2>

2.1.5.4 Additional command-line options
.......................................

 -- C Function: void gcc_jit_context_add_command_line_option
          (gcc_jit_context *ctxt, const char *optname)
     Add an arbitrary gcc command-line option to the context, for use
     by *note gcc_jit_context_compile(): 15. and *note
     gcc_jit_context_compile_to_file(): 4a.

     The parameter `optname' must be non-NULL.  The underlying buffer is
     copied, so that it does not need to outlive the call.

     Extra options added by `gcc_jit_context_add_command_line_option'
     are applied _after_ the regular options above, potentially
     overriding them.  Options from parent contexts are inherited by
     child contexts; options from the parent are applied _before_ those
     from the child.

     For example:

         gcc_jit_context_add_command_line_option (ctxt, "-ffast-math");
         gcc_jit_context_add_command_line_option (ctxt, "-fverbose-asm");

     Note that only some options are likely to be meaningful; there is
     no "frontend" within libgccjit, so typically only those affecting
     optimization and code-generation are likely to be useful.

     This entrypoint was added in *note LIBGCCJIT_ABI_1: 73.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option




File: libgccjit.info,  Node: Objects,  Next: Types,  Prev: Compilation contexts,  Up: Topic Reference

2.2 Objects
===========

 -- C Type: gcc_jit_object

  Almost every entity in the API (with the exception of *note
gcc_jit_context *: 8. and *note gcc_jit_result *: 16.) is a
"contextual" object, a *note gcc_jit_object *: e.

  A JIT object:

        * is associated with a *note gcc_jit_context *: 8.

        * is automatically cleaned up for you when its context is
          released so you don't need to manually track and cleanup all
          objects, just the contexts.

  Although the API is C-based, there is a form of class hierarchy, which
looks like this:

    +- gcc_jit_object
        +- gcc_jit_location
        +- gcc_jit_type
           +- gcc_jit_struct
        +- gcc_jit_field
        +- gcc_jit_function
        +- gcc_jit_block
        +- gcc_jit_rvalue
            +- gcc_jit_lvalue
               +- gcc_jit_param
        +- gcc_jit_case

There are casting methods for upcasting from subclasses to parent
classes.  For example, *note gcc_jit_type_as_object(): d.:

    gcc_jit_object *obj = gcc_jit_type_as_object (int_type);

The object "base class" has the following operations:

 -- C Function: gcc_jit_context *gcc_jit_object_get_context
          (gcc_jit_object *obj)
     Which context is "obj" within?

 -- C Function: const char *gcc_jit_object_get_debug_string
          (gcc_jit_object *obj)
     Generate a human-readable description for the given object.

     For example,

         printf ("obj: %s\n", gcc_jit_object_get_debug_string (obj));

     might give this text on stdout:

         obj: 4.0 * (float)i


          Note: If you call this on an object, the `const char *'
          buffer is allocated and generated on the first call for that
          object, and the buffer will have the same lifetime as the
          object  i.e. it will exist until the object's context is
          released.


File: libgccjit.info,  Node: Types,  Next: Expressions,  Prev: Objects,  Up: Topic Reference

2.3 Types
=========

 -- C Type: gcc_jit_type
     gcc_jit_type represents a type within the library.

 -- C Function: gcc_jit_object *gcc_jit_type_as_object
          (gcc_jit_type *type)
     Upcast a type to an object.

  Types can be created in several ways:

   * fundamental types can be accessed using *note
     gcc_jit_context_get_type(): b.:

         gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

     See *note gcc_jit_context_get_type(): b. for the available types.

   * derived types can be accessed by using functions such as *note
     gcc_jit_type_get_pointer(): 79. and *note
     gcc_jit_type_get_const(): 7a.:

         gcc_jit_type *const_int_star = gcc_jit_type_get_pointer (gcc_jit_type_get_const (int_type));
         gcc_jit_type *int_const_star = gcc_jit_type_get_const (gcc_jit_type_get_pointer (int_type));


   * by creating structures (see below).

* Menu:

* Standard types::
* Pointers, const, and volatile: Pointers const and volatile.
* Vector types::
* Structures and unions::
* Function pointer types::


File: libgccjit.info,  Node: Standard types,  Next: Pointers const and volatile,  Up: Types

2.3.1 Standard types
--------------------

 -- C Function: gcc_jit_type *gcc_jit_context_get_type
          (gcc_jit_context *ctxt, enum gcc_jit_types type_)
     Access a specific type.  The available types are:

     `enum gcc_jit_types' value                     Meaning
     ------------------------------------------------------------------------------------- 
     `GCC_JIT_TYPE_VOID'                            C's `void' type.
     `GCC_JIT_TYPE_VOID_PTR'                        C's `void *'.
     `GCC_JIT_TYPE_BOOL'                            C++'s `bool' type; also C99's
                                                    `_Bool' type, aka `bool' if using
                                                    stdbool.h.
     `GCC_JIT_TYPE_CHAR'                            C's `char' (of some signedness)
     `GCC_JIT_TYPE_SIGNED_CHAR'                     C's `signed char'
     `GCC_JIT_TYPE_UNSIGNED_CHAR'                   C's `unsigned char'
     `GCC_JIT_TYPE_SHORT'                           C's `short' (signed)
     `GCC_JIT_TYPE_UNSIGNED_SHORT'                  C's `unsigned short'
     `GCC_JIT_TYPE_INT'                             C's `int' (signed)
     `GCC_JIT_TYPE_UNSIGNED_INT'                    C's `unsigned int'
     `GCC_JIT_TYPE_LONG'                            C's `long' (signed)
     `GCC_JIT_TYPE_UNSIGNED_LONG'                   C's `unsigned long'
     `GCC_JIT_TYPE_LONG_LONG'                       C99's `long long' (signed)
     `GCC_JIT_TYPE_UNSIGNED_LONG_LONG'              C99's `unsigned long long'
     `GCC_JIT_TYPE_FLOAT'                           
     `GCC_JIT_TYPE_DOUBLE'                          
     `GCC_JIT_TYPE_LONG_DOUBLE'                     
     `GCC_JIT_TYPE_CONST_CHAR_PTR'                  C type: `(const char *)'
     `GCC_JIT_TYPE_SIZE_T'                          C's `size_t' type
     `GCC_JIT_TYPE_FILE_PTR'                        C type: `(FILE *)'
     `GCC_JIT_TYPE_COMPLEX_FLOAT'                   C99's `_Complex float'
     `GCC_JIT_TYPE_COMPLEX_DOUBLE'                  C99's `_Complex double'
     `GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE'             C99's `_Complex long double'


 -- C Function: gcc_jit_type * gcc_jit_context_get_int_type
          (gcc_jit_context *ctxt, int num_bytes, int is_signed)
     Access the integer type of the given size.


File: libgccjit.info,  Node: Pointers const and volatile,  Next: Vector types,  Prev: Standard types,  Up: Types

2.3.2 Pointers, `const', and `volatile'
---------------------------------------

 -- C Function: gcc_jit_type *gcc_jit_type_get_pointer
          (gcc_jit_type *type)
     Given type "T", get type "T*".

 -- C Function: gcc_jit_type *gcc_jit_type_get_const
          (gcc_jit_type *type)
     Given type "T", get type "const T".

 -- C Function: gcc_jit_type *gcc_jit_type_get_volatile
          (gcc_jit_type *type)
     Given type "T", get type "volatile T".

 -- C Function: gcc_jit_type * gcc_jit_context_new_array_type
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *element_type, int num_elements)
     Given type "T", get type "T[N]" (for a constant N).

 -- C Function: gcc_jit_type * gcc_jit_type_get_aligned
          (gcc_jit_type *type, size_t alignment_in_bytes)
     Given type "T", get type:

         T __attribute__ ((aligned (ALIGNMENT_IN_BYTES)))

     The alignment must be a power of two.

     This entrypoint was added in *note LIBGCCJIT_ABI_7: 81.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_aligned




File: libgccjit.info,  Node: Vector types,  Next: Structures and unions,  Prev: Pointers const and volatile,  Up: Types

2.3.3 Vector types
------------------

 -- C Function: gcc_jit_type * gcc_jit_type_get_vector
          (gcc_jit_type *type, size_t num_units)
     Given type "T", get type:

         T  __attribute__ ((vector_size (sizeof(T) * num_units))

     T must be integral or floating point; num_units must be a power of
     two.

     This can be used to construct a vector type in which operations
     are applied element-wise.  The compiler will automatically use
     SIMD instructions where possible.  See:
     <https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html>

     For example, assuming 4-byte `ints', then:

         typedef int v4si __attribute__ ((vector_size (16)));

     can be obtained using:

         gcc_jit_type *int_type = gcc_jit_context_get_type (ctxt,
                                                            GCC_JIT_TYPE_INT);
         gcc_jit_type *v4si_type = gcc_jit_type_get_vector (int_type, 4);

     This API entrypoint was added in *note LIBGCCJIT_ABI_8: 84.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_type_get_vector

     Vector rvalues can be generated using *note
     gcc_jit_context_new_rvalue_from_vector(): 85.


File: libgccjit.info,  Node: Structures and unions,  Next: Function pointer types,  Prev: Vector types,  Up: Types

2.3.4 Structures and unions
---------------------------

 -- C Type: gcc_jit_struct

  A compound type analagous to a C `struct'.

 -- C Type: gcc_jit_field

  A field within a *note gcc_jit_struct: 87.

  You can model C `struct' types by creating *note gcc_jit_struct *:
87. and *note gcc_jit_field: 88. instances, in either order:

   * by creating the fields, then the structure.  For example, to model:

         struct coord {double x; double y; };

     you could call:

         gcc_jit_field *field_x =
           gcc_jit_context_new_field (ctxt, NULL, double_type, "x");
         gcc_jit_field *field_y =
           gcc_jit_context_new_field (ctxt, NULL, double_type, "y");
         gcc_jit_field *fields[2] = {field_x, field_y};
         gcc_jit_struct *coord =
           gcc_jit_context_new_struct_type (ctxt, NULL, "coord", 2, fields);


   * by creating the structure, then populating it with fields,
     typically to allow modelling self-referential structs such as:

         struct node { int m_hash; struct node *m_next; };

     like this:

         gcc_jit_type *node =
           gcc_jit_context_new_opaque_struct (ctxt, NULL, "node");
         gcc_jit_type *node_ptr =
           gcc_jit_type_get_pointer (node);
         gcc_jit_field *field_hash =
           gcc_jit_context_new_field (ctxt, NULL, int_type, "m_hash");
         gcc_jit_field *field_next =
           gcc_jit_context_new_field (ctxt, NULL, node_ptr, "m_next");
         gcc_jit_field *fields[2] = {field_hash, field_next};
         gcc_jit_struct_set_fields (node, NULL, 2, fields);



 -- C Function: gcc_jit_field * gcc_jit_context_new_field
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, const char *name)
     Construct a new field, with the given type and name.

     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.

 -- C Function: gcc_jit_object * gcc_jit_field_as_object
          (gcc_jit_field *field)
     Upcast from field to object.

 -- C Function: gcc_jit_struct *gcc_jit_context_new_struct_type
          (gcc_jit_context *ctxt, gcc_jit_location *loc, const
          char *name, int num_fields, gcc_jit_field **fields)
          Construct a new struct type, with the given name and fields.

          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.

 -- C Function: gcc_jit_struct * gcc_jit_context_new_opaque_struct
          (gcc_jit_context *ctxt, gcc_jit_location *loc, const
          char *name)
     Construct a new struct type, with the given name, but without
     specifying the fields.   The fields can be omitted (in which case
     the size of the struct is not known), or later specified using
     *note gcc_jit_struct_set_fields(): 8d.

     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.

 -- C Function: gcc_jit_type * gcc_jit_struct_as_type
          (gcc_jit_struct *struct_type)
     Upcast from struct to type.

 -- C Function: void gcc_jit_struct_set_fields
          (gcc_jit_struct *struct_type, gcc_jit_location *loc,
          int num_fields, gcc_jit_field **fields)
     Populate the fields of a formerly-opaque struct type.

     This can only be called once on a given struct type.

 -- C Function: gcc_jit_type * gcc_jit_context_new_union_type
          (gcc_jit_context *ctxt, gcc_jit_location *loc, const
          char *name, int num_fields, gcc_jit_field **fields)
     Construct a new union type, with the given name and fields.

     The parameter `name' must be non-NULL.  It is copied, so the input
     buffer does not need to outlive the call.

     Example of use:


         union int_or_float
         {
           int as_int;
           float as_float;
         };

         void
         create_code (gcc_jit_context *ctxt, void *user_data)
         {
           /* Let's try to inject the equivalent of:
              float
              test_union (int i)
              {
                 union int_or_float u;
         	u.as_int = i;
         	return u.as_float;
              }
           */
           gcc_jit_type *int_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
           gcc_jit_type *float_type =
             gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
           gcc_jit_field *as_int =
             gcc_jit_context_new_field (ctxt,
                                        NULL,
                                        int_type,
                                        "as_int");
           gcc_jit_field *as_float =
             gcc_jit_context_new_field (ctxt,
                                        NULL,
                                        float_type,
                                        "as_float");
           gcc_jit_field *fields[] = {as_int, as_float};
           gcc_jit_type *union_type =
             gcc_jit_context_new_union_type (ctxt, NULL,
         				    "int_or_float", 2, fields);

           /* Build the test function.  */
           gcc_jit_param *param_i =
             gcc_jit_context_new_param (ctxt, NULL, int_type, "i");
           gcc_jit_function *test_fn =
             gcc_jit_context_new_function (ctxt, NULL,
                                           GCC_JIT_FUNCTION_EXPORTED,
                                           float_type,
                                           "test_union",
                                           1, &param_i,
                                           0);

           gcc_jit_lvalue *u =
             gcc_jit_function_new_local (test_fn, NULL,
         				union_type, "u");

           gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL);

           /* u.as_int = i; */
           gcc_jit_block_add_assignment (
             block,
             NULL,
             /* "u.as_int = ..." */
             gcc_jit_lvalue_access_field (u,
         				 NULL,
         				 as_int),
             gcc_jit_param_as_rvalue (param_i));

           /* return u.as_float; */
           gcc_jit_block_end_with_return (
             block, NULL,
             gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (u),
         				 NULL,
         				 as_float));
         }




File: libgccjit.info,  Node: Function pointer types,  Prev: Structures and unions,  Up: Types

2.3.5 Function pointer types
----------------------------

Function pointer types can be created using *note
gcc_jit_context_new_function_ptr_type(): 91.


File: libgccjit.info,  Node: Expressions,  Next: Creating and using functions,  Prev: Types,  Up: Topic Reference

2.4 Expressions
===============

* Menu:

* Rvalues::
* Lvalues::
* Working with pointers, structs and unions: Working with pointers structs and unions.

Rvalues

* Simple expressions::
* Vector expressions::
* Unary Operations::
* Binary Operations::
* Comparisons::
* Function calls::
* Function pointers::
* Type-coercion::

Lvalues

* Global variables::


File: libgccjit.info,  Node: Rvalues,  Next: Lvalues,  Up: Expressions

2.4.1 Rvalues
-------------

 -- C Type: gcc_jit_rvalue

  A *note gcc_jit_rvalue *: 13. 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).

 -- C Function: gcc_jit_type *gcc_jit_rvalue_get_type
          (gcc_jit_rvalue *rvalue)
     Get the type of this rvalue.

 -- C Function: gcc_jit_object *gcc_jit_rvalue_as_object
          (gcc_jit_rvalue *rvalue)
     Upcast the given rvalue to be an object.

* Menu:

* Simple expressions::
* Vector expressions::
* Unary Operations::
* Binary Operations::
* Comparisons::
* Function calls::
* Function pointers::
* Type-coercion::


File: libgccjit.info,  Node: Simple expressions,  Next: Vector expressions,  Up: Rvalues

2.4.1.1 Simple expressions
..........................

 -- C Function: 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.

 -- C Function: 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.

 -- C Function: 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)



 -- C Function: 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)



 -- C Function: 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.

 -- C Function: 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.

 -- C Function: 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)



 -- C Function: 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.


File: libgccjit.info,  Node: Vector expressions,  Next: Unary Operations,  Prev: Simple expressions,  Up: Rvalues

2.4.1.2 Vector expressions
..........................

 -- C Function: 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 *note
     gcc_jit_type_get_vector(): 83.

     "num_elements" should match that of the vector type.

     This entrypoint was added in *note LIBGCCJIT_ABI_10: 9c.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector




File: libgccjit.info,  Node: Unary Operations,  Next: Binary Operations,  Prev: Vector expressions,  Up: Rvalues

2.4.1.3 Unary Operations
........................

 -- C Function: 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.

 -- C Type: enum gcc_jit_unary_op

  The available unary operations are:

Unary Operation                                C equivalent
---------------------------------------------------------------- 
*note GCC_JIT_UNARY_OP_MINUS: a0.              `-(EXPR)'
*note GCC_JIT_UNARY_OP_BITWISE_NEGATE: a1.     `~(EXPR)'
*note GCC_JIT_UNARY_OP_LOGICAL_NEGATE: a2.     `!(EXPR)'
*note GCC_JIT_UNARY_OP_ABS: a3.                `abs (EXPR)'

 -- C Macro: GCC_JIT_UNARY_OP_MINUS
     Negate an arithmetic value; analogous to:

         -(EXPR)

     in C.

 -- C Macro: GCC_JIT_UNARY_OP_BITWISE_NEGATE
     Bitwise negation of an integer value (one's complement); analogous
     to:

         ~(EXPR)

     in C.

 -- C Macro: GCC_JIT_UNARY_OP_LOGICAL_NEGATE
     Logical negation of an arithmetic or pointer value; analogous to:

         !(EXPR)

     in C.

 -- C Macro: GCC_JIT_UNARY_OP_ABS
     Absolute value of an arithmetic expression; analogous to:

         abs (EXPR)

     in C.


File: libgccjit.info,  Node: Binary Operations,  Next: Comparisons,  Prev: Unary Operations,  Up: Rvalues

2.4.1.4 Binary Operations
.........................

 -- C Function: 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.

 -- C Type: enum gcc_jit_binary_op

  The available binary operations are:

Binary Operation                             C equivalent
-------------------------------------------------------------- 
*note GCC_JIT_BINARY_OP_PLUS: a6.            `x + y'
*note GCC_JIT_BINARY_OP_MINUS: a7.           `x - y'
*note GCC_JIT_BINARY_OP_MULT: a8.            `x * y'
*note GCC_JIT_BINARY_OP_DIVIDE: a9.          `x / y'
*note GCC_JIT_BINARY_OP_MODULO: aa.          `x % y'
*note GCC_JIT_BINARY_OP_BITWISE_AND: ab.     `x & y'
*note GCC_JIT_BINARY_OP_BITWISE_XOR: ac.     `x ^ y'
*note GCC_JIT_BINARY_OP_BITWISE_OR: ad.      `x | y'
*note GCC_JIT_BINARY_OP_LOGICAL_AND: ae.     `x && y'
*note GCC_JIT_BINARY_OP_LOGICAL_OR: af.      `x || y'
*note GCC_JIT_BINARY_OP_LSHIFT: b0.          `x << y'
*note GCC_JIT_BINARY_OP_RSHIFT: b1.          `x >> y'

 -- C Macro: GCC_JIT_BINARY_OP_PLUS
     Addition of arithmetic values; analogous to:

         (EXPR_A) + (EXPR_B)

     in C.

     For pointer addition, use *note
     gcc_jit_context_new_array_access(): b2.

 -- C Macro: GCC_JIT_BINARY_OP_MINUS
     Subtraction of arithmetic values; analogous to:

         (EXPR_A) - (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_MULT
     Multiplication of a pair of arithmetic values; analogous to:

         (EXPR_A) * (EXPR_B)

     in C.

 -- C Macro: 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.

 -- C Macro: GCC_JIT_BINARY_OP_MODULO
     Remainder of division of arithmetic values; analogous to:

         (EXPR_A) % (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_BITWISE_AND
     Bitwise AND; analogous to:

         (EXPR_A) & (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_BITWISE_XOR
     Bitwise exclusive OR; analogous to:

         (EXPR_A) ^ (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_BITWISE_OR
     Bitwise inclusive OR; analogous to:

         (EXPR_A) | (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_LOGICAL_AND
     Logical AND; analogous to:

         (EXPR_A) && (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_LOGICAL_OR
     Logical OR; analogous to:

         (EXPR_A) || (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_LSHIFT
     Left shift; analogous to:

         (EXPR_A) << (EXPR_B)

     in C.

 -- C Macro: GCC_JIT_BINARY_OP_RSHIFT
     Right shift; analogous to:

         (EXPR_A) >> (EXPR_B)

     in C.


File: libgccjit.info,  Node: Comparisons,  Next: Function calls,  Prev: Binary Operations,  Up: Rvalues

2.4.1.5 Comparisons
...................

 -- C Function: 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.

 -- C Type: enum gcc_jit_comparison

Comparison                                  C equivalent
------------------------------------------------------------- 
`GCC_JIT_COMPARISON_EQ'                     `x == y'
`GCC_JIT_COMPARISON_NE'                     `x != y'
`GCC_JIT_COMPARISON_LT'                     `x < y'
`GCC_JIT_COMPARISON_LE'                     `x <= y'
`GCC_JIT_COMPARISON_GT'                     `x > y'
`GCC_JIT_COMPARISON_GE'                     `x >= y'


File: libgccjit.info,  Node: Function calls,  Next: Function pointers,  Prev: Comparisons,  Up: Rvalues

2.4.1.6 Function calls
......................

 -- C Function: 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: *note gcc_jit_context_new_call(): b6. merely builds a
          *note gcc_jit_rvalue: 13. 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
          *note gcc_jit_block_add_eval(): b7.:

              /* Add "(void)printf (arg0, arg1);".  */
              gcc_jit_block_add_eval (
                block, NULL,
                gcc_jit_context_new_call (
                  ctxt,
                  NULL,
                  printf_func,
                  2, args));



 -- C Function: 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 *note
     gcc_jit_context_new_function_ptr_type(): 91.), 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 *note
          gcc_jit_context_new_call(): b6. applies.

 -- C Function: void gcc_jit_rvalue_set_bool_require_tail_call
          (gcc_jit_rvalue *call, int require_tail_call)
     Given an *note gcc_jit_rvalue *: 13. for a call created through
     *note gcc_jit_context_new_call(): b6. or *note
     gcc_jit_context_new_call_through_ptr(): b8, 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 *note LIBGCCJIT_ABI_6: ba.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_rvalue_set_bool_require_tail_call




File: libgccjit.info,  Node: Function pointers,  Next: Type-coercion,  Prev: Function calls,  Up: Rvalues

2.4.1.7 Function pointers
.........................

Function pointers can be obtained:

        * from a *note gcc_jit_function: 29. using *note
          gcc_jit_function_get_address(): bc, or

        * from an existing function using *note
          gcc_jit_context_new_rvalue_from_ptr(): 98, using a function
          pointer type obtained using *note
          gcc_jit_context_new_function_ptr_type(): 91.


File: libgccjit.info,  Node: Type-coercion,  Prev: Function pointers,  Up: Rvalues

2.4.1.8 Type-coercion
.....................

 -- C Function: 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


File: libgccjit.info,  Node: Lvalues,  Next: Working with pointers structs and unions,  Prev: Rvalues,  Up: Expressions

2.4.2 Lvalues
-------------

 -- C 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.

 -- C Function: gcc_jit_object * gcc_jit_lvalue_as_object
          (gcc_jit_lvalue *lvalue)
     Upcast an lvalue to be an object.

 -- C Function: gcc_jit_rvalue * gcc_jit_lvalue_as_rvalue
          (gcc_jit_lvalue *lvalue)
     Upcast an lvalue to be an rvalue.

 -- C Function: 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.

* Menu:

* Global variables::


File: libgccjit.info,  Node: Global variables,  Up: Lvalues

2.4.2.1 Global variables
........................

 -- C Function: 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 *note gcc_jit_result: 16.:

      -- C Type: enum gcc_jit_global_kind

      -- C Macro: GCC_JIT_GLOBAL_EXPORTED
          Global is defined by the client code and is visible by name
          outside of this JIT context via *note
          gcc_jit_result_get_global(): c7. (and this value is required
          for the global to be accessible via that entrypoint).

      -- C Macro: 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.

      -- C Macro: 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.


File: libgccjit.info,  Node: Working with pointers structs and unions,  Prev: Lvalues,  Up: Expressions

2.4.3 Working with pointers, structs and unions
-----------------------------------------------

 -- C Function: 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.

 -- C Function: 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.

 -- C Function: 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.

 -- C Function: 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'.

 -- C Function: 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').


File: libgccjit.info,  Node: Creating and using functions,  Next: Function pointers<2>,  Prev: Expressions,  Up: Topic Reference

2.5 Creating and using functions
================================

* Menu:

* Params::
* Functions::
* Blocks::
* Statements::


File: libgccjit.info,  Node: Params,  Next: Functions,  Up: Creating and using functions

2.5.1 Params
------------

 -- C Type: gcc_jit_param
     A `gcc_jit_param' represents a parameter to a function.

 -- C Function: gcc_jit_param * gcc_jit_context_new_param
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, const char *name)
     In preparation for creating a function, create a new parameter of
     the given type and name.

     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.

  Parameters are lvalues, and thus are also rvalues (and objects), so
the following upcasts are available:

 -- C Function: gcc_jit_lvalue * gcc_jit_param_as_lvalue
          (gcc_jit_param *param)
     Upcasting from param to lvalue.

 -- C Function: gcc_jit_rvalue * gcc_jit_param_as_rvalue
          (gcc_jit_param *param)
     Upcasting from param to rvalue.

 -- C Function: gcc_jit_object * gcc_jit_param_as_object
          (gcc_jit_param *param)
     Upcasting from param to object.


File: libgccjit.info,  Node: Functions,  Next: Blocks,  Prev: Params,  Up: Creating and using functions

2.5.2 Functions
---------------

 -- C Type: gcc_jit_function
     A `gcc_jit_function' represents a function - either one that we're
     creating ourselves, or one that we're referencing.

 -- C Function: gcc_jit_function * gcc_jit_context_new_function
          (gcc_jit_context *ctxt, gcc_jit_location *loc, enum
          gcc_jit_function_kind kind, gcc_jit_type *return_type, const
          char *name, int num_params, gcc_jit_param **params,
          int is_variadic)
     Create a gcc_jit_function with the given name and parameters.

      -- C Type: enum gcc_jit_function_kind

     This enum controls the kind of function created, and has the
     following values:

           -- C Macro: GCC_JIT_FUNCTION_EXPORTED
               Function is defined by the client code and visible by
               name outside of the JIT.

               This value is required if you want to extract machine
               code for this function from a *note gcc_jit_result: 16.
               via *note gcc_jit_result_get_code(): 17.

           -- C Macro: GCC_JIT_FUNCTION_INTERNAL
               Function is defined by the client code, but is invisible
               outside of the JIT.  Analogous to a "static" function.

           -- C Macro: GCC_JIT_FUNCTION_IMPORTED
               Function is not defined by the client code; we're merely
               referring to it.  Analogous to using an "extern"
               function from a header file.

           -- C Macro: GCC_JIT_FUNCTION_ALWAYS_INLINE
               Function is only ever inlined into other functions, and
               is invisible outside of the JIT.

               Analogous to prefixing with `inline' and adding
               `__attribute__((always_inline))'

               Inlining will only occur when the optimization level is
               above 0; when optimization is off, this is essentially
               the same as GCC_JIT_FUNCTION_INTERNAL.

     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.

 -- C Function: gcc_jit_function *gcc_jit_context_get_builtin_function
          (gcc_jit_context *ctxt, const char *name)

 -- C Function: gcc_jit_object * gcc_jit_function_as_object
          (gcc_jit_function *func)
     Upcasting from function to object.

 -- C Function: gcc_jit_param * gcc_jit_function_get_param
          (gcc_jit_function *func, int index)
     Get the param of the given index (0-based).

 -- C Function: void gcc_jit_function_dump_to_dot
          (gcc_jit_function *func, const char *path)
     Emit the function in graphviz format to the given path.

 -- C Function: gcc_jit_lvalue * gcc_jit_function_new_local
          (gcc_jit_function *func, gcc_jit_location *loc,
          gcc_jit_type *type, const char *name)
     Create a new local variable within the function, of the given type
     and name.

     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.


File: libgccjit.info,  Node: Blocks,  Next: Statements,  Prev: Functions,  Up: Creating and using functions

2.5.3 Blocks
------------

 -- C Type: gcc_jit_block
     A `gcc_jit_block' represents a basic block within a function  i.e.
     a sequence of statements with a single entry point and a single
     exit point.

     The first basic block that you create within a function will be
     the entrypoint.

     Each basic block that you create within a function must be
     terminated, either with a conditional, a jump, a return, or a
     switch.

     It's legal to have multiple basic blocks that return within one
     function.

 -- C Function: gcc_jit_block * gcc_jit_function_new_block
          (gcc_jit_function *func, const char *name)
     Create a basic block of the given name.  The name may be NULL, but
     providing meaningful names is often helpful when debugging: it may
     show up in dumps of the internal representation, and in error
     messages.  It is copied, so the input buffer does not need to
     outlive the call; you can pass in a pointer to an on-stack buffer,
     e.g.:

         for (pc = 0; pc < fn->fn_num_ops; pc++)
          {
            char buf[16];
            sprintf (buf, "instr%i", pc);
            state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf);
          }



 -- C Function: gcc_jit_object * gcc_jit_block_as_object
          (gcc_jit_block *block)
     Upcast from block to object.

 -- C Function: gcc_jit_function * gcc_jit_block_get_function
          (gcc_jit_block *block)
     Which function is this block within?


File: libgccjit.info,  Node: Statements,  Prev: Blocks,  Up: Creating and using functions

2.5.4 Statements
----------------

 -- C Function: void gcc_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;



 -- C Function: void gcc_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 given
     lvalue.

     This is roughly equivalent to this C code:

         lvalue = rvalue;



 -- C Function: void gcc_jit_block_add_assignment_op
          (gcc_jit_block *block, gcc_jit_location *loc,
          gcc_jit_lvalue *lvalue, enum gcc_jit_binary_op op,
          gcc_jit_rvalue *rvalue)
     Add evaluation of an rvalue, using the result to modify an lvalue.

     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));



 -- C Function: void gcc_jit_block_add_comment (gcc_jit_block *block,
          gcc_jit_location *loc, const char *text)
     Add a no-op textual comment to the internal representation of the
     code.  It will be optimized away, but will be visible in the dumps
     seen via *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: 66.  and
     *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: 1c, and thus may be
     of use when debugging how your project's internal representation
     gets converted to the libgccjit IR.

     The parameter `text' must be non-NULL.  It is copied, so the input
     buffer does not need to outlive the call.  For example:

         char buf[100];
         snprintf (buf, sizeof (buf),
                   "op%i: %s",
                   pc, opcode_names[op->op_opcode]);
         gcc_jit_block_add_comment (block, loc, buf);



 -- C Function: void gcc_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
     the result to the appropriate successor block.

     This is roughly equivalent to this C code:

         if (boolval)
           goto on_true;
         else
           goto on_false;

     block, boolval, on_true, and on_false must be non-NULL.

 -- C Function: void gcc_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:

         goto target;



 -- C Function: void gcc_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:

         return expression;



 -- C Function: void gcc_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
     function with "void" return type.

     This is equivalent to this C code:

         return;



 -- C Function: void gcc_jit_block_end_with_switch
          (gcc_jit_block *block, gcc_jit_location *loc,
          gcc_jit_rvalue *expr, gcc_jit_block *default_block,
          int num_cases, gcc_jit_case **cases)
     Terminate a block by adding evalation of an rvalue, then performing
     a multiway branch.

     This is roughly equivalent to this C code:

         switch (expr)
           {
           default:
             goto default_block;

           case C0.min_value ... C0.max_value:
             goto C0.dest_block;

           case C1.min_value ... C1.max_value:
             goto C1.dest_block;

           ...etc...

           case C[N - 1].min_value ... C[N - 1].max_value:
             goto C[N - 1].dest_block;
         }

     `block', `expr', `default_block' and `cases' must all be non-NULL.

     `expr' must be of the same integer type as all of the `min_value'
     and `max_value' within the cases.

     `num_cases' must be >= 0.

     The ranges of the cases must not overlap (or have duplicate
     values).

     The API entrypoints relating to switch statements and cases:

             * *note gcc_jit_block_end_with_switch(): e6.

             * *note gcc_jit_case_as_object(): e7.

             * *note gcc_jit_context_new_case(): e8.

     were added in *note LIBGCCJIT_ABI_3: e9.; you can test for their
     presence using

         #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS

     
      -- C Type: gcc_jit_case

     A `gcc_jit_case' represents a case within a switch statement, and
     is created within a particular *note gcc_jit_context: 8. using
     *note gcc_jit_context_new_case(): e8.

     Each case expresses a multivalued range of integer values.  You
     can express single-valued cases by passing in the same value for
     both `min_value' and `max_value'.

      -- C Function: 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' and `max_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 switch
          statement.

      -- C Function: 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:


              void
              create_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));
              }




File: libgccjit.info,  Node: Function pointers<2>,  Next: Source Locations,  Prev: Creating and using functions,  Up: Topic Reference

2.6 Function pointers
=====================

You can generate calls that use a function pointer via *note
gcc_jit_context_new_call_through_ptr(): b8.

  To do requires a *note gcc_jit_rvalue: 13. of the correct function
pointer type.

  Function pointers for a *note gcc_jit_function: 29. can be obtained
via *note gcc_jit_function_get_address(): bc.

 -- C Function: gcc_jit_rvalue * gcc_jit_function_get_address
          (gcc_jit_function *fn, gcc_jit_location *loc)
     Get the address of a function as an rvalue, of function pointer
     type.

     This entrypoint was added in *note LIBGCCJIT_ABI_9: ed.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_function_get_address



  Alternatively, given an existing function, you can obtain a pointer
to it in *note gcc_jit_rvalue: 13. form using *note
gcc_jit_context_new_rvalue_from_ptr(): 98, using a function pointer
type obtained using *note gcc_jit_context_new_function_ptr_type(): 91.

  Here's an example of creating a function pointer type corresponding
to C's `void (*) (int, int, int)':

    gcc_jit_type *void_type =
      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
    gcc_jit_type *int_type =
      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);

    /* Build the function ptr type.  */
    gcc_jit_type *param_types[3];
    param_types[0] = int_type;
    param_types[1] = int_type;
    param_types[2] = int_type;

    gcc_jit_type *fn_ptr_type =
      gcc_jit_context_new_function_ptr_type (ctxt, NULL,
                                             void_type,
                                             3, param_types, 0);


 -- C Function: gcc_jit_type * gcc_jit_context_new_function_ptr_type
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *return_type, int num_params,
          gcc_jit_type **param_types, int is_variadic)
     Generate a *note gcc_jit_type: a. for a function pointer with the
     given return type and parameters.


File: libgccjit.info,  Node: Source Locations,  Next: Compiling a context,  Prev: Function pointers<2>,  Up: Topic Reference

2.7 Source Locations
====================

 -- C Type: gcc_jit_location
     A `gcc_jit_location' encapsulates a source code location, so that
     you can (optionally) associate locations in your language with
     statements in the JIT-compiled code, allowing the debugger to
     single-step through your language.

     `gcc_jit_location' instances are optional: you can always pass
     NULL to any API entrypoint accepting one.

     You can construct them using *note gcc_jit_context_new_location():
     41.

     You need to enable *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the
     *note gcc_jit_context: 8. for these locations to actually be
     usable by the debugger:

         gcc_jit_context_set_bool_option (
           ctxt,
           GCC_JIT_BOOL_OPTION_DEBUGINFO,
           1);



 -- C Function: gcc_jit_location * gcc_jit_context_new_location
          (gcc_jit_context *ctxt, const char *filename, int line,
          int column)
     Create a `gcc_jit_location' instance representing the given source
     location.

     The parameter `filename' 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.

* Menu:

* Faking it::


File: libgccjit.info,  Node: Faking it,  Up: Source Locations

2.7.1 Faking it
---------------

If you don't have source code for your internal representation, but need
to debug, you can generate a C-like representation of the functions in
your context using *note gcc_jit_context_dump_to_file(): 5a.:

    gcc_jit_context_dump_to_file (ctxt, "/tmp/something.c",
                                  1 /* update_locations */);

This will dump C-like code to the given path.  If the `update_locations'
argument is true, this will also set up `gcc_jit_location' information
throughout the context, pointing at the dump file as if it were a source
file, giving you _something_ you can step through in the debugger.


File: libgccjit.info,  Node: Compiling a context,  Next: ABI and API compatibility,  Prev: Source Locations,  Up: Topic Reference

2.8 Compiling a context
=======================

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

  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.

* Menu:

* In-memory compilation::
* Ahead-of-time compilation::


File: libgccjit.info,  Node: In-memory compilation,  Next: Ahead-of-time compilation,  Up: Compiling a context

2.8.1 In-memory compilation
---------------------------

 -- C Function: 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 *note gcc_jit_result_release(): 39. on it once they're done
     with it.

 -- C Type: 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.

 -- C Function: 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 *note
     gcc_jit_context_new_function(): 11. with `kind' *note
     GCC_JIT_FUNCTION_EXPORTED: d7.:

         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 *note
     gcc_jit_result_release(): 39. is called on the *note
     gcc_jit_result *: 16.; attempting to call it after that may lead
     to a segmentation fault.

 -- C Function: 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 *note
     gcc_jit_context_new_global(): c4. with `kind' *note
     GCC_JIT_GLOBAL_EXPORTED: c6.

     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 *note
     gcc_jit_result_release(): 39. is called on the *note
     gcc_jit_result *: 16.; attempting to use it after that may lead to
     a segmentation fault.

 -- C Function: 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 *note gcc_jit_result_get_code(): 17. or *note
     gcc_jit_result_get_global(): c7. on it.


File: libgccjit.info,  Node: Ahead-of-time compilation,  Prev: In-memory compilation,  Up: Compiling a context

2.8.2 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 *note gcc_jit_context_compile_to_file(): 4a.  API
entrypoint.

 -- C Function: void gcc_jit_context_compile_to_file
          (gcc_jit_context *ctxt, enum gcc_jit_output_kind output_kind,
          const char *output_path)
     Compile the *note gcc_jit_context *: 8. to a file of the given
     kind.

  *note gcc_jit_context_compile_to_file(): 4a. 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.

 -- C Type: enum gcc_jit_output_kind

  The available kinds of output are:

Output kind                                        Typical suffix
---------------------------------------------------------------------- 
*note GCC_JIT_OUTPUT_KIND_ASSEMBLER: f6.           .s
*note GCC_JIT_OUTPUT_KIND_OBJECT_FILE: f7.         .o
*note GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY: f8.     .so or .dll
*note GCC_JIT_OUTPUT_KIND_EXECUTABLE: f9.          None, or .exe

 -- C Macro: GCC_JIT_OUTPUT_KIND_ASSEMBLER
     Compile the context to an assembler file.

 -- C Macro: GCC_JIT_OUTPUT_KIND_OBJECT_FILE
     Compile the context to an object file.

 -- C Macro: 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.

 -- C Macro: GCC_JIT_OUTPUT_KIND_EXECUTABLE
     Compile the context to an executable.

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


File: libgccjit.info,  Node: ABI and API compatibility,  Next: Performance,  Prev: Compiling a context,  Up: Topic Reference

2.9 ABI and API compatibility
=============================

The libgccjit developers strive for ABI and API backward-compatibility:
programs built against libgccjit.so stand a good chance of running
without recompilation against newer versions of libgccjit.so, and ought
to recompile without modification against newer versions of libgccjit.h.

     Note: The libgccjit++.h C++ API is more experimental, and less
     locked-down at this time.

  API compatibility is achieved by extending the API rather than
changing it.  For ABI compatiblity, we avoid bumping the SONAME, and
instead use symbol versioning to tag each symbol, so that a binary
linked against libgccjit.so is tagged according to the symbols that it
uses.

  For example, *note gcc_jit_context_add_command_line_option(): 72. was
added in `LIBGCCJIT_ABI_1'.  If a client program uses it, this can be
detected from metadata by using `objdump':

    $ objdump -p testsuite/jit/test-extra-options.c.exe | tail -n 8

    Version References:
      required from libgccjit.so.0:
        0x00824161 0x00 04 LIBGCCJIT_ABI_1
        0x00824160 0x00 03 LIBGCCJIT_ABI_0
      required from libc.so.6:

You can see the symbol tags provided by libgccjit.so using `objdump':

    $ objdump -p libgccjit.so | less
    [...snip...]
    Version definitions:
    1 0x01 0x0ff81f20 libgccjit.so.0
    2 0x00 0x00824160 LIBGCCJIT_ABI_0
    3 0x00 0x00824161 LIBGCCJIT_ABI_1
            LIBGCCJIT_ABI_0
    [...snip...]


* Menu:

* ABI symbol tags::

ABI symbol tags

* LIBGCCJIT_ABI_0::
* LIBGCCJIT_ABI_1::
* LIBGCCJIT_ABI_2::
* LIBGCCJIT_ABI_3::
* LIBGCCJIT_ABI_4::
* LIBGCCJIT_ABI_5::
* LIBGCCJIT_ABI_6::
* LIBGCCJIT_ABI_7::
* LIBGCCJIT_ABI_8::
* LIBGCCJIT_ABI_9::
* LIBGCCJIT_ABI_10::


File: libgccjit.info,  Node: ABI symbol tags,  Up: ABI and API compatibility

2.9.1 ABI symbol tags
---------------------

The initial release of libgccjit (in gcc 5.1) did not use symbol
versioning.

  Newer releases use the following tags.

* Menu:

* LIBGCCJIT_ABI_0::
* LIBGCCJIT_ABI_1::
* LIBGCCJIT_ABI_2::
* LIBGCCJIT_ABI_3::
* LIBGCCJIT_ABI_4::
* LIBGCCJIT_ABI_5::
* LIBGCCJIT_ABI_6::
* LIBGCCJIT_ABI_7::
* LIBGCCJIT_ABI_8::
* LIBGCCJIT_ABI_9::
* LIBGCCJIT_ABI_10::


File: libgccjit.info,  Node: LIBGCCJIT_ABI_0,  Next: LIBGCCJIT_ABI_1,  Up: ABI symbol tags

2.9.1.1 `LIBGCCJIT_ABI_0'
.........................

All entrypoints in the initial release of libgccjit are tagged with
`LIBGCCJIT_ABI_0', to signify the transition to symbol versioning.

  Binaries built against older copies of `libgccjit.so' should continue
to work, with this being handled transparently by the linker (see this
post(1))

  ---------- Footnotes ----------

  (1) https://gcc.gnu.org/ml/gcc-patches/2015-06/msg02126.html


File: libgccjit.info,  Node: LIBGCCJIT_ABI_1,  Next: LIBGCCJIT_ABI_2,  Prev: LIBGCCJIT_ABI_0,  Up: ABI symbol tags

2.9.1.2 `LIBGCCJIT_ABI_1'
.........................

`LIBGCCJIT_ABI_1' covers the addition of *note
gcc_jit_context_add_command_line_option(): 72.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_2,  Next: LIBGCCJIT_ABI_3,  Prev: LIBGCCJIT_ABI_1,  Up: ABI symbol tags

2.9.1.3 `LIBGCCJIT_ABI_2'
.........................

`LIBGCCJIT_ABI_2' covers the addition of *note
gcc_jit_context_set_bool_allow_unreachable_blocks(): 6b.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_3,  Next: LIBGCCJIT_ABI_4,  Prev: LIBGCCJIT_ABI_2,  Up: ABI symbol tags

2.9.1.4 `LIBGCCJIT_ABI_3'
.........................

`LIBGCCJIT_ABI_3' covers the addition of switch statements via API
entrypoints:

        * *note gcc_jit_block_end_with_switch(): e6.

        * *note gcc_jit_case_as_object(): e7.

        * *note gcc_jit_context_new_case(): e8.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_4,  Next: LIBGCCJIT_ABI_5,  Prev: LIBGCCJIT_ABI_3,  Up: ABI symbol tags

2.9.1.5 `LIBGCCJIT_ABI_4'
.........................

`LIBGCCJIT_ABI_4' covers the addition of timers via API entrypoints:

        * *note gcc_jit_context_get_timer(): 104.

        * *note gcc_jit_context_set_timer(): 105.

        * *note gcc_jit_timer_new(): 106.

        * *note gcc_jit_timer_release(): 107.

        * *note gcc_jit_timer_push(): 108.

        * *note gcc_jit_timer_pop(): 109.

        * *note gcc_jit_timer_print(): 10a.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_5,  Next: LIBGCCJIT_ABI_6,  Prev: LIBGCCJIT_ABI_4,  Up: ABI symbol tags

2.9.1.6 `LIBGCCJIT_ABI_5'
.........................

`LIBGCCJIT_ABI_5' covers the addition of *note
gcc_jit_context_set_bool_use_external_driver(): 6d.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_6,  Next: LIBGCCJIT_ABI_7,  Prev: LIBGCCJIT_ABI_5,  Up: ABI symbol tags

2.9.1.7 `LIBGCCJIT_ABI_6'
.........................

`LIBGCCJIT_ABI_6' covers the addition of *note
gcc_jit_rvalue_set_bool_require_tail_call(): b9.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_7,  Next: LIBGCCJIT_ABI_8,  Prev: LIBGCCJIT_ABI_6,  Up: ABI symbol tags

2.9.1.8 `LIBGCCJIT_ABI_7'
.........................

`LIBGCCJIT_ABI_7' covers the addition of *note
gcc_jit_type_get_aligned(): 80.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_8,  Next: LIBGCCJIT_ABI_9,  Prev: LIBGCCJIT_ABI_7,  Up: ABI symbol tags

2.9.1.9 `LIBGCCJIT_ABI_8'
.........................

`LIBGCCJIT_ABI_8' covers the addition of *note
gcc_jit_type_get_vector(): 83.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_9,  Next: LIBGCCJIT_ABI_10,  Prev: LIBGCCJIT_ABI_8,  Up: ABI symbol tags

2.9.1.10 `LIBGCCJIT_ABI_9'
..........................

`LIBGCCJIT_ABI_9' covers the addition of *note
gcc_jit_function_get_address(): bc.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_10,  Prev: LIBGCCJIT_ABI_9,  Up: ABI symbol tags

2.9.1.11 `LIBGCCJIT_ABI_10'
...........................

`LIBGCCJIT_ABI_10' covers the addition of *note
gcc_jit_context_new_rvalue_from_vector(): 85.


File: libgccjit.info,  Node: Performance,  Prev: ABI and API compatibility,  Up: Topic Reference

2.10 Performance
================

* Menu:

* The timing API::


File: libgccjit.info,  Node: The timing API,  Up: Performance

2.10.1 The timing API
---------------------

As of GCC 6, libgccjit exposes a timing API, for printing reports on
how long was spent in different parts of code.

  You can create a *note gcc_jit_timer: 114. instance, which will
measure time spent since its creation.  The timer maintains a stack of
"timer items": as control flow moves through your code, you can push
and pop named items relating to your code onto the stack, and the timer
will account the time spent accordingly.

  You can also asssociate a timer with a *note gcc_jit_context: 8, in
which case the time spent inside compilation will be subdivided.

  For example, the following code uses a timer, recording client items
"create_code", "compile", and "running code":

    /* Create a timer.  */
    gcc_jit_timer *timer = gcc_jit_timer_new ();
    if (!timer)
      {
         error ("gcc_jit_timer_new failed");
         return -1;
      }

    /* Let's repeatedly compile and run some code, accumulating it
       all into the timer.  */
    for (int i = 0; i < num_iterations; i++)
      {
        /* Create a context and associate it with the timer.  */
        gcc_jit_context *ctxt = gcc_jit_context_acquire ();
        if (!ctxt)
          {
            error ("gcc_jit_context_acquire failed");
            return -1;
          }
        gcc_jit_context_set_timer (ctxt, timer);

        /* Populate the context, timing it as client item "create_code".  */
        gcc_jit_timer_push (timer, "create_code");
        create_code (ctxt);
        gcc_jit_timer_pop (timer, "create_code");

        /* Compile the context, timing it as client item "compile".  */
        gcc_jit_timer_push (timer, "compile");
        result = gcc_jit_context_compile (ctxt);
        gcc_jit_timer_pop (timer, "compile");

        /* Run the generated code, timing it as client item "running code".  */
        gcc_jit_timer_push (timer, "running code");
        run_the_code (ctxt, result);
        gcc_jit_timer_pop (timer, "running code");

        /* Clean up.  */
        gcc_jit_context_release (ctxt);
        gcc_jit_result_release (result);
    }

    /* Print the accumulated timings.  */
    gcc_jit_timer_print (timer, stderr);
    gcc_jit_timer_release (timer);

giving output like this, showing the internal GCC items at the top, then
client items, then the total:

    Execution times (seconds)
    GCC items:
     phase setup             :   0.29 (14%) usr   0.00 ( 0%) sys   0.32 ( 5%) wall   10661 kB (50%) ggc
     phase parsing           :   0.02 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall     653 kB ( 3%) ggc
     phase finalize          :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     dump files              :   0.02 ( 1%) usr   0.00 ( 0%) sys   0.01 ( 0%) wall       0 kB ( 0%) ggc
     callgraph construction  :   0.02 ( 1%) usr   0.01 ( 6%) sys   0.01 ( 0%) wall     242 kB ( 1%) ggc
     callgraph optimization  :   0.03 ( 2%) usr   0.00 ( 0%) sys   0.02 ( 0%) wall     142 kB ( 1%) ggc
     trivially dead code     :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     df scan insns           :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       9 kB ( 0%) ggc
     df live regs            :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.01 ( 0%) wall       0 kB ( 0%) ggc
     inline parameters       :   0.02 ( 1%) usr   0.00 ( 0%) sys   0.01 ( 0%) wall      82 kB ( 0%) ggc
     tree CFG cleanup        :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     tree PHI insertion      :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.02 ( 0%) wall      64 kB ( 0%) ggc
     tree SSA other          :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.01 ( 0%) wall      18 kB ( 0%) ggc
     expand                  :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall     398 kB ( 2%) ggc
     jump                    :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     loop init               :   0.01 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall      67 kB ( 0%) ggc
     integrated RA           :   0.02 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall    2468 kB (12%) ggc
     thread pro- & epilogue  :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall     162 kB ( 1%) ggc
     final                   :   0.01 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall     216 kB ( 1%) ggc
     rest of compilation     :   1.37 (69%) usr   0.00 ( 0%) sys   1.13 (18%) wall    1391 kB ( 6%) ggc
     assemble JIT code       :   0.01 ( 1%) usr   0.00 ( 0%) sys   4.04 (66%) wall       0 kB ( 0%) ggc
     load JIT result         :   0.02 ( 1%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     JIT client code         :   0.00 ( 0%) usr   0.01 ( 6%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
    Client items:
     create_code             :   0.00 ( 0%) usr   0.01 ( 6%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     compile                 :   0.36 (18%) usr   0.15 (83%) sys   0.86 (14%) wall   14939 kB (70%) ggc
     running code            :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall       0 kB ( 0%) ggc
     TOTAL                   :   2.00             0.18             6.12              21444 kB

The exact format is intended to be human-readable, and is subject to
change.

 -- C Macro: LIBGCCJIT_HAVE_TIMING_API
     The timer API was added to libgccjit in GCC 6.  This macro is only
     defined in versions of libgccjit.h which have the timer API, and
     so can be used to guard code that may need to compile against
     earlier releases:

         #ifdef LIBGCCJIT_HAVE_TIMING_API
         gcc_jit_timer *t = gcc_jit_timer_new ();
         gcc_jit_context_set_timer (ctxt, t);
         #endif



 -- C Type: gcc_jit_timer

 -- C Function: gcc_jit_timer * gcc_jit_timer_new (void)
     Create a *note gcc_jit_timer: 114. instance, and start timing:

         gcc_jit_timer *t = gcc_jit_timer_new ();

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: void gcc_jit_timer_release (gcc_jit_timer *timer)
     Release a *note gcc_jit_timer: 114. instance:

         gcc_jit_timer_release (t);

     This should be called exactly once on a timer.

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: void gcc_jit_context_set_timer (gcc_jit_context *ctxt,
          gcc_jit_timer *timer)
     Associate a *note gcc_jit_timer: 114. instance with a context:

         gcc_jit_context_set_timer (ctxt, t);

     A timer instance can be shared between multiple *note
     gcc_jit_context: 8. instances.

     Timers have no locking, so if you have a multithreaded program, you
     must provide your own locks if more than one thread could be
     working with the same timer via timer-associated contexts.

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: gcc_jit_timer *gcc_jit_context_get_timer
          (gcc_jit_context *ctxt)
     Get the timer associated with a context (if any).

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: void gcc_jit_timer_push (gcc_jit_timer *timer, const
          char *item_name)
     Push the given item onto the timer's stack:

         gcc_jit_timer_push (t, "running code");
         run_the_code (ctxt, result);
         gcc_jit_timer_pop (t, "running code");

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: void gcc_jit_timer_pop (gcc_jit_timer *timer, const
          char *item_name)
     Pop the top item from the timer's stack.

     If "item_name" is provided, it must match that of the top item.
     Alternatively, `NULL' can be passed in, to suppress checking.

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API



 -- C Function: void gcc_jit_timer_print (gcc_jit_timer *timer,
          FILE *f_out)
     Print timing information to the given stream about activity since
     the timer was started.

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 103.; you
     can test for its presence using

         #ifdef LIBGCCJIT_HAVE_TIMING_API




File: libgccjit.info,  Node: C++ bindings for libgccjit,  Next: Internals,  Prev: Topic Reference,  Up: Top

3 C++ bindings for libgccjit
****************************

This document describes the C++ bindings to libgccjit(1), an API for
embedding GCC inside programs and libraries.

  The C++ bindings consist of a single header file `libgccjit++.h'.

  This is a collection of "thin" wrapper classes around the C API.
Everything is an inline function, implemented in terms of the C API, so
there is nothing extra to link against.

  Note that libgccjit is currently of "Alpha" quality; the APIs are not
yet set in stone, and they shouldn't be used in production yet.

  Contents:

* Menu:

* Tutorial: Tutorial<2>.
* Topic Reference: Topic Reference<2>.

Tutorial

* Tutorial part 1; "Hello world": Tutorial part 1 "Hello world"<2>.
* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>.
* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>.
* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>.

Tutorial part 2: Creating a trivial machine code function

* Options: Options<3>.
* Full example: Full example<3>.

Tutorial part 3: Loops and variables

* Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>.
* Control flow: Control flow<2>.
* Visualizing the control flow graph: Visualizing the control flow graph<2>.
* Full example: Full example<4>.

Tutorial part 4: Adding JIT-compilation to a toy interpreter

* Our toy interpreter: Our toy interpreter<2>.
* Compiling to machine code: Compiling to machine code<2>.
* Setting things up: Setting things up<2>.
* Populating the function: Populating the function<2>.
* Verifying the control flow graph: Verifying the control flow graph<2>.
* Compiling the context: Compiling the context<2>.
* Single-stepping through the generated code: Single-stepping through the generated code<2>.
* Examining the generated code: Examining the generated code<2>.
* Putting it all together: Putting it all together<2>.
* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>.

Behind the curtain: How does our code get optimized?

* Optimizing away stack manipulation: Optimizing away stack manipulation<2>.
* Elimination of tail recursion: Elimination of tail recursion<2>.

Topic Reference

* Compilation contexts: Compilation contexts<2>.
* Objects: Objects<2>.
* Types: Types<2>.
* Expressions: Expressions<2>.
* Creating and using functions: Creating and using functions<2>.
* Source Locations: Source Locations<2>.
* Compiling a context: Compiling a context<2>.

Compilation contexts

* Lifetime-management: Lifetime-management<2>.
* Thread-safety: Thread-safety<2>.
* Error-handling: Error-handling<3>.
* Debugging: Debugging<2>.
* Options: Options<4>.

Options

* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
* Additional command-line options: Additional command-line options<2>.

Types

* Standard types: Standard types<2>.
* Pointers, const, and volatile: Pointers const and volatile<2>.
* Vector types: Vector types<2>.
* Structures and unions: Structures and unions<2>.

Expressions

* Rvalues: Rvalues<2>.
* Lvalues: Lvalues<2>.
* Working with pointers, structs and unions: Working with pointers structs and unions<2>.

Rvalues

* Simple expressions: Simple expressions<2>.
* Vector expressions: Vector expressions<2>.
* Unary Operations: Unary Operations<2>.
* Binary Operations: Binary Operations<2>.
* Comparisons: Comparisons<2>.
* Function calls: Function calls<2>.
* Function pointers: Function pointers<3>.
* Type-coercion: Type-coercion<2>.

Lvalues

* Global variables: Global variables<2>.

Creating and using functions

* Params: Params<2>.
* Functions: Functions<2>.
* Blocks: Blocks<2>.
* Statements: Statements<2>.

Source Locations

* Faking it: Faking it<2>.

Compiling a context

* In-memory compilation: In-memory compilation<2>.
* Ahead-of-time compilation: Ahead-of-time compilation<2>.

  ---------- Footnotes ----------

  (1) http://gcc.gnu.org/wiki/JIT


File: libgccjit.info,  Node: Tutorial<2>,  Next: Topic Reference<2>,  Up: C++ bindings for libgccjit

3.1 Tutorial
============

* Menu:

* Tutorial part 1; "Hello world": Tutorial part 1 "Hello world"<2>.
* Tutorial part 2; Creating a trivial machine code function: Tutorial part 2 Creating a trivial machine code function<2>.
* Tutorial part 3; Loops and variables: Tutorial part 3 Loops and variables<2>.
* Tutorial part 4; Adding JIT-compilation to a toy interpreter: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>.


File: libgccjit.info,  Node: Tutorial part 1 "Hello world"<2>,  Next: Tutorial part 2 Creating a trivial machine code function<2>,  Up: Tutorial<2>

3.1.1 Tutorial part 1: "Hello world"
------------------------------------

Before we look at the details of the API, let's look at building and
running programs that use the library.

  Here's a toy "hello world" program that uses the library's C++ API to
synthesize a call to `printf' and uses it to write a message to stdout.

  Don't worry about the content of the program for now; we'll cover the
details in later parts of this tutorial.

         /* Smoketest example for libgccjit.so C++ API
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit++.h>

         #include <stdlib.h>
         #include <stdio.h>

         static void
         create_code (gccjit::context ctxt)
         {
           /* Let's try to inject the equivalent of this C code:
              void
              greet (const char *name)
              {
                 printf ("hello %s\n", name);
              }
           */
           gccjit::type void_type = ctxt.get_type (GCC_JIT_TYPE_VOID);
           gccjit::type const_char_ptr_type =
             ctxt.get_type (GCC_JIT_TYPE_CONST_CHAR_PTR);
           gccjit::param param_name =
             ctxt.new_param (const_char_ptr_type, "name");
           std::vector<gccjit::param> func_params;
           func_params.push_back (param_name);
           gccjit::function func =
             ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                                void_type,
                                "greet",
                                func_params, 0);

           gccjit::param param_format =
             ctxt.new_param (const_char_ptr_type, "format");
           std::vector<gccjit::param> printf_params;
           printf_params.push_back (param_format);
           gccjit::function printf_func =
             ctxt.new_function (GCC_JIT_FUNCTION_IMPORTED,
                                ctxt.get_type (GCC_JIT_TYPE_INT),
                                "printf",
                                printf_params, 1);

           gccjit::block block = func.new_block ();
           block.add_eval (ctxt.new_call (printf_func,
                                          ctxt.new_rvalue ("hello %s\n"),
                                          param_name));
           block.end_with_return ();
         }

         int
         main (int argc, char **argv)
         {
           gccjit::context ctxt;
           gcc_jit_result *result;

           /* Get a "context" object for working with the library.  */
           ctxt = gccjit::context::acquire ();

           /* Set some options on the context.
              Turn this on to see the code being generated, in assembler form.  */
           ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           result = ctxt.compile ();
           if (!result)
             {
               fprintf (stderr, "NULL result");
               exit (1);
             }

           ctxt.release ();

           /* Extract the generated code from "result".  */
           typedef void (*fn_type) (const char *);
           fn_type greet =
             (fn_type)gcc_jit_result_get_code (result, "greet");
           if (!greet)
             {
               fprintf (stderr, "NULL greet");
               exit (1);
             }

           /* Now call the generated function: */
           greet ("world");
           fflush (stdout);

           gcc_jit_result_release (result);
           return 0;
         }



  Copy the above to `tut01-hello-world.cc'.

  Assuming you have the jit library installed, build the test program
using:

    $ gcc \
        tut01-hello-world.cc \
        -o tut01-hello-world \
        -lgccjit

You should then be able to run the built program:

    $ ./tut01-hello-world
    hello world



File: libgccjit.info,  Node: Tutorial part 2 Creating a trivial machine code function<2>,  Next: Tutorial part 3 Loops and variables<2>,  Prev: Tutorial part 1 "Hello world"<2>,  Up: Tutorial<2>

3.1.2 Tutorial part 2: Creating a trivial machine code function
---------------------------------------------------------------

Consider this C function:

    int square (int i)
    {
      return i * i;
    }

How can we construct this at run-time using libgccjit's C++ API?

  First we need to include the relevant header:

    #include <libgccjit++.h>

All state associated with compilation is associated with a
`gccjit::context', which is a thin C++ wrapper around the C API's *note
gcc_jit_context *: 8.

  Create one using *note gccjit;;context;;acquire(): 11e.:

    gccjit::context ctxt;
    ctxt = gccjit::context::acquire ();

The JIT library has a system of types.  It is statically-typed: every
expression is of a specific type, fixed at compile-time.  In our
example, all of the expressions are of the C `int' type, so let's
obtain this from the context, as a `gccjit::type', using *note
gccjit;;context;;get_type(): 11f.:

    gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);

`gccjit::type' is an example of a "contextual" object: every entity in
the API is associated with a `gccjit::context'.

  Memory management is easy: all such "contextual" objects are
automatically cleaned up for you when the context is released, using
*note gccjit;;context;;release(): 120.:

    ctxt.release ();

so you don't need to manually track and cleanup all objects, just the
contexts.

  All of the C++ classes in the API are thin wrappers around pointers to
types in the C API.

  The C++ class hierarchy within the `gccjit' namespace looks like this:

    +- object
        +- location
        +- type
           +- struct
        +- field
        +- function
        +- block
        +- rvalue
            +- lvalue
               +- param

One thing you can do with a `gccjit::object' is to ask it for a
human-readable description as a `std::string', using *note
gccjit;;object;;get_debug_string(): 121.:

    printf ("obj: %s\n", obj.get_debug_string ().c_str ());

giving this text on stdout:

    obj: int

This is invaluable when debugging.

  Let's create the function.  To do so, we first need to construct its
single parameter, specifying its type and giving it a name, using *note
gccjit;;context;;new_param(): 122.:

    gccjit::param param_i = ctxt.new_param (int_type, "i");

and we can then make a vector of all of the params of the function, in
this case just one:

    std::vector<gccjit::param> params;
    params.push_back (param_i);

Now we can create the function, using `gccjit::context::new_function()':

    gccjit::function func =
      ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                         int_type,
                         "square",
                         params,
                         0);

To define the code within the function, we must create basic blocks
containing statements.

  Every basic block contains a list of statements, eventually terminated
by a statement that either returns, or jumps to another basic block.

  Our function has no control-flow, so we just need one basic block:

    gccjit::block block = func.new_block ();

Our basic block is relatively simple: it immediately terminates by
returning the value of an expression.

  We can build the expression using *note
gccjit;;context;;new_binary_op(): 123.:

    gccjit::rvalue expr =
      ctxt.new_binary_op (
        GCC_JIT_BINARY_OP_MULT, int_type,
        param_i, param_i);

A `gccjit::rvalue' is another example of a `gccjit::object' subclass.
As before, we can print it with *note
gccjit;;object;;get_debug_string(): 121.

    printf ("expr: %s\n", expr.get_debug_string ().c_str ());

giving this output:

    expr: i * i

Note that `gccjit::rvalue' provides numerous overloaded operators which
can be used to dramatically reduce the amount of typing needed.  We can
build the above binary operation more directly with this one-liner:

    gccjit::rvalue expr = param_i * param_i;

Creating the expression in itself doesn't do anything; we have to add
this expression to a statement within the block.  In this case, we use
it to build a return statement, which terminates the basic block:

    block.end_with_return (expr);

OK, we've populated the context.  We can now compile it using *note
gccjit;;context;;compile(): 124.:

    gcc_jit_result *result;
    result = ctxt.compile ();

and get a *note gcc_jit_result *: 16.

  We can now use *note gcc_jit_result_get_code(): 17. to look up a
specific machine code routine within the result, in this case, the
function we created above.

    void *fn_ptr = gcc_jit_result_get_code (result, "square");
    if (!fn_ptr)
      {
        fprintf (stderr, "NULL fn_ptr");
        goto error;
      }

We can now cast the pointer to an appropriate function pointer type, and
then call it:

    typedef int (*fn_type) (int);
    fn_type square = (fn_type)fn_ptr;
    printf ("result: %d", square (5));


    result: 25


* Menu:

* Options: Options<3>.
* Full example: Full example<3>.


File: libgccjit.info,  Node: Options<3>,  Next: Full example<3>,  Up: Tutorial part 2 Creating a trivial machine code function<2>

3.1.2.1 Options
...............

To get more information on what's going on, you can set debugging flags
on the context using *note gccjit;;context;;set_bool_option(): 126.

  Setting *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: 1c. will dump a
C-like representation to stderr when you compile (GCC's "GIMPLE"
representation):

    ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);
    result = ctxt.compile ();


    square (signed int i)
    {
      signed int D.260;

      entry:
      D.260 = i * i;
      return D.260;
    }

We can see the generated machine code in assembler form (on stderr) by
setting *note GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE: 1d. on the
context before compiling:

    ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1);
    result = ctxt.compile ();


          .file   "fake.c"
          .text
          .globl  square
          .type   square, @function
    square:
    .LFB6:
          .cfi_startproc
          pushq   %rbp
          .cfi_def_cfa_offset 16
          .cfi_offset 6, -16
          movq    %rsp, %rbp
          .cfi_def_cfa_register 6
          movl    %edi, -4(%rbp)
    .L14:
          movl    -4(%rbp), %eax
          imull   -4(%rbp), %eax
          popq    %rbp
          .cfi_def_cfa 7, 8
          ret
          .cfi_endproc
    .LFE6:
          .size   square, .-square
          .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)"
          .section       .note.GNU-stack,"",@progbits

By default, no optimizations are performed, the equivalent of GCC's
`-O0' option.  We can turn things up to e.g. `-O3' by calling *note
gccjit;;context;;set_int_option(): 127. with *note
GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 1f.:

    ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);


          .file   "fake.c"
          .text
          .p2align 4,,15
          .globl  square
          .type   square, @function
    square:
    .LFB7:
          .cfi_startproc
    .L16:
          movl    %edi, %eax
          imull   %edi, %eax
          ret
          .cfi_endproc
    .LFE7:
          .size   square, .-square
          .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-0.5.1920c315ff984892399893b380305ab36e07b455.fc20)"
          .section        .note.GNU-stack,"",@progbits

Naturally this has only a small effect on such a trivial function.


File: libgccjit.info,  Node: Full example<3>,  Prev: Options<3>,  Up: Tutorial part 2 Creating a trivial machine code function<2>

3.1.2.2 Full example
....................

Here's what the above looks like as a complete program:

         /* Usage example for libgccjit.so's C++ API
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit++.h>

         #include <stdlib.h>
         #include <stdio.h>

         void
         create_code (gccjit::context ctxt)
         {
           /* Let's try to inject the equivalent of this C code:

               int square (int i)
               {
                 return i * i;
               }
           */
           gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
           gccjit::param param_i = ctxt.new_param (int_type, "i");
           std::vector<gccjit::param> params;
           params.push_back (param_i);
           gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                                                      int_type,
                                                      "square",
                                                      params, 0);

           gccjit::block block = func.new_block ();

           gccjit::rvalue expr =
             ctxt.new_binary_op (GCC_JIT_BINARY_OP_MULT, int_type,
                                 param_i, param_i);

           block.end_with_return (expr);
         }

         int
         main (int argc, char **argv)
         {
           /* Get a "context" object for working with the library.  */
           gccjit::context ctxt = gccjit::context::acquire ();

           /* Set some options on the context.
              Turn this on to see the code being generated, in assembler form.  */
           ctxt.set_bool_option (
             GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
             0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           gcc_jit_result *result = ctxt.compile ();

           /* We're done with the context; we can release it: */
           ctxt.release ();

           if (!result)
             {
               fprintf (stderr, "NULL result");
               return 1;
             }

           /* Extract the generated code from "result".  */
           void *fn_ptr = gcc_jit_result_get_code (result, "square");
           if (!fn_ptr)
              {
                fprintf (stderr, "NULL fn_ptr");
                gcc_jit_result_release (result);
                return 1;
              }

           typedef int (*fn_type) (int);
           fn_type square = (fn_type)fn_ptr;
           printf ("result: %d\n", square (5));

           gcc_jit_result_release (result);
           return 0;
         }



  Building and running it:

    $ gcc \
        tut02-square.cc \
        -o tut02-square \
        -lgccjit

    # Run the built program:
    $ ./tut02-square
    result: 25



File: libgccjit.info,  Node: Tutorial part 3 Loops and variables<2>,  Next: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,  Prev: Tutorial part 2 Creating a trivial machine code function<2>,  Up: Tutorial<2>

3.1.3 Tutorial part 3: Loops and variables
------------------------------------------

Consider this C function:

         int loop_test (int n)
         {
           int sum = 0;
           for (int i = 0; i < n; i++)
             sum += i * i;
           return sum;
         }



  This example demonstrates some more features of libgccjit, with local
variables and a loop.

  To break this down into libgccjit terms, it's usually easier to reword
the `for' loop as a `while' loop, giving:

         int loop_test (int n)
         {
           int sum = 0;
           int i = 0;
           while (i < n)
           {
             sum += i * i;
             i++;
           }
           return sum;
         }



  Here's what the final control flow graph will look like:

       Figure


  As before, we include the libgccjit++ header and make a
`gccjit::context'.

    #include <libgccjit++.h>

    void test (void)
    {
      gccjit::context ctxt;
      ctxt = gccjit::context::acquire ();

The function works with the C `int' type.

  In the previous tutorial we acquired this via

    gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_INT);

though we could equally well make it work on, say, `double':

    gccjit::type the_type = ctxt.get_type (ctxt, GCC_JIT_TYPE_DOUBLE);

For integer types we can use `gccjit::context::get_int_type' to
directly bind a specific type:

    gccjit::type the_type = ctxt.get_int_type <int> ();

Let's build the function:

    gcc_jit_param n = ctxt.new_param (the_type, "n");
    std::vector<gccjit::param> params;
    params.push_back (n);
    gccjit::function func =
      ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                         return_type,
                         "loop_test",
                         params, 0);


* Menu:

* Expressions; lvalues and rvalues: Expressions lvalues and rvalues<2>.
* Control flow: Control flow<2>.
* Visualizing the control flow graph: Visualizing the control flow graph<2>.
* Full example: Full example<4>.


File: libgccjit.info,  Node: Expressions lvalues and rvalues<2>,  Next: Control flow<2>,  Up: Tutorial part 3 Loops and variables<2>

3.1.3.1 Expressions: lvalues and rvalues
........................................

The base class of expression is the `gccjit::rvalue', representing an
expression that can be on the _right_-hand side of an assignment: a
value that can be computed somehow, and assigned _to_ a storage area
(such as a variable).  It has a specific `gccjit::type'.

  Anothe important class is `gccjit::lvalue'.  A `gccjit::lvalue'. is
something that can of the _left_-hand side of an assignment: a storage
area (such as a variable).

  In other words, every assignment can be thought of as:

    LVALUE = RVALUE;

Note that `gccjit::lvalue' is a subclass of `gccjit::rvalue', where in
an assignment of the form:

    LVALUE_A = LVALUE_B;

the `LVALUE_B' implies reading the current value of that storage area,
assigning it into the `LVALUE_A'.

  So far the only expressions we've seen are from the previous tutorial:

  1. the multiplication `i * i':

         gccjit::rvalue expr =
           ctxt.new_binary_op (
             GCC_JIT_BINARY_OP_MULT, int_type,
             param_i, param_i);

         /* Alternatively, using operator-overloading: */
         gccjit::rvalue expr = param_i * param_i;

     which is a `gccjit::rvalue', and

  2. the various function parameters: `param_i' and `param_n',
     instances of `gccjit::param', which is a subclass of
     `gccjit::lvalue' (and, in turn, of `gccjit::rvalue'): we can both
     read from and write to function parameters within the body of a
     function.

  Our new example has a new kind of expression: we have two local
variables.  We create them by calling *note
gccjit;;function;;new_local(): 12c, supplying a type and a name:

    /* Build locals:  */
    gccjit::lvalue i = func.new_local (the_type, "i");
    gccjit::lvalue sum = func.new_local (the_type, "sum");

These are instances of `gccjit::lvalue' - they can be read from and
written to.

  Note that there is no precanned way to create _and_ initialize a
variable like in C:

    int i = 0;

Instead, having added the local to the function, we have to separately
add an assignment of `0' to `local_i' at the beginning of the function.


File: libgccjit.info,  Node: Control flow<2>,  Next: Visualizing the control flow graph<2>,  Prev: Expressions lvalues and rvalues<2>,  Up: Tutorial part 3 Loops and variables<2>

3.1.3.2 Control flow
....................

This function has a loop, so we need to build some basic blocks to
handle the control flow.  In this case, we need 4 blocks:

  1. before the loop (initializing the locals)

  2. the conditional at the top of the loop (comparing `i < n')

  3. the body of the loop

  4. after the loop terminates (`return sum')

  so we create these as `gccjit::block' instances within the
`gccjit::function':

    gccjit::block b_initial = func.new_block ("initial");
    gccjit::block b_loop_cond = func.new_block ("loop_cond");
    gccjit::block b_loop_body = func.new_block ("loop_body");
    gccjit::block b_after_loop = func.new_block ("after_loop");

We now populate each block with statements.

  The entry block `b_initial' consists of initializations followed by a
jump to the conditional.  We assign `0' to `i' and to `sum', using
*note gccjit;;block;;add_assignment(): 12e. to add an assignment
statement, and using *note gccjit;;context;;zero(): 12f. to get the
constant value `0' for the relevant type for the right-hand side of the
assignment:

    /* sum = 0; */
    b_initial.add_assignment (sum, ctxt.zero (the_type));

    /* i = 0; */
    b_initial.add_assignment (i, ctxt.zero (the_type));

We can then terminate the entry block by jumping to the conditional:

    b_initial.end_with_jump (b_loop_cond);

The conditional block is equivalent to the line `while (i < n)' from our
C example. It contains a single statement: a conditional, which jumps to
one of two destination blocks depending on a boolean `gccjit::rvalue',
in this case the comparison of `i' and `n'.

  We could build the comparison using *note
gccjit;;context;;new_comparison(): 130.:

    gccjit::rvalue guard =
      ctxt.new_comparison (GCC_JIT_COMPARISON_GE,
                           i, n);

and can then use this to add `b_loop_cond''s sole statement, via *note
gccjit;;block;;end_with_conditional(): 131.:

    b_loop_cond.end_with_conditional (guard,
                                      b_after_loop, // on_true
                                      b_loop_body); // on_false

However `gccjit::rvalue' has overloaded operators for this, so we
express the conditional as

    gccjit::rvalue guard = (i >= n);

and hence we can write the block more concisely as:

    b_loop_cond.end_with_conditional (
      i >= n,
      b_after_loop, // on_true
      b_loop_body); // on_false

Next, we populate the body of the loop.

  The C statement `sum += i * i;' is an assignment operation, where an
lvalue is modified "in-place".  We use *note
gccjit;;block;;add_assignment_op(): 132. to handle these operations:

    /* sum += i * i */
    b_loop_body.add_assignment_op (sum,
                                   GCC_JIT_BINARY_OP_PLUS,
                                   i * i);

The `i++' can be thought of as `i += 1', and can thus be handled in a
similar way.  We use *note gcc_jit_context_one(): 2f. to get the
constant value `1' (for the relevant type) for the right-hand side of
the assignment.

    /* i++ */
    b_loop_body.add_assignment_op (i,
                                   GCC_JIT_BINARY_OP_PLUS,
                                   ctxt.one (the_type));


     Note: For numeric constants other than 0 or 1, we could use *note
     gccjit;;context;;new_rvalue(): 133, which has overloads for both
     `int' and `double'.

  The loop body completes by jumping back to the conditional:

    b_loop_body.end_with_jump (b_loop_cond);

Finally, we populate the `b_after_loop' block, reached when the loop
conditional is false.  We want to generate the equivalent of:

    return sum;

so the block is just one statement:

    /* return sum */
    b_after_loop.end_with_return (sum);


     Note: You can intermingle block creation with statement creation,
     but given that the terminator statements generally include
     references to other blocks, I find it's clearer to create all the
     blocks, _then_ all the statements.

  We've finished populating the function.  As before, we can now
compile it to machine code:

    gcc_jit_result *result;
    result = ctxt.compile ();

    ctxt.release ();

    if (!result)
      {
        fprintf (stderr, "NULL result");
        return 1;
      }

    typedef int (*loop_test_fn_type) (int);
    loop_test_fn_type loop_test =
     (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
    if (!loop_test)
      {
        fprintf (stderr, "NULL loop_test");
        gcc_jit_result_release (result);
        return 1;
      }
    printf ("result: %d", loop_test (10));


    result: 285



File: libgccjit.info,  Node: Visualizing the control flow graph<2>,  Next: Full example<4>,  Prev: Control flow<2>,  Up: Tutorial part 3 Loops and variables<2>

3.1.3.3 Visualizing the control flow graph
..........................................

You can see the control flow graph of a function using *note
gccjit;;function;;dump_to_dot(): 135.:

    func.dump_to_dot ("/tmp/sum-of-squares.dot");

giving a .dot file in GraphViz format.

  You can convert this to an image using `dot':

    $ dot -Tpng /tmp/sum-of-squares.dot -o /tmp/sum-of-squares.png

or use a viewer (my preferred one is xdot.py; see
<https://github.com/jrfonseca/xdot.py>; on Fedora you can install it
with `yum install python-xdot'):

       Figure



File: libgccjit.info,  Node: Full example<4>,  Prev: Visualizing the control flow graph<2>,  Up: Tutorial part 3 Loops and variables<2>

3.1.3.4 Full example
....................

         /* Usage example for libgccjit.so's C++ API
            Copyright (C) 2014-2019 Free Software Foundation, Inc.

         This file is part of GCC.

         GCC is free software; you can redistribute it and/or modify it
         under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 3, or (at your option)
         any later version.

         GCC is distributed in the hope that it will be useful, but
         WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with GCC; see the file COPYING3.  If not see
         <http://www.gnu.org/licenses/>.  */

         #include <libgccjit++.h>

         #include <stdlib.h>
         #include <stdio.h>

         void
         create_code (gccjit::context ctxt)
         {
           /*
             Simple sum-of-squares, to test conditionals and looping

             int loop_test (int n)
             {
               int i;
               int sum = 0;
               for (i = 0; i < n ; i ++)
               {
         	sum += i * i;
               }
               return sum;
            */
           gccjit::type the_type = ctxt.get_int_type <int> ();
           gccjit::type return_type = the_type;

           gccjit::param n = ctxt.new_param (the_type, "n");
           std::vector<gccjit::param> params;
           params.push_back (n);
           gccjit::function func =
             ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                                return_type,
                                "loop_test",
                                params, 0);

           /* Build locals:  */
           gccjit::lvalue i = func.new_local (the_type, "i");
           gccjit::lvalue sum = func.new_local (the_type, "sum");

           gccjit::block b_initial = func.new_block ("initial");
           gccjit::block b_loop_cond = func.new_block ("loop_cond");
           gccjit::block b_loop_body = func.new_block ("loop_body");
           gccjit::block b_after_loop = func.new_block ("after_loop");

           /* sum = 0; */
           b_initial.add_assignment (sum, ctxt.zero (the_type));

           /* i = 0; */
           b_initial.add_assignment (i, ctxt.zero (the_type));

           b_initial.end_with_jump (b_loop_cond);

           /* if (i >= n) */
           b_loop_cond.end_with_conditional (
             i >= n,
             b_after_loop,
             b_loop_body);

           /* sum += i * i */
           b_loop_body.add_assignment_op (sum,
                                          GCC_JIT_BINARY_OP_PLUS,
                                          i * i);

           /* i++ */
           b_loop_body.add_assignment_op (i,
                                         GCC_JIT_BINARY_OP_PLUS,
                                         ctxt.one (the_type));

           b_loop_body.end_with_jump (b_loop_cond);

           /* return sum */
           b_after_loop.end_with_return (sum);
         }

         int
         main (int argc, char **argv)
         {
           gccjit::context ctxt;
           gcc_jit_result *result = NULL;

           /* Get a "context" object for working with the library.  */
           ctxt = gccjit::context::acquire ();

           /* Set some options on the context.
              Turn this on to see the code being generated, in assembler form.  */
           ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
                                 0);

           /* Populate the context.  */
           create_code (ctxt);

           /* Compile the code.  */
           result = ctxt.compile ();

           ctxt.release ();

           if (!result)
             {
               fprintf (stderr, "NULL result");
               return 1;
             }

           /* Extract the generated code from "result".  */
           typedef int (*loop_test_fn_type) (int);
           loop_test_fn_type loop_test =
             (loop_test_fn_type)gcc_jit_result_get_code (result, "loop_test");
           if (!loop_test)
             {
               fprintf (stderr, "NULL loop_test");
               gcc_jit_result_release (result);
               return 1;
             }

           /* Run the generated code.  */
           int val = loop_test (10);
           printf("loop_test returned: %d\n", val);

           gcc_jit_result_release (result);
           return 0;
         }



  Building and running it:

    $ gcc \
        tut03-sum-of-squares.cc \
        -o tut03-sum-of-squares \
        -lgccjit

    # Run the built program:
    $ ./tut03-sum-of-squares
    loop_test returned: 285



File: libgccjit.info,  Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>,  Prev: Tutorial part 3 Loops and variables<2>,  Up: Tutorial<2>

3.1.4 Tutorial part 4: Adding JIT-compilation to a toy interpreter
------------------------------------------------------------------

In this example we construct a "toy" interpreter, and add
JIT-compilation to it.

* Menu:

* Our toy interpreter: Our toy interpreter<2>.
* Compiling to machine code: Compiling to machine code<2>.
* Setting things up: Setting things up<2>.
* Populating the function: Populating the function<2>.
* Verifying the control flow graph: Verifying the control flow graph<2>.
* Compiling the context: Compiling the context<2>.
* Single-stepping through the generated code: Single-stepping through the generated code<2>.
* Examining the generated code: Examining the generated code<2>.
* Putting it all together: Putting it all together<2>.
* Behind the curtain; How does our code get optimized?: Behind the curtain How does our code get optimized?<2>.


File: libgccjit.info,  Node: Our toy interpreter<2>,  Next: Compiling to machine code<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.1 Our toy interpreter
...........................

It's a stack-based interpreter, and is intended as a (very simple)
example of the kind of bytecode interpreter seen in dynamic languages
such as Python, Ruby etc.

  For the sake of simplicity, our toy virtual machine is very limited:

        * The only data type is `int'

        * It can only work on one function at a time (so that the only
          function call that can be made is to recurse).

        * Functions can only take one parameter.

        * Functions have a stack of `int' values.

        * We'll implement function call within the interpreter by
          calling a function in our implementation, rather than
          implementing our own frame stack.

        * The parser is only good enough to get the examples to work.

  Naturally, a real interpreter would be much more complicated that
this.

  The following operations are supported:

Operation                  Meaning                      Old Stack           New Stack
------------------------------------------------------------------------------------------------- 
DUP                        Duplicate top of stack.      `[..., x]'          `[..., x, x]'
ROT                        Swap top two elements of     `[..., x, y]'       `[..., y, x]'
                           stack.                                           
BINARY_ADD                 Add the top two elements on  `[..., x, y]'       `[..., (x+y)]'
                           the stack.                                       
BINARY_SUBTRACT            Likewise, but subtract.      `[..., x, y]'       `[..., (x-y)]'
BINARY_MULT                Likewise, but multiply.      `[..., x, y]'       `[..., (x*y)]'
BINARY_COMPARE_LT          Compare the top two          `[..., x, y]'       `[..., (x<y)]'
                           elements on the stack and                        
                           push a nonzero/zero if                           
                           (x<y).                                           
RECURSE                    Recurse, passing the top of  `[..., x]'          `[..., fn(x)]'
                           the stack, and popping the                       
                           result.                                          
RETURN                     Return the top of the stack. `[x]'               `[]'
PUSH_CONST `arg'           Push an int const.           `[...]'             `[..., arg]'
JUMP_ABS_IF_TRUE `arg'     Pop; if top of stack was     `[..., x]'          `[...]'
                           nonzero, jump to `arg'.                          

  Programs can be interpreted, disassembled, and compiled to machine
code.

  The interpreter reads `.toy' scripts.  Here's what a simple recursive
factorial program looks like, the script `factorial.toy'.  The parser
ignores lines beginning with a `#'.

         # Simple recursive factorial implementation, roughly equivalent to:
         #
         #  int factorial (int arg)
         #  {
         #     if (arg < 2)
         #       return arg
         #     return arg * factorial (arg - 1)
         #  }

         # Initial state:
         # stack: [arg]

         # 0:
         DUP
         # stack: [arg, arg]

         # 1:
         PUSH_CONST 2
         # stack: [arg, arg, 2]

         # 2:
         BINARY_COMPARE_LT
         # stack: [arg, (arg < 2)]

         # 3:
         JUMP_ABS_IF_TRUE 9
         # stack: [arg]

         # 4:
         DUP
         # stack: [arg, arg]

         # 5:
         PUSH_CONST 1
         # stack: [arg, arg, 1]

         # 6:
         BINARY_SUBTRACT
         # stack: [arg,  (arg - 1)

         # 7:
         RECURSE
         # stack: [arg, factorial(arg - 1)]

         # 8:
         BINARY_MULT
         # stack: [arg * factorial(arg - 1)]

         # 9:
         RETURN



  The interpreter is a simple infinite loop with a big `switch'
statement based on what the next opcode is:


         int
         toyvm_function::interpret (int arg, FILE *trace)
         {
           toyvm_frame frame;
         #define PUSH(ARG) (frame.push (ARG))
         #define POP(ARG) (frame.pop ())

           frame.frm_function = this;
           frame.frm_pc = 0;
           frame.frm_cur_depth = 0;

           PUSH (arg);

           while (1)
             {
               toyvm_op *op;
               int x, y;
               assert (frame.frm_pc < fn_num_ops);
               op = &fn_ops[frame.frm_pc++];

               if (trace)
         	{
         	  frame.dump_stack (trace);
         	  disassemble_op (op, frame.frm_pc, trace);
         	}

               switch (op->op_opcode)
         	{
         	  /* Ops taking no operand.  */
         	case DUP:
         	  x = POP ();
         	  PUSH (x);
         	  PUSH (x);
         	  break;

         	case ROT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (y);
         	  PUSH (x);
         	  break;

         	case BINARY_ADD:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x + y);
         	  break;

         	case BINARY_SUBTRACT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x - y);
         	  break;

         	case BINARY_MULT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x * y);
         	  break;

         	case BINARY_COMPARE_LT:
         	  y = POP ();
         	  x = POP ();
         	  PUSH (x < y);
         	  break;

         	case RECURSE:
         	  x = POP ();
         	  x = interpret (x, trace);
         	  PUSH (x);
         	  break;

         	case RETURN:
         	  return POP ();

         	  /* Ops taking an operand.  */
         	case PUSH_CONST:
         	  PUSH (op->op_operand);
         	  break;

         	case JUMP_ABS_IF_TRUE:
         	  x = POP ();
         	  if (x)
         	    frame.frm_pc = op->op_operand;
         	  break;

         	default:
         	  assert (0); /* unknown opcode */

         	} /* end of switch on opcode */
             } /* end of while loop */

         #undef PUSH
         #undef POP
         }




File: libgccjit.info,  Node: Compiling to machine code<2>,  Next: Setting things up<2>,  Prev: Our toy interpreter<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.2 Compiling to machine code
.................................

We want to generate machine code that can be cast to this type and then
directly executed in-process:

         typedef int (*toyvm_compiled_func) (int);



  Our compiler isn't very sophisticated; it takes the implementation of
each opcode above, and maps it directly to the operations supported by
the libgccjit API.

  How should we handle the stack?  In theory we could calculate what the
stack depth will be at each opcode, and optimize away the stack
manipulation "by hand".  We'll see below that libgccjit is able to do
this for us, so we'll implement stack manipulation in a direct way, by
creating a `stack' array and `stack_depth' variables, local within the
generated function, equivalent to this C code:

    int stack_depth;
    int stack[MAX_STACK_DEPTH];

We'll also have local variables `x' and `y' for use when implementing
the opcodes, equivalent to this:

    int x;
    int y;

This means our compiler has the following state:


           toyvm_function &toyvmfn;

           gccjit::context ctxt;

           gccjit::type int_type;
           gccjit::type bool_type;
           gccjit::type stack_type; /* int[MAX_STACK_DEPTH] */

           gccjit::rvalue const_one;

           gccjit::function fn;
           gccjit::param param_arg;
           gccjit::lvalue stack;
           gccjit::lvalue stack_depth;
           gccjit::lvalue x;
           gccjit::lvalue y;

           gccjit::location op_locs[MAX_OPS];
           gccjit::block initial_block;
           gccjit::block op_blocks[MAX_OPS];




File: libgccjit.info,  Node: Setting things up<2>,  Next: Populating the function<2>,  Prev: Compiling to machine code<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.3 Setting things up
.........................

First we create our types:


         void
         compilation_state::create_types ()
         {
           /* Create types.  */
           int_type = ctxt.get_type (GCC_JIT_TYPE_INT);
           bool_type = ctxt.get_type (GCC_JIT_TYPE_BOOL);
           stack_type = ctxt.new_array_type (int_type, MAX_STACK_DEPTH);



  along with extracting a useful `int' constant:

           const_one = ctxt.one (int_type);

         }



  We'll implement push and pop in terms of the `stack' array and
`stack_depth'.  Here are helper functions for adding statements to a
block, implementing pushing and popping values:


         void
         compilation_state::add_push (gccjit::block block,
                                      gccjit::rvalue rvalue,
                                      gccjit::location loc)
         {
           /* stack[stack_depth] = RVALUE */
           block.add_assignment (
             /* stack[stack_depth] */
             ctxt.new_array_access (
               stack,
               stack_depth,
               loc),
             rvalue,
             loc);

           /* "stack_depth++;".  */
           block.add_assignment_op (
             stack_depth,
             GCC_JIT_BINARY_OP_PLUS,
             const_one,
             loc);
         }

         void
         compilation_state::add_pop (gccjit::block block,
                                     gccjit::lvalue lvalue,
                                     gccjit::location loc)
         {
           /* "--stack_depth;".  */
           block.add_assignment_op (
             stack_depth,
             GCC_JIT_BINARY_OP_MINUS,
             const_one,
             loc);

           /* "LVALUE = stack[stack_depth];".  */
           block.add_assignment (
             lvalue,
             /* stack[stack_depth] */
             ctxt.new_array_access (stack,
                                    stack_depth,
                                    loc),
             loc);
         }



  We will support single-stepping through the generated code in the
debugger, so we need to create `gccjit::location' instances, one per
operation in the source code.  These will reference the lines of e.g.
`factorial.toy'.


         void
         compilation_state::create_locations ()
         {
           for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
             {
               toyvm_op *op = &toyvmfn.fn_ops[pc];

               op_locs[pc] = ctxt.new_location (toyvmfn.fn_filename,
                                                op->op_linenum,
                                                0); /* column */
             }
         }



  Let's create the function itself.  As usual, we create its parameter
first, then use the parameter to create the function:


         void
         compilation_state::create_function (const char *funcname)
         {
           std::vector <gccjit::param> params;
           param_arg = ctxt.new_param (int_type, "arg", op_locs[0]);
           params.push_back (param_arg);
           fn = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                                   int_type,
                                   funcname,
                                   params, 0,
                                   op_locs[0]);



  We create the locals within the function.

           stack = fn.new_local (stack_type, "stack");
           stack_depth = fn.new_local (int_type, "stack_depth");
           x = fn.new_local (int_type, "x");
           y = fn.new_local (int_type, "y");




File: libgccjit.info,  Node: Populating the function<2>,  Next: Verifying the control flow graph<2>,  Prev: Setting things up<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.4 Populating the function
...............................

There's some one-time initialization, and the API treats the first block
you create as the entrypoint of the function, so we need to create that
block first:

           initial_block = fn.new_block ("initial");



  We can now create blocks for each of the operations.  Most of these
will be consolidated into larger blocks when the optimizer runs.

           for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
             {
               char buf[16];
               sprintf (buf, "instr%i", pc);
               op_blocks[pc] = fn.new_block (buf);
             }



  Now that we have a block it can jump to when it's done, we can
populate the initial block:


           /* "stack_depth = 0;".  */
           initial_block.add_assignment (stack_depth,
                                         ctxt.zero (int_type),
                                         op_locs[0]);

           /* "PUSH (arg);".  */
           add_push (initial_block,
         	    param_arg,
                     op_locs[0]);

           /* ...and jump to insn 0.  */
           initial_block.end_with_jump (op_blocks[0],
                                        op_locs[0]);



  We can now populate the blocks for the individual operations.  We loop
through them, adding instructions to their blocks:

           for (int pc = 0; pc < toyvmfn.fn_num_ops; pc++)
             {
               gccjit::location loc = op_locs[pc];

               gccjit::block block = op_blocks[pc];
               gccjit::block next_block = (pc < toyvmfn.fn_num_ops
                                           ? op_blocks[pc + 1]
                                           : NULL);

               toyvm_op *op;
               op = &toyvmfn.fn_ops[pc];



  We're going to have another big `switch' statement for implementing
the opcodes, this time for compiling them, rather than interpreting
them.  It's helpful to have macros for implementing push and pop, so
that we can make the `switch' statement that's coming up look as much as
possible like the one above within the interpreter:


    #define X_EQUALS_POP()\
          add_pop (block, x, loc)
    #define Y_EQUALS_POP()\
          add_pop (block, y, loc)
    #define PUSH_RVALUE(RVALUE)\
          add_push (block, (RVALUE), loc)
    #define PUSH_X()\
          PUSH_RVALUE (x)
    #define PUSH_Y() \
          PUSH_RVALUE (y)


     Note: A particularly clever implementation would have an
     _identical_ `switch' statement shared by the interpreter and the
     compiler, with some preprocessor "magic".  We're not doing that
     here, for the sake of simplicity.

  When I first implemented this compiler, I accidentally missed an edit
when copying and pasting the `Y_EQUALS_POP' macro, so that popping the
stack into `y' instead erroneously assigned it to `x', leaving `y'
uninitialized.

  To track this kind of thing down, we can use *note
gccjit;;block;;add_comment(): 13d. to add descriptive comments to the
internal representation.  This is invaluable when looking through the
generated IR for, say `factorial':


               block.add_comment (opcode_names[op->op_opcode], loc);



  We can now write the big `switch' statement that implements the
individual opcodes, populating the relevant block with statements:


               switch (op->op_opcode)
         	{
         	case DUP:
         	  X_EQUALS_POP ();
         	  PUSH_X ();
         	  PUSH_X ();
         	  break;

         	case ROT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_Y ();
         	  PUSH_X ();
         	  break;

         	case BINARY_ADD:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	   ctxt.new_binary_op (
         	     GCC_JIT_BINARY_OP_PLUS,
         	     int_type,
                      x, y,
                      loc));
         	  break;

         	case BINARY_SUBTRACT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
                    ctxt.new_binary_op (
         	     GCC_JIT_BINARY_OP_MINUS,
         	     int_type,
                      x, y,
                      loc));
         	  break;

         	case BINARY_MULT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
                    ctxt.new_binary_op (
         	     GCC_JIT_BINARY_OP_MULT,
         	     int_type,
                      x, y,
                      loc));
         	  break;

         	case BINARY_COMPARE_LT:
         	  Y_EQUALS_POP ();
         	  X_EQUALS_POP ();
         	  PUSH_RVALUE (
         	     /* cast of bool to int */
         	     ctxt.new_cast (
         	       /* (x < y) as a bool */
         	       ctxt.new_comparison (
         		 GCC_JIT_COMPARISON_LT,
                          x, y,
                          loc),
         	       int_type,
                        loc));
         	  break;

         	case RECURSE:
         	  {
         	    X_EQUALS_POP ();
         	    PUSH_RVALUE (
         	      ctxt.new_call (
         		fn,
         		x,
                         loc));
         	    break;
         	  }

         	case RETURN:
         	  X_EQUALS_POP ();
         	  block.end_with_return (x, loc);
         	  break;

         	  /* Ops taking an operand.  */
         	case PUSH_CONST:
         	  PUSH_RVALUE (
         	    ctxt.new_rvalue (int_type, op->op_operand));
         	  break;

         	case JUMP_ABS_IF_TRUE:
         	  X_EQUALS_POP ();
         	  block.end_with_conditional (
         	    /* "(bool)x".  */
                     ctxt.new_cast (x, bool_type, loc),
         	    op_blocks[op->op_operand], /* on_true */
         	    next_block, /* on_false */
                     loc);
         	  break;

         	default:
         	  assert(0);
         	} /* end of switch on opcode */



  Every block must be terminated, via a call to one of the
`gccjit::block::end_with_' entrypoints.  This has been done for two of
the opcodes, but we need to do it for the other ones, by jumping to the
next block.

               if (op->op_opcode != JUMP_ABS_IF_TRUE
         	  && op->op_opcode != RETURN)
         	block.end_with_jump (next_block, loc);



  This is analogous to simply incrementing the program counter.


File: libgccjit.info,  Node: Verifying the control flow graph<2>,  Next: Compiling the context<2>,  Prev: Populating the function<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.5 Verifying the control flow graph
........................................

Having finished looping over the blocks, the context is complete.

  As before, we can verify that the control flow and statements are
sane by using *note gccjit;;function;;dump_to_dot(): 135.:

    fn.dump_to_dot ("/tmp/factorial.dot");

and viewing the result.  Note how the label names, comments, and
variable names show up in the dump, to make it easier to spot errors in
our compiler.

       Figure



File: libgccjit.info,  Node: Compiling the context<2>,  Next: Single-stepping through the generated code<2>,  Prev: Verifying the control flow graph<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.6 Compiling the context
.............................

Having finished looping over the blocks and populating them with
statements, the context is complete.

  We can now compile it, extract machine code from the result, and run
it:


         class compilation_result
         {
         public:
           compilation_result (gcc_jit_result *result) :
             m_result (result)
           {
           }
           ~compilation_result ()
           {
             gcc_jit_result_release (m_result);
           }

           void *get_code (const char *funcname)
           {
             return gcc_jit_result_get_code (m_result, funcname);
           }

         private:
           gcc_jit_result *m_result;
         };


           compilation_result compiler_result = fn->compile ();

           const char *funcname = fn->get_function_name ();
           toyvm_compiled_func code
             = (toyvm_compiled_func)compiler_result.get_code (funcname);

           printf ("compiler result: %d\n",
         	  code (atoi (argv[2])));




File: libgccjit.info,  Node: Single-stepping through the generated code<2>,  Next: Examining the generated code<2>,  Prev: Compiling the context<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.7 Single-stepping through the generated code
..................................................

It's possible to debug the generated code.  To do this we need to both:

        * Set up source code locations for our statements, so that we
          can meaningfully step through the code.  We did this above by
          calling *note gccjit;;context;;new_location(): 141. and using
          the results.

        * Enable the generation of debugging information, by setting
          *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the
          `gccjit::context' via *note
          gccjit;;context;;set_bool_option(): 126.:

              ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);



  Having done this, we can put a breakpoint on the generated function:

    $ gdb --args ./toyvm factorial.toy 10
    (gdb) break factorial
    Function "factorial" not defined.
    Make breakpoint pending on future shared library load? (y or [n]) y
    Breakpoint 1 (factorial) pending.
    (gdb) run
    Breakpoint 1, factorial (arg=10) at factorial.toy:14
    14    DUP

We've set up location information, which references `factorial.toy'.
This allows us to use e.g. `list' to see where we are in the script:

    (gdb) list
    9
    10    # Initial state:
    11    # stack: [arg]
    12
    13    # 0:
    14    DUP
    15    # stack: [arg, arg]
    16
    17    # 1:
    18    PUSH_CONST 2

and to step through the function, examining the data:

    (gdb) n
    18    PUSH_CONST 2
    (gdb) n
    22    BINARY_COMPARE_LT
    (gdb) print stack
    $5 = {10, 10, 2, 0, -7152, 32767, 0, 0}
    (gdb) print stack_depth
    $6 = 3

You'll see that the parts of the `stack' array that haven't been
touched yet are uninitialized.

     Note: Turning on optimizations may lead to unpredictable results
     when stepping through the generated code: the execution may appear
     to "jump around" the source code.  This is analogous to turning up
     the optimization level in a regular compiler.


File: libgccjit.info,  Node: Examining the generated code<2>,  Next: Putting it all together<2>,  Prev: Single-stepping through the generated code<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.8 Examining the generated code
....................................

How good is the optimized code?

  We can turn up optimizations, by calling *note
gccjit;;context;;set_int_option(): 127. with *note
GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 1f.:

    ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 3);

One of GCC's internal representations is called "gimple".  A dump of the
initial gimple representation of the code can be seen by setting:

    ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);

With optimization on and source locations displayed, this gives:

    factorial (signed int arg)
    {
      <unnamed type> D.80;
      signed int D.81;
      signed int D.82;
      signed int D.83;
      signed int D.84;
      signed int D.85;
      signed int y;
      signed int x;
      signed int stack_depth;
      signed int stack[8];

      try
        {
          initial:
          stack_depth = 0;
          stack[stack_depth] = arg;
          stack_depth = stack_depth + 1;
          goto instr0;
          instr0:
          /* DUP */:
          stack_depth = stack_depth + -1;
          x = stack[stack_depth];
          stack[stack_depth] = x;
          stack_depth = stack_depth + 1;
          stack[stack_depth] = x;
          stack_depth = stack_depth + 1;
          goto instr1;
          instr1:
          /* PUSH_CONST */:
          stack[stack_depth] = 2;
          stack_depth = stack_depth + 1;
          goto instr2;

          /* etc */

You can see the generated machine code in assembly form via:

    ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE, 1);
    result = ctxt.compile ();

which shows that (on this x86_64 box) the compiler has unrolled the loop
and is using MMX instructions to perform several multiplications
simultaneously:

            .file   "fake.c"
            .text
    .Ltext0:
            .p2align 4,,15
            .globl  factorial
            .type   factorial, @function
    factorial:
    .LFB0:
            .file 1 "factorial.toy"
            .loc 1 14 0
            .cfi_startproc
    .LVL0:
    .L2:
            .loc 1 26 0
            cmpl    $1, %edi
            jle     .L13
            leal    -1(%rdi), %edx
            movl    %edx, %ecx
            shrl    $2, %ecx
            leal    0(,%rcx,4), %esi
            testl   %esi, %esi
            je      .L14
            cmpl    $9, %edx
            jbe     .L14
            leal    -2(%rdi), %eax
            movl    %eax, -16(%rsp)
            leal    -3(%rdi), %eax
            movd    -16(%rsp), %xmm0
            movl    %edi, -16(%rsp)
            movl    %eax, -12(%rsp)
            movd    -16(%rsp), %xmm1
            xorl    %eax, %eax
            movl    %edx, -16(%rsp)
            movd    -12(%rsp), %xmm4
            movd    -16(%rsp), %xmm6
            punpckldq       %xmm4, %xmm0
            movdqa  .LC1(%rip), %xmm4
            punpckldq       %xmm6, %xmm1
            punpcklqdq      %xmm0, %xmm1
            movdqa  .LC0(%rip), %xmm0
            jmp     .L5
            # etc - edited for brevity

This is clearly overkill for a function that will likely overflow the
`int' type before the vectorization is worthwhile - but then again, this
is a toy example.

  Turning down the optimization level to 2:

    ctxt.set_int_option (GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 2);

yields this code, which is simple enough to quote in its entirety:

            .file   "fake.c"
            .text
            .p2align 4,,15
            .globl  factorial
            .type   factorial, @function
    factorial:
    .LFB0:
            .cfi_startproc
    .L2:
            cmpl    $1, %edi
            jle     .L8
            movl    $1, %edx
            jmp     .L4
            .p2align 4,,10
            .p2align 3
    .L6:
            movl    %eax, %edi
    .L4:
    .L5:
            leal    -1(%rdi), %eax
            imull   %edi, %edx
            cmpl    $1, %eax
            jne     .L6
    .L3:
    .L7:
            imull   %edx, %eax
            ret
    .L8:
            movl    %edi, %eax
            movl    $1, %edx
            jmp     .L7
            .cfi_endproc
    .LFE0:
            .size   factorial, .-factorial
            .ident  "GCC: (GNU) 4.9.0 20131023 (Red Hat 0.2-%{gcc_release})"
            .section        .note.GNU-stack,"",@progbits

Note that the stack pushing and popping have been eliminated, as has the
recursive call (in favor of an iteration).


File: libgccjit.info,  Node: Putting it all together<2>,  Next: Behind the curtain How does our code get optimized?<2>,  Prev: Examining the generated code<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.9 Putting it all together
...............................

The complete example can be seen in the source tree at
`gcc/jit/docs/examples/tut04-toyvm/toyvm.cc'

  along with a Makefile and a couple of sample .toy scripts:

    $ ls -al
    drwxrwxr-x. 2 david david   4096 Sep 19 17:46 .
    drwxrwxr-x. 3 david david   4096 Sep 19 15:26 ..
    -rw-rw-r--. 1 david david    615 Sep 19 12:43 factorial.toy
    -rw-rw-r--. 1 david david    834 Sep 19 13:08 fibonacci.toy
    -rw-rw-r--. 1 david david    238 Sep 19 14:22 Makefile
    -rw-rw-r--. 1 david david  16457 Sep 19 17:07 toyvm.cc

    $ make toyvm
    g++ -Wall -g -o toyvm toyvm.cc -lgccjit

    $ ./toyvm factorial.toy 10
    interpreter result: 3628800
    compiler result: 3628800

    $ ./toyvm fibonacci.toy 10
    interpreter result: 55
    compiler result: 55



File: libgccjit.info,  Node: Behind the curtain How does our code get optimized?<2>,  Prev: Putting it all together<2>,  Up: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>

3.1.4.10 Behind the curtain: How does our code get optimized?
.............................................................

Our example is done, but you may be wondering about exactly how the
compiler turned what we gave it into the machine code seen above.

  We can examine what the compiler is doing in detail by setting:

    state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING, 1);
    state.ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES, 1);

This will dump detailed information about the compiler's state to a
directory under `/tmp', and keep it from being cleaned up.

  The precise names and their formats of these files is subject to
change.  Higher optimization levels lead to more files.  Here's what I
saw (edited for brevity; there were almost 200 files):

    intermediate files written to /tmp/libgccjit-KPQbGw
    $ ls /tmp/libgccjit-KPQbGw/
    fake.c.000i.cgraph
    fake.c.000i.type-inheritance
    fake.c.004t.gimple
    fake.c.007t.omplower
    fake.c.008t.lower
    fake.c.011t.eh
    fake.c.012t.cfg
    fake.c.014i.visibility
    fake.c.015i.early_local_cleanups
    fake.c.016t.ssa
    # etc

The gimple code is converted into Static Single Assignment form, with
annotations for use when generating the debuginfo:

    $ less /tmp/libgccjit-KPQbGw/fake.c.016t.ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;
      signed int _56;

    initial:
      stack_depth_3 = 0;
      # DEBUG stack_depth => stack_depth_3
      stack[stack_depth_3] = arg_5(D);
      stack_depth_7 = stack_depth_3 + 1;
      # DEBUG stack_depth => stack_depth_7
      # DEBUG instr0 => NULL
      # DEBUG /* DUP */ => NULL
      stack_depth_8 = stack_depth_7 + -1;
      # DEBUG stack_depth => stack_depth_8
      x_9 = stack[stack_depth_8];
      # DEBUG x => x_9
      stack[stack_depth_8] = x_9;
      stack_depth_11 = stack_depth_8 + 1;
      # DEBUG stack_depth => stack_depth_11
      stack[stack_depth_11] = x_9;
      stack_depth_13 = stack_depth_11 + 1;
      # DEBUG stack_depth => stack_depth_13
      # DEBUG instr1 => NULL
      # DEBUG /* PUSH_CONST */ => NULL
      stack[stack_depth_13] = 2;

      /* etc; edited for brevity */

We can perhaps better see the code by turning off *note
GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. to suppress all those `DEBUG'
statements, giving:

    $ less /tmp/libgccjit-1Hywc0/fake.c.016t.ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;
      signed int _56;

    initial:
      stack_depth_3 = 0;
      stack[stack_depth_3] = arg_5(D);
      stack_depth_7 = stack_depth_3 + 1;
      stack_depth_8 = stack_depth_7 + -1;
      x_9 = stack[stack_depth_8];
      stack[stack_depth_8] = x_9;
      stack_depth_11 = stack_depth_8 + 1;
      stack[stack_depth_11] = x_9;
      stack_depth_13 = stack_depth_11 + 1;
      stack[stack_depth_13] = 2;
      stack_depth_15 = stack_depth_13 + 1;
      stack_depth_16 = stack_depth_15 + -1;
      y_17 = stack[stack_depth_16];
      stack_depth_18 = stack_depth_16 + -1;
      x_19 = stack[stack_depth_18];
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack[stack_depth_18] = _21;
      stack_depth_23 = stack_depth_18 + 1;
      stack_depth_24 = stack_depth_23 + -1;
      x_25 = stack[stack_depth_24];
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      stack_depth_26 = stack_depth_24 + -1;
      x_27 = stack[stack_depth_26];
      stack[stack_depth_26] = x_27;
      stack_depth_29 = stack_depth_26 + 1;
      stack[stack_depth_29] = x_27;
      stack_depth_31 = stack_depth_29 + 1;
      stack[stack_depth_31] = 1;
      stack_depth_33 = stack_depth_31 + 1;
      stack_depth_34 = stack_depth_33 + -1;
      y_35 = stack[stack_depth_34];
      stack_depth_36 = stack_depth_34 + -1;
      x_37 = stack[stack_depth_36];
      _38 = x_37 - y_35;
      stack[stack_depth_36] = _38;
      stack_depth_40 = stack_depth_36 + 1;
      stack_depth_41 = stack_depth_40 + -1;
      x_42 = stack[stack_depth_41];
      _44 = factorial (x_42);
      stack[stack_depth_41] = _44;
      stack_depth_46 = stack_depth_41 + 1;
      stack_depth_47 = stack_depth_46 + -1;
      y_48 = stack[stack_depth_47];
      stack_depth_49 = stack_depth_47 + -1;
      x_50 = stack[stack_depth_49];
      _51 = x_50 * y_48;
      stack[stack_depth_49] = _51;
      stack_depth_53 = stack_depth_49 + 1;

      # stack_depth_1 = PHI <stack_depth_24(2), stack_depth_53(3)>
    instr9:
    /* RETURN */:
      stack_depth_54 = stack_depth_1 + -1;
      x_55 = stack[stack_depth_54];
      _56 = x_55;
      stack ={v} {CLOBBER};
      return _56;

    }

Note in the above how all the `gccjit::block' instances we created have
been consolidated into just 3 blocks in GCC's internal representation:
`initial', `instr4' and `instr9'.

* Menu:

* Optimizing away stack manipulation: Optimizing away stack manipulation<2>.
* Elimination of tail recursion: Elimination of tail recursion<2>.


File: libgccjit.info,  Node: Optimizing away stack manipulation<2>,  Next: Elimination of tail recursion<2>,  Up: Behind the curtain How does our code get optimized?<2>

3.1.4.11 Optimizing away stack manipulation
...........................................

Recall our simple implementation of stack operations.  Let's examine
how the stack operations are optimized away.

  After a pass of constant-propagation, the depth of the stack at each
opcode can be determined at compile-time:

    $ less /tmp/libgccjit-1Hywc0/fake.c.021t.ccp1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack[0] = arg_5(D);
      x_9 = stack[0];
      stack[0] = x_9;
      stack[1] = x_9;
      stack[2] = 2;
      y_17 = stack[2];
      x_19 = stack[1];
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack[1] = _21;
      x_25 = stack[1];
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      x_27 = stack[0];
      stack[0] = x_27;
      stack[1] = x_27;
      stack[2] = 1;
      y_35 = stack[2];
      x_37 = stack[1];
      _38 = x_37 - y_35;
      stack[1] = _38;
      x_42 = stack[1];
      _44 = factorial (x_42);
      stack[1] = _44;
      y_48 = stack[1];
      x_50 = stack[0];
      _51 = x_50 * y_48;
      stack[0] = _51;

    instr9:
    /* RETURN */:
      x_55 = stack[0];
      x_56 = x_55;
      stack ={v} {CLOBBER};
      return x_56;

    }

Note how, in the above, all those `stack_depth' values are now just
constants: we're accessing specific stack locations at each opcode.

  The "esra" pass ("Early Scalar Replacement of Aggregates") breaks out
our "stack" array into individual elements:

    $ less /tmp/libgccjit-1Hywc0/fake.c.024t.esra


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    Created a replacement for stack offset: 0, size: 32: stack$0
    Created a replacement for stack offset: 32, size: 32: stack$1
    Created a replacement for stack offset: 64, size: 32: stack$2

    Symbols to be put in SSA form
    { D.89 D.90 D.91 }
    Incremental SSA update started at block: 0
    Number of blocks in CFG: 5
    Number of blocks to update: 4 ( 80%)


    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack$0_45 = arg_5(D);
      x_9 = stack$0_45;
      stack$0_39 = x_9;
      stack$1_32 = x_9;
      stack$2_30 = 2;
      y_17 = stack$2_30;
      x_19 = stack$1_32;
      _20 = x_19 < y_17;
      _21 = (signed int) _20;
      stack$1_28 = _21;
      x_25 = stack$1_28;
      if (x_25 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      x_27 = stack$0_39;
      stack$0_22 = x_27;
      stack$1_14 = x_27;
      stack$2_12 = 1;
      y_35 = stack$2_12;
      x_37 = stack$1_14;
      _38 = x_37 - y_35;
      stack$1_10 = _38;
      x_42 = stack$1_10;
      _44 = factorial (x_42);
      stack$1_6 = _44;
      y_48 = stack$1_6;
      x_50 = stack$0_22;
      _51 = x_50 * y_48;
      stack$0_1 = _51;

      # stack$0_52 = PHI <stack$0_39(2), stack$0_1(3)>
    instr9:
    /* RETURN */:
      x_55 = stack$0_52;
      x_56 = x_55;
      stack ={v} {CLOBBER};
      return x_56;

    }

Hence at this point, all those pushes and pops of the stack are now
simply assignments to specific temporary variables.

  After some copy propagation, the stack manipulation has been
completely optimized away:

    $ less /tmp/libgccjit-1Hywc0/fake.c.026t.copyprop1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int _44;
      signed int _51;

    initial:
      stack$0_39 = arg_5(D);
      _20 = arg_5(D) <= 1;
      _21 = (signed int) _20;
      if (_21 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _38 = arg_5(D) + -1;
      _44 = factorial (_38);
      _51 = arg_5(D) * _44;
      stack$0_1 = _51;

      # stack$0_52 = PHI <arg_5(D)(2), _51(3)>
    instr9:
    /* RETURN */:
      stack ={v} {CLOBBER};
      return stack$0_52;

    }

Later on, another pass finally eliminated `stack_depth' local and the
unused parts of the `stack`' array altogether:

    $ less /tmp/libgccjit-1Hywc0/fake.c.036t.release_ssa


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)

    Released 44 names, 314.29%, removed 44 holes
    factorial (signed int arg)
    {
      signed int stack$0;
      signed int mult_acc_1;
      <unnamed type> _5;
      signed int _6;
      signed int _7;
      signed int mul_tmp_10;
      signed int mult_acc_11;
      signed int mult_acc_13;

      # arg_9 = PHI <arg_8(D)(0)>
      # mult_acc_13 = PHI <1(0)>
    initial:

      <bb 5>:
      # arg_4 = PHI <arg_9(2), _7(3)>
      # mult_acc_1 = PHI <mult_acc_13(2), mult_acc_11(3)>
      _5 = arg_4 <= 1;
      _6 = (signed int) _5;
      if (_6 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _7 = arg_4 + -1;
      mult_acc_11 = mult_acc_1 * arg_4;
      goto <bb 5>;

      # stack$0_12 = PHI <arg_4(5)>
    instr9:
    /* RETURN */:
      mul_tmp_10 = mult_acc_1 * stack$0_12;
      return mul_tmp_10;

    }



File: libgccjit.info,  Node: Elimination of tail recursion<2>,  Prev: Optimizing away stack manipulation<2>,  Up: Behind the curtain How does our code get optimized?<2>

3.1.4.12 Elimination of tail recursion
......................................

Another significant optimization is the detection that the call to
`factorial' is tail recursion, which can be eliminated in favor of an
iteration:

    $ less /tmp/libgccjit-1Hywc0/fake.c.030t.tailr1


    ;; Function factorial (factorial, funcdef_no=0, decl_uid=53, symbol_order=0)


    Symbols to be put in SSA form
    { D.88 }
    Incremental SSA update started at block: 0
    Number of blocks in CFG: 5
    Number of blocks to update: 4 ( 80%)


    factorial (signed int arg)
    {
      signed int stack$2;
      signed int stack$1;
      signed int stack$0;
      signed int stack[8];
      signed int stack_depth;
      signed int x;
      signed int y;
      signed int mult_acc_1;
      <unnamed type> _20;
      signed int _21;
      signed int _38;
      signed int mul_tmp_44;
      signed int mult_acc_51;

      # arg_5 = PHI <arg_39(D)(0), _38(3)>
      # mult_acc_1 = PHI <1(0), mult_acc_51(3)>
    initial:
      _20 = arg_5 <= 1;
      _21 = (signed int) _20;
      if (_21 != 0)
        goto <bb 4> (instr9);
      else
        goto <bb 3> (instr4);

    instr4:
    /* DUP */:
      _38 = arg_5 + -1;
      mult_acc_51 = mult_acc_1 * arg_5;
      goto <bb 2> (initial);

      # stack$0_52 = PHI <arg_5(2)>
    instr9:
    /* RETURN */:
      stack ={v} {CLOBBER};
      mul_tmp_44 = mult_acc_1 * stack$0_52;
      return mul_tmp_44;

    }



File: libgccjit.info,  Node: Topic Reference<2>,  Prev: Tutorial<2>,  Up: C++ bindings for libgccjit

3.2 Topic Reference
===================

* Menu:

* Compilation contexts: Compilation contexts<2>.
* Objects: Objects<2>.
* Types: Types<2>.
* Expressions: Expressions<2>.
* Creating and using functions: Creating and using functions<2>.
* Source Locations: Source Locations<2>.
* Compiling a context: Compiling a context<2>.

Compilation contexts

* Lifetime-management: Lifetime-management<2>.
* Thread-safety: Thread-safety<2>.
* Error-handling: Error-handling<3>.
* Debugging: Debugging<2>.
* Options: Options<4>.

Options

* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
* Additional command-line options: Additional command-line options<2>.

Types

* Standard types: Standard types<2>.
* Pointers, const, and volatile: Pointers const and volatile<2>.
* Vector types: Vector types<2>.
* Structures and unions: Structures and unions<2>.

Expressions

* Rvalues: Rvalues<2>.
* Lvalues: Lvalues<2>.
* Working with pointers, structs and unions: Working with pointers structs and unions<2>.

Rvalues

* Simple expressions: Simple expressions<2>.
* Vector expressions: Vector expressions<2>.
* Unary Operations: Unary Operations<2>.
* Binary Operations: Binary Operations<2>.
* Comparisons: Comparisons<2>.
* Function calls: Function calls<2>.
* Function pointers: Function pointers<3>.
* Type-coercion: Type-coercion<2>.

Lvalues

* Global variables: Global variables<2>.

Creating and using functions

* Params: Params<2>.
* Functions: Functions<2>.
* Blocks: Blocks<2>.
* Statements: Statements<2>.

Source Locations

* Faking it: Faking it<2>.

Compiling a context

* In-memory compilation: In-memory compilation<2>.
* Ahead-of-time compilation: Ahead-of-time compilation<2>.


File: libgccjit.info,  Node: Compilation contexts<2>,  Next: Objects<2>,  Up: Topic Reference<2>

3.2.1 Compilation contexts
--------------------------

 -- C++ Class: gccjit::context

  The top-level of the C++ API is the *note gccjit;;context: 14b. type.

  A *note gccjit;;context: 14b. instance encapsulates the state of a
compilation.

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

  It is a thin wrapper around the C API's *note gcc_jit_context *: 8.

* Menu:

* Lifetime-management: Lifetime-management<2>.
* Thread-safety: Thread-safety<2>.
* Error-handling: Error-handling<3>.
* Debugging: Debugging<2>.
* Options: Options<4>.


File: libgccjit.info,  Node: Lifetime-management<2>,  Next: Thread-safety<2>,  Up: Compilation contexts<2>

3.2.1.1 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.

 -- C++ Function: gccjit::context gccjit::context::acquire ()
     This function acquires a new *note gccjit;;context: 14b. instance,
     which is independent of any others that may be present within this
     process.

 -- C++ Function: 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 ();



 -- C++ Function: 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.


File: libgccjit.info,  Node: Thread-safety<2>,  Next: Error-handling<3>,  Prev: Lifetime-management<2>,  Up: Compilation contexts<2>

3.2.1.2 Thread-safety
.....................

Instances of *note gccjit;;context: 14b. created via *note
gccjit;;context;;acquire(): 11e. 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 *note gccjit;;context;;new_child_context(): 14d.
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.


File: libgccjit.info,  Node: Error-handling<3>,  Next: Debugging<2>,  Prev: Thread-safety<2>,  Up: Compilation contexts<2>

3.2.1.3 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 *note
gccjit;;context;;get_first_error(): 150.

 -- C++ Function: 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.


File: libgccjit.info,  Node: Debugging<2>,  Next: Options<4>,  Prev: Error-handling<3>,  Up: Compilation contexts<2>

3.2.1.4 Debugging
.................

 -- C++ Function: 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 *note
     gccjit;;location: 153.  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.

 -- C++ Function: void gccjit::context::dump_reproducer_to_file
          (gcc_jit_context* ctxt, const char* path)
     This is a thin wrapper around the C API *note
     gcc_jit_context_dump_reproducer_to_file(): 5d, 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.


File: libgccjit.info,  Node: Options<4>,  Prev: Debugging<2>,  Up: Compilation contexts<2>

3.2.1.5 Options
...............

* Menu:

* String Options: String Options<2>.
* Boolean options: Boolean options<2>.
* Integer options: Integer options<2>.
* Additional command-line options: Additional command-line options<2>.


File: libgccjit.info,  Node: String Options<2>,  Next: Boolean options<2>,  Up: Options<4>

3.2.1.6 String Options
......................

 -- C++ Function: 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 *note
     gcc_jit_context_set_str_option(): 61.; the options have the same
     meaning.


File: libgccjit.info,  Node: Boolean options<2>,  Next: Integer options<2>,  Prev: String Options<2>,  Up: Options<4>

3.2.1.7 Boolean options
.......................

 -- C++ Function: 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 *note
     gcc_jit_context_set_bool_option(): 1b.; the options have the same
     meaning.

 -- C++ Function: 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 *note
     gcc_jit_context_set_bool_allow_unreachable_blocks(): 6b.

     This entrypoint was added in *note LIBGCCJIT_ABI_2: 6c.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks



 -- C++ Function: 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
     *note gcc_jit_context_set_bool_use_external_driver(): 6d.

     This entrypoint was added in *note LIBGCCJIT_ABI_5: 6e.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver




File: libgccjit.info,  Node: Integer options<2>,  Next: Additional command-line options<2>,  Prev: Boolean options<2>,  Up: Options<4>

3.2.1.8 Integer options
.......................

 -- C++ Function: 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 *note
     gcc_jit_context_set_int_option(): 1e.; the options have the same
     meaning.


File: libgccjit.info,  Node: Additional command-line options<2>,  Prev: Integer options<2>,  Up: Options<4>

3.2.1.9 Additional command-line options
.......................................

 -- C++ Function: 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 *note
     gcc_jit_context_add_command_line_option(): 72.

     This entrypoint was added in *note LIBGCCJIT_ABI_1: 73.; you can
     test for its presence using

         #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option




File: libgccjit.info,  Node: Objects<2>,  Next: Types<2>,  Prev: Compilation contexts<2>,  Up: Topic Reference<2>

3.2.2 Objects
-------------

 -- C++ Class: gccjit::object

  Almost every entity in the API (with the exception of *note
gccjit;;context: 14b. and *note gcc_jit_result *: 16.) is a
"contextual" object, a *note gccjit;;object: 160.

  A JIT object:

        * is associated with a *note gccjit;;context: 14b.

        * is automatically cleaned up for you when its context is
          released so you don't need to manually track and cleanup all
          objects, just the contexts.

  The C++ class hierarchy within the `gccjit' namespace looks like this:

    +- object
        +- location
        +- type
           +- struct
        +- field
        +- function
        +- block
        +- rvalue
            +- lvalue
               +- param
        +- case_

The *note gccjit;;object: 160. base class has the following operations:

 -- C++ Function: gccjit::context gccjit::object::get_context () const
     Which context is the obj within?

 -- C++ Function: std::string gccjit::object::get_debug_string () const
     Generate a human-readable description for the given object.

     For example,

         printf ("obj: %s\n", obj.get_debug_string ().c_str ());

     might give this text on stdout:

         obj: 4.0 * (float)i




File: libgccjit.info,  Node: Types<2>,  Next: Expressions<2>,  Prev: Objects<2>,  Up: Topic Reference<2>

3.2.3 Types
-----------

 -- C++ Class: gccjit::type
     gccjit::type represents a type within the library.  It is a
     subclass of *note gccjit;;object: 160.

  Types can be created in several ways:

   * fundamental types can be accessed using *note
     gccjit;;context;;get_type(): 11f.:

         gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);

     or using the `gccjit::context::get_int_type' template:

         gccjit::type t = ctxt.get_int_type <unsigned short> ();

     See *note gcc_jit_context_get_type(): b. for the available types.

   * derived types can be accessed by using functions such as *note
     gccjit;;type;;get_pointer(): 165. and *note
     gccjit;;type;;get_const(): 166.:

         gccjit::type const_int_star = int_type.get_const ().get_pointer ();
         gccjit::type int_const_star = int_type.get_pointer ().get_const ();


   * by creating structures (see below).

* Menu:

* Standard types: Standard types<2>.
* Pointers, const, and volatile: Pointers const and volatile<2>.
* Vector types: Vector types<2>.
* Structures and unions: Structures and unions<2>.


File: libgccjit.info,  Node: Standard types<2>,  Next: Pointers const and volatile<2>,  Up: Types<2>

3.2.3.1 Standard types
......................

 -- C++ Function: gccjit::type gccjit::context::get_type (enum
          gcc_jit_types)
     Access a specific type.  This is a thin wrapper around *note
     gcc_jit_context_get_type(): b.; the parameter has the same meaning.

 -- C++ Function: gccjit::type gccjit::context::get_int_type (size_t
          num_bytes, int is_signed)
     Access the integer type of the given size.

 -- C++ Function: gccjit::type gccjit::context::get_int_type<T> ()
     Access the given integer type.  For example, you could map the
     `unsigned short' type into a gccjit::type via:

         gccjit::type t = ctxt.get_int_type <unsigned short> ();




File: libgccjit.info,  Node: Pointers const and volatile<2>,  Next: Vector types<2>,  Prev: Standard types<2>,  Up: Types<2>

3.2.3.2 Pointers, `const', and `volatile'
.........................................

 -- C++ Function: gccjit::type gccjit::type::get_pointer ()
     Given type "T", get type "T*".

 -- C++ Function: gccjit::type gccjit::type::get_const ()
     Given type "T", get type "const T".

 -- C++ Function: gccjit::type gccjit::type::get_volatile ()
     Given type "T", get type "volatile T".

 -- C++ Function: gccjit::type gccjit::type::get_aligned (size_t
          alignment_in_bytes)
     Given type "T", get type:

         T __attribute__ ((aligned (ALIGNMENT_IN_BYTES)))

     The alignment must be a power of two.

 -- C++ Function: gccjit::type gccjit::context::new_array_type
          (gccjit::type element_type, int num_elements,
          gccjit::location loc)
     Given type "T", get type "T[N]" (for a constant N).  Param "loc"
     is optional.


File: libgccjit.info,  Node: Vector types<2>,  Next: Structures and unions<2>,  Prev: Pointers const and volatile<2>,  Up: Types<2>

3.2.3.3 Vector types
....................

 -- C++ Function: gccjit::type gccjit::type::get_vector (size_t
          num_units)
     Given type "T", get type:

         T  __attribute__ ((vector_size (sizeof(T) * num_units))

     T must be integral or floating point; num_units must be a power of
     two.


File: libgccjit.info,  Node: Structures and unions<2>,  Prev: Vector types<2>,  Up: Types<2>

3.2.3.4 Structures and unions
.............................

 -- C++ Class: gccjit::struct_

  A compound type analagous to a C `struct'.

  *note gccjit;;struct_: 171. is a subclass of *note gccjit;;type: 164.
(and thus of *note gccjit;;object: 160. in turn).

 -- C++ Class: gccjit::field

  A field within a *note gccjit;;struct_: 171.

  *note gccjit;;field: 172. is a subclass of *note gccjit;;object: 160.

  You can model C `struct' types by creating *note gccjit;;struct_:
171. and *note gccjit;;field: 172. instances, in either order:

   * by creating the fields, then the structure.  For example, to model:

         struct coord {double x; double y; };

     you could call:

         gccjit::field field_x = ctxt.new_field (double_type, "x");
         gccjit::field field_y = ctxt.new_field (double_type, "y");
         std::vector fields;
         fields.push_back (field_x);
         fields.push_back (field_y);
         gccjit::struct_ coord = ctxt.new_struct_type ("coord", fields);


   * by creating the structure, then populating it with fields,
     typically to allow modelling self-referential structs such as:

         struct node { int m_hash; struct node *m_next; };

     like this:

         gccjit::struct_ node = ctxt.new_opaque_struct_type ("node");
         gccjit::type node_ptr = node.get_pointer ();
         gccjit::field field_hash = ctxt.new_field (int_type, "m_hash");
         gccjit::field field_next = ctxt.new_field (node_ptr, "m_next");
         std::vector fields;
         fields.push_back (field_hash);
         fields.push_back (field_next);
         node.set_fields (fields);



 -- C++ Function: gccjit::field gccjit::context::new_field
          (gccjit::type type, const char* name, gccjit::location loc)
     Construct a new field, with the given type and name.

 -- C++ Function: gccjit::struct_ gccjit::context::new_struct_type
          (const std::string& name, std::vector<field>& fields,
          gccjit::location loc)
          Construct a new struct type, with the given name and fields.

 -- C++ Function: gccjit::struct_ gccjit::context::new_opaque_struct
          (const std::string& name, gccjit::location loc)
     Construct a new struct type, with the given name, but without
     specifying the fields.   The fields can be omitted (in which case
     the size of the struct is not known), or later specified using
     *note gcc_jit_struct_set_fields(): 8d.


File: libgccjit.info,  Node: Expressions<2>,  Next: Creating and using functions<2>,  Prev: Types<2>,  Up: Topic Reference<2>

3.2.4 Expressions
-----------------

* Menu:

* Rvalues: Rvalues<2>.
* Lvalues: Lvalues<2>.
* Working with pointers, structs and unions: Working with pointers structs and unions<2>.

Rvalues

* Simple expressions: Simple expressions<2>.
* Vector expressions: Vector expressions<2>.
* Unary Operations: Unary Operations<2>.
* Binary Operations: Binary Operations<2>.
* Comparisons: Comparisons<2>.
* Function calls: Function calls<2>.
* Function pointers: Function pointers<3>.
* Type-coercion: Type-coercion<2>.

Lvalues

* Global variables: Global variables<2>.


File: libgccjit.info,  Node: Rvalues<2>,  Next: Lvalues<2>,  Up: Expressions<2>

3.2.4.1 Rvalues
...............

 -- C++ Class: gccjit::rvalue

  A *note gccjit;;rvalue: 179. is an expression that can be computed.
It is a subclass of *note gccjit;;object: 160, and is a thin wrapper
around *note gcc_jit_rvalue *: 13. from the C API.

  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).

 -- C++ Function: gccjit::type gccjit::rvalue::get_type ()
     Get the type of this rvalue.

* Menu:

* Simple expressions: Simple expressions<2>.
* Vector expressions: Vector expressions<2>.
* Unary Operations: Unary Operations<2>.
* Binary Operations: Binary Operations<2>.
* Comparisons: Comparisons<2>.
* Function calls: Function calls<2>.
* Function pointers: Function pointers<3>.
* Type-coercion: Type-coercion<2>.


File: libgccjit.info,  Node: Simple expressions<2>,  Next: Vector expressions<2>,  Up: Rvalues<2>

3.2.4.2 Simple expressions
..........................

 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue
          (gccjit::type numeric_type, int value) const
     Given a numeric type (integer or floating point), build an rvalue
     for the given constant `int' value.

 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue
          (gccjit::type numeric_type, long value) const
     Given a numeric type (integer or floating point), build an rvalue
     for the given constant `long' value.

 -- C++ Function: gccjit::rvalue gccjit::context::zero (gccjit::type
          numeric_type) const
     Given a numeric type (integer or floating point), get the rvalue
     for zero.  Essentially this is just a shortcut for:

         ctxt.new_rvalue (numeric_type, 0)



 -- C++ Function: gccjit::rvalue gccjit::context::one (gccjit::type
          numeric_type) const
     Given a numeric type (integer or floating point), get the rvalue
     for one.  Essentially this is just a shortcut for:

         ctxt.new_rvalue (numeric_type, 1)



 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue
          (gccjit::type numeric_type, double value) const
     Given a numeric type (integer or floating point), build an rvalue
     for the given constant `double' value.

 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue
          (gccjit::type pointer_type, void* value) const
     Given a pointer type, build an rvalue for the given address.

 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue (const
          std::string& value) const
     Generate an rvalue of type `GCC_JIT_TYPE_CONST_CHAR_PTR' for the
     given string.  This is akin to a string literal.


File: libgccjit.info,  Node: Vector expressions<2>,  Next: Unary Operations<2>,  Prev: Simple expressions<2>,  Up: Rvalues<2>

3.2.4.3 Vector expressions
..........................

 -- C++ Function: gccjit::rvalue gccjit::context::new_rvalue
          (gccjit::type vector_type, std::vector<gccjit::rvalue>
          elements) const
     Given a vector type, and a vector of scalar rvalue elements,
     generate a vector rvalue.

     The number of elements needs to match that of the vector type.


File: libgccjit.info,  Node: Unary Operations<2>,  Next: Binary Operations<2>,  Prev: Vector expressions<2>,  Up: Rvalues<2>

3.2.4.4 Unary Operations
........................

 -- C++ Function: gccjit::rvalue gccjit::context::new_unary_op (enum
          gcc_jit_unary_op, gccjit::type result_type, gccjit::rvalue
          rvalue, gccjit::location loc)
     Build a unary operation out of an input rvalue.

     Parameter `loc' is optional.

     This is a thin wrapper around the C API's *note
     gcc_jit_context_new_unary_op(): 9e. and the available unary
     operations are documented there.

  There are shorter ways to spell the various specific kinds of unary
operation:

 -- C++ Function: gccjit::rvalue gccjit::context::new_minus
          (gccjit::type result_type, gccjit::rvalue a, gccjit::location
          loc)
     Negate an arithmetic value; for example:

         gccjit::rvalue negpi = ctxt.new_minus (t_double, pi);

     builds the equivalent of this C expression:

         -pi



 -- C++ Function: gccjit::rvalue new_bitwise_negate (gccjit::type
          result_type, gccjit::rvalue a, gccjit::location loc)
     Bitwise negation of an integer value (one's complement); for
     example:

         gccjit::rvalue mask = ctxt.new_bitwise_negate (t_int, a);

     builds the equivalent of this C expression:

         ~a



 -- C++ Function: gccjit::rvalue new_logical_negate (gccjit::type
          result_type, gccjit::rvalue a, gccjit::location loc)
     Logical negation of an arithmetic or pointer value; for example:

         gccjit::rvalue guard = ctxt.new_logical_negate (t_bool, cond);

     builds the equivalent of this C expression:

         !cond



  The most concise way to spell them is with overloaded operators:

 -- C++ Function: gccjit::rvalue operator- (gccjit::rvalue a)
         gccjit::rvalue negpi = -pi;



 -- C++ Function: gccjit::rvalue operator~ (gccjit::rvalue a)
         gccjit::rvalue mask = ~a;



 -- C++ Function: gccjit::rvalue operator! (gccjit::rvalue a)
         gccjit::rvalue guard = !cond;




File: libgccjit.info,  Node: Binary Operations<2>,  Next: Comparisons<2>,  Prev: Unary Operations<2>,  Up: Rvalues<2>

3.2.4.5 Binary Operations
.........................

 -- C++ Function: gccjit::rvalue gccjit::context::new_binary_op (enum
          gcc_jit_binary_op, gccjit::type result_type, gccjit::rvalue
          a, gccjit::rvalue b, gccjit::location loc)
     Build a binary operation out of two constituent rvalues.

     Parameter `loc' is optional.

     This is a thin wrapper around the C API's *note
     gcc_jit_context_new_binary_op(): 12. and the available binary
     operations are documented there.

  There are shorter ways to spell the various specific kinds of binary
operation:

 -- C++ Function: gccjit::rvalue gccjit::context::new_plus
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_minus
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_mult
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_divide
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_modulo
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_bitwise_and
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_bitwise_xor
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_bitwise_or
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_logical_and
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_logical_or
          (gccjit::type result_type, gccjit::rvalue a, gccjit::rvalue
          b, gccjit::location loc)

  The most concise way to spell them is with overloaded operators:

 -- C++ Function: gccjit::rvalue operator+ (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue sum = a + b;



 -- C++ Function: gccjit::rvalue operator- (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue diff = a - b;



 -- C++ Function: gccjit::rvalue operator* (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue prod = a * b;



 -- C++ Function: gccjit::rvalue operator/ (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue result = a / b;



 -- C++ Function: gccjit::rvalue operator% (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue mod = a % b;



 -- C++ Function: gccjit::rvalue operator& (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue x = a & b;



 -- C++ Function: gccjit::rvalue operator^ (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue x = a ^ b;



 -- C++ Function: gccjit::rvalue operator| (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue x = a | b;



 -- C++ Function: gccjit::rvalue operator&& (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = a && b;



 -- C++ Function: gccjit::rvalue operator|| (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = a || b;



  These can of course be combined, giving a terse way to build compound
expressions:

         gccjit::rvalue discriminant = (b * b) - (four * a * c);




File: libgccjit.info,  Node: Comparisons<2>,  Next: Function calls<2>,  Prev: Binary Operations<2>,  Up: Rvalues<2>

3.2.4.6 Comparisons
...................

 -- C++ Function: gccjit::rvalue gccjit::context::new_comparison (enum
          gcc_jit_comparison, gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)
     Build a boolean rvalue out of the comparison of two other rvalues.

     Parameter `loc' is optional.

     This is a thin wrapper around the C API's *note
     gcc_jit_context_new_comparison(): 2c. and the available kinds of
     comparison are documented there.

  There are shorter ways to spell the various specific kinds of binary
operation:

 -- C++ Function: gccjit::rvalue gccjit::context::new_eq
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_ne
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_lt
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_le
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_gt
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::rvalue gccjit::context::new_ge
          (gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

  The most concise way to spell them is with overloaded operators:

 -- C++ Function: gccjit::rvalue operator== (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = (a == ctxt.zero (t_int));



 -- C++ Function: gccjit::rvalue operator!= (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = (i != j);



 -- C++ Function: gccjit::rvalue operator< (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = i < n;



 -- C++ Function: gccjit::rvalue operator<= (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = i <= n;



 -- C++ Function: gccjit::rvalue operator> (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = (ch > limit);



 -- C++ Function: gccjit::rvalue operator>= (gccjit::rvalue a,
          gccjit::rvalue b)
         gccjit::rvalue cond = (score >= ctxt.new_rvalue (t_int, 100));




File: libgccjit.info,  Node: Function calls<2>,  Next: Function pointers<3>,  Prev: Comparisons<2>,  Up: Rvalues<2>

3.2.4.7 Function calls
......................

 -- C++ Function: 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: `gccjit::context::new_call()' merely builds a *note
          gccjit;;rvalue: 179. 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
          *note gccjit;;block;;add_eval(): 1af.:

              /* Add "(void)printf (arg0, arg1);".  */
              block.add_eval (ctxt.new_call (printf_func, arg0, arg1));




File: libgccjit.info,  Node: Function pointers<3>,  Next: Type-coercion<2>,  Prev: Function calls<2>,  Up: Rvalues<2>

3.2.4.8 Function pointers
.........................

 -- C++ Function: gccjit::rvalue gccjit::function::get_address
          (gccjit::location loc)
     Get the address of a function as an rvalue, of function pointer
     type.


File: libgccjit.info,  Node: Type-coercion<2>,  Prev: Function pointers<3>,  Up: Rvalues<2>

3.2.4.9 Type-coercion
.....................

 -- C++ Function: gccjit::rvalue gccjit::context::new_cast
          (gccjit::rvalue rvalue, gccjit::type type, gccjit::location
          loc)
     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


File: libgccjit.info,  Node: Lvalues<2>,  Next: Working with pointers structs and unions<2>,  Prev: Rvalues<2>,  Up: Expressions<2>

3.2.4.10 Lvalues
................

 -- C++ Class: gccjit::lvalue

  An lvalue is something that can of the _left_-hand side of an
assignment: a storage area (such as a variable).  It is a subclass of
*note gccjit;;rvalue: 179, where the rvalue is computed by reading from
the storage area.

  It iss a thin wrapper around *note gcc_jit_lvalue *: 24. from the C
API.

 -- C++ Function: gccjit::rvalue gccjit::lvalue::get_address
          (gccjit::location loc)
     Take the address of an lvalue; analogous to:

         &(EXPR)

     in C.

     Parameter "loc" is optional.

* Menu:

* Global variables: Global variables<2>.


File: libgccjit.info,  Node: Global variables<2>,  Up: Lvalues<2>

3.2.4.11 Global variables
.........................

 -- C++ Function: gccjit::lvalue gccjit::context::new_global (enum
          gcc_jit_global_kind, gccjit::type type, const char* name,
          gccjit::location loc)
     Add a new global variable of the given type and name to the
     context.

     This is a thin wrapper around *note gcc_jit_context_new_global():
     c4. from the C API; the "kind" parameter has the same meaning as
     there.


File: libgccjit.info,  Node: Working with pointers structs and unions<2>,  Prev: Lvalues<2>,  Up: Expressions<2>

3.2.4.12 Working with pointers, structs and unions
..................................................

 -- C++ Function: gccjit::lvalue gccjit::rvalue::dereference
          (gccjit::location loc)
     Given an rvalue of pointer type `T *', dereferencing the pointer,
     getting an lvalue of type `T'.  Analogous to:

         *(EXPR)

     in C.

     Parameter "loc" is optional.

  If you don't need to specify the location, this can also be expressed
using an overloaded operator:

 -- C++ Function: gccjit::lvalue gccjit::rvalue::operator* ()
         gccjit::lvalue content = *ptr;



  Field access is provided separately for both lvalues and rvalues:

 -- C++ Function: gccjit::lvalue gccjit::lvalue::access_field
          (gccjit::field field, gccjit::location loc)
     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.

 -- C++ Function: gccjit::rvalue gccjit::rvalue::access_field
          (gccjit::field field, gccjit::location loc)
     Given an rvalue of struct or union type, access the given field as
     an rvalue.  Analogous to:

         (EXPR).field

     in C.

 -- C++ Function: gccjit::lvalue gccjit::rvalue::dereference_field
          (gccjit::field field, gccjit::location loc)
     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'.

 -- C++ Function: gccjit::lvalue gccjit::context::new_array_access
          (gccjit::rvalue ptr, gccjit::rvalue index, gccjit::location
          loc)
     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').

     Parameter "loc" is optional.

  For array accesses where you don't need to specify a *note
gccjit;;location: 153, two overloaded operators are available:

     gccjit::lvalue gccjit::rvalue::operator[] (gccjit::rvalue index)

         gccjit::lvalue element = array[idx];

     gccjit::lvalue gccjit::rvalue::operator[] (int index)

         gccjit::lvalue element = array[0];




File: libgccjit.info,  Node: Creating and using functions<2>,  Next: Source Locations<2>,  Prev: Expressions<2>,  Up: Topic Reference<2>

3.2.5 Creating and using functions
----------------------------------

* Menu:

* Params: Params<2>.
* Functions: Functions<2>.
* Blocks: Blocks<2>.
* Statements: Statements<2>.


File: libgccjit.info,  Node: Params<2>,  Next: Functions<2>,  Up: Creating and using functions<2>

3.2.5.1 Params
..............

 -- C++ Class: gccjit::param
     A `gccjit::param' represents a parameter to a function.

 -- C++ Function: gccjit::param gccjit::context::new_param
          (gccjit::type type, const char* name, gccjit::location loc)
     In preparation for creating a function, create a new parameter of
     the given type and name.

  *note gccjit;;param: 1c3. is a subclass of *note gccjit;;lvalue: 1b5.
(and thus of *note gccjit;;rvalue: 179. and *note gccjit;;object:
160.).  It is a thin wrapper around the C API's *note gcc_jit_param *:
25.


File: libgccjit.info,  Node: Functions<2>,  Next: Blocks<2>,  Prev: Params<2>,  Up: Creating and using functions<2>

3.2.5.2 Functions
.................

 -- C++ Class: gccjit::function
     A `gccjit::function' represents a function - either one that we're
     creating ourselves, or one that we're referencing.

 -- C++ Function: gccjit::function gccjit::context::new_function (enum
          gcc_jit_function_kind, gccjit::type return_type, const char*
          name, std::vector<param>& params, int is_variadic,
          gccjit::location loc)
     Create a gcc_jit_function with the given name and parameters.

     Parameters "is_variadic" and "loc" are optional.

     This is a wrapper around the C API's *note
     gcc_jit_context_new_function(): 11.

 -- C++ Function: gccjit::function
          gccjit::context::get_builtin_function (const char* name)
     This is a wrapper around the C API's *note
     gcc_jit_context_get_builtin_function(): db.

 -- C++ Function: gccjit::param gccjit::function::get_param (int index)
          const
     Get the param of the given index (0-based).

 -- C++ Function: void gccjit::function::dump_to_dot (const char* path)
     Emit the function in graphviz format to the given path.

 -- C++ Function: gccjit::lvalue gccjit::function::new_local
          (gccjit::type type, const char* name, gccjit::location loc)
     Create a new local variable within the function, of the given type
     and name.


File: libgccjit.info,  Node: Blocks<2>,  Next: Statements<2>,  Prev: Functions<2>,  Up: Creating and using functions<2>

3.2.5.3 Blocks
..............

 -- C++ Class: gccjit::block
     A `gccjit::block' represents a basic block within a function  i.e.
     a sequence of statements with a single entry point and a single
     exit point.

     *note gccjit;;block: 1ca. is a subclass of *note gccjit;;object:
     160.

     The first basic block that you create within a function will be
     the entrypoint.

     Each basic block that you create within a function must be
     terminated, either with a conditional, a jump, a return, or a
     switch.

     It's legal to have multiple basic blocks that return within one
     function.

 -- C++ Function: gccjit::block gccjit::function::new_block (const
          char* name)
     Create a basic block of the given name.  The name may be NULL, but
     providing meaningful names is often helpful when debugging: it may
     show up in dumps of the internal representation, and in error
     messages.


File: libgccjit.info,  Node: Statements<2>,  Prev: Blocks<2>,  Up: Creating and using functions<2>

3.2.5.4 Statements
..................

 -- C++ Function: void gccjit::block::add_eval (gccjit::rvalue rvalue,
          gccjit::location loc)
     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;



 -- C++ Function: void gccjit::block::add_assignment (gccjit::lvalue
          lvalue, gccjit::rvalue rvalue, gccjit::location loc)
     Add evaluation of an rvalue, assigning the result to the given
     lvalue.

     This is roughly equivalent to this C code:

         lvalue = rvalue;



 -- C++ Function: void gccjit::block::add_assignment_op (gccjit::lvalue
          lvalue, enum gcc_jit_binary_op, gccjit::rvalue rvalue,
          gccjit::location loc)
     Add evaluation of an rvalue, using the result to modify an lvalue.

     This is analogous to "+=" and friends:

         lvalue += rvalue;
         lvalue *= rvalue;
         lvalue /= rvalue;

     etc.  For example:

         /* "i++" */
         loop_body.add_assignment_op (
           i,
           GCC_JIT_BINARY_OP_PLUS,
           ctxt.one (int_type));



 -- C++ Function: void gccjit::block::add_comment (const char* text,
          gccjit::location loc)
     Add a no-op textual comment to the internal representation of the
     code.  It will be optimized away, but will be visible in the dumps
     seen via *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: 66.  and
     *note GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: 1c, and thus may be
     of use when debugging how your project's internal representation
     gets converted to the libgccjit IR.

     Parameter "loc" is optional.

 -- C++ Function: void gccjit::block::end_with_conditional
          (gccjit::rvalue boolval, gccjit::block on_true, gccjit::block
          on_false, gccjit::location loc)
     Terminate a block by adding evaluation of an rvalue, branching on
     the result to the appropriate successor block.

     This is roughly equivalent to this C code:

         if (boolval)
           goto on_true;
         else
           goto on_false;

     block, boolval, on_true, and on_false must be non-NULL.

 -- C++ Function: void gccjit::block::end_with_jump (gccjit::block
          target, gccjit::location loc)
     Terminate a block by adding a jump to the given target block.

     This is roughly equivalent to this C code:

         goto target;



 -- C++ Function: void gccjit::block::end_with_return (gccjit::rvalue
          rvalue, gccjit::location loc)
     Terminate a block.

     Both params are optional.

     An rvalue must be provided for a function returning non-void, and
     must not be provided by a function "returning" `void'.

     If an rvalue is provided, the block is terminated by evaluating the
     rvalue and returning the value.

     This is roughly equivalent to this C code:

         return expression;

     If an rvalue is not provided, the block is terminated by adding a
     valueless return, for use within a function with "void" return
     type.

     This is equivalent to this C code:

         return;



 -- C++ Function: void gccjit::block::end_with_switch (gccjit::rvalue
          expr, gccjit::block default_block, std::vector<gccjit::case_>
          cases, gccjit::location loc)
     Terminate a block by adding evalation of an rvalue, then performing
     a multiway branch.

     This is roughly equivalent to this C code:

         switch (expr)
           {
           default:
             goto default_block;

           case C0.min_value ... C0.max_value:
             goto C0.dest_block;

           case C1.min_value ... C1.max_value:
             goto C1.dest_block;

           ...etc...

           case C[N - 1].min_value ... C[N - 1].max_value:
             goto C[N - 1].dest_block;
         }

     `expr' must be of the same integer type as all of the `min_value'
     and `max_value' within the cases.

     The ranges of the cases must not overlap (or have duplicate
     values).

     The API entrypoints relating to switch statements and cases:

             * *note gccjit;;block;;end_with_switch(): 1cf.

             * *note gccjit;;context;;new_case(): 1d0.

     were added in *note LIBGCCJIT_ABI_3: e9.; you can test for their
     presence using

         #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS

     
      -- C++ Class: gccjit::case_

     A `gccjit::case_' represents a case within a switch statement, and
     is created within a particular *note gccjit;;context: 14b. using
     *note gccjit;;context;;new_case(): 1d0.  It is a subclass of *note
     gccjit;;object: 160.

     Each case expresses a multivalued range of integer values.  You
     can express single-valued cases by passing in the same value for
     both `min_value' and `max_value'.

      -- C++ Function: gccjit::case_* gccjit::context::new_case
               (gccjit::rvalue min_value, gccjit::rvalue max_value,
               gccjit::block dest_block)
          Create a new gccjit::case for use in a switch statement.
          `min_value' and `max_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 switch
          statement.

     Here's an example of creating a switch statement:


              void
              create_code (gcc_jit_context *c_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;
              	  }
                    }
                 */
                gccjit::context ctxt (c_ctxt);
                gccjit::type t_int = ctxt.get_type (GCC_JIT_TYPE_INT);
                gccjit::type return_type = t_int;
                gccjit::param x = ctxt.new_param (t_int, "x");
                std::vector <gccjit::param> params;
                params.push_back (x);
                gccjit::function func = ctxt.new_function (GCC_JIT_FUNCTION_EXPORTED,
                                                           return_type,
                                                           "test_switch",
                                                           params, 0);

                gccjit::block b_initial = func.new_block ("initial");

                gccjit::block b_default = func.new_block ("default");
                gccjit::block b_case_0_5 = func.new_block ("case_0_5");
                gccjit::block b_case_25_27 = func.new_block ("case_25_27");
                gccjit::block b_case_m42_m17 = func.new_block ("case_m42_m17");
                gccjit::block b_case_40 = func.new_block ("case_40");

                std::vector <gccjit::case_> cases;
                cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 0),
                                                ctxt.new_rvalue (t_int, 5),
                                                b_case_0_5));
                cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 25),
                                                ctxt.new_rvalue (t_int, 27),
                                                b_case_25_27));
                cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, -42),
                                                ctxt.new_rvalue (t_int, -17),
                                                b_case_m42_m17));
                cases.push_back (ctxt.new_case (ctxt.new_rvalue (t_int, 40),
                                                ctxt.new_rvalue (t_int, 40),
                                                b_case_40));
                b_initial.end_with_switch (x,
                                           b_default,
                                           cases);

                b_case_0_5.end_with_return (ctxt.new_rvalue (t_int, 3));
                b_case_25_27.end_with_return (ctxt.new_rvalue (t_int, 4));
                b_case_m42_m17.end_with_return (ctxt.new_rvalue (t_int, 83));
                b_case_40.end_with_return (ctxt.new_rvalue (t_int, 8));
                b_default.end_with_return (ctxt.new_rvalue (t_int, 10));
              }




File: libgccjit.info,  Node: Source Locations<2>,  Next: Compiling a context<2>,  Prev: Creating and using functions<2>,  Up: Topic Reference<2>

3.2.6 Source Locations
----------------------

 -- C++ Class: gccjit::location
     A `gccjit::location' encapsulates a source code location, so that
     you can (optionally) associate locations in your language with
     statements in the JIT-compiled code, allowing the debugger to
     single-step through your language.

     `gccjit::location' instances are optional: you can always omit them
     from any C++ API entrypoint accepting one.

     You can construct them using *note
     gccjit;;context;;new_location(): 141.

     You need to enable *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the
     *note gccjit;;context: 14b. for these locations to actually be
     usable by the debugger:

         ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);



 -- C++ Function: gccjit::location gccjit::context::new_location (const
          char* filename, int line, int column)
     Create a `gccjit::location' instance representing the given source
     location.

* Menu:

* Faking it: Faking it<2>.


File: libgccjit.info,  Node: Faking it<2>,  Up: Source Locations<2>

3.2.6.1 Faking it
.................

If you don't have source code for your internal representation, but need
to debug, you can generate a C-like representation of the functions in
your context using *note gccjit;;context;;dump_to_file(): 152.:

    ctxt.dump_to_file ("/tmp/something.c",
                       1 /* update_locations */);

This will dump C-like code to the given path.  If the `update_locations'
argument is true, this will also set up `gccjit::location' information
throughout the context, pointing at the dump file as if it were a source
file, giving you _something_ you can step through in the debugger.


File: libgccjit.info,  Node: Compiling a context<2>,  Prev: Source Locations<2>,  Up: Topic Reference<2>

3.2.7 Compiling a context
-------------------------

Once populated, a *note gccjit;;context: 14b. can be compiled to
machine code, either in-memory via *note gccjit;;context;;compile():
124. or to disk via *note gccjit;;context;;compile_to_file(): 1d7.

  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.

* Menu:

* In-memory compilation: In-memory compilation<2>.
* Ahead-of-time compilation: Ahead-of-time compilation<2>.


File: libgccjit.info,  Node: In-memory compilation<2>,  Next: Ahead-of-time compilation<2>,  Up: Compiling a context<2>

3.2.7.1 In-memory compilation
.............................

 -- C++ Function: gcc_jit_result* gccjit::context::compile ()
     This calls into GCC and builds the code, returning a
     `gcc_jit_result *'.

     This is a thin wrapper around the *note gcc_jit_context_compile():
     15. API entrypoint.


File: libgccjit.info,  Node: Ahead-of-time compilation<2>,  Prev: In-memory compilation<2>,  Up: Compiling a context<2>

3.2.7.2 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 *note gccjit;;context;;compile_to_file(): 1d7.
method.

 -- C++ Function: void gccjit::context::compile_to_file (enum
          gcc_jit_output_kind, const char* output_path)
     Compile the *note gccjit;;context: 14b. to a file of the given
     kind.

     This is a thin wrapper around the *note
     gcc_jit_context_compile_to_file(): 4a. API entrypoint.


File: libgccjit.info,  Node: Internals,  Next: Indices and tables,  Prev: C++ bindings for libgccjit,  Up: Top

4 Internals
***********

* Menu:

* Working on the JIT library::
* Running the test suite::
* Environment variables::
* Packaging notes::
* Overview of code structure::
* Design notes::
* Submitting patches::


File: libgccjit.info,  Node: Working on the JIT library,  Next: Running the test suite,  Up: Internals

4.1 Working on the JIT library
==============================

Having checked out the source code (to "src"), you can configure and
build the JIT library like this:

    mkdir build
    mkdir install
    PREFIX=$(pwd)/install
    cd build
    ../src/configure \
       --enable-host-shared \
       --enable-languages=jit,c++ \
       --disable-bootstrap \
       --enable-checking=release \
       --prefix=$PREFIX
    nice make -j4 # altering the "4" to however many cores you have

This should build a libgccjit.so within jit/build/gcc:

    [build] $ file gcc/libgccjit.so*
    gcc/libgccjit.so:       symbolic link to `libgccjit.so.0'
    gcc/libgccjit.so.0:     symbolic link to `libgccjit.so.0.0.1'
    gcc/libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped

Here's what those configuration options mean:

 -- Option: -enable-host-shared
     Configuring with this option means that the compiler is built as
     position-independent code, which incurs a slight performance hit,
     but it necessary for a shared library.

 -- Option: -enable-languages=jit,c++
     This specifies which frontends to build.  The JIT library looks
     like a frontend to the rest of the code.

     The C++ portion of the JIT test suite requires the C++ frontend to
     be enabled at configure-time, or you may see errors like this when
     running the test suite:

         xgcc: error: /home/david/jit/src/gcc/testsuite/jit.dg/test-quadratic.cc: C++ compiler not installed on this system
         c++: error trying to exec 'cc1plus': execvp: No such file or directory



 -- Option: -disable-bootstrap
     For hacking on the "jit" subdirectory, performing a full bootstrap
     can be overkill, since it's unused by a bootstrap.  However, when
     submitting patches, you should remove this option, to ensure that
     the compiler can still bootstrap itself.

 -- Option: -enable-checking=release
     The compile can perform extensive self-checking as it runs, useful
     when debugging, but slowing things down.

     For maximum speed, configure with `--enable-checking=release' to
     disable this self-checking.


File: libgccjit.info,  Node: Running the test suite,  Next: Environment variables,  Prev: Working on the JIT library,  Up: Internals

4.2 Running the test suite
==========================

    [build] $ cd gcc
    [gcc] $ make check-jit RUNTESTFLAGS="-v -v -v"

A summary of the tests can then be seen in:

    jit/build/gcc/testsuite/jit/jit.sum

and detailed logs in:

    jit/build/gcc/testsuite/jit/jit.log

The test executables are normally deleted after each test is run.  For
debugging, they can be preserved by setting `PRESERVE_EXECUTABLES' in
the environment.  If so, they can then be seen as:

    jit/build/gcc/testsuite/jit/*.exe

which can be run independently.

  You can compile and run individual tests by passing
"jit.exp=TESTNAME" to RUNTESTFLAGS e.g.:

    [gcc] $ PRESERVE_EXECUTABLES= \
              make check-jit \
                RUNTESTFLAGS="-v -v -v jit.exp=test-factorial.c"

and once a test has been compiled, you can debug it directly:

    [gcc] $ PATH=.:$PATH \
            LD_LIBRARY_PATH=. \
            LIBRARY_PATH=. \
              gdb --args \
                testsuite/jit/test-factorial.c.exe


* Menu:

* Running under valgrind::


File: libgccjit.info,  Node: Running under valgrind,  Up: Running the test suite

4.2.1 Running under valgrind
----------------------------

The jit testsuite detects if `RUN_UNDER_VALGRIND' is present in the
environment (with any value).  If it is present, it runs the test client
code under valgrind(1), specifcally, the default memcheck(2) tool with
-leak-check=full(3).

  It automatically parses the output from valgrind, injecting XFAIL
results if any issues are found, or PASS results if the output is
clean.  The output is saved to `TESTNAME.exe.valgrind.txt'.

  For example, the following invocation verbosely runs the testcase
`test-sum-of-squares.c' under valgrind, showing an issue:

    $ RUN_UNDER_VALGRIND= \
        make check-jit \
          RUNTESTFLAGS="-v -v -v jit.exp=test-sum-of-squares.c"

    (...verbose log contains detailed valgrind errors, if any...)

                    === jit Summary ===

    # of expected passes            28
    # of expected failures          2

    $ less testsuite/jit/jit.sum
    (...other results...)
    XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: definitely lost: 8 bytes in 1 blocks
    XFAIL: jit.dg/test-sum-of-squares.c: test-sum-of-squares.c.exe.valgrind.txt: unsuppressed errors: 1
    (...other results...)

    $ less testsuite/jit/test-sum-of-squares.c.exe.valgrind.txt
    (...shows full valgrind report for this test case...)

When running under valgrind, it's best to have configured gcc with
`--enable-valgrind-annotations', which automatically suppresses various
known false positives.

  ---------- Footnotes ----------

  (1) http://valgrind.org

  (2) http://valgrind.org/docs/manual/mc-manual.html

  (3) http://valgrind.org/docs/manual/mc-manual.html#opt.leak-check


File: libgccjit.info,  Node: Environment variables,  Next: Packaging notes,  Prev: Running the test suite,  Up: Internals

4.3 Environment variables
=========================

When running client code against a locally-built libgccjit, three
environment variables need to be set up:

 -- Environment Variable: LD_LIBRARY_PATH
          `libgccjit.so' is dynamically linked into client code, so if
          running against a locally-built library, `LD_LIBRARY_PATH'
          needs to be set up appropriately.  The library can be found
          within the "gcc" subdirectory of the build tree:

         $ file libgccjit.so*
         libgccjit.so:       symbolic link to `libgccjit.so.0'
         libgccjit.so.0:     symbolic link to `libgccjit.so.0.0.1'
         libgccjit.so.0.0.1: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, not stripped



 -- Environment Variable: PATH
     The library uses a driver executable for converting from .s
     assembler files to .so shared libraries.  Specifically, it looks
     for a name expanded from
     `${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}' such as
     `x86_64-unknown-linux-gnu-gcc-5.0.0'.

     Hence `PATH' needs to include a directory where the library can
     locate this executable.

     The executable is normally installed to the installation bindir
     (e.g. /usr/bin), but a copy is also created within the "gcc"
     subdirectory of the build tree for running the testsuite, and for
     ease of development.

 -- Environment Variable: LIBRARY_PATH
     The driver executable invokes the linker, and the latter needs to
     locate support libraries needed by the generated code, or you will
     see errors like:

         ld: cannot find crtbeginS.o: No such file or directory
         ld: cannot find -lgcc
         ld: cannot find -lgcc_s

     Hence if running directly from a locally-built copy (without
     installing), `LIBRARY_PATH' needs to contain the "gcc"
     subdirectory of the build tree.

  For example, to run a binary that uses the library against a
non-installed build of the library in LIBGCCJIT_BUILD_DIR you need an
invocation of the client code like this, to preprend the dir to each of
the environment variables:

    $ LD_LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LD_LIBRARY_PATH) \
      PATH=$(LIBGCCJIT_BUILD_DIR):$(PATH) \
      LIBRARY_PATH=$(LIBGCCJIT_BUILD_DIR):$(LIBRARY_PATH) \
        ./jit-hello-world
    hello world



File: libgccjit.info,  Node: Packaging notes,  Next: Overview of code structure,  Prev: Environment variables,  Up: Internals

4.4 Packaging notes
===================

The configure-time option *note -enable-host-shared: 1dd. is needed when
building the jit in order to get position-independent code.  This will
slow down the regular compiler by a few percent.  Hence when packaging
gcc with libgccjit, please configure and build twice:

        * once without *note -enable-host-shared: 1dd. for most
          languages, and

        * once with *note -enable-host-shared: 1dd. for the jit

  For example:

    # Configure and build with --enable-host-shared
    # for the jit:
    mkdir configuration-for-jit
    pushd configuration-for-jit
    $(SRCDIR)/configure \
      --enable-host-shared \
      --enable-languages=jit \
      --prefix=$(DESTDIR)
    make
    popd

    # Configure and build *without* --enable-host-shared
    # for maximum speed:
    mkdir standard-configuration
    pushd standard-configuration
    $(SRCDIR)/configure \
      --enable-languages=all \
      --prefix=$(DESTDIR)
    make
    popd

    # Both of the above are configured to install to $(DESTDIR)
    # Install the configuration with --enable-host-shared first
    # *then* the one without, so that the faster build
    # of "cc1" et al overwrites the slower build.
    pushd configuration-for-jit
    make install
    popd

    pushd standard-configuration
    make install
    popd



File: libgccjit.info,  Node: Overview of code structure,  Next: Design notes,  Prev: Packaging notes,  Up: Internals

4.5 Overview of code structure
==============================

The library is implemented in C++.  The source files have the `.c'
extension for legacy reasons.

   * `libgccjit.c' implements the API entrypoints.  It performs error
     checking, then calls into classes of the gcc::jit::recording
     namespace within `jit-recording.c' and `jit-recording.h'.

   * The gcc::jit::recording classes (within `jit-recording.c' and
     `jit-recording.h') record the API calls that are made:


                /* Indentation indicates inheritance: */
                class context;
                class memento;
                  class string;
                  class location;
                  class type;
                    class function_type;
                    class compound_type;
                      class struct_;
              	class union_;
                    class vector_type;
                  class field;
                  class fields;
                  class function;
                  class block;
                  class rvalue;
                    class lvalue;
                      class local;
              	class global;
                      class param;
                    class base_call;
                    class function_pointer;
                  class statement;
                  class case_;



   * When the context is compiled, the gcc::jit::playback classes
     (within `jit-playback.c' and `jit-playback.h') replay the API calls
     within langhook:parse_file:


                /* Indentation indicates inheritance: */
                class context;
                class wrapper;
                  class type;
                    class compound_type;
                  class field;
                  class function;
                  class block;
                  class rvalue;
                    class lvalue;
                      class param;
                  class source_file;
                  class source_line;
                  class location;
                  class case_;


              Client Code   . Generated .            libgccjit.so
                            . code      .
                            .           . JIT API  . JIT "Frontend". (libbackend.a)
              ....................................................................................
                 │          .           .          .               .
                  ──────────────────────────>      .               .
                            .           .    │     .               .
                            .           .    V     .               .
                            .           .    ──> libgccjit.c       .
                            .           .        │ (error-checking).
                            .           .        │                 .
                            .           .        ──> jit-recording.c
                            .           .              (record API calls)
                            .           .    <───────              .
                            .           .    │     .               .
                 <───────────────────────────      .               .
                 │          .           .          .               .
                 │          .           .          .               .
                 V          .           .  gcc_jit_context_compile .
                  ──────────────────────────>      .               .
                            .           .    │ start of recording::context::compile ()
                            .           .    │     .               .
                            .           .    │ start of playback::context::compile ()
                            .           .    │   (create tempdir)  .
                            .           .    │     .               .
                            .           .    │ ACQUIRE MUTEX       .
                            .           .    │     .               .
                            .           .    V───────────────────────> toplev::main (for now)
                            .           .          .               .       │
                            .           .          .               .   (various code)
                            .           .          .               .       │
                            .           .          .               .       V
                            .           .          .    <───────────────── langhook:parse_file
                            .           .          .    │          .
                            .           .          .    │ (jit_langhook_parse_file)
                            .           .          .    │          .
              ..........................................│..................VVVVVVVVVVVVV...
                            .           .          .    │          .       No GC in here
                            .           .          .    │ jit-playback.c
                            .           .          .    │   (playback of API calls)
                            .           .          .    ───────────────> creation of functions,
                            .           .          .               .     types, expression trees
                            .           .          .    <──────────────── etc
                            .           .          .    │(handle_locations: add locations to
                            .           .          .    │ linemap and associate them with trees)
                            .           .          .    │          .
                            .           .          .    │          .       No GC in here
              ..........................................│..................AAAAAAAAAAAAA...
                            .           .          .    │ for each function
                            .           .          .    ──> postprocess
                            .           .          .        │      .
                            .           .          .        ────────────> cgraph_finalize_function
                            .           .          .        <────────────
                            .           .          .     <──       .
                            .           .          .    │          .
                            .           .          .    ──────────────────> (end of
                            .           .          .               .       │ langhook_parse_file)
                            .           .          .               .       │
                            .           .          .               .   (various code)
                            .           .          .               .       │
                            .           .          .               .       ↓
                            .           .          .    <───────────────── langhook:write_globals
                            .           .          .    │          .
                            .           .          .    │ (jit_langhook_write_globals)
                            .           .          .    │          .
                            .           .          .    │          .
                            .           .          .    ──────────────────> finalize_compilation_unit
                            .           .          .               .       │
                            .           .          .               .   (the middle─end and backend)
                            .           .          .               .       ↓
                            .           .    <───────────────────────────── end of toplev::main
                            .           .    │     .               .
                            .           .    V───────────────────────> toplev::finalize
                            .           .          .               . │   (purge internal state)
                            .           .    <──────────────────────── end of toplev::finalize
                            .           .    │     .               .
                            .           .    V─> playback::context::postprocess:
                            .           .      │   .               .
                            .           .      │   (assuming an in-memory compile):
                            .           .      │   .               .
                            .           .      --> Convert assembler to DSO, via embedded
                            .           .          copy of driver:
                            .           .           driver::main ()
                            .           .             invocation of "as"
                            .           .             invocation of "ld"
                            .           .           driver::finalize ()
                            .           .      <----
                            .           .      │   .               .
                            .           .      │   . Load DSO (dlopen "fake.so")
                            .           .      │   .               .
                            .           .      │   . Bundle it up in a jit::result
                            .           .    <──   .               .
                            .           .    │     .               .
                            .           .    │ RELEASE MUTEX       .
                            .           .    │     .               .
                            .           .    │ end of playback::context::compile ()
                            .           .    │     .               .
                            .           .    │ playback::context dtor
                            .           .     ──>  .               .
                            .           .       │ Normally we cleanup the tempdir here:
                            .           .       │   ("fake.so" is unlinked from the
                            .           .       │    filesystem at this point)
                            .           .       │ If the client code requested debuginfo, the
                            .           .       │ cleanup happens later (in gcc_jit_result_release)
                            .           .       │ to make it easier on the debugger (see PR jit/64206)
                            .           .    <──   .               .
                            .           .    │     .               .
                            .           .    │ end of recording::context::compile ()
                 <───────────────────────────      .               .
                 │          .           .          .               .
                 V          .           .  gcc_jit_result_get_code .
                  ──────────────────────────>      .               .
                            .           .    │ dlsym () within loaded DSO
                 <───────────────────────────      .               .
                 Get (void*).           .          .               .
                 │          .           .          .               .
                 │ Call it  .           .          .               .
                 ───────────────>       .          .               .
                            .    │      .          .               .
                            .    │      .          .               .
                 <───────────────       .          .               .
                 │          .           .          .               .
              etc│          .           .          .               .
                 │          .           .          .               .
                 V          .           .  gcc_jit_result_release  .
                  ──────────────────────────>      .               .
                            .           .    │ dlclose () the loaded DSO
                            .           .    │    (code becomes uncallable)
                            .           .    │     .               .
                            .           .    │ If the client code requested debuginfo, then
                            .           .    │ cleanup of the tempdir was delayed.
                            .           .    │ If that was the case, clean it up now.
                 <───────────────────────────      .               .
                 │          .           .          .               .



  Here is a high-level summary from `jit-common.h':

     In order to allow jit objects to be usable outside of a compile
     whilst working with the existing structure of GCC's code the C API
     is implemented in terms of a gcc::jit::recording::context, which
     records the calls made to it.

     When a gcc_jit_context is compiled, the recording context creates a
     playback context.  The playback context invokes the bulk of the GCC
     code, and within the "frontend" parsing hook, plays back the
     recorded API calls, creating GCC tree objects.

     So there are two parallel families of classes: those relating to
     recording, and those relating to playback:

        * Visibility: recording objects are exposed back to client code,
          whereas playback objects are internal to the library.

        * Lifetime: recording objects have a lifetime equal to that of
          the recording context that created them, whereas playback
          objects only exist within the frontend hook.

        * Memory allocation: recording objects are allocated by the
          recording context, and automatically freed by it when the
          context is released, whereas playback objects are allocated
          within the GC heap, and garbage-collected; they can own
          GC-references.

        * Integration with rest of GCC: recording objects are unrelated
          to the rest of GCC, whereas playback objects are wrappers
          around "tree" instances.  Hence you can't ask a recording
          rvalue or lvalue what its type is, whereas you can for a
          playback rvalue of lvalue (since it can work with the
          underlying GCC tree nodes).

        * Instancing: There can be multiple recording contexts "alive"
          at once (albeit it only one compiling at once), whereas there
          can only be one playback context alive at one time (since it
          interacts with the GC).

     Ultimately if GCC could support multiple GC heaps and contexts, and
     finer-grained initialization, then this recording vs playback
     distinction could be eliminated.

     During a playback, we associate objects from the recording with
     their counterparts during this playback.  For simplicity, we store
     this within the recording objects, as `void *m_playback_obj',
     casting it to the appropriate playback object subclass.  For these
     casts to make sense, the two class hierarchies need to have the
     same structure.

     Note that the playback objects that `m_playback_obj' points to are
     GC-allocated, but the recording objects don't own references:
     these associations only exist within a part of the code where the
     GC doesn't collect, and are set back to NULL before the GC can run.

  Another way to understand the structure of the code is to enable
logging, via *note gcc_jit_context_set_logfile(): 5b.  Here is an
example of a log generated via this call:

    JIT: libgccjit (GCC) version 6.0.0 20150803 (experimental) (x86_64-pc-linux-gnu)
    JIT:	compiled by GNU C version 4.8.3 20140911 (Red Hat 4.8.3-7), GMP version 5.1.2, MPFR version 3.1.2, MPC version 1.0.1
    JIT: entering: gcc_jit_context_set_str_option
    JIT:  GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe"
    JIT: exiting: gcc_jit_context_set_str_option
    JIT: entering: gcc_jit_context_set_int_option
    JIT:  GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3
    JIT: exiting: gcc_jit_context_set_int_option
    JIT: entering: gcc_jit_context_set_bool_option
    JIT:  GCC_JIT_BOOL_OPTION_DEBUGINFO: true
    JIT: exiting: gcc_jit_context_set_bool_option
    JIT: entering: gcc_jit_context_set_bool_option
    JIT:  GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false
    JIT: exiting: gcc_jit_context_set_bool_option
    JIT: entering: gcc_jit_context_set_bool_option
    JIT:  GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false
    JIT: exiting: gcc_jit_context_set_bool_option
    JIT: entering: gcc_jit_context_set_bool_option
    JIT:  GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true
    JIT: exiting: gcc_jit_context_set_bool_option
    JIT: entering: gcc_jit_context_set_bool_option
    JIT:  GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false
    JIT: exiting: gcc_jit_context_set_bool_option
    JIT: entering: gcc_jit_context_get_type
    JIT: exiting: gcc_jit_context_get_type
    JIT: entering: gcc_jit_context_get_type
    JIT: exiting: gcc_jit_context_get_type
    JIT: entering: gcc_jit_context_new_param
    JIT: exiting: gcc_jit_context_new_param
    JIT: entering: gcc_jit_context_new_function
    JIT: exiting: gcc_jit_context_new_function
    JIT: entering: gcc_jit_context_new_param
    JIT: exiting: gcc_jit_context_new_param
    JIT: entering: gcc_jit_context_get_type
    JIT: exiting: gcc_jit_context_get_type
    JIT: entering: gcc_jit_context_new_function
    JIT: exiting: gcc_jit_context_new_function
    JIT: entering: gcc_jit_context_new_string_literal
    JIT: exiting: gcc_jit_context_new_string_literal
    JIT: entering: gcc_jit_function_new_block
    JIT: exiting: gcc_jit_function_new_block
    JIT: entering: gcc_jit_block_add_comment
    JIT: exiting: gcc_jit_block_add_comment
    JIT: entering: gcc_jit_context_new_call
    JIT: exiting: gcc_jit_context_new_call
    JIT: entering: gcc_jit_block_add_eval
    JIT: exiting: gcc_jit_block_add_eval
    JIT: entering: gcc_jit_block_end_with_void_return
    JIT: exiting: gcc_jit_block_end_with_void_return
    JIT: entering: gcc_jit_context_dump_reproducer_to_file
    JIT:  entering: void gcc::jit::recording::context::dump_reproducer_to_file(const char*)
    JIT:  exiting: void gcc::jit::recording::context::dump_reproducer_to_file(const char*)
    JIT: exiting: gcc_jit_context_dump_reproducer_to_file
    JIT: entering: gcc_jit_context_compile
    JIT:  in-memory compile of ctxt: 0x1283e20
    JIT:  entering: gcc::jit::result* gcc::jit::recording::context::compile()
    JIT:   GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe"
    JIT:   GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL: 3
    JIT:   GCC_JIT_BOOL_OPTION_DEBUGINFO: true
    JIT:   GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE: false
    JIT:   GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE: false
    JIT:   GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE: false
    JIT:   GCC_JIT_BOOL_OPTION_DUMP_SUMMARY: false
    JIT:   GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING: false
    JIT:   GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true
    JIT:   GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: false
    JIT:   gcc_jit_context_set_bool_allow_unreachable_blocks: false
    JIT:   gcc_jit_context_set_bool_use_external_driver: false
    JIT:   entering: void gcc::jit::recording::context::validate()
    JIT:   exiting: void gcc::jit::recording::context::validate()
    JIT:   entering: gcc::jit::playback::context::context(gcc::jit::recording::context*)
    JIT:   exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*)
    JIT:   entering: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*)
    JIT:   exiting: gcc::jit::playback::compile_to_memory::compile_to_memory(gcc::jit::recording::context*)
    JIT:   entering: void gcc::jit::playback::context::compile()
    JIT:    entering: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
    JIT:    exiting: gcc::jit::tempdir::tempdir(gcc::jit::logger*, int)
    JIT:    entering: bool gcc::jit::tempdir::create()
    JIT:     m_path_template: /tmp/libgccjit-XXXXXX
    JIT:     m_path_tempdir: /tmp/libgccjit-CKq1M9
    JIT:    exiting: bool gcc::jit::tempdir::create()
    JIT:    entering: void gcc::jit::playback::context::acquire_mutex()
    JIT:    exiting: void gcc::jit::playback::context::acquire_mutex()
    JIT:    entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
    JIT:     reusing cached configure-time options
    JIT:     configure_time_options[0]: -mtune=generic
    JIT:     configure_time_options[1]: -march=x86-64
    JIT:    exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
    JIT:    entering: toplev::main
    JIT:     argv[0]: ./test-hello-world.c.exe
    JIT:     argv[1]: /tmp/libgccjit-CKq1M9/fake.c
    JIT:     argv[2]: -fPIC
    JIT:     argv[3]: -O3
    JIT:     argv[4]: -g
    JIT:     argv[5]: -quiet
    JIT:     argv[6]: --param
    JIT:     argv[7]: ggc-min-expand=0
    JIT:     argv[8]: --param
    JIT:     argv[9]: ggc-min-heapsize=0
    JIT:     argv[10]: -mtune=generic
    JIT:     argv[11]: -march=x86-64
    JIT:     entering: bool jit_langhook_init()
    JIT:     exiting: bool jit_langhook_init()
    JIT:     entering: void gcc::jit::playback::context::replay()
    JIT:      entering: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*)
    JIT:      exiting: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*)
    JIT:      entering: void gcc::jit::recording::context::disassociate_from_playback()
    JIT:      exiting: void gcc::jit::recording::context::disassociate_from_playback()
    JIT:      entering: void gcc::jit::playback::context::handle_locations()
    JIT:      exiting: void gcc::jit::playback::context::handle_locations()
    JIT:      entering: void gcc::jit::playback::function::build_stmt_list()
    JIT:      exiting: void gcc::jit::playback::function::build_stmt_list()
    JIT:      entering: void gcc::jit::playback::function::build_stmt_list()
    JIT:      exiting: void gcc::jit::playback::function::build_stmt_list()
    JIT:      entering: void gcc::jit::playback::function::postprocess()
    JIT:      exiting: void gcc::jit::playback::function::postprocess()
    JIT:      entering: void gcc::jit::playback::function::postprocess()
    JIT:      exiting: void gcc::jit::playback::function::postprocess()
    JIT:     exiting: void gcc::jit::playback::context::replay()
    JIT:    exiting: toplev::main
    JIT:    entering: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*)
    JIT:    exiting: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*)
    JIT:    entering: toplev::finalize
    JIT:    exiting: toplev::finalize
    JIT:    entering: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*)
    JIT:     entering: void gcc::jit::playback::context::convert_to_dso(const char*)
    JIT:      entering: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool)
    JIT:       entering: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*)
    JIT:       exiting: void gcc::jit::playback::context::add_multilib_driver_arguments(vec<char*>*)
    JIT:       argv[0]: x86_64-unknown-linux-gnu-gcc-6.0.0
    JIT:       argv[1]: -m64
    JIT:       argv[2]: -shared
    JIT:       argv[3]: /tmp/libgccjit-CKq1M9/fake.s
    JIT:       argv[4]: -o
    JIT:       argv[5]: /tmp/libgccjit-CKq1M9/fake.so
    JIT:       argv[6]: -fno-use-linker-plugin
    JIT:       entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*)
    JIT:       exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*)
    JIT:      exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool)
    JIT:     exiting: void gcc::jit::playback::context::convert_to_dso(const char*)
    JIT:     entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
    JIT:      GCC_JIT_BOOL_OPTION_DEBUGINFO was set: handing over tempdir to jit::result
    JIT:      entering: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
    JIT:      exiting: gcc::jit::result::result(gcc::jit::logger*, void*, gcc::jit::tempdir*)
    JIT:     exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
    JIT:    exiting: virtual void gcc::jit::playback::compile_to_memory::postprocess(const char*)
    JIT:    entering: void gcc::jit::playback::context::release_mutex()
    JIT:    exiting: void gcc::jit::playback::context::release_mutex()
    JIT:   exiting: void gcc::jit::playback::context::compile()
    JIT:   entering: gcc::jit::playback::context::~context()
    JIT:   exiting: gcc::jit::playback::context::~context()
    JIT:  exiting: gcc::jit::result* gcc::jit::recording::context::compile()
    JIT:  gcc_jit_context_compile: returning (gcc_jit_result *)0x12f75d0
    JIT: exiting: gcc_jit_context_compile
    JIT: entering: gcc_jit_result_get_code
    JIT:  locating fnname: hello_world
    JIT:  entering: void* gcc::jit::result::get_code(const char*)
    JIT:  exiting: void* gcc::jit::result::get_code(const char*)
    JIT:  gcc_jit_result_get_code: returning (void *)0x7ff6b8cd87f0
    JIT: exiting: gcc_jit_result_get_code
    JIT: entering: gcc_jit_context_release
    JIT:  deleting ctxt: 0x1283e20
    JIT:  entering: gcc::jit::recording::context::~context()
    JIT:  exiting: gcc::jit::recording::context::~context()
    JIT: exiting: gcc_jit_context_release
    JIT: entering: gcc_jit_result_release
    JIT:  deleting result: 0x12f75d0
    JIT:  entering: virtual gcc::jit::result::~result()
    JIT:   entering: gcc::jit::tempdir::~tempdir()
    JIT:    unlinking .s file: /tmp/libgccjit-CKq1M9/fake.s
    JIT:    unlinking .so file: /tmp/libgccjit-CKq1M9/fake.so
    JIT:    removing tempdir: /tmp/libgccjit-CKq1M9
    JIT:   exiting: gcc::jit::tempdir::~tempdir()
    JIT:  exiting: virtual gcc::jit::result::~result()
    JIT: exiting: gcc_jit_result_release
    JIT: gcc::jit::logger::~logger()



File: libgccjit.info,  Node: Design notes,  Next: Submitting patches,  Prev: Overview of code structure,  Up: Internals

4.6 Design notes
================

It should not be possible for client code to cause an internal compiler
error.  If this _does_ happen, the root cause should be isolated
(perhaps using *note gcc_jit_context_dump_reproducer_to_file(): 5d.)
and the cause should be rejected via additional checking.  The checking
ideally should be within the libgccjit API entrypoints in libgccjit.c,
since this is as close as possible to the error; failing that, a good
place is within `recording::context::validate ()' in jit-recording.c.


File: libgccjit.info,  Node: Submitting patches,  Prev: Design notes,  Up: Internals

4.7 Submitting patches
======================

Please read the contribution guidelines for gcc at
<https://gcc.gnu.org/contribute.html>.

  Patches for the jit should be sent to both the
<gcc-patches@gcc.gnu.org> and <jit@gcc.gnu.org> mailing lists, with
"jit" and "PATCH" in the Subject line.

  You don't need to do a full bootstrap for code that just touches the
`jit' and `testsuite/jit.dg' subdirectories.  However, please run `make
check-jit' before submitting the patch, and mention the results in your
email (along with the host triple that the tests were run on).

  A good patch should contain the information listed in the gcc
contribution guide linked to above; for a `jit' patch, the patch shold
contain:

        * the code itself (for example, a new API entrypoint will
          typically touch `libgccjit.h' and `.c', along with support
          code in `jit-recording.[ch]' and `jit-playback.[ch]' as
          appropriate)

        * test coverage

        * documentation for the C API

        * documentation for the C++ API

  A patch that adds new API entrypoints should also contain:

        * a feature macro in `libgccjit.h' so that client code that
          doesn't use a "configure" mechanism can still easily detect
          the presence of the entrypoint.  See e.g.
          `LIBGCCJIT_HAVE_SWITCH_STATEMENTS' (for a category of
          entrypoints) and
          `LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks'
          (for an individual entrypoint).

        * a new ABI tag containing the new symbols (in
          `libgccjit.map'), so that we can detect client code that uses
          them

        * Support for *note gcc_jit_context_dump_reproducer_to_file():
          5d.  Most jit testcases attempt to dump their contexts to a
          .c file; `jit.exp' then sanity-checks the generated c by
          compiling them (though not running them).   A new API
          entrypoint needs to "know" how to write itself back out to C
          (by implementing
          `gcc::jit::recording::memento::write_reproducer' for the
          appropriate `memento' subclass).

        * C++ bindings for the new entrypoints (see `libgccjit++.h');
          ideally with test coverage, though the C++ API test coverage
          is admittedly spotty at the moment

        * documentation for the new C entrypoints

        * documentation for the new C++ entrypoints

        * documentation for the new ABI tag (see
          `topics/compatibility.rst').

  Depending on the patch you can either extend an existing test case, or
add a new test case.  If you add an entirely new testcase: `jit.exp'
expects jit testcases to begin with `test-', or `test-error-' (for a
testcase that generates an error on a *note gcc_jit_context: 8.).

  Every new testcase that doesn't generate errors should also touch
`gcc/testsuite/jit.dg/all-non-failing-tests.h':

        * Testcases that don't generate errors should ideally be added
          to the `testcases' array in that file; this means that, in
          addition to being run standalone, they also get run within
          `test-combination.c' (which runs all successful tests inside
          one big *note gcc_jit_context: 8.), and `test-threads.c'
          (which runs all successful tests in one process, each one
          running in a different thread on a different *note
          gcc_jit_context: 8.).

               Note: Given that exported functions within a *note
               gcc_jit_context: 8.  must have unique names, and most
               testcases are run within `test-combination.c', this
               means that every jit-compiled test function typically
               needs a name that's unique across the entire test suite.

        * Testcases that aren't to be added to the `testcases' array
          should instead add a comment to the file clarifying why
          they're not in that array. See the file for examples.

  Typically a patch that touches the .rst documentation will also need
the texinfo to be regenerated.  You can do this with Sphinx 1.0(1) or
later by running `make texinfo' within `SRCDIR/gcc/jit/docs'.   Don't
do this within the patch sent to the mailing list; it can often be
relatively large and inconsequential (e.g. anchor renumbering), rather
like generated "configure" changes from configure.ac.  You can
regenerate it when committing to svn.

  ---------- Footnotes ----------

  (1) http://sphinx-doc.org/


File: libgccjit.info,  Node: Indices and tables,  Next: Index,  Prev: Internals,  Up: Top

Indices and tables
******************

   * _genindex_

   * _modindex_

   * _search_


File: libgccjit.info,  Node: Index,  Prev: Indices and tables,  Up: Top

Index
*****

[index]
* Menu:

* command line option; -disable-bootstrap: Working on the JIT library.
                                                              (line  48)
* command line option; -enable-checking=release: Working on the JIT library.
                                                              (line  54)
* command line option; -enable-host-shared: Working on the JIT library.
                                                              (line  30)
* command line option; -enable-languages=jit,c++: Working on the JIT library.
                                                              (line  35)
* environment variable; LD_LIBRARY_PATH: Environment variables.
                                                              (line   9)
* environment variable; LIBRARY_PATH:    Environment variables.
                                                              (line  37)
* environment variable; PATH:            Environment variables.
                                                              (line  22)
* environment variable; PRESERVE_EXECUTABLES: Running the test suite.
                                                              (line  18)
* environment variable; RUN_UNDER_VALGRIND: Running under valgrind.
                                                              (line   6)
* gcc_jit_binary_op (C type):            Binary Operations.   (line  12)
* GCC_JIT_BINARY_OP_BITWISE_AND (C macro): Binary Operations. (line  73)
* GCC_JIT_BINARY_OP_BITWISE_OR (C macro): Binary Operations.  (line  87)
* GCC_JIT_BINARY_OP_BITWISE_XOR (C macro): Binary Operations. (line  80)
* GCC_JIT_BINARY_OP_DIVIDE (C macro):    Binary Operations.   (line  55)
* GCC_JIT_BINARY_OP_LOGICAL_AND (C macro): Binary Operations. (line  94)
* GCC_JIT_BINARY_OP_LOGICAL_OR (C macro): Binary Operations.  (line 101)
* GCC_JIT_BINARY_OP_LSHIFT (C macro):    Binary Operations.   (line 108)
* GCC_JIT_BINARY_OP_MINUS (C macro):     Binary Operations.   (line  41)
* GCC_JIT_BINARY_OP_MODULO (C macro):    Binary Operations.   (line  66)
* GCC_JIT_BINARY_OP_MULT (C macro):      Binary Operations.   (line  48)
* GCC_JIT_BINARY_OP_PLUS (C macro):      Binary Operations.   (line  31)
* GCC_JIT_BINARY_OP_RSHIFT (C macro):    Binary Operations.   (line 115)
* gcc_jit_block (C type):                Blocks.              (line   6)
* gcc_jit_block_add_assignment (C function): Statements.      (line  17)
* gcc_jit_block_add_assignment_op (C function): Statements.   (line  29)
* gcc_jit_block_add_comment (C function): Statements.         (line  52)
* gcc_jit_block_add_eval (C function):   Statements.          (line   6)
* gcc_jit_block_as_object (C function):  Blocks.              (line  39)
* gcc_jit_block_end_with_conditional (C function): Statements.
                                                              (line  72)
* gcc_jit_block_end_with_jump (C function): Statements.       (line  88)
* gcc_jit_block_end_with_return (C function): Statements.     (line  98)
* gcc_jit_block_end_with_switch (C function): Statements.     (line 121)
* gcc_jit_block_end_with_void_return (C function): Statements.
                                                              (line 110)
* gcc_jit_block_get_function (C function): Blocks.            (line  43)
* gcc_jit_bool_option (C type):          Boolean options.     (line  12)
* GCC_JIT_BOOL_OPTION_DEBUGINFO (C macro): Boolean options.   (line  14)
* GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING (C macro): Boolean options.
                                                              (line 108)
* GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE (C macro): Boolean options.
                                                              (line  72)
* GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE (C macro): Boolean options.
                                                              (line  56)
* GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE (C macro): Boolean options.
                                                              (line  24)
* GCC_JIT_BOOL_OPTION_DUMP_SUMMARY (C macro): Boolean options.
                                                              (line 104)
* GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (C macro): Boolean options.
                                                              (line 123)
* GCC_JIT_BOOL_OPTION_SELFCHECK_GC (C macro): Boolean options.
                                                              (line 116)
* gcc_jit_case (C type):                 Statements.          (line 170)
* gcc_jit_case_as_object (C function):   Statements.          (line 192)
* gcc_jit_comparison (C type):           Comparisons.         (line  11)
* gcc_jit_context (C type):              Compilation contexts.
                                                              (line   6)
* gcc_jit_context_acquire (C function):  Lifetime-management. (line  10)
* gcc_jit_context_add_command_line_option (C function): Additional command-line options.
                                                              (line   6)
* gcc_jit_context_compile (C function):  In-memory compilation.
                                                              (line   6)
* gcc_jit_context_compile_to_file (C function): Ahead-of-time compilation.
                                                              (line  11)
* gcc_jit_context_dump_reproducer_to_file (C function): Debugging.
                                                              (line  62)
* gcc_jit_context_dump_to_file (C function): Debugging.       (line   6)
* gcc_jit_context_enable_dump (C function): Debugging.        (line  83)
* gcc_jit_context_get_builtin_function (C function): Functions.
                                                              (line  54)
* gcc_jit_context_get_first_error (C function): Error-handling<2>.
                                                              (line  26)
* gcc_jit_context_get_int_type (C function): Standard types.  (line  39)
* gcc_jit_context_get_last_error (C function): Error-handling<2>.
                                                              (line  40)
* gcc_jit_context_get_timer (C function): The timing API.     (line 164)
* gcc_jit_context_get_type (C function): Standard types.      (line   6)
* gcc_jit_context_new_array_access (C function): Working with pointers structs and unions.
                                                              (line  47)
* gcc_jit_context_new_array_type (C function): Pointers const and volatile.
                                                              (line  18)
* gcc_jit_context_new_binary_op (C function): Binary Operations.
                                                              (line   6)
* gcc_jit_context_new_call (C function): Function calls.      (line   6)
* gcc_jit_context_new_call (C++ function): Function calls<2>. (line   6)
* gcc_jit_context_new_call_through_ptr (C function): Function calls.
                                                              (line  33)
* gcc_jit_context_new_case (C function): Statements.          (line 181)
* gcc_jit_context_new_cast (C function): Type-coercion.       (line   6)
* gcc_jit_context_new_child_context (C function): Lifetime-management.
                                                              (line  28)
* gcc_jit_context_new_comparison (C function): Comparisons.   (line   6)
* gcc_jit_context_new_field (C function): Structures and unions.
                                                              (line  52)
* gcc_jit_context_new_function (C function): Functions.       (line  10)
* gcc_jit_context_new_function_ptr_type (C function): Function pointers<2>.
                                                              (line  51)
* gcc_jit_context_new_global (C function): Global variables.  (line   6)
* gcc_jit_context_new_location (C function): Source Locations.
                                                              (line  29)
* gcc_jit_context_new_opaque_struct (C function): Structures and unions.
                                                              (line  74)
* gcc_jit_context_new_param (C function): Params.             (line   9)
* gcc_jit_context_new_rvalue_from_double (C function): Simple expressions.
                                                              (line  35)
* gcc_jit_context_new_rvalue_from_int (C function): Simple expressions.
                                                              (line   6)
* gcc_jit_context_new_rvalue_from_long (C function): Simple expressions.
                                                              (line  11)
* gcc_jit_context_new_rvalue_from_ptr (C function): Simple expressions.
                                                              (line  41)
* gcc_jit_context_new_rvalue_from_vector (C function): Vector expressions.
                                                              (line   6)
* gcc_jit_context_new_string_literal (C function): Simple expressions.
                                                              (line  55)
* gcc_jit_context_new_struct_type (C function): Structures and unions.
                                                              (line  65)
* gcc_jit_context_new_unary_op (C function): Unary Operations.
                                                              (line   6)
* gcc_jit_context_new_union_type (C function): Structures and unions.
                                                              (line  97)
* gcc_jit_context_null (C function):     Simple expressions.  (line  46)
* gcc_jit_context_one (C function):      Simple expressions.  (line  26)
* gcc_jit_context_release (C function):  Lifetime-management. (line  15)
* gcc_jit_context_set_bool_allow_unreachable_blocks (C function): Boolean options.
                                                              (line 128)
* gcc_jit_context_set_bool_option (C function): Boolean options.
                                                              (line   6)
* gcc_jit_context_set_bool_use_external_driver (C function): Boolean options.
                                                              (line 142)
* gcc_jit_context_set_int_option (C function): Integer options.
                                                              (line   6)
* gcc_jit_context_set_logfile (C function): Debugging.        (line  18)
* gcc_jit_context_set_str_option (C function): String Options.
                                                              (line   6)
* gcc_jit_context_set_timer (C function): The timing API.     (line 144)
* gcc_jit_context_zero (C function):     Simple expressions.  (line  17)
* gcc_jit_field (C type):                Structures and unions.
                                                              (line  10)
* gcc_jit_field_as_object (C function):  Structures and unions.
                                                              (line  61)
* gcc_jit_function (C type):             Functions.           (line   6)
* GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro): Functions.        (line  39)
* gcc_jit_function_as_object (C function): Functions.         (line  57)
* gcc_jit_function_dump_to_dot (C function): Functions.       (line  65)
* GCC_JIT_FUNCTION_EXPORTED (C macro):   Functions.           (line  22)
* gcc_jit_function_get_address (C function): Function pointers<2>.
                                                              (line  15)
* gcc_jit_function_get_param (C function): Functions.         (line  61)
* GCC_JIT_FUNCTION_IMPORTED (C macro):   Functions.           (line  34)
* GCC_JIT_FUNCTION_INTERNAL (C macro):   Functions.           (line  30)
* gcc_jit_function_kind (C type):        Functions.           (line  17)
* gcc_jit_function_new_block (C function): Blocks.            (line  21)
* gcc_jit_function_new_local (C function): Functions.         (line  69)
* GCC_JIT_GLOBAL_EXPORTED (C macro):     Global variables.    (line  22)
* GCC_JIT_GLOBAL_IMPORTED (C macro):     Global variables.    (line  34)
* GCC_JIT_GLOBAL_INTERNAL (C macro):     Global variables.    (line  28)
* gcc_jit_global_kind (C type):          Global variables.    (line  20)
* gcc_jit_int_option (C type):           Integer options.     (line  11)
* GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL (C macro): Integer options.
                                                              (line  15)
* gcc_jit_location (C type):             Source Locations.    (line   6)
* gcc_jit_lvalue (C type):               Lvalues.             (line   6)
* gcc_jit_lvalue_access_field (C function): Working with pointers structs and unions.
                                                              (line  17)
* gcc_jit_lvalue_as_object (C function): Lvalues.             (line  13)
* gcc_jit_lvalue_as_rvalue (C function): Lvalues.             (line  17)
* gcc_jit_lvalue_get_address (C function): Lvalues.           (line  21)
* gcc_jit_object (C type):               Objects.             (line   6)
* gcc_jit_object_get_context (C function): Objects.           (line  42)
* gcc_jit_object_get_debug_string (C function): Objects.      (line  46)
* gcc_jit_output_kind (C type):          Ahead-of-time compilation.
                                                              (line  24)
* GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro): Ahead-of-time compilation.
                                                              (line  35)
* GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro): Ahead-of-time compilation.
                                                              (line  41)
* GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro): Ahead-of-time compilation.
                                                              (line  47)
* GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro): Ahead-of-time compilation.
                                                              (line  38)
* gcc_jit_param (C type):                Params.              (line   6)
* gcc_jit_param_as_lvalue (C function):  Params.              (line  22)
* gcc_jit_param_as_object (C function):  Params.              (line  30)
* gcc_jit_param_as_rvalue (C function):  Params.              (line  26)
* gcc_jit_result (C type):               In-memory compilation.
                                                              (line  15)
* gcc_jit_result_get_code (C function):  In-memory compilation.
                                                              (line  20)
* gcc_jit_result_get_global (C function): In-memory compilation.
                                                              (line  52)
* gcc_jit_result_release (C function):   In-memory compilation.
                                                              (line  91)
* gcc_jit_rvalue (C type):               Rvalues.             (line   6)
* gcc_jit_rvalue_access_field (C function): Working with pointers structs and unions.
                                                              (line  27)
* gcc_jit_rvalue_as_object (C function): Rvalues.             (line  36)
* gcc_jit_rvalue_dereference (C function): Working with pointers structs and unions.
                                                              (line   6)
* gcc_jit_rvalue_dereference_field (C function): Working with pointers structs and unions.
                                                              (line  37)
* gcc_jit_rvalue_get_type (C function):  Rvalues.             (line  32)
* gcc_jit_rvalue_set_bool_require_tail_call (C function): Function calls.
                                                              (line  44)
* gcc_jit_str_option (C type):           String Options.      (line  11)
* GCC_JIT_STR_OPTION_PROGNAME (C macro): String Options.      (line  19)
* gcc_jit_struct (C type):               Structures and unions.
                                                              (line   6)
* gcc_jit_struct_as_type (C function):   Structures and unions.
                                                              (line  86)
* gcc_jit_struct_set_fields (C function): Structures and unions.
                                                              (line  90)
* gcc_jit_timer (C type):                The timing API.      (line 116)
* gcc_jit_timer_new (C function):        The timing API.      (line 118)
* gcc_jit_timer_pop (C function):        The timing API.      (line 190)
* gcc_jit_timer_print (C function):      The timing API.      (line 204)
* gcc_jit_timer_push (C function):       The timing API.      (line 175)
* gcc_jit_timer_release (C function):    The timing API.      (line 130)
* gcc_jit_type (C type):                 Types.               (line   6)
* gcc_jit_type_as_object (C function):   Types.               (line   9)
* gcc_jit_type_get_aligned (C function): Pointers const and volatile.
                                                              (line  23)
* gcc_jit_type_get_const (C function):   Pointers const and volatile.
                                                              (line  10)
* gcc_jit_type_get_pointer (C function): Pointers const and volatile.
                                                              (line   6)
* gcc_jit_type_get_vector (C function):  Vector types.        (line   6)
* gcc_jit_type_get_volatile (C function): Pointers const and volatile.
                                                              (line  14)
* gcc_jit_unary_op (C type):             Unary Operations.    (line  12)
* GCC_JIT_UNARY_OP_ABS (C macro):        Unary Operations.    (line  45)
* GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro): Unary Operations.
                                                              (line  30)
* GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro): Unary Operations.
                                                              (line  38)
* GCC_JIT_UNARY_OP_MINUS (C macro):      Unary Operations.    (line  23)
* gccjit;;block (C++ class):             Blocks<2>.           (line   6)
* gccjit;;block;;add_assignment (C++ function): Statements<2>.
                                                              (line  17)
* gccjit;;block;;add_assignment_op (C++ function): Statements<2>.
                                                              (line  28)
* gccjit;;block;;add_comment (C++ function): Statements<2>.   (line  49)
* gccjit;;block;;add_eval (C++ function): Statements<2>.      (line   6)
* gccjit;;block;;end_with_conditional (C++ function): Statements<2>.
                                                              (line  60)
* gccjit;;block;;end_with_jump (C++ function): Statements<2>. (line  75)
* gccjit;;block;;end_with_return (C++ function): Statements<2>.
                                                              (line  85)
* gccjit;;block;;end_with_switch (C++ function): Statements<2>.
                                                              (line 111)
* gccjit;;block;;end_with_switch;;gccjit;;case_ (C++ class): Statements<2>.
                                                              (line 153)
* gccjit;;block;;end_with_switch;;gccjit;;context;;new_case (C++ function): Statements<2>.
                                                              (line 165)
* gccjit;;context (C++ class):           Compilation contexts<2>.
                                                              (line   6)
* gccjit;;context;;acquire (C++ function): Lifetime-management<2>.
                                                              (line  10)
* gccjit;;context;;add_command_line_option (C++ function): Additional command-line options<2>.
                                                              (line   6)
* gccjit;;context;;compile (C++ function): In-memory compilation<2>.
                                                              (line   6)
* gccjit;;context;;compile_to_file (C++ function): Ahead-of-time compilation<2>.
                                                              (line  11)
* gccjit;;context;;dump_reproducer_to_file (C++ function): Debugging<2>.
                                                              (line  17)
* gccjit;;context;;dump_to_file (C++ function): Debugging<2>. (line   6)
* gccjit;;context;;get_builtin_function (C++ function): Functions<2>.
                                                              (line  21)
* gccjit;;context;;get_first_error (C++ function): Error-handling<3>.
                                                              (line  16)
* gccjit;;context;;get_int_type (C++ function): Standard types<2>.
                                                              (line  11)
* gccjit;;context;;get_int_type<T> (C++ function): Standard types<2>.
                                                              (line  15)
* gccjit;;context;;get_type (C++ function): Standard types<2>.
                                                              (line   6)
* gccjit;;context;;new_array_access (C++ function): Working with pointers structs and unions<2>.
                                                              (line  54)
* gccjit;;context;;new_array_type (C++ function): Pointers const and volatile<2>.
                                                              (line  23)
* gccjit;;context;;new_binary_op (C++ function): Binary Operations<2>.
                                                              (line   6)
* gccjit;;context;;new_bitwise_and (C++ function): Binary Operations<2>.
                                                              (line  40)
* gccjit;;context;;new_bitwise_or (C++ function): Binary Operations<2>.
                                                              (line  48)
* gccjit;;context;;new_bitwise_xor (C++ function): Binary Operations<2>.
                                                              (line  44)
* gccjit;;context;;new_cast (C++ function): Type-coercion<2>. (line   6)
* gccjit;;context;;new_child_context (C++ function): Lifetime-management<2>.
                                                              (line  28)
* gccjit;;context;;new_comparison (C++ function): Comparisons<2>.
                                                              (line   6)
* gccjit;;context;;new_divide (C++ function): Binary Operations<2>.
                                                              (line  32)
* gccjit;;context;;new_eq (C++ function): Comparisons<2>.     (line  20)
* gccjit;;context;;new_field (C++ function): Structures and unions<2>.
                                                              (line  54)
* gccjit;;context;;new_function (C++ function): Functions<2>. (line  10)
* gccjit;;context;;new_ge (C++ function): Comparisons<2>.     (line  35)
* gccjit;;context;;new_global (C++ function): Global variables<2>.
                                                              (line   6)
* gccjit;;context;;new_gt (C++ function): Comparisons<2>.     (line  32)
* gccjit;;context;;new_le (C++ function): Comparisons<2>.     (line  29)
* gccjit;;context;;new_location (C++ function): Source Locations<2>.
                                                              (line  26)
* gccjit;;context;;new_logical_and (C++ function): Binary Operations<2>.
                                                              (line  52)
* gccjit;;context;;new_logical_or (C++ function): Binary Operations<2>.
                                                              (line  56)
* gccjit;;context;;new_lt (C++ function): Comparisons<2>.     (line  26)
* gccjit;;context;;new_minus (C++ function) <1>: Unary Operations<2>.
                                                              (line  20)
* gccjit;;context;;new_minus (C++ function): Binary Operations<2>.
                                                              (line  24)
* gccjit;;context;;new_modulo (C++ function): Binary Operations<2>.
                                                              (line  36)
* gccjit;;context;;new_mult (C++ function): Binary Operations<2>.
                                                              (line  28)
* gccjit;;context;;new_ne (C++ function): Comparisons<2>.     (line  23)
* gccjit;;context;;new_opaque_struct (C++ function): Structures and unions<2>.
                                                              (line  63)
* gccjit;;context;;new_param (C++ function): Params<2>.       (line   9)
* gccjit;;context;;new_plus (C++ function): Binary Operations<2>.
                                                              (line  20)
* gccjit;;context;;new_rvalue (C++ function) <1>: Simple expressions<2>.
                                                              (line  39)
* gccjit;;context;;new_rvalue (C++ function) <2>: Vector expressions<2>.
                                                              (line   6)
* gccjit;;context;;new_rvalue (C++ function): Simple expressions<2>.
                                                              (line  34)
* gccjit;;context;;new_struct_type (C++ function): Structures and unions<2>.
                                                              (line  58)
* gccjit;;context;;new_unary_op (C++ function): Unary Operations<2>.
                                                              (line   6)
* gccjit;;context;;one (C++ function):   Simple expressions<2>.
                                                              (line  25)
* gccjit;;context;;release (C++ function): Lifetime-management<2>.
                                                              (line  15)
* gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function): Boolean options<2>.
                                                              (line  14)
* gccjit;;context;;set_bool_option (C++ function): Boolean options<2>.
                                                              (line   6)
* gccjit;;context;;set_bool_use_external_driver (C++ function): Boolean options<2>.
                                                              (line  31)
* gccjit;;context;;set_int_option (C++ function): Integer options<2>.
                                                              (line   6)
* gccjit;;context;;set_str_option (C++ function): String Options<2>.
                                                              (line   6)
* gccjit;;context;;zero (C++ function):  Simple expressions<2>.
                                                              (line  16)
* gccjit;;field (C++ class):             Structures and unions<2>.
                                                              (line  13)
* gccjit;;function (C++ class):          Functions<2>.        (line   6)
* gccjit;;function;;dump_to_dot (C++ function): Functions<2>. (line  30)
* gccjit;;function;;get_address (C++ function): Function pointers<3>.
                                                              (line   6)
* gccjit;;function;;get_param (C++ function): Functions<2>.   (line  26)
* gccjit;;function;;new_block (C++ function): Blocks<2>.      (line  24)
* gccjit;;function;;new_local (C++ function): Functions<2>.   (line  33)
* gccjit;;location (C++ class):          Source Locations<2>. (line   6)
* gccjit;;lvalue (C++ class):            Lvalues<2>.          (line   6)
* gccjit;;lvalue;;access_field (C++ function): Working with pointers structs and unions<2>.
                                                              (line  27)
* gccjit;;lvalue;;get_address (C++ function): Lvalues<2>.     (line  16)
* gccjit;;object (C++ class):            Objects<2>.          (line   6)
* gccjit;;object;;get_context (C++ function): Objects<2>.     (line  36)
* gccjit;;object;;get_debug_string (C++ function): Objects<2>.
                                                              (line  39)
* gccjit;;param (C++ class):             Params<2>.           (line   6)
* gccjit;;rvalue (C++ class):            Rvalues<2>.          (line   6)
* gccjit;;rvalue;;access_field (C++ function): Working with pointers structs and unions<2>.
                                                              (line  36)
* gccjit;;rvalue;;dereference (C++ function): Working with pointers structs and unions<2>.
                                                              (line   6)
* gccjit;;rvalue;;dereference_field (C++ function): Working with pointers structs and unions<2>.
                                                              (line  45)
* gccjit;;rvalue;;get_type (C++ function): Rvalues<2>.        (line  34)
* gccjit;;rvalue;;operator* (C++ function): Working with pointers structs and unions<2>.
                                                              (line  20)
* gccjit;;struct_ (C++ class):           Structures and unions<2>.
                                                              (line   6)
* gccjit;;type (C++ class):              Types<2>.            (line   6)
* gccjit;;type;;get_aligned (C++ function): Pointers const and volatile<2>.
                                                              (line  15)
* gccjit;;type;;get_const (C++ function): Pointers const and volatile<2>.
                                                              (line   9)
* gccjit;;type;;get_pointer (C++ function): Pointers const and volatile<2>.
                                                              (line   6)
* gccjit;;type;;get_vector (C++ function): Vector types<2>.   (line   6)
* gccjit;;type;;get_volatile (C++ function): Pointers const and volatile<2>.
                                                              (line  12)
* LIBGCCJIT_HAVE_TIMING_API (C macro):   The timing API.      (line 103)
* new_bitwise_negate (C++ function):     Unary Operations<2>. (line  33)
* new_logical_negate (C++ function):     Unary Operations<2>. (line  46)
* operator! (C++ function):              Unary Operations<2>. (line  70)
* operator!= (C++ function):             Comparisons<2>.      (line  46)
* operator% (C++ function):              Binary Operations<2>.
                                                              (line  86)
* operator& (C++ function):              Binary Operations<2>.
                                                              (line  92)
* operator&& (C++ function):             Binary Operations<2>.
                                                              (line 110)
* operator* (C++ function):              Binary Operations<2>.
                                                              (line  74)
* operator+ (C++ function):              Binary Operations<2>.
                                                              (line  62)
* operator- (C++ function) <1>:          Unary Operations<2>. (line  60)
* operator- (C++ function):              Binary Operations<2>.
                                                              (line  68)
* operator/ (C++ function):              Binary Operations<2>.
                                                              (line  80)
* operator< (C++ function):              Comparisons<2>.      (line  52)
* operator<= (C++ function):             Comparisons<2>.      (line  58)
* operator== (C++ function):             Comparisons<2>.      (line  40)
* operator> (C++ function):              Comparisons<2>.      (line  64)
* operator>= (C++ function):             Comparisons<2>.      (line  70)
* operator^ (C++ function):              Binary Operations<2>.
                                                              (line  98)
* operator| (C++ function):              Binary Operations<2>.
                                                              (line 104)
* operator|| (C++ function):             Binary Operations<2>.
                                                              (line 116)
* operator~ (C++ function):              Unary Operations<2>. (line  65)
* PRESERVE_EXECUTABLES:                  Running the test suite.
                                                              (line  18)
* RUN_UNDER_VALGRIND:                    Running under valgrind.
                                                              (line   6)



Tag Table:
Node: Top526
Ref: index doc785
Ref: 0785
Ref: Top-Footnote-18270
Node: Tutorial8305
Ref: intro/index libgccjit8392
Ref: 18392
Ref: intro/index doc8392
Ref: 28392
Ref: intro/index tutorial8392
Ref: 38392
Node: Tutorial part 1 "Hello world"8926
Ref: intro/tutorial01 doc9068
Ref: 49068
Ref: intro/tutorial01 tutorial-part-1-hello-world9068
Ref: 59068
Node: Tutorial part 2 Creating a trivial machine code function14221
Ref: intro/tutorial02 doc14407
Ref: 614407
Ref: intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function14407
Ref: 714407
Node: Error-handling19795
Ref: intro/tutorial02 error-handling19921
Ref: 1819921
Node: Options20820
Ref: intro/tutorial02 options20967
Ref: 1a20967
Node: Full example23487
Ref: intro/tutorial02 full-example23611
Ref: 2023611
Node: Tutorial part 3 Loops and variables27691
Ref: intro/tutorial03 tutorial-part-3-loops-and-variables27907
Ref: 2127907
Ref: intro/tutorial03 doc27907
Ref: 2227907
Node: Expressions lvalues and rvalues29835
Ref: intro/tutorial03 expressions-lvalues-and-rvalues29962
Ref: 2329962
Node: Control flow32133
Ref: intro/tutorial03 control-flow32303
Ref: 2732303
Node: Visualizing the control flow graph37060
Ref: intro/tutorial03 visualizing-the-control-flow-graph37214
Ref: 3237214
Node: Full example<2>37791
Ref: intro/tutorial03 full-example37924
Ref: 3437924
Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter43835
Ref: intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter44049
Ref: 3544049
Ref: intro/tutorial04 doc44049
Ref: 3644049
Node: Our toy interpreter44656
Ref: intro/tutorial04 our-toy-interpreter44808
Ref: 3744808
Node: Compiling to machine code51000
Ref: intro/tutorial04 compiling-to-machine-code51178
Ref: 3851178
Node: Setting things up53169
Ref: intro/tutorial04 setting-things-up53351
Ref: 3a53351
Node: Populating the function57338
Ref: intro/tutorial04 populating-the-function57527
Ref: 3c57527
Node: Verifying the control flow graph64998
Ref: intro/tutorial04 verifying-the-control-flow-graph65191
Ref: 3e65191
Node: Compiling the context65699
Ref: intro/tutorial04 compiling-the-context65911
Ref: 3f65911
Node: Single-stepping through the generated code72034
Ref: intro/tutorial04 single-stepping-through-the-generated-code72242
Ref: 4072242
Node: Examining the generated code74311
Ref: intro/tutorial04 examining-the-generated-code74521
Ref: 4374521
Node: Putting it all together79185
Ref: intro/tutorial04 putting-it-all-together79404
Ref: 4479404
Node: Behind the curtain How does our code get optimized?80229
Ref: intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized80411
Ref: 4580411
Node: Optimizing away stack manipulation86060
Ref: intro/tutorial04 optimizing-away-stack-manipulation86223
Ref: 4686223
Node: Elimination of tail recursion92137
Ref: intro/tutorial04 elimination-of-tail-recursion92300
Ref: 4792300
Node: Tutorial part 5 Implementing an Ahead-of-Time compiler93747
Ref: intro/tutorial05 doc93917
Ref: 4893917
Ref: intro/tutorial05 tutorial-part-5-implementing-an-ahead-of-time-compiler93917
Ref: 4993917
Node: The "brainf" language94758
Ref: intro/tutorial05 the-brainf-language94924
Ref: 4b94924
Node: Converting a brainf script to libgccjit IR97109
Ref: intro/tutorial05 converting-a-brainf-script-to-libgccjit-ir97313
Ref: 4c97313
Node: Compiling a context to a file108608
Ref: intro/tutorial05 compiling-a-context-to-a-file108831
Ref: 4d108831
Node: Other forms of ahead-of-time-compilation115491
Ref: intro/tutorial05 other-forms-of-ahead-of-time-compilation115663
Ref: 4e115663
Node: Topic Reference116021
Ref: topics/index doc116131
Ref: 4f116131
Ref: topics/index topic-reference116131
Ref: 50116131
Node: Compilation contexts117654
Ref: topics/contexts compilation-contexts117745
Ref: 51117745
Ref: topics/contexts doc117745
Ref: 52117745
Ref: topics/contexts gcc_jit_context117796
Ref: 8117796
Node: Lifetime-management118257
Ref: topics/contexts lifetime-management118358
Ref: 53118358
Ref: topics/contexts gcc_jit_context_acquire118623
Ref: 9118623
Ref: topics/contexts gcc_jit_context_release118846
Ref: c118846
Ref: topics/contexts gcc_jit_context_new_child_context119299
Ref: 54119299
Node: Thread-safety120701
Ref: topics/contexts thread-safety120828
Ref: 55120828
Node: Error-handling<2>121516
Ref: topics/contexts error-handling121633
Ref: 19121633
Ref: topics/contexts id1121633
Ref: 56121633
Ref: topics/contexts gcc_jit_context_get_first_error122669
Ref: 57122669
Ref: topics/contexts gcc_jit_context_get_last_error123182
Ref: 58123182
Node: Debugging123525
Ref: topics/contexts debugging123639
Ref: 59123639
Ref: topics/contexts gcc_jit_context_dump_to_file123672
Ref: 5a123672
Ref: topics/contexts gcc_jit_context_set_logfile124260
Ref: 5b124260
Ref: topics/contexts gcc_jit_context_dump_reproducer_to_file125924
Ref: 5d125924
Ref: topics/contexts gcc_jit_context_enable_dump127092
Ref: 5e127092
Node: Options<2>128591
Ref: topics/contexts options128679
Ref: 5f128679
Node: String Options129195
Ref: topics/contexts string-options129283
Ref: 60129283
Ref: topics/contexts gcc_jit_context_set_str_option129330
Ref: 61129330
Ref: topics/contexts gcc_jit_str_option129516
Ref: 62129516
Ref: topics/contexts GCC_JIT_STR_OPTION_PROGNAME129789
Ref: 63129789
Node: Boolean options129999
Ref: topics/contexts boolean-options130111
Ref: 64130111
Ref: topics/contexts gcc_jit_context_set_bool_option130160
Ref: 1b130160
Ref: topics/contexts gcc_jit_bool_option130398
Ref: 65130398
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DEBUGINFO130441
Ref: 42130441
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE130921
Ref: 66130921
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE132833
Ref: 1c132833
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE133285
Ref: 1d133285
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DUMP_SUMMARY134380
Ref: 67134380
Ref: topics/contexts GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING134564
Ref: 68134564
Ref: topics/contexts GCC_JIT_BOOL_OPTION_SELFCHECK_GC135025
Ref: 6a135025
Ref: topics/contexts GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES135361
Ref: 69135361
Ref: topics/contexts gcc_jit_context_set_bool_allow_unreachable_blocks135595
Ref: 6b135595
Ref: topics/contexts gcc_jit_context_set_bool_use_external_driver136058
Ref: 6d136058
Node: Integer options136667
Ref: topics/contexts integer-options136796
Ref: 6f136796
Ref: topics/contexts gcc_jit_context_set_int_option136845
Ref: 1e136845
Ref: topics/contexts gcc_jit_int_option137025
Ref: 70137025
Ref: topics/contexts GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL137126
Ref: 1f137126
Node: Additional command-line options137377
Ref: topics/contexts additional-command-line-options137482
Ref: 71137482
Ref: topics/contexts gcc_jit_context_add_command_line_option137563
Ref: 72137563
Node: Objects138829
Ref: topics/objects objects138934
Ref: 74138934
Ref: topics/objects doc138934
Ref: 75138934
Ref: topics/objects gcc_jit_object138959
Ref: e138959
Ref: topics/objects gcc_jit_object_get_context140041
Ref: 76140041
Ref: topics/objects gcc_jit_object_get_debug_string140170
Ref: f140170
Node: Types140780
Ref: topics/types doc140876
Ref: 77140876
Ref: topics/types types140876
Ref: 78140876
Ref: topics/types gcc_jit_type140897
Ref: a140897
Ref: topics/types gcc_jit_type_as_object140979
Ref: d140979
Node: Standard types141948
Ref: topics/types standard-types142043
Ref: 7b142043
Ref: topics/types gcc_jit_context_get_type142086
Ref: b142086
Ref: topics/types gcc_jit_context_get_int_type144202
Ref: 7c144202
Node: Pointers const and volatile144375
Ref: topics/types pointers-const-and-volatile144491
Ref: 7d144491
Ref: topics/types gcc_jit_type_get_pointer144572
Ref: 79144572
Ref: topics/types gcc_jit_type_get_const144695
Ref: 7a144695
Ref: topics/types gcc_jit_type_get_volatile144821
Ref: 7e144821
Ref: topics/types gcc_jit_context_new_array_type144953
Ref: 7f144953
Ref: topics/types gcc_jit_type_get_aligned145186
Ref: 80145186
Node: Vector types145598
Ref: topics/types vector-types145721
Ref: 82145721
Ref: topics/types gcc_jit_type_get_vector145760
Ref: 83145760
Node: Structures and unions146919
Ref: topics/types structures-and-unions147037
Ref: 86147037
Ref: topics/types gcc_jit_struct147094
Ref: 87147094
Ref: topics/types gcc_jit_field147168
Ref: 88147168
Ref: topics/types gcc_jit_context_new_field148615
Ref: 89148615
Ref: topics/types gcc_jit_field_as_object149000
Ref: 8a149000
Ref: topics/types gcc_jit_context_new_struct_type149125
Ref: 8b149125
Ref: topics/types gcc_jit_context_new_opaque_struct149564
Ref: 8c149564
Ref: topics/types gcc_jit_struct_as_type150130
Ref: 8e150130
Ref: topics/types gcc_jit_struct_set_fields150258
Ref: 8d150258
Ref: topics/types gcc_jit_context_new_union_type150537
Ref: 8f150537
Node: Function pointer types153478
Ref: topics/types function-pointer-types153575
Ref: 90153575
Node: Expressions153730
Ref: topics/expressions expressions153847
Ref: 92153847
Ref: topics/expressions doc153847
Ref: 93153847
Node: Rvalues154206
Ref: topics/expressions rvalues154280
Ref: 94154280
Ref: topics/expressions gcc_jit_rvalue154309
Ref: 13154309
Ref: topics/expressions gcc_jit_rvalue_get_type154943
Ref: 95154943
Ref: topics/expressions gcc_jit_rvalue_as_object155067
Ref: 14155067
Node: Simple expressions155380
Ref: topics/expressions simple-expressions155472
Ref: 96155472
Ref: topics/expressions gcc_jit_context_new_rvalue_from_int155527
Ref: 30155527
Ref: topics/expressions gcc_jit_context_new_rvalue_from_long155782
Ref: 97155782
Ref: topics/expressions gcc_jit_context_zero156050
Ref: 2b156050
Ref: topics/expressions gcc_jit_context_one156365
Ref: 2f156365
Ref: topics/expressions gcc_jit_context_new_rvalue_from_double156678
Ref: 31156678
Ref: topics/expressions gcc_jit_context_new_rvalue_from_ptr156952
Ref: 98156952
Ref: topics/expressions gcc_jit_context_null157173
Ref: 99157173
Ref: topics/expressions gcc_jit_context_new_string_literal157466
Ref: 9a157466
Node: Vector expressions157857
Ref: topics/expressions vector-expressions157974
Ref: 9b157974
Ref: topics/expressions gcc_jit_context_new_rvalue_from_vector158029
Ref: 85158029
Node: Unary Operations158640
Ref: topics/expressions unary-operations158756
Ref: 9d158756
Ref: topics/expressions gcc_jit_context_new_unary_op158807
Ref: 9e158807
Ref: topics/expressions gcc_jit_unary_op159077
Ref: 9f159077
Ref: topics/expressions GCC_JIT_UNARY_OP_MINUS159509
Ref: a0159509
Ref: topics/expressions GCC_JIT_UNARY_OP_BITWISE_NEGATE159623
Ref: a1159623
Ref: topics/expressions GCC_JIT_UNARY_OP_LOGICAL_NEGATE159780
Ref: a2159780
Ref: topics/expressions GCC_JIT_UNARY_OP_ABS159927
Ref: a3159927
Node: Binary Operations160058
Ref: topics/expressions binary-operations160167
Ref: a4160167
Ref: topics/expressions gcc_jit_context_new_binary_op160220
Ref: 12160220
Ref: topics/expressions gcc_jit_binary_op160514
Ref: a5160514
Ref: topics/expressions GCC_JIT_BINARY_OP_PLUS161353
Ref: a6161353
Ref: topics/expressions GCC_JIT_BINARY_OP_MINUS161565
Ref: a7161565
Ref: topics/expressions GCC_JIT_BINARY_OP_MULT161698
Ref: a8161698
Ref: topics/expressions GCC_JIT_BINARY_OP_DIVIDE161843
Ref: a9161843
Ref: topics/expressions GCC_JIT_BINARY_OP_MODULO162200
Ref: aa162200
Ref: topics/expressions GCC_JIT_BINARY_OP_BITWISE_AND162344
Ref: ab162344
Ref: topics/expressions GCC_JIT_BINARY_OP_BITWISE_XOR162462
Ref: ac162462
Ref: topics/expressions GCC_JIT_BINARY_OP_BITWISE_OR162589
Ref: ad162589
Ref: topics/expressions GCC_JIT_BINARY_OP_LOGICAL_AND162715
Ref: ae162715
Ref: topics/expressions GCC_JIT_BINARY_OP_LOGICAL_OR162834
Ref: af162834
Ref: topics/expressions GCC_JIT_BINARY_OP_LSHIFT162951
Ref: b0162951
Ref: topics/expressions GCC_JIT_BINARY_OP_RSHIFT163064
Ref: b1163064
Node: Comparisons163178
Ref: topics/expressions comparisons163285
Ref: b3163285
Ref: topics/expressions gcc_jit_context_new_comparison163326
Ref: 2c163326
Ref: topics/expressions gcc_jit_comparison163596
Ref: b4163596
Node: Function calls164070
Ref: topics/expressions function-calls164177
Ref: b5164177
Ref: topics/expressions gcc_jit_context_new_call164224
Ref: b6164224
Ref: topics/expressions gcc_jit_context_new_call_through_ptr165332
Ref: b8165332
Ref: topics/expressions gcc_jit_rvalue_set_bool_require_tail_call165865
Ref: b9165865
Node: Function pointers166920
Ref: topics/expressions function-pointers167029
Ref: bb167029
Node: Type-coercion167443
Ref: topics/expressions type-coercion167529
Ref: bd167529
Ref: topics/expressions gcc_jit_context_new_cast167574
Ref: be167574
Node: Lvalues167990
Ref: topics/expressions lvalues168113
Ref: bf168113
Ref: topics/expressions gcc_jit_lvalue168142
Ref: 24168142
Ref: topics/expressions gcc_jit_lvalue_as_object168380
Ref: c0168380
Ref: topics/expressions gcc_jit_lvalue_as_rvalue168513
Ref: c1168513
Ref: topics/expressions gcc_jit_lvalue_get_address168646
Ref: c2168646
Node: Global variables168876
Ref: topics/expressions global-variables168939
Ref: c3168939
Ref: topics/expressions gcc_jit_context_new_global168990
Ref: c4168990
Ref: topics/expressions gcc_jit_global_kind169555
Ref: c5169555
Ref: topics/expressions GCC_JIT_GLOBAL_EXPORTED169598
Ref: c6169598
Ref: topics/expressions GCC_JIT_GLOBAL_INTERNAL169894
Ref: c8169894
Ref: topics/expressions GCC_JIT_GLOBAL_IMPORTED170193
Ref: c9170193
Node: Working with pointers structs and unions170397
Ref: topics/expressions working-with-pointers-structs-and-unions170504
Ref: ca170504
Ref: topics/expressions gcc_jit_rvalue_dereference170601
Ref: cb170601
Ref: topics/expressions gcc_jit_lvalue_access_field170941
Ref: cc170941
Ref: topics/expressions gcc_jit_rvalue_access_field171265
Ref: cd171265
Ref: topics/expressions gcc_jit_rvalue_dereference_field171556
Ref: ce171556
Ref: topics/expressions gcc_jit_context_new_array_access171920
Ref: b2171920
Node: Creating and using functions172382
Ref: topics/functions doc172514
Ref: cf172514
Ref: topics/functions creating-and-using-functions172514
Ref: d0172514
Node: Params172642
Ref: topics/functions params172734
Ref: d1172734
Ref: topics/functions gcc_jit_param172761
Ref: 25172761
Ref: topics/functions gcc_jit_context_new_param172849
Ref: 10172849
Ref: topics/functions gcc_jit_param_as_lvalue173385
Ref: d2173385
Ref: topics/functions gcc_jit_param_as_rvalue173513
Ref: d3173513
Ref: topics/functions gcc_jit_param_as_object173641
Ref: d4173641
Node: Functions173769
Ref: topics/functions functions173876
Ref: d5173876
Ref: topics/functions gcc_jit_function173909
Ref: 29173909
Ref: topics/functions gcc_jit_context_new_function174067
Ref: 11174067
Ref: topics/functions gcc_jit_function_kind174421
Ref: d6174421
Ref: topics/functions GCC_JIT_FUNCTION_EXPORTED174557
Ref: d7174557
Ref: topics/functions GCC_JIT_FUNCTION_INTERNAL174912
Ref: d8174912
Ref: topics/functions GCC_JIT_FUNCTION_IMPORTED175104
Ref: d9175104
Ref: topics/functions GCC_JIT_FUNCTION_ALWAYS_INLINE175334
Ref: da175334
Ref: topics/functions gcc_jit_context_get_builtin_function175979
Ref: db175979
Ref: topics/functions gcc_jit_function_as_object176103
Ref: dc176103
Ref: topics/functions gcc_jit_function_get_param176239
Ref: dd176239
Ref: topics/functions gcc_jit_function_dump_to_dot176394
Ref: 33176394
Ref: topics/functions gcc_jit_function_new_local176559
Ref: 26176559
Node: Blocks176976
Ref: topics/functions blocks177087
Ref: de177087
Ref: topics/functions gcc_jit_block177114
Ref: 28177114
Ref: topics/functions gcc_jit_function_new_block177620
Ref: df177620
Ref: topics/functions gcc_jit_block_as_object178316
Ref: e0178316
Ref: topics/functions gcc_jit_block_get_function178441
Ref: e1178441
Node: Statements178579
Ref: topics/functions statements178672
Ref: e2178672
Ref: topics/functions gcc_jit_block_add_eval178707
Ref: b7178707
Ref: topics/functions gcc_jit_block_add_assignment179008
Ref: 2a179008
Ref: topics/functions gcc_jit_block_add_assignment_op179332
Ref: 2e179332
Ref: topics/functions gcc_jit_block_add_comment179955
Ref: 3d179955
Ref: topics/functions gcc_jit_block_end_with_conditional180808
Ref: 2d180808
Ref: topics/functions gcc_jit_block_end_with_jump181337
Ref: e3181337
Ref: topics/functions gcc_jit_block_end_with_return181607
Ref: e4181607
Ref: topics/functions gcc_jit_block_end_with_void_return181913
Ref: e5181913
Ref: topics/functions gcc_jit_block_end_with_switch182196
Ref: e6182196
Ref: topics/functions gcc_jit_case183617
Ref: ea183617
Ref: topics/functions gcc_jit_context_new_case184011
Ref: e8184011
Ref: topics/functions gcc_jit_case_as_object184538
Ref: e7184538
Node: Function pointers<2>188702
Ref: topics/function-pointers doc188839
Ref: eb188839
Ref: topics/function-pointers function-pointers188839
Ref: ec188839
Ref: topics/function-pointers gcc_jit_function_get_address189191
Ref: bc189191
Ref: topics/function-pointers gcc_jit_context_new_function_ptr_type190479
Ref: 91190479
Node: Source Locations190825
Ref: topics/locations source-locations190953
Ref: ee190953
Ref: topics/locations doc190953
Ref: ef190953
Ref: topics/locations gcc_jit_location190996
Ref: 3b190996
Ref: topics/locations gcc_jit_context_new_location191758
Ref: 41191758
Node: Faking it192189
Ref: topics/locations faking-it192254
Ref: f0192254
Node: Compiling a context192901
Ref: topics/compilation compiling-a-context193034
Ref: f1193034
Ref: topics/compilation doc193034
Ref: f2193034
Node: In-memory compilation193526
Ref: topics/compilation in-memory-compilation193640
Ref: f3193640
Ref: topics/compilation gcc_jit_context_compile193697
Ref: 15193697
Ref: topics/compilation gcc_jit_result194027
Ref: 16194027
Ref: topics/compilation gcc_jit_result_get_code194234
Ref: 17194234
Ref: topics/compilation gcc_jit_result_get_global195775
Ref: c7195775
Ref: topics/compilation gcc_jit_result_release197193
Ref: 39197193
Node: Ahead-of-time compilation197578
Ref: topics/compilation ahead-of-time-compilation197692
Ref: f4197692
Ref: topics/compilation gcc_jit_context_compile_to_file197974
Ref: 4a197974
Ref: topics/compilation gcc_jit_output_kind198517
Ref: f5198517
Ref: topics/compilation GCC_JIT_OUTPUT_KIND_ASSEMBLER198968
Ref: f6198968
Ref: topics/compilation GCC_JIT_OUTPUT_KIND_OBJECT_FILE199059
Ref: f7199059
Ref: topics/compilation GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY199149
Ref: f8199149
Ref: topics/compilation GCC_JIT_OUTPUT_KIND_EXECUTABLE199335
Ref: f9199335
Node: ABI and API compatibility199506
Ref: topics/compatibility abi-and-api-compatibility199634
Ref: fa199634
Ref: topics/compatibility doc199634
Ref: fb199634
Node: ABI symbol tags201371
Ref: topics/compatibility abi-symbol-tags201451
Ref: fc201451
Node: LIBGCCJIT_ABI_0201847
Ref: topics/compatibility libgccjit-abi-0201941
Ref: fd201941
Ref: topics/compatibility id1201941
Ref: fe201941
Ref: LIBGCCJIT_ABI_0-Footnote-1202318
Node: LIBGCCJIT_ABI_1202382
Ref: topics/compatibility libgccjit-abi-1202500
Ref: 73202500
Ref: topics/compatibility id2202500
Ref: ff202500
Node: LIBGCCJIT_ABI_2202648
Ref: topics/compatibility libgccjit-abi-2202766
Ref: 6c202766
Ref: topics/compatibility id3202766
Ref: 100202766
Node: LIBGCCJIT_ABI_3202924
Ref: topics/compatibility libgccjit-abi-3203042
Ref: e9203042
Ref: topics/compatibility id4203042
Ref: 101203042
Node: LIBGCCJIT_ABI_4203326
Ref: topics/compatibility id5203444
Ref: 102203444
Ref: topics/compatibility libgccjit-abi-4203444
Ref: 103203444
Node: LIBGCCJIT_ABI_5203891
Ref: topics/compatibility id6204009
Ref: 10b204009
Ref: topics/compatibility libgccjit-abi-5204009
Ref: 6e204009
Node: LIBGCCJIT_ABI_6204162
Ref: topics/compatibility id7204280
Ref: 10c204280
Ref: topics/compatibility libgccjit-abi-6204280
Ref: ba204280
Node: LIBGCCJIT_ABI_7204430
Ref: topics/compatibility libgccjit-abi-7204548
Ref: 81204548
Ref: topics/compatibility id8204548
Ref: 10d204548
Node: LIBGCCJIT_ABI_8204681
Ref: topics/compatibility libgccjit-abi-8204799
Ref: 84204799
Ref: topics/compatibility id9204799
Ref: 10e204799
Node: LIBGCCJIT_ABI_9204931
Ref: topics/compatibility id10205050
Ref: 10f205050
Ref: topics/compatibility libgccjit-abi-9205050
Ref: ed205050
Node: LIBGCCJIT_ABI_10205189
Ref: topics/compatibility id11205284
Ref: 110205284
Ref: topics/compatibility libgccjit-abi-10205284
Ref: 9c205284
Node: Performance205436
Ref: topics/performance performance205536
Ref: 111205536
Ref: topics/performance doc205536
Ref: 112205536
Node: The timing API205600
Ref: topics/performance the-timing-api205665
Ref: 113205665
Ref: topics/performance LIBGCCJIT_HAVE_TIMING_API210940
Ref: 115210940
Ref: topics/performance gcc_jit_timer211369
Ref: 114211369
Ref: topics/performance gcc_jit_timer_new211396
Ref: 106211396
Ref: topics/performance gcc_jit_timer_release211727
Ref: 107211727
Ref: topics/performance gcc_jit_context_set_timer212089
Ref: 105212089
Ref: topics/performance gcc_jit_context_get_timer212762
Ref: 104212762
Ref: topics/performance gcc_jit_timer_push213063
Ref: 108213063
Ref: topics/performance gcc_jit_timer_pop213499
Ref: 109213499
Ref: topics/performance gcc_jit_timer_print213932
Ref: 10a213932
Node: C++ bindings for libgccjit214273
Ref: cp/index c-bindings-for-libgccjit214384
Ref: 116214384
Ref: cp/index doc214384
Ref: 117214384
Ref: C++ bindings for libgccjit-Footnote-1218473
Node: Tutorial<2>218508
Ref: cp/intro/index doc218612
Ref: 118218612
Ref: cp/intro/index tutorial218612
Ref: 119218612
Node: Tutorial part 1 "Hello world"<2>219047
Ref: cp/intro/tutorial01 doc219198
Ref: 11a219198
Ref: cp/intro/tutorial01 tutorial-part-1-hello-world219198
Ref: 11b219198
Node: Tutorial part 2 Creating a trivial machine code function<2>223816
Ref: cp/intro/tutorial02 doc224014
Ref: 11c224014
Ref: cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function224014
Ref: 11d224014
Node: Options<3>228988
Ref: cp/intro/tutorial02 options229121
Ref: 125229121
Node: Full example<3>231511
Ref: cp/intro/tutorial02 full-example231644
Ref: 128231644
Node: Tutorial part 3 Loops and variables<2>235213
Ref: cp/intro/tutorial03 tutorial-part-3-loops-and-variables235441
Ref: 129235441
Ref: cp/intro/tutorial03 doc235441
Ref: 12a235441
Node: Expressions lvalues and rvalues<2>237452
Ref: cp/intro/tutorial03 expressions-lvalues-and-rvalues237588
Ref: 12b237588
Node: Control flow<2>239737
Ref: cp/intro/tutorial03 control-flow239919
Ref: 12d239919
Node: Visualizing the control flow graph<2>244500
Ref: cp/intro/tutorial03 visualizing-the-control-flow-graph244663
Ref: 134244663
Node: Full example<4>245228
Ref: cp/intro/tutorial03 full-example245367
Ref: 136245367
Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>250218
Ref: cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter250378
Ref: 137250378
Ref: cp/intro/tutorial04 doc250378
Ref: 138250378
Node: Our toy interpreter<2>251258
Ref: cp/intro/tutorial04 our-toy-interpreter251419
Ref: 139251419
Node: Compiling to machine code<2>257503
Ref: cp/intro/tutorial04 compiling-to-machine-code257693
Ref: 13a257693
Node: Setting things up<2>259286
Ref: cp/intro/tutorial04 setting-things-up259480
Ref: 13b259480
Node: Populating the function<2>263036
Ref: cp/intro/tutorial04 populating-the-function263237
Ref: 13c263237
Node: Verifying the control flow graph<2>269547
Ref: cp/intro/tutorial04 verifying-the-control-flow-graph269752
Ref: 13e269752
Node: Compiling the context<2>270242
Ref: cp/intro/tutorial04 compiling-the-context270466
Ref: 13f270466
Node: Single-stepping through the generated code<2>271521
Ref: cp/intro/tutorial04 single-stepping-through-the-generated-code271741
Ref: 140271741
Node: Examining the generated code<2>273744
Ref: cp/intro/tutorial04 examining-the-generated-code273966
Ref: 142273966
Node: Putting it all together<2>278422
Ref: cp/intro/tutorial04 putting-it-all-together278653
Ref: 143278653
Node: Behind the curtain How does our code get optimized?<2>279485
Ref: cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized279676
Ref: 144279676
Node: Optimizing away stack manipulation<2>285209
Ref: cp/intro/tutorial04 optimizing-away-stack-manipulation285381
Ref: 145285381
Node: Elimination of tail recursion<2>291295
Ref: cp/intro/tutorial04 elimination-of-tail-recursion291467
Ref: 146291467
Node: Topic Reference<2>292914
Ref: cp/topics/index doc293018
Ref: 147293018
Ref: cp/topics/index topic-reference293018
Ref: 148293018
Node: Compilation contexts<2>294764
Ref: cp/topics/contexts compilation-contexts294864
Ref: 149294864
Ref: cp/topics/contexts doc294864
Ref: 14a294864
Ref: cp/topics/contexts gccjit context294919
Ref: 14b294919
Node: Lifetime-management<2>295519
Ref: cp/topics/contexts lifetime-management295629
Ref: 14c295629
Ref: cp/topics/contexts gccjit context acquire295898
Ref: 11e295898
Ref: cp/topics/contexts gccjit context release296119
Ref: 120296119
Ref: cp/topics/contexts gccjit context new_child_context296530
Ref: 14d296530
Node: Thread-safety<2>297895
Ref: cp/topics/contexts thread-safety298031
Ref: 14e298031
Node: Error-handling<3>298728
Ref: cp/topics/contexts error-handling298854
Ref: 14f298854
Ref: cp/topics/contexts gccjit context get_first_error__gccjit contextP299284
Ref: 150299284
Node: Debugging<2>299582
Ref: cp/topics/contexts debugging299702
Ref: 151299702
Ref: cp/topics/contexts gccjit context dump_to_file__ssCR i299739
Ref: 152299739
Ref: cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP300296
Ref: 154300296
Node: Options<4>300693
Ref: cp/topics/contexts options300787
Ref: 155300787
Node: String Options<2>301016
Ref: cp/topics/contexts string-options301110
Ref: 156301110
Ref: cp/topics/contexts gccjit context set_str_option__enum cCP301157
Ref: 157301157
Node: Boolean options<2>301445
Ref: cp/topics/contexts boolean-options301566
Ref: 158301566
Ref: cp/topics/contexts gccjit context set_bool_option__enum i301615
Ref: 126301615
Ref: cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i301899
Ref: 159301899
Ref: cp/topics/contexts gccjit context set_bool_use_external_driver__i302463
Ref: 15a302463
Node: Integer options<2>303153
Ref: cp/topics/contexts integer-options303291
Ref: 15b303291
Ref: cp/topics/contexts gccjit context set_int_option__enum i303340
Ref: 127303340
Node: Additional command-line options<2>303622
Ref: cp/topics/contexts additional-command-line-options303733
Ref: 15c303733
Ref: cp/topics/contexts gccjit context add_command_line_option__cCP303814
Ref: 15d303814
Node: Objects<2>304283
Ref: cp/topics/objects objects304400
Ref: 15e304400
Ref: cp/topics/objects doc304400
Ref: 15f304400
Ref: cp/topics/objects gccjit object304429
Ref: 160304429
Ref: cp/topics/objects gccjit object get_contextC305240
Ref: 161305240
Ref: cp/topics/objects gccjit object get_debug_stringC305350
Ref: 121305350
Node: Types<2>305643
Ref: cp/topics/types doc305751
Ref: 162305751
Ref: cp/topics/types types305751
Ref: 163305751
Ref: cp/topics/types gccjit type305776
Ref: 164305776
Node: Standard types<2>306864
Ref: cp/topics/types standard-types306968
Ref: 167306968
Ref: cp/topics/types gccjit context get_type__enum307015
Ref: 11f307015
Ref: cp/topics/types gccjit context get_int_type__s i307243
Ref: 168307243
Ref: cp/topics/types gccjit context get_int_type T307397
Ref: 169307397
Node: Pointers const and volatile<2>307653
Ref: cp/topics/types pointers-const-and-volatile307781
Ref: 16a307781
Ref: cp/topics/types gccjit type get_pointer307866
Ref: 165307866
Ref: cp/topics/types gccjit type get_const307963
Ref: 166307963
Ref: cp/topics/types gccjit type get_volatile308063
Ref: 16b308063
Ref: cp/topics/types gccjit type get_aligned__s308169
Ref: 16c308169
Ref: cp/topics/types gccjit context new_array_type__gccjit type i gccjit location308399
Ref: 16d308399
Node: Vector types<2>308639
Ref: cp/topics/types vector-types308774
Ref: 16e308774
Ref: cp/topics/types gccjit type get_vector__s308817
Ref: 16f308817
Node: Structures and unions<2>309083
Ref: cp/topics/types structures-and-unions309179
Ref: 170309179
Ref: cp/topics/types gccjit struct_309240
Ref: 171309240
Ref: cp/topics/types gccjit field309441
Ref: 172309441
Ref: cp/topics/types gccjit context new_field__gccjit type cCP gccjit location310808
Ref: 173310808
Ref: cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location310996
Ref: 174310996
Ref: cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location311231
Ref: 175311231
Node: Expressions<2>311609
Ref: cp/topics/expressions expressions311738
Ref: 176311738
Ref: cp/topics/expressions doc311738
Ref: 177311738
Node: Rvalues<2>312302
Ref: cp/topics/expressions rvalues312385
Ref: 178312385
Ref: cp/topics/expressions gccjit rvalue312418
Ref: 179312418
Ref: cp/topics/expressions gccjit rvalue get_type313174
Ref: 17a313174
Node: Simple expressions<2>313598
Ref: cp/topics/expressions simple-expressions313699
Ref: 17b313699
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type iC313754
Ref: 133313754
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type lC313983
Ref: 17c313983
Ref: cp/topics/expressions gccjit context zero__gccjit typeC314214
Ref: 12f314214
Ref: cp/topics/expressions gccjit context one__gccjit typeC314487
Ref: 17d314487
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC314758
Ref: 17e314758
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC314993
Ref: 17f314993
Ref: cp/topics/expressions gccjit context new_rvalue__ssCRC315178
Ref: 180315178
Node: Vector expressions<2>315407
Ref: cp/topics/expressions vector-expressions315536
Ref: 181315536
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C315591
Ref: 182315591
Node: Unary Operations<2>315910
Ref: cp/topics/expressions unary-operations316038
Ref: 183316038
Ref: cp/topics/expressions gccjit context new_unary_op__enum gccjit type gccjit rvalue gccjit location316089
Ref: 184316089
Ref: cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location316595
Ref: 185316595
Ref: cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location316919
Ref: 186316919
Ref: cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location317262
Ref: 187317262
Ref: cp/topics/expressions sub-operator__gccjit rvalue317671
Ref: 188317671
Ref: cp/topics/expressions inv-operator__gccjit rvalue317773
Ref: 189317773
Ref: cp/topics/expressions not-operator__gccjit rvalue317873
Ref: 18a317873
Node: Binary Operations<2>317977
Ref: cp/topics/expressions binary-operations318098
Ref: 18b318098
Ref: cp/topics/expressions gccjit context new_binary_op__enum gccjit type gccjit rvalue gccjit rvalue gccjit location318151
Ref: 123318151
Ref: cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location318684
Ref: 18c318684
Ref: cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location318849
Ref: 18d318849
Ref: cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location319015
Ref: 18e319015
Ref: cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location319180
Ref: 18f319180
Ref: cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location319347
Ref: 190319347
Ref: cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location319514
Ref: 191319514
Ref: cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location319686
Ref: 192319686
Ref: cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location319858
Ref: 193319858
Ref: cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location320029
Ref: 194320029
Ref: cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location320201
Ref: 195320201
Ref: cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue320440
Ref: 196320440
Ref: cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue320570
Ref: 197320570
Ref: cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue320701
Ref: 198320701
Ref: cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue320832
Ref: 199320832
Ref: cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue320965
Ref: 19a320965
Ref: cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue321095
Ref: 19b321095
Ref: cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue321223
Ref: 19c321223
Ref: cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue321351
Ref: 19d321351
Ref: cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue321479
Ref: 19e321479
Ref: cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue321612
Ref: 19f321612
Node: Comparisons<2>321899
Ref: cp/topics/expressions comparisons322018
Ref: 1a0322018
Ref: cp/topics/expressions gccjit context new_comparison__enum gccjit rvalue gccjit rvalue gccjit location322059
Ref: 130322059
Ref: cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location322581
Ref: 1a1322581
Ref: cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location322708
Ref: 1a2322708
Ref: cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location322835
Ref: 1a3322835
Ref: cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location322962
Ref: 1a4322962
Ref: cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location323089
Ref: 1a5323089
Ref: cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location323216
Ref: 1a6323216
Ref: cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue323411
Ref: 1a7323411
Ref: cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue323562
Ref: 1a8323562
Ref: cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue323697
Ref: 1a9323697
Ref: cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue323828
Ref: 1aa323828
Ref: cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue323961
Ref: 1ab323961
Ref: cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue324099
Ref: 1ac324099
Node: Function calls<2>324265
Ref: cp/topics/expressions function-calls324384
Ref: 1ad324384
Ref: cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP324431
Ref: 1ae324431
Node: Function pointers<3>325389
Ref: cp/topics/expressions function-pointers325510
Ref: 1b0325510
Ref: cp/topics/expressions gccjit function get_address__gccjit location325563
Ref: 1b1325563
Node: Type-coercion<2>325740
Ref: cp/topics/expressions type-coercion325835
Ref: 1b2325835
Ref: cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location325880
Ref: 1b3325880
Node: Lvalues<2>326271
Ref: cp/topics/expressions lvalues326406
Ref: 1b4326406
Ref: cp/topics/expressions gccjit lvalue326441
Ref: 1b5326441
Ref: cp/topics/expressions gccjit lvalue get_address__gccjit location326773
Ref: 1b6326773
Node: Global variables<2>327034
Ref: cp/topics/expressions global-variables327103
Ref: 1b7327103
Ref: cp/topics/expressions gccjit context new_global__enum gccjit type cCP gccjit location327156
Ref: 1b8327156
Node: Working with pointers structs and unions<2>327557
Ref: cp/topics/expressions working-with-pointers-structs-and-unions327673
Ref: 1b9327673
Ref: cp/topics/expressions gccjit rvalue dereference__gccjit location327776
Ref: 1ba327776
Ref: cp/topics/expressions gccjit rvalue mul-operator328161
Ref: 1bb328161
Ref: cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location328335
Ref: 1bc328335
Ref: cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location328623
Ref: 1bd328623
Ref: cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location328878
Ref: 1be328878
Ref: cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location329210
Ref: 1bf329210
Node: Creating and using functions<2>330032
Ref: cp/topics/functions doc330172
Ref: 1c0330172
Ref: cp/topics/functions creating-and-using-functions330172
Ref: 1c1330172
Node: Params<2>330351
Ref: cp/topics/functions params330452
Ref: 1c2330452
Ref: cp/topics/functions gccjit param330483
Ref: 1c3330483
Ref: cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location330574
Ref: 122330574
Node: Functions<2>331019
Ref: cp/topics/functions functions331138
Ref: 1c4331138
Ref: cp/topics/functions gccjit function331175
Ref: 1c5331175
Ref: cp/topics/functions gccjit context new_function__enum gccjit type cCP std vector param R i gccjit location331336
Ref: 1c6331336
Ref: cp/topics/functions gccjit context get_builtin_function__cCP331784
Ref: 1c7331784
Ref: cp/topics/functions gccjit function get_param__iC331984
Ref: 1c8331984
Ref: cp/topics/functions gccjit function dump_to_dot__cCP332122
Ref: 135332122
Ref: cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location332256
Ref: 12c332256
Node: Blocks<2>332475
Ref: cp/topics/functions blocks332598
Ref: 1c9332598
Ref: cp/topics/functions gccjit block332629
Ref: 1ca332629
Ref: cp/topics/functions gccjit function new_block__cCP333219
Ref: 1cb333219
Node: Statements<2>333535
Ref: cp/topics/functions statements333637
Ref: 1cc333637
Ref: cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location333676
Ref: 1af333676
Ref: cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location333956
Ref: 12e333956
Ref: cp/topics/functions gccjit block add_assignment_op__gccjit lvalue enum gccjit rvalue gccjit location334248
Ref: 132334248
Ref: cp/topics/functions gccjit block add_comment__cCP gccjit location334787
Ref: 13d334787
Ref: cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location335318
Ref: 131335318
Ref: cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location335814
Ref: 1cd335814
Ref: cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location336063
Ref: 1ce336063
Ref: cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location336763
Ref: 1cf336763
Ref: cp/topics/functions gccjit block end_with_switch gccjit case_337996
Ref: 1d1337996
Ref: cp/topics/functions gccjit block end_with_switch gccjit context new_case__gccjit rvalue gccjit rvalue gccjit block338452
Ref: 1d0338452
Node: Source Locations<2>342191
Ref: cp/topics/locations source-locations342339
Ref: 1d2342339
Ref: cp/topics/locations doc342339
Ref: 1d3342339
Ref: cp/topics/locations gccjit location342386
Ref: 153342386
Ref: cp/topics/locations gccjit context new_location__cCP i i343110
Ref: 141343110
Node: Faking it<2>343355
Ref: cp/topics/locations faking-it343426
Ref: 1d4343426
Node: Compiling a context<2>344051
Ref: cp/topics/compilation compiling-a-context344159
Ref: 1d5344159
Ref: cp/topics/compilation doc344159
Ref: 1d6344159
Node: In-memory compilation<2>344713
Ref: cp/topics/compilation in-memory-compilation344836
Ref: 1d8344836
Ref: cp/topics/compilation gccjit context compile344897
Ref: 124344897
Node: Ahead-of-time compilation<2>345141
Ref: cp/topics/compilation ahead-of-time-compilation345264
Ref: 1d9345264
Ref: cp/topics/compilation gccjit context compile_to_file__enum cCP345543
Ref: 1d7345543
Node: Internals345847
Ref: internals/index internals345961
Ref: 1da345961
Ref: internals/index doc345961
Ref: 1db345961
Node: Working on the JIT library346171
Ref: internals/index working-on-the-jit-library346277
Ref: 1dc346277
Ref: internals/index cmdoption--enable-host-shared347148
Ref: 1dd347148
Ref: internals/index cmdoption--enable-languages347366
Ref: 1de347366
Ref: internals/index cmdoption--disable-bootstrap347901
Ref: 1df347901
Ref: internals/index cmdoption--enable-checking348193
Ref: 1e0348193
Node: Running the test suite348453
Ref: internals/index running-the-test-suite348589
Ref: 1e1348589
Node: Running under valgrind349629
Ref: internals/index running-under-valgrind349713
Ref: 1e2349713
Ref: Running under valgrind-Footnote-1351261
Ref: Running under valgrind-Footnote-2351288
Ref: Running under valgrind-Footnote-3351342
Node: Environment variables351411
Ref: internals/index environment-variables351536
Ref: 1e3351536
Ref: internals/index envvar-LD_LIBRARY_PATH351697
Ref: 1e4351697
Ref: internals/index envvar-PATH352295
Ref: 1e5352295
Ref: internals/index envvar-LIBRARY_PATH352933
Ref: 1e6352933
Node: Packaging notes353878
Ref: internals/index packaging-notes354007
Ref: 1e7354007
Node: Overview of code structure355358
Ref: internals/index overview-of-code-structure355478
Ref: 1e8355478
Ref: internals/index example-of-log-file371722
Ref: 5c371722
Node: Design notes382639
Ref: internals/index design-notes382762
Ref: 1e9382762
Node: Submitting patches383287
Ref: internals/index submitting-patches383375
Ref: 1ea383375
Ref: Submitting patches-Footnote-1387825
Node: Indices and tables387855
Ref: index indices-and-tables387948
Ref: 1eb387948
Node: Index388036

End Tag Table
