Sindbad~EG File Manager

Current Path : /usr/local/share/info/gcc13/
Upload File :
Current File : //usr/local/share/info/gcc13/libgccjit.info

This is libgccjit.info, produced by makeinfo version 7.1 from
libgccjit.texi.

     libgccjit 12.0.1 (experimental 20220411), Apr 12, 2022

     David Malcolm

     Copyright © 2014-2023 Free Software Foundation, Inc.

INFO-DIR-SECTION Miscellaneous
START-INFO-DIR-ENTRY
* libgccjit: (libgccjit.info). GCC-based Just In Time compiler library.
END-INFO-DIR-ENTRY


   Generated by Sphinx 2.2.2.


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

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

     libgccjit 12.0.1 (experimental 20220411), Apr 12, 2022

     David Malcolm

     Copyright © 2014-2023 Free Software Foundation, Inc.

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

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::
* Using Assembly Language with libgccjit::

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::
* Reflection API::

Expressions

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

Rvalues

* Simple expressions::
* Constructor 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

* Programmatically checking version::
* 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::
* LIBGCCJIT_ABI_11::
* LIBGCCJIT_ABI_12::
* LIBGCCJIT_ABI_13::
* LIBGCCJIT_ABI_14::
* LIBGCCJIT_ABI_15::
* LIBGCCJIT_ABI_16::
* LIBGCCJIT_ABI_17::
* LIBGCCJIT_ABI_18::
* LIBGCCJIT_ABI_19::
* LIBGCCJIT_ABI_20::
* LIBGCCJIT_ABI_21::
* LIBGCCJIT_ABI_22::
* LIBGCCJIT_ABI_23::
* LIBGCCJIT_ABI_24::

Performance

* The timing API::

Using Assembly Language with libgccjit

* Adding assembler instructions within a function::
* Adding top-level assembler statements::

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>.
* Using Assembly Language with libgccjit++::

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

Using Assembly Language with libgccjit++

* Adding assembler instructions within a function: Adding assembler instructions within a function<2>.
* Adding top-level assembler statements: Adding top-level assembler statements<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) https://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-2023 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-2023 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:

[image src="libgccjit-figures/sum-of-squares1.png" alt="image of a control flow graph"]


     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’):

[image src="libgccjit-figures/sum-of-squares1.png" alt="image of a control flow graph"]


     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-2023 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     ‘[..., x, y]’       ‘[..., (x+y)]’
                           on 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     ‘[..., x]’          ‘[..., fn(x)]’
                           of the stack, and popping                        
                           the result.
                           
                                                                            
RETURN                     Return the top of the        ‘[x]’               ‘[]’
                           stack.                                           
                           
                                                                            
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[100];
                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.

[image src="libgccjit-figures/factorial1.png" alt="image of a control flow graph"]


     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:

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::
* Using Assembly Language with libgccjit::


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

 -- C Function: void gcc_jit_context_set_bool_print_errors_to_stderr
          (gcc_jit_context *ctxt, int enabled)

     By default, libgccjit will print errors to stderr.

     This entrypoint can be used to disable the printing.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_print_errors_to_stderr


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: 75.; you can
     test for its presence using

          #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option

 -- C Function: void gcc_jit_context_add_driver_option
          (gcc_jit_context *ctxt, const char *optname)

     Add an arbitrary gcc driver 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_driver_option’ are
     applied `after' all other options 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_driver_option (ctxt, "-lm");
          gcc_jit_context_add_driver_option (ctxt, "-fuse-linker-plugin");

          gcc_jit_context_add_driver_option (ctxt, "obj.o");

          gcc_jit_context_add_driver_option (ctxt, "-L.");
          gcc_jit_context_add_driver_option (ctxt, "-lwhatever");

     Note that only some options are likely to be meaningful; there is
     no “frontend” within libgccjit, so typically only those affecting
     assembler and linker are likely to be useful.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_context_add_driver_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
         +- gcc_jit_extended_asm

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(): 7d. and *note gcc_jit_type_get_const():
     7e.:

          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::
* Reflection API::


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_UINT8_T’                         C99’s ‘uint8_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_UINT16_T’                        C99’s ‘uint16_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_UINT32_T’                        C99’s ‘uint32_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_UINT64_T’                        C99’s ‘uint64_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_UINT128_T’                       C99’s ‘__uint128_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_INT8_T’                          C99’s ‘int8_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_INT16_T’                         C99’s ‘int16_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_INT32_T’                         C99’s ‘int32_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_INT64_T’                         C99’s ‘int64_t’
                                                    
                                                    
     ‘GCC_JIT_TYPE_INT128_T’                        C99’s ‘__int128_t’
                                                    
                                                    
     ‘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 non-‘void’ 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 non-‘void’ 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: 85.; 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: 88.; 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(): 89.


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: 8b.

You can model C ‘struct’ types by creating *note gcc_jit_struct: 8b. and
*note gcc_jit_field: 8c. 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 ‘type’ must be non-‘void’.

     The parameter ‘name’ must be non-NULL. The call takes a copy of the
     underlying string, so it is valid to pass in a pointer to an
     on-stack buffer.

 -- C Function: gcc_jit_field * gcc_jit_context_new_bitfield
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, int width, const char *name)

     Construct a new bit field, with the given type width 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.

     The parameter ‘type’ must be an integer type.

     The parameter ‘width’ must be a positive integer that does not
     exceed the size of ‘type’.

     This API entrypoint was added in *note LIBGCCJIT_ABI_12: 8f.; you
     can test for its presence using

          #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitfield

 -- 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(): 93.

     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,  Next: Reflection API,  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(): 97.


File: libgccjit.info,  Node: Reflection API,  Prev: Function pointer types,  Up: Types

2.3.6 Reflection API
--------------------

 -- C Function: gcc_jit_type * gcc_jit_type_dyncast_array
          (gcc_jit_type *type)

     Get the element type of an array type or NULL if it’s not an array.

 -- C Function: int gcc_jit_type_is_bool (gcc_jit_type *type)

     Return non-zero if the type is a bool.

 -- C Function: gcc_jit_function_type *
          gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)

     Return the function type if it is one or NULL.

 -- C Function: gcc_jit_type * gcc_jit_function_type_get_return_type
          (gcc_jit_function_type *function_type)

     Given a function type, return its return type.

 -- C Function: size_t gcc_jit_function_type_get_param_count
          (gcc_jit_function_type *function_type)

     Given a function type, return its number of parameters.

 -- C Function: gcc_jit_type * gcc_jit_function_type_get_param_type
          (gcc_jit_function_type *function_type, size_t index)

     Given a function type, return the type of the specified parameter.

 -- C Function: int gcc_jit_type_is_integral (gcc_jit_type *type)

     Return non-zero if the type is an integral.

 -- C Function: gcc_jit_type * gcc_jit_type_is_pointer
          (gcc_jit_type *type)

     Return the type pointed by the pointer type or NULL if it’s not a
     pointer.

 -- C Function: gcc_jit_vector_type * gcc_jit_type_dyncast_vector
          (gcc_jit_type *type)

     Given a type, return a dynamic cast to a vector type or NULL.

 -- C Function: gcc_jit_struct * gcc_jit_type_is_struct
          (gcc_jit_type *type)

     Given a type, return a dynamic cast to a struct type or NULL.

 -- C Function: size_t gcc_jit_vector_type_get_num_units
          (gcc_jit_vector_type *vector_type)

     Given a vector type, return the number of units it contains.

 -- C Function: gcc_jit_type * gcc_jit_vector_type_get_element_type
          (gcc_jit_vector_type * vector_type)

     Given a vector type, return the type of its elements.

 -- C Function: gcc_jit_type * gcc_jit_type_unqualified
          (gcc_jit_type *type)

     Given a type, return the unqualified type, removing “const”,
     “volatile” and alignment qualifiers.

 -- C Function: gcc_jit_field * gcc_jit_struct_get_field
          (gcc_jit_struct *struct_type, size_t index)

     Get a struct field by index.

 -- C Function: size_t gcc_jit_struct_get_field_count
          (gcc_jit_struct *struct_type)

          Get the number of fields in the struct.

     The API entrypoints related to the reflection API:

             * *note gcc_jit_function_type_get_return_type(): 9c.

             * *note gcc_jit_function_type_get_param_count(): 9d.

             * *note gcc_jit_function_type_get_param_type(): 9e.

             * *note gcc_jit_type_unqualified(): a5.

             * *note gcc_jit_type_dyncast_array(): 99.

             * *note gcc_jit_type_is_bool(): 9a.

             * *note gcc_jit_type_dyncast_function_ptr_type(): 9b.

             * *note gcc_jit_type_is_integral(): 9f.

             * *note gcc_jit_type_is_pointer(): a0.

             * *note gcc_jit_type_dyncast_vector(): a1.

             * *note gcc_jit_vector_type_get_element_type(): a4.

             * *note gcc_jit_vector_type_get_num_units(): a3.

             * *note gcc_jit_struct_get_field(): a6.

             * *note gcc_jit_type_is_struct(): a2.

             * *note gcc_jit_struct_get_field_count(): a7.

     were added in *note LIBGCCJIT_ABI_16: a8.; you can test for their
     presence using

          #ifdef LIBGCCJIT_HAVE_REFLECTION

      -- C Type: gcc_jit_case

 -- C Function: int gcc_jit_compatible_types (gcc_jit_type *ltype,
          gcc_jit_type *rtype)

          Return non-zero if the two types are compatible.  For
          instance, if ‘GCC_JIT_TYPE_UINT64_T’ and
          ‘GCC_JIT_TYPE_UNSIGNED_LONG’ are the same size on the target,
          this will return non-zero.  The parameters ‘ltype’ and ‘rtype’
          must be non-NULL. Return 0 on errors.

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

          #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS

 -- C Function: ssize_t gcc_jit_type_get_size (gcc_jit_type *type)

          Return the size of a type, in bytes.  It only works on integer
          types for now.  The parameter ‘type’ must be non-NULL. Return
          -1 on errors.

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

          #ifdef LIBGCCJIT_HAVE_SIZED_INTEGERS


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.


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::
* Constructor expressions::
* Vector expressions::
* Unary Operations::
* Binary Operations::
* Comparisons::
* Function calls::
* Function pointers::
* Type-coercion::


File: libgccjit.info,  Node: Simple expressions,  Next: Constructor 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: Constructor expressions,  Next: Vector expressions,  Prev: Simple expressions,  Up: Rvalues

2.4.1.2 Constructor expressions
...............................

     The following functions make constructors for array, struct and
     union types.

     The constructor rvalue can be used for assignment to locals.  It
     can be used to initialize global variables with *note
     gcc_jit_global_set_initializer_rvalue(): b7.  It can also be used
     as a temporary value for function calls and return values, but its
     address can’t be taken.

     Note that arrays in libgccjit do not collapse to pointers like in
     C. I.e.  if an array constructor is used as e.g.  a return value,
     the whole array would be returned by value - array constructors can
     be assigned to array variables.

     The constructor can contain nested constructors.

     Note that a string literal rvalue can’t be used to construct a char
     array; the latter needs one rvalue for each char.

     These entrypoints were added in *note LIBGCCJIT_ABI_19: b8.; you
     can test for their presence using:

          #ifdef LIBGCCJIT_HAVE_CTORS

 -- C Function: gcc_jit_rvalue * gcc_jit_context_new_array_constructor
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, size_t num_values,
          gcc_jit_rvalue **values)

     Create a constructor for an array as an rvalue.

     Returns NULL on error.  ‘values’ are copied and do not have to
     outlive the context.

     ‘type’ specifies what the constructor will build and has to be an
     array.

     ‘num_values’ specifies the number of elements in ‘values’ and it
     can’t have more elements than the array type.

     Each value in ‘values’ sets the corresponding value in the array.
     If the array type itself has more elements than ‘values’, the
     left-over elements will be zeroed.

     Each value in ‘values’ need to be the same unqualified type as the
     array type’s element type.

     If ‘num_values’ is 0, the ‘values’ parameter will be ignored and
     zero initialization will be used.

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

          #ifdef LIBGCCJIT_HAVE_CTORS

 -- C Function: gcc_jit_rvalue * gcc_jit_context_new_struct_constructor
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, size_t num_values, gcc_jit_field **fields,
          gcc_jit_rvalue **values)

     Create a constructor for a struct as an rvalue.

     Returns NULL on error.  The two parameter arrays are copied and do
     not have to outlive the context.

     ‘type’ specifies what the constructor will build and has to be a
     struct.

     ‘num_values’ specifies the number of elements in ‘values’.

     ‘fields’ need to have the same length as ‘values’, or be NULL.

     If ‘fields’ is null, the values are applied in definition order.

     Otherwise, each field in ‘fields’ specifies which field in the
     struct to set to the corresponding value in ‘values’.  ‘fields’ and
     ‘values’ are paired by index.

     The fields in ‘fields’ have to be in definition order, but there
     can be gaps.  Any field in the struct that is not specified in
     ‘fields’ will be zeroed.

     The fields in ‘fields’ need to be the same objects that were used
     to create the struct.

     Each value has to have have the same unqualified type as the field
     it is applied to.

     A NULL value element in ‘values’ is a shorthand for zero
     initialization of the corresponding field.

     If ‘num_values’ is 0, the array parameters will be ignored and zero
     initialization will be used.

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

          #ifdef LIBGCCJIT_HAVE_CTORS

 -- C Function: gcc_jit_rvalue * gcc_jit_context_new_union_constructor
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_type *type, gcc_jit_field *field,
          gcc_jit_rvalue *value)

     Create a constructor for a union as an rvalue.

     Returns NULL on error.

     ‘type’ specifies what the constructor will build and has to be an
     union.

     ‘field’ specifies which field to set.  If it is NULL, the first
     field in the union will be set.''field'' need to be the same object
     that were used to create the union.

     ‘value’ specifies what value to set the corresponding field to.  If
     ‘value’ is NULL, zero initialization will be used.

     Each value has to have have the same unqualified type as the field
     it is applied to.

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

          #ifdef LIBGCCJIT_HAVE_CTORS


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

2.4.1.3 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(): 87.

     “num_elements” should match that of the vector type.

     This entrypoint was added in *note LIBGCCJIT_ABI_10: bd.; 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.4 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.

     The parameter ‘result_type’ must be a numeric type.

 -- C Type: enum gcc_jit_unary_op

The available unary operations are:

Unary Operation                                C equivalent
                                               
----------------------------------------------------------------
                                               
*note GCC_JIT_UNARY_OP_MINUS: c1.              ‘-(EXPR)’
                                               
                                               
*note GCC_JIT_UNARY_OP_BITWISE_NEGATE: c2.     ‘~(EXPR)’
                                               
                                               
*note GCC_JIT_UNARY_OP_LOGICAL_NEGATE: c3.     ‘!(EXPR)’
                                               
                                               
*note GCC_JIT_UNARY_OP_ABS: c4.                ‘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.5 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.

     The parameter ‘result_type’ must be a numeric type.

 -- C Type: enum gcc_jit_binary_op

The available binary operations are:

Binary Operation                             C equivalent
                                             
--------------------------------------------------------------
                                             
*note GCC_JIT_BINARY_OP_PLUS: c7.            ‘x + y’
                                             
                                             
*note GCC_JIT_BINARY_OP_MINUS: c8.           ‘x - y’
                                             
                                             
*note GCC_JIT_BINARY_OP_MULT: c9.            ‘x * y’
                                             
                                             
*note GCC_JIT_BINARY_OP_DIVIDE: ca.          ‘x / y’
                                             
                                             
*note GCC_JIT_BINARY_OP_MODULO: cb.          ‘x % y’
                                             
                                             
*note GCC_JIT_BINARY_OP_BITWISE_AND: cc.     ‘x & y’
                                             
                                             
*note GCC_JIT_BINARY_OP_BITWISE_XOR: cd.     ‘x ^ y’
                                             
                                             
*note GCC_JIT_BINARY_OP_BITWISE_OR: ce.      ‘x | y’
                                             
                                             
*note GCC_JIT_BINARY_OP_LOGICAL_AND: cf.     ‘x && y’
                                             
                                             
*note GCC_JIT_BINARY_OP_LOGICAL_OR: d0.      ‘x || y’
                                             
                                             
*note GCC_JIT_BINARY_OP_LSHIFT: d1.          ‘x << y’
                                             
                                             
*note GCC_JIT_BINARY_OP_RSHIFT: d2.          ‘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():
     d3.

 -- 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.6 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.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: *note gcc_jit_context_new_call(): d7. 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(): d8.:

               /* 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(): 97.), 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():
          d7. 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(): d7. or *note
     gcc_jit_context_new_call_through_ptr(): d9, 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: db.; 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.8 Function pointers
.........................

Function pointers can be obtained:

        * from a *note gcc_jit_function: 29. using *note
          gcc_jit_function_get_address(): dd, or

        * from an existing function using *note
          gcc_jit_context_new_rvalue_from_ptr(): b3, using a function
          pointer type obtained using *note
          gcc_jit_context_new_function_ptr_type(): 97.


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

2.4.1.9 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

 -- C Function: gcc_jit_rvalue * gcc_jit_context_new_bitcast
          (gcc_jit_context *ctxt, gcc_jit_location *loc,
          gcc_jit_rvalue *rvalue, gcc_jit_type *type)

     Given an rvalue of T, bitcast it to another type, meaning that this
     will generate a new rvalue by interpreting the bits of ‘rvalue’ to
     the layout of ‘type’.

     The type of rvalue must be the same size as the size of ‘type’.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast


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.

 -- C Function: void gcc_jit_lvalue_set_tls_model
          (gcc_jit_lvalue *lvalue, enum gcc_jit_tls_model model)

     Make a variable a thread-local variable.

     The “model” parameter determines the thread-local storage model of
     the “lvalue”:

      -- C Type: enum gcc_jit_tls_model

      -- C Macro: GCC_JIT_TLS_MODEL_NONE

          Don’t set the TLS model.

      -- C Macro: GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC

      -- C Macro: GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC

      -- C Macro: GCC_JIT_TLS_MODEL_INITIAL_EXEC

      -- C Macro: GCC_JIT_TLS_MODEL_LOCAL_EXEC

     This is analogous to:

          _Thread_local int foo __attribute__ ((tls_model("MODEL")));

     in C.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_tls_model

 -- C Function: void gcc_jit_lvalue_set_link_section
          (gcc_jit_lvalue *lvalue, const char *section_name)

     Set the link section of a variable.  The parameter ‘section_name’
     must be non-NULL and must contain the leading dot.  Analogous to:

          int variable __attribute__((section(".section")));

     in C.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_link_section

 -- C Function: void gcc_jit_lvalue_set_register_name (gcc_jit_lvalue
          *lvalue, const char *reg_name);

     Set the register name of a variable.  The parameter ‘reg_name’ must
     be non-NULL. Analogous to:

          register int variable asm ("r12");

     in C.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_lvalue_set_register_name

 -- C Function: void gcc_jit_lvalue_set_alignment
          (gcc_jit_lvalue *lvalue, unsigned bytes)

     Set the alignment of a variable, in bytes.  Analogous to:

          int variable __attribute__((aligned (16)));

     in C.

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

          #ifdef LIBGCCJIT_HAVE_ALIGNMENT

 -- C Function: unsigned gcc_jit_lvalue_get_alignment
          (gcc_jit_lvalue *lvalue)

     Return the alignment of a variable set by
     ‘gcc_jit_lvalue_set_alignment’.  Return 0 if the alignment was not
     set.  Analogous to:

          _Alignof (variable)

     in C.

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

          #ifdef LIBGCCJIT_HAVE_ALIGNMENT

* 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 ‘type’ must be non-‘void’.

     The parameter ‘name’ must be non-NULL. The call takes a copy of the
     underlying string, so it is valid to pass in a pointer to an
     on-stack buffer.

     The “kind” parameter determines the visibility of the “global”
     outside of the *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(): f8. (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.

 -- C Function: gcc_jit_lvalue * gcc_jit_global_set_initializer
          (gcc_jit_lvalue *global, const void *blob, size_t num_bytes)

     Set an initializer for ‘global’ using the memory content pointed by
     ‘blob’ for ‘num_bytes’.  ‘global’ must be an array of an integral
     type.  Return the global itself.

     The parameter ‘blob’ must be non-NULL. The call copies the memory
     pointed by ‘blob’ for ‘num_bytes’ bytes, so it is valid to pass in
     a pointer to an on-stack buffer.  The content will be stored in the
     compilation unit and used as initialization value of the array.

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

          #ifdef LIBGCCJIT_HAVE_gcc_jit_global_set_initializer

 -- C Function: gcc_jit_lvalue * gcc_jit_global_set_initializer_rvalue
          (gcc_jit_lvalue *global, gcc_jit_rvalue *init_value)

     Set the initial value of a global with an rvalue.

     The rvalue needs to be a constant expression, e.g.  no function
     calls.

     The global can’t have the ‘kind’ *note GCC_JIT_GLOBAL_IMPORTED: fa.

     As a non-comprehensive example it is OK to do the equivalent of:

          int foo = 3 * 2; /* rvalue from gcc_jit_context_new_binary_op.  */
          int arr[] = {1,2,3,4}; /* rvalue from gcc_jit_context_new_constructor.  */
          int *bar = &arr[2] + 1; /* rvalue from nested "get address" of "array access".  */
          const int baz = 3; /* rvalue from gcc_jit_context_rvalue_from_int.  */
          int boz = baz; /* rvalue from gcc_jit_lvalue_as_rvalue.  */

     Use together with *note gcc_jit_context_new_struct_constructor():
     ba, *note gcc_jit_context_new_union_constructor(): bb, *note
     gcc_jit_context_new_array_constructor(): b9. to initialize structs,
     unions and arrays.

     On success, returns the ‘global’ parameter unchanged.  Otherwise,
     ‘NULL’.

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

          #ifdef LIBGCCJIT_HAVE_CTORS


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 ‘type’ must be non-‘void’.

     The parameter ‘name’ must be non-NULL. The call takes a copy of the
     underlying string, so it is valid to pass in a pointer to an
     on-stack buffer.

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)

     Get the *note gcc_jit_function: 29. for the built-in function with
     the given name.  For example:

          gcc_jit_function *fn
            = gcc_jit_context_get_builtin_function (ctxt, "__builtin_memcpy");

          Note: Due to technical limitations with how libgccjit
          interacts with the insides of GCC, not all built-in functions
          are supported.  More precisely, not all types are supported
          for parameters of built-in functions from libgccjit.  Attempts
          to get a built-in function that uses such a parameter will
          lead to an error being emitted within the context.

 -- 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 ‘type’ must be non-‘void’.

     The parameter ‘name’ must be non-NULL. The call takes a copy of the
     underlying string, so it is valid to pass in a pointer to an
     on-stack buffer.

 -- C Function: size_t gcc_jit_function_get_param_count
          (gcc_jit_function *func)

     Get the number of parameters of the function.

 -- C Function: gcc_jit_type * gcc_jit_function_get_return_type
          (gcc_jit_function *func)

     Get the return type of the function.

     The API entrypoints relating to getting info about parameters and
     return types:

             * *note gcc_jit_function_get_return_type(): 112.

             * *note gcc_jit_function_get_param_count(): 111.

     were added in *note LIBGCCJIT_ABI_16: a8.; you can test for their
     presence using

          #ifdef LIBGCCJIT_HAVE_REFLECTION

      -- C Type: gcc_jit_case


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(): 11c.

             * *note gcc_jit_case_as_object(): 11d.

             * *note gcc_jit_context_new_case(): 11e.

     were added in *note LIBGCCJIT_ABI_3: 11f.; 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(): 11e.

     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));
               }


See also *note gcc_jit_extended_asm: 120. for entrypoints for adding
inline assembler statements to a function.


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(): d9.

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(): dd.

 -- 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: 123.; 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(): b3, using a function pointer type
obtained using *note gcc_jit_context_new_function_ptr_type(): 97.

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.

     Each of ‘param_types’ must be non-‘void’; ‘return_type’ may be
     ‘void’.


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: 10a.:

          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(): f5. with ‘kind’ *note
     GCC_JIT_GLOBAL_EXPORTED: f7.

     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(): f8. 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.

For linking in object files, use *note
gcc_jit_context_add_driver_option(): 76.

 -- 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: 12c.          .s
                                                   
                                                   
*note GCC_JIT_OUTPUT_KIND_OBJECT_FILE: 12d.        .o
                                                   
                                                   
*note GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY: 12e.    .so or .dll
                                                   
                                                   
*note GCC_JIT_OUTPUT_KIND_EXECUTABLE: 12f.         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.

 -- C Macro: GCC_JIT_OUTPUT_KIND_EXECUTABLE

     Compile the context to an executable.


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(): 74. 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:

* Programmatically checking version::
* ABI symbol tags::


File: libgccjit.info,  Node: Programmatically checking version,  Next: ABI symbol tags,  Up: ABI and API compatibility

2.9.1 Programmatically checking version
---------------------------------------

Client code can programmatically check libgccjit version using:

 -- C Function: int gcc_jit_version_major (void)

     Return libgccjit major version.  This is analogous to __GNUC__ in C
     code.

 -- C Function: int gcc_jit_version_minor (void)

     Return libgccjit minor version.  This is analogous to
     __GNUC_MINOR__ in C code.

 -- C Function: int gcc_jit_version_patchlevel (void)

     Return libgccjit patchlevel version.  This is analogous to
     __GNUC_PATCHLEVEL__ in C code.

     Note: These entry points has been added with ‘LIBGCCJIT_ABI_13’
     (see below).


File: libgccjit.info,  Node: ABI symbol tags,  Prev: Programmatically checking version,  Up: ABI and API compatibility

2.9.2 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::
* LIBGCCJIT_ABI_11::
* LIBGCCJIT_ABI_12::
* LIBGCCJIT_ABI_13::
* LIBGCCJIT_ABI_14::
* LIBGCCJIT_ABI_15::
* LIBGCCJIT_ABI_16::
* LIBGCCJIT_ABI_17::
* LIBGCCJIT_ABI_18::
* LIBGCCJIT_ABI_19::
* LIBGCCJIT_ABI_20::
* LIBGCCJIT_ABI_21::
* LIBGCCJIT_ABI_22::
* LIBGCCJIT_ABI_23::
* LIBGCCJIT_ABI_24::


File: libgccjit.info,  Node: LIBGCCJIT_ABI_0,  Next: LIBGCCJIT_ABI_1,  Up: ABI symbol tags

2.9.2.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.2.2 ‘LIBGCCJIT_ABI_1’
.........................

‘LIBGCCJIT_ABI_1’ covers the addition of *note
gcc_jit_context_add_command_line_option(): 74.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_2,  Next: LIBGCCJIT_ABI_3,  Prev: LIBGCCJIT_ABI_1,  Up: ABI symbol tags

2.9.2.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.2.4 ‘LIBGCCJIT_ABI_3’
.........................

‘LIBGCCJIT_ABI_3’ covers the addition of switch statements via API
entrypoints:

        * *note gcc_jit_block_end_with_switch(): 11c.

        * *note gcc_jit_case_as_object(): 11d.

        * *note gcc_jit_context_new_case(): 11e.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_4,  Next: LIBGCCJIT_ABI_5,  Prev: LIBGCCJIT_ABI_3,  Up: ABI symbol tags

2.9.2.5 ‘LIBGCCJIT_ABI_4’
.........................

‘LIBGCCJIT_ABI_4’ covers the addition of timers via API entrypoints:

        * *note gcc_jit_context_get_timer(): 13e.

        * *note gcc_jit_context_set_timer(): 13f.

        * *note gcc_jit_timer_new(): 140.

        * *note gcc_jit_timer_release(): 141.

        * *note gcc_jit_timer_push(): 142.

        * *note gcc_jit_timer_pop(): 143.

        * *note gcc_jit_timer_print(): 144.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_5,  Next: LIBGCCJIT_ABI_6,  Prev: LIBGCCJIT_ABI_4,  Up: ABI symbol tags

2.9.2.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.2.7 ‘LIBGCCJIT_ABI_6’
.........................

‘LIBGCCJIT_ABI_6’ covers the addition of *note
gcc_jit_rvalue_set_bool_require_tail_call(): da.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_7,  Next: LIBGCCJIT_ABI_8,  Prev: LIBGCCJIT_ABI_6,  Up: ABI symbol tags

2.9.2.8 ‘LIBGCCJIT_ABI_7’
.........................

‘LIBGCCJIT_ABI_7’ covers the addition of *note
gcc_jit_type_get_aligned(): 84.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_8,  Next: LIBGCCJIT_ABI_9,  Prev: LIBGCCJIT_ABI_7,  Up: ABI symbol tags

2.9.2.9 ‘LIBGCCJIT_ABI_8’
.........................

‘LIBGCCJIT_ABI_8’ covers the addition of *note
gcc_jit_type_get_vector(): 87.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_9,  Next: LIBGCCJIT_ABI_10,  Prev: LIBGCCJIT_ABI_8,  Up: ABI symbol tags

2.9.2.10 ‘LIBGCCJIT_ABI_9’
..........................

‘LIBGCCJIT_ABI_9’ covers the addition of *note
gcc_jit_function_get_address(): dd.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_10,  Next: LIBGCCJIT_ABI_11,  Prev: LIBGCCJIT_ABI_9,  Up: ABI symbol tags

2.9.2.11 ‘LIBGCCJIT_ABI_10’
...........................

‘LIBGCCJIT_ABI_10’ covers the addition of *note
gcc_jit_context_new_rvalue_from_vector(): 89.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_11,  Next: LIBGCCJIT_ABI_12,  Prev: LIBGCCJIT_ABI_10,  Up: ABI symbol tags

2.9.2.12 ‘LIBGCCJIT_ABI_11’
...........................

‘LIBGCCJIT_ABI_11’ covers the addition of *note
gcc_jit_context_add_driver_option(): 76.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_12,  Next: LIBGCCJIT_ABI_13,  Prev: LIBGCCJIT_ABI_11,  Up: ABI symbol tags

2.9.2.13 ‘LIBGCCJIT_ABI_12’
...........................

‘LIBGCCJIT_ABI_12’ covers the addition of *note
gcc_jit_context_new_bitfield(): 8e.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_13,  Next: LIBGCCJIT_ABI_14,  Prev: LIBGCCJIT_ABI_12,  Up: ABI symbol tags

2.9.2.14 ‘LIBGCCJIT_ABI_13’
...........................

‘LIBGCCJIT_ABI_13’ covers the addition of version functions via API
entrypoints:

        * *note gcc_jit_version_major(): 133.

        * *note gcc_jit_version_minor(): 134.

        * *note gcc_jit_version_patchlevel(): 135.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_14,  Next: LIBGCCJIT_ABI_15,  Prev: LIBGCCJIT_ABI_13,  Up: ABI symbol tags

2.9.2.15 ‘LIBGCCJIT_ABI_14’
...........................

‘LIBGCCJIT_ABI_14’ covers the addition of *note
gcc_jit_global_set_initializer(): fb.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_15,  Next: LIBGCCJIT_ABI_16,  Prev: LIBGCCJIT_ABI_14,  Up: ABI symbol tags

2.9.2.16 ‘LIBGCCJIT_ABI_15’
...........................

‘LIBGCCJIT_ABI_15’ covers the addition of API entrypoints for directly
embedding assembler instructions:

        * *note gcc_jit_block_add_extended_asm(): 152.

        * *note gcc_jit_block_end_with_extended_asm_goto(): 153.

        * *note gcc_jit_extended_asm_as_object(): 154.

        * *note gcc_jit_extended_asm_set_volatile_flag(): 155.

        * *note gcc_jit_extended_asm_set_inline_flag(): 156.

        * *note gcc_jit_extended_asm_add_output_operand(): 157.

        * *note gcc_jit_extended_asm_add_input_operand(): 158.

        * *note gcc_jit_extended_asm_add_clobber(): 159.

        * *note gcc_jit_context_add_top_level_asm(): 15a.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_16,  Next: LIBGCCJIT_ABI_17,  Prev: LIBGCCJIT_ABI_15,  Up: ABI symbol tags

2.9.2.17 ‘LIBGCCJIT_ABI_16’
...........................

‘LIBGCCJIT_ABI_16’ covers the addition of reflection functions via API
entrypoints:

        * *note gcc_jit_function_get_return_type(): 112.

        * *note gcc_jit_function_get_param_count(): 111.

        * *note gcc_jit_type_dyncast_array(): 99.

        * *note gcc_jit_type_is_bool(): 9a.

        * *note gcc_jit_type_is_integral(): 9f.

        * *note gcc_jit_type_is_pointer(): a0.

        * *note gcc_jit_type_is_struct(): a2.

        * *note gcc_jit_type_dyncast_vector(): a1.

        * *note gcc_jit_type_unqualified(): a5.

        * *note gcc_jit_type_dyncast_function_ptr_type(): 9b.

        * *note gcc_jit_function_type_get_return_type(): 9c.

        * *note gcc_jit_function_type_get_param_count(): 9d.

        * *note gcc_jit_function_type_get_param_type(): 9e.

        * *note gcc_jit_vector_type_get_num_units(): a3.

        * *note gcc_jit_vector_type_get_element_type(): a4.

        * *note gcc_jit_struct_get_field(): a6.

        * *note gcc_jit_struct_get_field_count(): a7.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_17,  Next: LIBGCCJIT_ABI_18,  Prev: LIBGCCJIT_ABI_16,  Up: ABI symbol tags

2.9.2.18 ‘LIBGCCJIT_ABI_17’
...........................

‘LIBGCCJIT_ABI_17’ covers the addition of an API entrypoint to set the
thread-local storage model of a variable:

        * *note gcc_jit_lvalue_set_tls_model(): e6.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_18,  Next: LIBGCCJIT_ABI_19,  Prev: LIBGCCJIT_ABI_17,  Up: ABI symbol tags

2.9.2.19 ‘LIBGCCJIT_ABI_18’
...........................

‘LIBGCCJIT_ABI_18’ covers the addition of an API entrypoint to set the
link section of a variable:

        * *note gcc_jit_lvalue_set_link_section(): ee.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_19,  Next: LIBGCCJIT_ABI_20,  Prev: LIBGCCJIT_ABI_18,  Up: ABI symbol tags

2.9.2.20 ‘LIBGCCJIT_ABI_19’
...........................

‘LIBGCCJIT_ABI_19’ covers the addition of API entrypoints to set the
initial value of a global with an rvalue and to use constructors:

        * *note gcc_jit_context_new_array_constructor(): b9.

        * *note gcc_jit_context_new_struct_constructor(): ba.

        * *note gcc_jit_context_new_union_constructor(): bb.

        * *note gcc_jit_global_set_initializer_rvalue(): b7.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_20,  Next: LIBGCCJIT_ABI_21,  Prev: LIBGCCJIT_ABI_19,  Up: ABI symbol tags

2.9.2.21 ‘LIBGCCJIT_ABI_20’
...........................

‘LIBGCCJIT_ABI_20’ covers the addition of sized integer types, including
128-bit integers and helper functions for types:

        * *note gcc_jit_compatible_types(): aa.

        * *note gcc_jit_type_get_size(): ac.

        * ‘GCC_JIT_TYPE_UINT8_T’

        * ‘GCC_JIT_TYPE_UINT16_T’

        * ‘GCC_JIT_TYPE_UINT32_T’

        * ‘GCC_JIT_TYPE_UINT64_T’

        * ‘GCC_JIT_TYPE_UINT128_T’

        * ‘GCC_JIT_TYPE_INT8_T’

        * ‘GCC_JIT_TYPE_INT16_T’

        * ‘GCC_JIT_TYPE_INT32_T’

        * ‘GCC_JIT_TYPE_INT64_T’

        * ‘GCC_JIT_TYPE_INT128_T’


File: libgccjit.info,  Node: LIBGCCJIT_ABI_21,  Next: LIBGCCJIT_ABI_22,  Prev: LIBGCCJIT_ABI_20,  Up: ABI symbol tags

2.9.2.22 ‘LIBGCCJIT_ABI_21’
...........................

‘LIBGCCJIT_ABI_21’ covers the addition of an API entrypoint to bitcast a
value from one type to another:

        * *note gcc_jit_context_new_bitcast(): e0.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_22,  Next: LIBGCCJIT_ABI_23,  Prev: LIBGCCJIT_ABI_21,  Up: ABI symbol tags

2.9.2.23 ‘LIBGCCJIT_ABI_22’
...........................

‘LIBGCCJIT_ABI_22’ covers the addition of an API entrypoint to set the
register name of a variable:

        * ‘gcc_jit_lvalue_set_register_name()’


File: libgccjit.info,  Node: LIBGCCJIT_ABI_23,  Next: LIBGCCJIT_ABI_24,  Prev: LIBGCCJIT_ABI_22,  Up: ABI symbol tags

2.9.2.24 ‘LIBGCCJIT_ABI_23’
...........................

‘LIBGCCJIT_ABI_23’ covers the addition of an API entrypoint to hide
stderr logs:

        * *note gcc_jit_context_set_bool_print_errors_to_stderr(): 6f.


File: libgccjit.info,  Node: LIBGCCJIT_ABI_24,  Prev: LIBGCCJIT_ABI_23,  Up: ABI symbol tags

2.9.2.25 ‘LIBGCCJIT_ABI_24’
...........................

‘LIBGCCJIT_ABI_24’ covers the addition of functions to get and set the
alignment of a variable:

        * *note gcc_jit_lvalue_set_alignment(): f1.

        * *note gcc_jit_lvalue_get_alignment(): f3.


File: libgccjit.info,  Node: Performance,  Next: Using Assembly Language with libgccjit,  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: 167. 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: 167. instance, and start timing:

          gcc_jit_timer *t = gcc_jit_timer_new ();

     This API entrypoint was added in *note LIBGCCJIT_ABI_4: 13d.; 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: 167. 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: 13d.; 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: 167. 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: 13d.; 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: 13d.; 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: 13d.; 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: 13d.; 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: 13d.; you
     can test for its presence using

          #ifdef LIBGCCJIT_HAVE_TIMING_API


File: libgccjit.info,  Node: Using Assembly Language with libgccjit,  Prev: Performance,  Up: Topic Reference

2.11 Using Assembly Language with libgccjit
===========================================

libgccjit has some support for directly embedding assembler
instructions.  This is based on GCC’s support for inline ‘asm’ in C
code, and the following assumes a familiarity with that functionality.
See How to Use Inline Assembly Language in C Code(1) in GCC’s
documentation, the “Extended Asm” section in particular.

These entrypoints were added in *note LIBGCCJIT_ABI_15: 151.; you can
test for their presence using

          #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS

* Menu:

* Adding assembler instructions within a function::
* Adding top-level assembler statements::

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

   (1) 
https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html


File: libgccjit.info,  Node: Adding assembler instructions within a function,  Next: Adding top-level assembler statements,  Up: Using Assembly Language with libgccjit

2.11.1 Adding assembler instructions within a function
------------------------------------------------------

 -- C Type: gcc_jit_extended_asm

     A ‘gcc_jit_extended_asm’ represents an extended ‘asm’ statement: a
     series of low-level instructions inside a function that convert
     inputs to outputs.

     To avoid having an API entrypoint with a very large number of
     parameters, an extended ‘asm’ statement is made in stages: an
     initial call to create the *note gcc_jit_extended_asm: 120,
     followed by calls to add operands and set other properties of the
     statement.

     There are two API entrypoints for creating a *note
     gcc_jit_extended_asm: 120.:

        * *note gcc_jit_block_add_extended_asm(): 152. for an ‘asm’
          statement with no control flow, and

        * *note gcc_jit_block_end_with_extended_asm_goto(): 153. for an
          ‘asm goto’.

     For example, to create the equivalent of:

                 asm ("mov %1, %0\n\t"
                      "add $1, %0"
                      : "=r" (dst)
                      : "r" (src));

     the following API calls could be used:

            gcc_jit_extended_asm *ext_asm
              = gcc_jit_block_add_extended_asm (block, NULL,
          				      "mov %1, %0\n\t"
          				      "add $1, %0");
            gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);
            gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
          					  gcc_jit_lvalue_as_rvalue (src));

          Warning: When considering the numbering of operands within an
          extended ‘asm’ statement (e.g.  the ‘%0’ and ‘%1’ above), the
          equivalent to the C syntax is followed i.e.  all output
          operands, then all input operands, regardless of what order
          the calls to *note gcc_jit_extended_asm_add_output_operand():
          157. and *note gcc_jit_extended_asm_add_input_operand(): 158.
          were made in.

     As in the C syntax, operands can be given symbolic names to avoid
     having to number them.  For example, to create the equivalent of:

                 asm ("bsfl %[aMask], %[aIndex]"
                      : [aIndex] "=r" (Index)
                      : [aMask] "r" (Mask)
                      : "cc");

     the following API calls could be used:

            gcc_jit_extended_asm *ext_asm
              = gcc_jit_block_add_extended_asm (block, NULL,
          				      "bsfl %[aMask], %[aIndex]");
            gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);
            gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
          					  gcc_jit_param_as_rvalue (mask));
            gcc_jit_extended_asm_add_clobber (ext_asm, "cc");

 -- C Function: gcc_jit_extended_asm * gcc_jit_block_add_extended_asm
          (gcc_jit_block *block, gcc_jit_location *loc, const
          char *asm_template)

     Create a *note gcc_jit_extended_asm: 120. for an extended ‘asm’
     statement with no control flow (i.e.  without the ‘goto’
     qualifier).

     The parameter ‘asm_template’ corresponds to the ‘AssemblerTemplate’
     within C’s extended ‘asm’ syntax.  It 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_extended_asm *
          gcc_jit_block_end_with_extended_asm_goto
          (gcc_jit_block *block, gcc_jit_location *loc, const
          char *asm_template, int num_goto_blocks,
          gcc_jit_block **goto_blocks, gcc_jit_block *fallthrough_block)

     Create a *note gcc_jit_extended_asm: 120. for an extended ‘asm’
     statement that may perform jumps, and use it to terminate the given
     block.  This is equivalent to the ‘goto’ qualifier in C’s extended
     ‘asm’ syntax.

     For example, to create the equivalent of:

                 asm goto ("btl %1, %0\n\t"
                           "jc %l[carry]"
                           : // No outputs
                           : "r" (p1), "r" (p2)
                           : "cc"
                           : carry);

     the following API calls could be used:

            const char *asm_template =
              (use_name
               ? /* Label referred to by name: "%l[carry]".  */
                 ("btl %1, %0\n\t"
                  "jc %l[carry]")
               : /* Label referred to numerically: "%l2".  */
                 ("btl %1, %0\n\t"
                  "jc %l2"));

            gcc_jit_extended_asm *ext_asm
              = gcc_jit_block_end_with_extended_asm_goto (b_start, NULL,
          						asm_template,
          						1, &b_carry,
          						b_fallthru);
            gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
          					  gcc_jit_param_as_rvalue (p1));
            gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
          					  gcc_jit_param_as_rvalue (p2));
            gcc_jit_extended_asm_add_clobber (ext_asm, "cc");

     here referencing a *note gcc_jit_block: 28. named “carry”.

     ‘num_goto_blocks’ must be >= 0.

     ‘goto_blocks’ must be non-NULL. This corresponds to the
     ‘GotoLabels’ parameter within C’s extended ‘asm’ syntax.  The block
     names can be referenced within the assembler template.

     ‘fallthrough_block’ can be NULL. If non-NULL, it specifies the
     block to fall through to after the statement.

          Note: This is needed since each *note gcc_jit_block: 28. must
          have a single exit point, as a basic block: you can’t jump
          from the middle of a block.  A “goto” is implicitly added
          after the asm to handle the fallthrough case, which is
          equivalent to what would have happened in the C case.

 -- C Function: void gcc_jit_extended_asm_set_volatile_flag
          (gcc_jit_extended_asm *ext_asm, int flag)

     Set whether the *note gcc_jit_extended_asm: 120. has side-effects,
     equivalent to the volatile(1) qualifier in C’s extended asm syntax.

     For example, to create the equivalent of:

          asm volatile ("rdtsc\n\t"    // Returns the time in EDX:EAX.
                         "shl $32, %%rdx\n\t"  // Shift the upper bits left.
                         "or %%rdx, %0"        // 'Or' in the lower bits.
                         : "=a" (msr)
                         :
                         : "rdx");

     the following API calls could be used:

            gcc_jit_extended_asm *ext_asm
              = gcc_jit_block_add_extended_asm
          	(block, NULL,
          	 "rdtsc\n\t"  /* Returns the time in EDX:EAX.  */
          	 "shl $32, %%rdx\n\t"  /* Shift the upper bits left.  */
          	 "or %%rdx, %0");  /* 'Or' in the lower bits.  */
            gcc_jit_extended_asm_set_volatile_flag (ext_asm, 1);
            gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=a", msr);
            gcc_jit_extended_asm_add_clobber (ext_asm, "rdx");

     where the *note gcc_jit_extended_asm: 120. is flagged as volatile.

 -- C Function: void gcc_jit_extended_asm_set_inline_flag
          (gcc_jit_extended_asm *ext_asm, int flag)

     Set the equivalent of the inline(2) qualifier in C’s extended ‘asm’
     syntax.

 -- C Function: void gcc_jit_extended_asm_add_output_operand
          (gcc_jit_extended_asm *ext_asm, const char *asm_symbolic_name,
          const char *constraint, gcc_jit_lvalue *dest)

     Add an output operand to the extended ‘asm’ statement.  See the
     Output Operands(3) section of the documentation of the C syntax.

     ‘asm_symbolic_name’ corresponds to the ‘asmSymbolicName’ component
     of C’s extended ‘asm’ syntax.  It can be NULL. If non-NULL it
     specifies the symbolic name for the operand.

     ‘constraint’ corresponds to the ‘constraint’ component of C’s
     extended ‘asm’ syntax.  It must be non-NULL.

     ‘dest’ corresponds to the ‘cvariablename’ component of C’s extended
     ‘asm’ syntax.  It must be non-NULL.

          // Example with a NULL symbolic name, the equivalent of:
          //   : "=r" (dst)
          gcc_jit_extended_asm_add_output_operand (ext_asm, NULL, "=r", dst);

          // Example with a symbolic name ("aIndex"), the equivalent of:
          //   : [aIndex] "=r" (index)
          gcc_jit_extended_asm_add_output_operand (ext_asm, "aIndex", "=r", index);

     This function can’t be called on an ‘asm goto’ as such instructions
     can’t have outputs; see the Goto Labels(4) section of GCC’s
     “Extended Asm” documentation.

 -- C Function: void gcc_jit_extended_asm_add_input_operand
          (gcc_jit_extended_asm *ext_asm, const char *asm_symbolic_name,
          const char *constraint, gcc_jit_rvalue *src)

     Add an input operand to the extended ‘asm’ statement.  See the
     Input Operands(5) section of the documentation of the C syntax.

     ‘asm_symbolic_name’ corresponds to the ‘asmSymbolicName’ component
     of C’s extended ‘asm’ syntax.  It can be NULL. If non-NULL it
     specifies the symbolic name for the operand.

     ‘constraint’ corresponds to the ‘constraint’ component of C’s
     extended ‘asm’ syntax.  It must be non-NULL.

     ‘src’ corresponds to the ‘cexpression’ component of C’s extended
     ‘asm’ syntax.  It must be non-NULL.

          // Example with a NULL symbolic name, the equivalent of:
          //   : "r" (src)
          gcc_jit_extended_asm_add_input_operand (ext_asm, NULL, "r",
                                                  gcc_jit_lvalue_as_rvalue (src));

          // Example with a symbolic name ("aMask"), the equivalent of:
          //   : [aMask] "r" (Mask)
          gcc_jit_extended_asm_add_input_operand (ext_asm, "aMask", "r",
                                                  gcc_jit_lvalue_as_rvalue (mask));

 -- C Function: void gcc_jit_extended_asm_add_clobber
          (gcc_jit_extended_asm *ext_asm, const char *victim)

     Add ‘victim’ to the list of registers clobbered by the extended
     ‘asm’ statement.  It must be non-NULL. See the Clobbers and Scratch
     Registers(6) section of the documentation of the C syntax.

     Statements with multiple clobbers will require multiple calls, one
     per clobber.

     For example:

          gcc_jit_extended_asm_add_clobber (ext_asm, "r0");
          gcc_jit_extended_asm_add_clobber (ext_asm, "cc");
          gcc_jit_extended_asm_add_clobber (ext_asm, "memory");

A *note gcc_jit_extended_asm: 120. is a *note gcc_jit_object: e. “owned”
by the block’s context.  The following upcast is available:

 -- C Function: gcc_jit_object * gcc_jit_extended_asm_as_object
          (gcc_jit_extended_asm *ext_asm)

     Upcast from extended ‘asm’ to object.

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

   (1) https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile

   (2) 
https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm

   (3) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands

   (4) https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels

   (5) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands

   (6) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#


File: libgccjit.info,  Node: Adding top-level assembler statements,  Prev: Adding assembler instructions within a function,  Up: Using Assembly Language with libgccjit

2.11.2 Adding top-level assembler statements
--------------------------------------------

In addition to creating extended ‘asm’ instructions within a function,
there is support for creating “top-level” assembler statements, outside
of any function.

 -- C Function: void gcc_jit_context_add_top_level_asm
          (gcc_jit_context *ctxt, gcc_jit_location *loc, const
          char *asm_stmts)

     Create a set of top-level asm statements, analogous to those
     created by GCC’s “basic” ‘asm’ syntax in C at file scope.

     For example, to create the equivalent of:

               asm ("\t.pushsection .text\n"
                    "\t.globl add_asm\n"
                    "\t.type add_asm, @function\n"
                    "add_asm:\n"
                    "\tmovq %rdi, %rax\n"
                    "\tadd %rsi, %rax\n"
                    "\tret\n"
                    "\t.popsection\n");

     the following API calls could be used:

            gcc_jit_context_add_top_level_asm (ctxt, NULL,
                                               "\t.pushsection .text\n"
                                               "\t.globl add_asm\n"
                                               "\t.type add_asm, @function\n"
                                               "add_asm:\n"
                                               "\tmovq %rdi, %rax\n"
                                               "\tadd %rsi, %rax\n"
                                               "\tret\n"
                                               "\t# some asm here\n"
                                               "\t.popsection\n");


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.

Contents:

* Menu:

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

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

   (1) https://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-2023 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 *note
gccjit;;context: 175, which is a thin C++ wrapper around the C API’s
*note gcc_jit_context *: 8.

Create one using *note gccjit;;context;;acquire(): 176.:

     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 *note gccjit;;type: 177, using *note
gccjit;;context;;get_type(): 178.:

     gccjit::type int_type = ctxt.get_type (GCC_JIT_TYPE_INT);

*note gccjit;;type: 177. is an example of a “contextual” object: every
entity in the API is associated with a *note gccjit;;context: 175.

Memory management is easy: all such “contextual” objects are
automatically cleaned up for you when the context is released, using
*note gccjit;;context;;release(): 179.:

     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 *note gccjit;;object: 17a. is to ask it for
a human-readable description as a ‘std::string’, using *note
gccjit;;object;;get_debug_string(): 17b.:

     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(): 17c.:

     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(): 17d.:

     gccjit::rvalue expr =
       ctxt.new_binary_op (
         GCC_JIT_BINARY_OP_MULT, int_type,
         param_i, param_i);

A *note gccjit;;rvalue: 17e. is another example of a *note
gccjit;;object: 17a. subclass.  As before, we can print it with *note
gccjit;;object;;get_debug_string(): 17b.

     printf ("expr: %s\n", expr.get_debug_string ().c_str ());

giving this output:

     expr: i * i

Note that *note gccjit;;rvalue: 17e. 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(): 17f.:

     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(): 181.

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(): 182. 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-2023 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:

[image src="libgccjit-figures/sum-of-squares.png" alt="image of a control flow graph"]


     Figure
As before, we include the libgccjit++ header and make a *note
gccjit;;context: 175.

     #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 *note gccjit;;rvalue: 17e,
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
gccjit;;type: 177.

Anothe important class is *note gccjit;;lvalue: 187.  A *note
gccjit;;lvalue: 187.  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 gccjit;;lvalue: 187. is a subclass of *note
gccjit;;rvalue: 17e, 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 *note gccjit;;rvalue: 17e, and

  2. the various function parameters: ‘param_i’ and ‘param_n’, instances
     of *note gccjit;;param: 188, which is a subclass of *note
     gccjit;;lvalue: 187. (and, in turn, of *note gccjit;;rvalue: 17e.):
     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(): 189, 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 *note gccjit;;lvalue: 187. - 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 *note gccjit;;block: 18b. instances within the
*note gccjit;;function: 18c.:

     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(): 18d. to add an assignment statement,
and using *note gccjit;;context;;zero(): 18e. 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 *note
gccjit;;rvalue: 17e, in this case the comparison of ‘i’ and ‘n’.

We could build the comparison using *note
gccjit;;context;;new_comparison(): 18f.:

     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(): 190.:

     b_loop_cond.end_with_conditional (guard,
                                       b_after_loop, // on_true
                                       b_loop_body); // on_false

However *note gccjit;;rvalue: 17e. 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(): 191. 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(): 192, 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(): 194.:

     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’):

[image src="libgccjit-figures/sum-of-squares.png" alt="image of a control flow graph"]


     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-2023 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     ‘[..., x, y]’       ‘[..., (x+y)]’
                           on 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     ‘[..., x]’          ‘[..., fn(x)]’
                           of the stack, and popping                        
                           the result.
                           
                                                                            
RETURN                     Return the top of the        ‘[x]’               ‘[]’
                           stack.                                           
                           
                                                                            
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 *note gccjit;;location: 19b. 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[100];
                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(): 19d. 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(): 194.:

     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.

[image src="libgccjit-figures/factorial.png" alt="image of a control flow graph"]


     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(): 1a1. and using
          the results.

        * Enable the generation of debugging information, by setting
          *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the *note
          gccjit;;context: 175. via *note
          gccjit;;context;;set_bool_option(): 181.:

               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(): 182. 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 *note gccjit;;block: 18b. 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>.
* Using Assembly Language with libgccjit++::


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: 175. type.

A *note gccjit;;context: 175. 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(): 17f. 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::*note context: 175. gccjit::*note context:
          175.::acquire ()

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

 -- C++ Function: void gccjit::*note context: 175.::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::*note context: 175. gccjit::*note context:
          175.::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: 175. created via *note
gccjit;;context;;acquire(): 176. 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(): 1b5.
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(): 1bb.

 -- C++ Function: const char *gccjit::*note context:
          175.::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::*note context: 175.::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: 19b. 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::*note context:
          175.::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::*note context: 175.::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::*note context: 175.::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::*note context:
          175.::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::*note context:
          175.::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::*note context: 175.::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::*note context:
          175.::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(): 74.

     This entrypoint was added in *note LIBGCCJIT_ABI_1: 75.; 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: 175. and *note gcc_jit_result *: 16.) is a “contextual”
object, a *note gccjit;;object: 17a.

A JIT object:

        * is associated with a *note gccjit;;context: 175.

        * 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: 17a. base class has the following operations:

 -- C++ Function: gccjit::*note context: 175. gccjit::*note object:
          17a.::get_context () const

     Which context is the obj within?

 -- C++ Function: std::string gccjit::*note object:
          17a.::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: 17a.

Types can be created in several ways:

   * fundamental types can be accessed using *note
     gccjit;;context;;get_type(): 178.:

          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(): 1f4. and *note
     gccjit;;type;;get_const(): 1f5.:

          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::*note type: 177. gccjit::*note context:
          175.::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::*note type: 177. gccjit::*note context:
          175.::get_int_type (size_t num_bytes, int is_signed)

     Access the integer type of the given size.

 -- C++ Function: template<>gccjit::*note type: 177. gccjit::*note
          context: 175.::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::*note type: 177. gccjit::*note type:
          177.::get_pointer ()

     Given type “T”, get type “T*”.

 -- C++ Function: gccjit::*note type: 177. gccjit::*note type:
          177.::get_const ()

     Given type “T”, get type “const T”.

 -- C++ Function: gccjit::*note type: 177. gccjit::*note type:
          177.::get_volatile ()

     Given type “T”, get type “volatile T”.

 -- C++ Function: gccjit::*note type: 177. gccjit::*note type:
          177.::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::*note type: 177. gccjit::*note context:
          175.::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::*note type: 177. gccjit::*note type:
          177.::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_: 21a. is a subclass of *note gccjit;;type: 177.
(and thus of *note gccjit;;object: 17a. in turn).

 -- C++ Class: gccjit::field

A field within a *note gccjit;;struct_: 21a.

*note gccjit;;field: 21e. is a subclass of *note gccjit;;object: 17a.

You can model C ‘struct’ types by creating *note gccjit;;struct_: 21a.
and *note gccjit;;field: 21e. 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::*note field: 21e. gccjit::*note context:
          175.::new_field (gccjit::type type, const char *name,
          gccjit::location loc)

     Construct a new field, with the given type and name.

 -- C++ Function: gccjit::*note struct_: 21a. gccjit::*note context:
          175.::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::*note struct_: 21a. gccjit::*note context:
          175.::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(): 93.


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


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: 17e. is an expression that can be computed.  It
is a subclass of *note gccjit;;object: 17a, 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::*note type: 177. gccjit::*note rvalue:
          17e.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::new_rvalue (gccjit::type pointer_type, void *value)
          const

     Given a pointer type, build an rvalue for the given address.

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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(): bf. and the available unary
     operations are documented there.

There are shorter ways to spell the various specific kinds of unary
operation:

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. 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::*note rvalue: 17e. 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::*note rvalue: 17e. operator- (gccjit::rvalue
          a)

          gccjit::rvalue negpi = -pi;

 -- C++ Function: gccjit::*note rvalue: 17e. operator~ (gccjit::rvalue
          a)

          gccjit::rvalue mask = ~a;

 -- C++ Function: gccjit::*note rvalue: 17e. 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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::new_plus (gccjit::type result_type, gccjit::rvalue a,
          gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_minus (gccjit::type result_type, gccjit::rvalue a,
          gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_mult (gccjit::type result_type, gccjit::rvalue a,
          gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_divide (gccjit::type result_type, gccjit::rvalue a,
          gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_modulo (gccjit::type result_type, gccjit::rvalue a,
          gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_bitwise_and (gccjit::type result_type,
          gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_bitwise_xor (gccjit::type result_type,
          gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_bitwise_or (gccjit::type result_type, gccjit::rvalue
          a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_logical_and (gccjit::type result_type,
          gccjit::rvalue a, gccjit::rvalue b, gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. operator+ (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue sum = a + b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator- (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue diff = a - b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator* (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue prod = a * b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator/ (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue result = a / b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator% (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue mod = a % b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator& (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue x = a & b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator^ (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue x = a ^ b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator| (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue x = a | b;

 -- C++ Function: gccjit::*note rvalue: 17e. operator&& (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = a && b;

 -- C++ Function: gccjit::*note rvalue: 17e. 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::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. gccjit::*note context:
          175.::new_eq (gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_ne (gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_lt (gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_le (gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::new_gt (gccjit::rvalue a, gccjit::rvalue b,
          gccjit::location loc)

 -- C++ Function: gccjit::*note rvalue: 17e. gccjit::*note context:
          175.::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::*note rvalue: 17e. operator== (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = (a == ctxt.zero (t_int));

 -- C++ Function: gccjit::*note rvalue: 17e. operator!= (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = (i != j);

 -- C++ Function: gccjit::*note rvalue: 17e. operator< (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = i < n;

 -- C++ Function: gccjit::*note rvalue: 17e. operator<= (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = i <= n;

 -- C++ Function: gccjit::*note rvalue: 17e. operator> (gccjit::rvalue
          a, gccjit::rvalue b)

          gccjit::rvalue cond = (ch > limit);

 -- C++ Function: gccjit::*note rvalue: 17e. 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: 17e. 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(): 302.:

               /* 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::*note rvalue: 17e. gccjit::*note function:
          18c.::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::*note rvalue: 17e. gccjit::*note context:
          175.::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: 17e, 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::*note rvalue: 17e. gccjit::*note lvalue:
          187.::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::*note lvalue: 187. gccjit::*note context:
          175.::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():
     f5. 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::*note lvalue: 187. gccjit::*note rvalue:
          17e.::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::*note lvalue: 187. gccjit::*note rvalue:
          17e.::operator* ()

          gccjit::lvalue content = *ptr;

Field access is provided separately for both lvalues and rvalues:

 -- C++ Function: gccjit::*note lvalue: 187. gccjit::*note lvalue:
          187.::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::*note rvalue: 17e. gccjit::*note rvalue:
          17e.::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::*note lvalue: 187. gccjit::*note rvalue:
          17e.::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::*note lvalue: 187. gccjit::*note context:
          175.::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: 19b, 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::*note param: 188. gccjit::*note context:
          175.::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: 188. is a subclass of *note gccjit;;lvalue: 187.
(and thus of *note gccjit;;rvalue: 17e. and *note gccjit;;object: 17a.).
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::*note function: 18c. gccjit::*note context:
          175.::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::*note function: 18c. gccjit::*note context:
          175.::get_builtin_function (const char *name)

     This is a wrapper around the C API’s *note
     gcc_jit_context_get_builtin_function(): 10e.

 -- C++ Function: gccjit::*note param: 188. gccjit::*note function:
          18c.::get_param (int index) const

     Get the param of the given index (0-based).

 -- C++ Function: void gccjit::*note function: 18c.::dump_to_dot (const
          char *path)

     Emit the function in graphviz format to the given path.

 -- C++ Function: gccjit::*note lvalue: 187. gccjit::*note function:
          18c.::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: 18b. is a subclass of *note gccjit;;object:
     17a.

     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::*note block: 18b. gccjit::*note function:
          18c.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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::*note block: 18b.::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(): 372.

             * ‘gccjit::context::new_case()’

     were added in *note LIBGCCJIT_ABI_3: 11f.; you can test for their
     presence using

          #ifdef LIBGCCJIT_HAVE_SWITCH_STATEMENTS

     A ‘gccjit::case_’ represents a case within a switch statement, and
     is created within a particular *note gccjit;;context: 175. using
     ‘gccjit::context::new_case()’.  It is a subclass of *note
     gccjit;;object: 17a.

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

     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():
     1a1.

     You need to enable *note GCC_JIT_BOOL_OPTION_DEBUGINFO: 42. on the
     *note gccjit;;context: 175. for these locations to actually be
     usable by the debugger:

          ctxt.set_bool_option (GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);

 -- C++ Function: gccjit::*note location: 19b. gccjit::*note context:
          175.::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(): 1c0.:

     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>,  Next: Using Assembly Language with libgccjit++,  Prev: Source Locations<2>,  Up: Topic Reference<2>

3.2.7 Compiling a context
-------------------------

Once populated, a *note gccjit;;context: 175. can be compiled to machine
code, either in-memory via *note gccjit;;context;;compile(): 17f. or to
disk via *note gccjit;;context;;compile_to_file(): 381.

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::*note context: 175.::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(): 381.
method.

 -- C++ Function: void gccjit::*note context: 175.::compile_to_file
          (enum gcc_jit_output_kind, const char *output_path)

     Compile the *note gccjit;;context: 175. 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: Using Assembly Language with libgccjit++,  Prev: Compiling a context<2>,  Up: Topic Reference<2>

3.2.8 Using Assembly Language with libgccjit++
----------------------------------------------

libgccjit has some support for directly embedding assembler
instructions.  This is based on GCC’s support for inline ‘asm’ in C
code, and the following assumes a familiarity with that functionality.
See How to Use Inline Assembly Language in C Code(1) in GCC’s
documentation, the “Extended Asm” section in particular.

These entrypoints were added in *note LIBGCCJIT_ABI_15: 151.; you can
test for their presence using

          #ifdef LIBGCCJIT_HAVE_ASM_STATEMENTS

* Menu:

* Adding assembler instructions within a function: Adding assembler instructions within a function<2>.
* Adding top-level assembler statements: Adding top-level assembler statements<2>.

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

   (1) 
https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html


File: libgccjit.info,  Node: Adding assembler instructions within a function<2>,  Next: Adding top-level assembler statements<2>,  Up: Using Assembly Language with libgccjit++

3.2.8.1 Adding assembler instructions within a function
.......................................................

 -- C++ Class: gccjit::extended_asm

     A ‘gccjit::extended_asm’ represents an extended ‘asm’ statement: a
     series of low-level instructions inside a function that convert
     inputs to outputs.

     *note gccjit;;extended_asm: 38d. is a subclass of *note
     gccjit;;object: 17a.  It is a thin wrapper around the C API’s *note
     gcc_jit_extended_asm *: 120.

     To avoid having an API entrypoint with a very large number of
     parameters, an extended ‘asm’ statement is made in stages: an
     initial call to create the *note gccjit;;extended_asm: 38d,
     followed by calls to add operands and set other properties of the
     statement.

     There are two API entrypoints for creating a *note
     gccjit;;extended_asm: 38d.:

        * *note gccjit;;block;;add_extended_asm(): 391. for an ‘asm’
          statement with no control flow, and

        * *note gccjit;;block;;end_with_extended_asm_goto(): 392. for an
          ‘asm goto’.

     For example, to create the equivalent of:

                 asm ("mov %1, %0\n\t"
                      "add $1, %0"
                      : "=r" (dst)
                      : "r" (src));

     the following API calls could be used:

              block.add_extended_asm ("mov %1, %0\n\t"
                                      "add $1, %0")
              .add_output_operand ("=r", dst)
              .add_input_operand ("r", src);

          Warning: When considering the numbering of operands within an
          extended ‘asm’ statement (e.g.  the ‘%0’ and ‘%1’ above), the
          equivalent to the C syntax is followed i.e.  all output
          operands, then all input operands, regardless of what order
          the calls to *note gccjit;;extended_asm;;add_output_operand():
          393. and *note gccjit;;extended_asm;;add_input_operand(): 394.
          were made in.

     As in the C syntax, operands can be given symbolic names to avoid
     having to number them.  For example, to create the equivalent of:

                 asm ("bsfl %[aMask], %[aIndex]"
                      : [aIndex] "=r" (Index)
                      : [aMask] "r" (Mask)
                      : "cc");

     the following API calls could be used:

              block.add_extended_asm ("bsfl %[aMask], %[aIndex]")
              .add_output_operand ("aIndex", "=r", index)
              .add_input_operand ("aMask", "r", mask)
              .add_clobber ("cc");

 -- C++ Function: *note extended_asm: 38d. gccjit::*note block:
          18b.::add_extended_asm (const std::string &asm_template,
          gccjit::location loc = location())

     Create a *note gccjit;;extended_asm: 38d. for an extended ‘asm’
     statement with no control flow (i.e.  without the ‘goto’
     qualifier).

     The parameter ‘asm_template’ corresponds to the ‘AssemblerTemplate’
     within C’s extended ‘asm’ syntax.  It 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: *note extended_asm: 38d. gccjit::*note block:
          18b.::end_with_extended_asm_goto (const std::string
          &asm_template, std::vector<block> goto_blocks, block
          *fallthrough_block, location loc = location())

     Create a *note gccjit;;extended_asm: 38d. for an extended ‘asm’
     statement that may perform jumps, and use it to terminate the given
     block.  This is equivalent to the ‘goto’ qualifier in C’s extended
     ‘asm’ syntax.

     For example, to create the equivalent of:

                 asm goto ("btl %1, %0\n\t"
                           "jc %l[carry]"
                           : // No outputs
                           : "r" (p1), "r" (p2)
                           : "cc"
                           : carry);

     the following API calls could be used:

            const char *asm_template =
              (use_name
               ? /* Label referred to by name: "%l[carry]".  */
                 ("btl %1, %0\n\t"
                  "jc %l[carry]")
               : /* Label referred to numerically: "%l2".  */
                 ("btl %1, %0\n\t"
                  "jc %l2"));

            std::vector<gccjit::block> goto_blocks ({b_carry});
            gccjit::extended_asm ext_asm
              = (b_start.end_with_extended_asm_goto (asm_template,
          					  goto_blocks,
          					  &b_fallthru)
                 .add_input_operand ("r", p1)
                 .add_input_operand ("r", p2)
                 .add_clobber ("cc"));

     here referencing a ‘gcc_jit_block’ named “carry”.

     ‘num_goto_blocks’ corresponds to the ‘GotoLabels’ parameter within
     C’s extended ‘asm’ syntax.  The block names can be referenced
     within the assembler template.

     ‘fallthrough_block’ can be NULL. If non-NULL, it specifies the
     block to fall through to after the statement.

          Note: This is needed since each *note gccjit;;block: 18b. must
          have a single exit point, as a basic block: you can’t jump
          from the middle of a block.  A “goto” is implicitly added
          after the asm to handle the fallthrough case, which is
          equivalent to what would have happened in the C case.

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::set_volatile_flag (bool flag)

     Set whether the *note gccjit;;extended_asm: 38d. has side-effects,
     equivalent to the volatile(1) qualifier in C’s extended asm syntax.

     For example, to create the equivalent of:

          asm volatile ("rdtsc\n\t"    // Returns the time in EDX:EAX.
                         "shl $32, %%rdx\n\t"  // Shift the upper bits left.
                         "or %%rdx, %0"        // 'Or' in the lower bits.
                         : "=a" (msr)
                         :
                         : "rdx");

     the following API calls could be used:

            gccjit::extended_asm ext_asm
              = block.add_extended_asm
          	("rdtsc\n\t"  /* Returns the time in EDX:EAX.  */
          	 "shl $32, %%rdx\n\t"  /* Shift the upper bits left.  */
          	 "or %%rdx, %0")  /* 'Or' in the lower bits.  */
              .set_volatile_flag (true)
              .add_output_operand ("=a", msr)
              .add_clobber ("rdx");

     where the *note gccjit;;extended_asm: 38d. is flagged as volatile.

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::set_inline_flag (bool flag)

     Set the equivalent of the inline(2) qualifier in C’s extended ‘asm’
     syntax.

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::add_output_operand (const std::string
          &asm_symbolic_name, const std::string &constraint,
          gccjit::lvalue dest)

     Add an output operand to the extended ‘asm’ statement.  See the
     Output Operands(3) section of the documentation of the C syntax.

     ‘asm_symbolic_name’ corresponds to the ‘asmSymbolicName’ component
     of C’s extended ‘asm’ syntax, and specifies the symbolic name for
     the operand.  See the overload below for an alternative that does
     not supply a symbolic name.

     ‘constraint’ corresponds to the ‘constraint’ component of C’s
     extended ‘asm’ syntax.

     ‘dest’ corresponds to the ‘cvariablename’ component of C’s extended
     ‘asm’ syntax.

          // Example with a symbolic name ("aIndex"), the equivalent of:
          //   : [aIndex] "=r" (index)
          ext_asm.add_output_operand ("aIndex", "=r", index);

     This function can’t be called on an ‘asm goto’ as such instructions
     can’t have outputs; see the Goto Labels(4) section of GCC’s
     “Extended Asm” documentation.

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::add_output_operand (const std::string
          &constraint, gccjit::lvalue dest)

     As above, but don’t supply a symbolic name for the operand.

          // Example without a symbolic name, the equivalent of:
          //   : "=r" (dst)
          ext_asm.add_output_operand ("=r", dst);

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::add_input_operand (const std::string
          &asm_symbolic_name, const std::string &constraint,
          gccjit::rvalue src)

     Add an input operand to the extended ‘asm’ statement.  See the
     Input Operands(5) section of the documentation of the C syntax.

     ‘asm_symbolic_name’ corresponds to the ‘asmSymbolicName’ component
     of C’s extended ‘asm’ syntax.  See the overload below for an
     alternative that does not supply a symbolic name.

     ‘constraint’ corresponds to the ‘constraint’ component of C’s
     extended ‘asm’ syntax.

     ‘src’ corresponds to the ‘cexpression’ component of C’s extended
     ‘asm’ syntax.

          // Example with a symbolic name ("aMask"), the equivalent of:
          //   : [aMask] "r" (Mask)
          ext_asm.add_input_operand ("aMask", "r", mask);

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::add_input_operand (const std::string
          &constraint, gccjit::rvalue src)

     As above, but don’t supply a symbolic name for the operand.

          // Example without a symbolic name, the equivalent of:
          //   : "r" (src)
          ext_asm.add_input_operand ("r", src);

 -- C++ Function: gccjit::*note extended_asm: 38d. &gccjit::*note
          extended_asm: 38d.::add_clobber (const std::string &victim)

     Add ‘victim’ to the list of registers clobbered by the extended
     ‘asm’ statement.  See the Clobbers and Scratch Registers(6) section
     of the documentation of the C syntax.

     Statements with multiple clobbers will require multiple calls, one
     per clobber.

     For example:

          ext_asm.add_clobber ("r0").add_clobber ("cc").add_clobber ("memory");

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

   (1) https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile

   (2) 
https://gcc.gnu.org/onlinedocs/gcc/Size-of-an-asm.html#Size-of-an-asm

   (3) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#OutputOperands

   (4) https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels

   (5) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands

   (6) 
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Clobbers-and-Scratch-Registers#


File: libgccjit.info,  Node: Adding top-level assembler statements<2>,  Prev: Adding assembler instructions within a function<2>,  Up: Using Assembly Language with libgccjit++

3.2.8.2 Adding top-level assembler statements
.............................................

In addition to creating extended ‘asm’ instructions within a function,
there is support for creating “top-level” assembler statements, outside
of any function.

 -- C++ Function: void gccjit::*note context: 175.::add_top_level_asm
          (const char *asm_stmts, gccjit::location loc = location())

     Create a set of top-level asm statements, analogous to those
     created by GCC’s “basic” ‘asm’ syntax in C at file scope.

     For example, to create the equivalent of:

               asm ("\t.pushsection .text\n"
                    "\t.globl add_asm\n"
                    "\t.type add_asm, @function\n"
                    "add_asm:\n"
                    "\tmovq %rdi, %rax\n"
                    "\tadd %rsi, %rax\n"
                    "\tret\n"
                    "\t.popsection\n");

     the following API calls could be used:

            ctxt.add_top_level_asm ("\t.pushsection .text\n"
                                    "\t.globl add_asm\n"
                                    "\t.type add_asm, @function\n"
                                    "add_asm:\n"
                                    "\tmovq %rdi, %rax\n"
                                    "\tadd %rsi, %rax\n"
                                    "\tret\n"
                                    "\t# some asm here\n"
                                    "\t.popsection\n");


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) https://valgrind.org

   (2) https://valgrind.org/docs/manual/mc-manual.html

   (3) https://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: 3bd. 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: 3bd. for most
          languages, and

        * once with *note -enable-host-shared: 3bd. 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.cc’ implements the API entrypoints.  It performs error
     checking, then calls into classes of the gcc::jit::recording
     namespace within ‘jit-recording.cc’ and ‘jit-recording.h’.

   * The gcc::jit::recording classes (within ‘jit-recording.cc’ 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 bitfield;
                   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 extended_asm;
                   class case_;
                 class top_level_asm;


   * When the context is compiled, the gcc::jit::playback classes
     (within ‘jit-playback.cc’ 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.cc       .
                             .           .        │ (error-checking).
                             .           .        │                 .
                             .           .        ──> jit-recording.cc
                             .           .              (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.cc
                             .           .          .    │   (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.cc,
since this is as close as possible to the error; failing that, a good
place is within ‘recording::context::validate ()’ in jit-recording.cc.


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) https://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  55)
* 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  36)
* environment variable; LD_LIBRARY_PATH: Environment variables.
                                                              (line   9)
* environment variable; LIBRARY_PATH:    Environment variables.
                                                              (line  37)
* environment variable; PATH:            Environment variables.
                                                              (line  21)
* 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  15)
* GCC_JIT_BINARY_OP_BITWISE_AND (C macro): Binary Operations. (line 106)
* GCC_JIT_BINARY_OP_BITWISE_OR (C macro): Binary Operations.  (line 122)
* GCC_JIT_BINARY_OP_BITWISE_XOR (C macro): Binary Operations. (line 114)
* GCC_JIT_BINARY_OP_DIVIDE (C macro):    Binary Operations.   (line  86)
* GCC_JIT_BINARY_OP_LOGICAL_AND (C macro): Binary Operations. (line 130)
* GCC_JIT_BINARY_OP_LOGICAL_OR (C macro): Binary Operations.  (line 138)
* GCC_JIT_BINARY_OP_LSHIFT (C macro):    Binary Operations.   (line 146)
* GCC_JIT_BINARY_OP_MINUS (C macro):     Binary Operations.   (line  70)
* GCC_JIT_BINARY_OP_MODULO (C macro):    Binary Operations.   (line  98)
* GCC_JIT_BINARY_OP_MULT (C macro):      Binary Operations.   (line  78)
* GCC_JIT_BINARY_OP_PLUS (C macro):      Binary Operations.   (line  59)
* GCC_JIT_BINARY_OP_RSHIFT (C macro):    Binary Operations.   (line 154)
* gcc_jit_block (C type):                Blocks.              (line   6)
* gcc_jit_block_add_assignment (C function): Statements.      (line  16)
* gcc_jit_block_add_assignment_op (C function): Statements.   (line  27)
* gcc_jit_block_add_comment (C function): Statements.         (line  49)
* gcc_jit_block_add_eval (C function):   Statements.          (line   6)
* gcc_jit_block_add_extended_asm (C function): Adding assembler instructions within a function.
                                                              (line  70)
* gcc_jit_block_as_object (C function):  Blocks.              (line  39)
* gcc_jit_block_end_with_conditional (C function): Statements.
                                                              (line  68)
* gcc_jit_block_end_with_extended_asm_goto (C function): Adding assembler instructions within a function.
                                                              (line  83)
* gcc_jit_block_end_with_jump (C function): Statements.       (line  85)
* gcc_jit_block_end_with_return (C function): Statements.     (line  94)
* gcc_jit_block_end_with_switch (C function): Statements.     (line 115)
* gcc_jit_block_end_with_void_return (C function): Statements.
                                                              (line 105)
* gcc_jit_block_get_function (C function): Blocks.            (line  44)
* gcc_jit_bool_option (C type):          Boolean options.     (line  13)
* GCC_JIT_BOOL_OPTION_DEBUGINFO (C macro): Boolean options.   (line  15)
* 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  57)
* GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE (C macro): Boolean options.
                                                              (line  26)
* GCC_JIT_BOOL_OPTION_DUMP_SUMMARY (C macro): Boolean options.
                                                              (line 103)
* GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES (C macro): Boolean options.
                                                              (line 124)
* GCC_JIT_BOOL_OPTION_SELFCHECK_GC (C macro): Boolean options.
                                                              (line 117)
* gcc_jit_case (C type):                 Reflection API.      (line 118)
* gcc_jit_case (C type) <1>:             Functions.           (line 126)
* gcc_jit_case (C type) <2>:             Statements.          (line 165)
* gcc_jit_case_as_object (C function):   Statements.          (line 187)
* gcc_jit_comparison (C type):           Comparisons.         (line  12)
* gcc_jit_compatible_types (C function): Reflection API.      (line 120)
* 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_add_driver_option (C function): Additional command-line options.
                                                              (line  36)
* gcc_jit_context_add_top_level_asm (C function): Adding top-level assembler statements.
                                                              (line  10)
* gcc_jit_context_compile (C function):  In-memory compilation.
                                                              (line   6)
* gcc_jit_context_compile_to_file (C function): Ahead-of-time compilation.
                                                              (line  14)
* gcc_jit_context_dump_reproducer_to_file (C function): Debugging.
                                                              (line  63)
* gcc_jit_context_dump_to_file (C function): Debugging.       (line   6)
* gcc_jit_context_enable_dump (C function): Debugging.        (line  85)
* gcc_jit_context_get_builtin_function (C function): Functions.
                                                              (line  60)
* gcc_jit_context_get_first_error (C function): Error-handling<2>.
                                                              (line  26)
* gcc_jit_context_get_int_type (C function): Standard types.  (line 113)
* gcc_jit_context_get_last_error (C function): Error-handling<2>.
                                                              (line  40)
* gcc_jit_context_get_timer (C function): The timing API.     (line 160)
* 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  51)
* gcc_jit_context_new_array_constructor (C function): Constructor expressions.
                                                              (line  30)
* gcc_jit_context_new_array_type (C function): Pointers const and volatile.
                                                              (line  21)
* gcc_jit_context_new_binary_op (C function): Binary Operations.
                                                              (line   6)
* gcc_jit_context_new_bitcast (C function): Type-coercion.    (line  20)
* gcc_jit_context_new_bitfield (C function): Structures and unions.
                                                              (line  61)
* 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  32)
* gcc_jit_context_new_case (C function): Statements.          (line 175)
* 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  49)
* gcc_jit_context_new_function (C function): Functions.       (line  11)
* gcc_jit_context_new_function_ptr_type (C function): Function pointers<2>.
                                                              (line  50)
* gcc_jit_context_new_global (C function): Global variables.  (line   6)
* gcc_jit_context_new_location (C function): Source Locations.
                                                              (line  28)
* gcc_jit_context_new_opaque_struct (C function): Structures and unions.
                                                              (line  96)
* gcc_jit_context_new_param (C function): Params.             (line  10)
* 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  12)
* gcc_jit_context_new_rvalue_from_ptr (C function): Simple expressions.
                                                              (line  42)
* gcc_jit_context_new_rvalue_from_vector (C function): Vector expressions.
                                                              (line   6)
* gcc_jit_context_new_string_literal (C function): Simple expressions.
                                                              (line  56)
* gcc_jit_context_new_struct_constructor (C function): Constructor expressions.
                                                              (line  61)
* gcc_jit_context_new_struct_type (C function): Structures and unions.
                                                              (line  86)
* gcc_jit_context_new_unary_op (C function): Unary Operations.
                                                              (line   6)
* gcc_jit_context_new_union_constructor (C function): Constructor expressions.
                                                              (line 105)
* gcc_jit_context_new_union_type (C function): Structures and unions.
                                                              (line 122)
* gcc_jit_context_null (C function):     Simple expressions.  (line  48)
* gcc_jit_context_one (C function):      Simple expressions.  (line  27)
* gcc_jit_context_release (C function):  Lifetime-management. (line  16)
* gcc_jit_context_set_bool_allow_unreachable_blocks (C function): Boolean options.
                                                              (line 130)
* gcc_jit_context_set_bool_option (C function): Boolean options.
                                                              (line   6)
* gcc_jit_context_set_bool_print_errors_to_stderr (C function): Boolean options.
                                                              (line 159)
* gcc_jit_context_set_bool_use_external_driver (C function): Boolean options.
                                                              (line 143)
* gcc_jit_context_set_int_option (C function): Integer options.
                                                              (line   6)
* gcc_jit_context_set_logfile (C function): Debugging.        (line  19)
* gcc_jit_context_set_str_option (C function): String Options.
                                                              (line   6)
* gcc_jit_context_set_timer (C function): The timing API.     (line 141)
* gcc_jit_context_zero (C function):     Simple expressions.  (line  19)
* gcc_jit_extended_asm (C type):         Adding assembler instructions within a function.
                                                              (line   6)
* gcc_jit_extended_asm_add_clobber (C function): Adding assembler instructions within a function.
                                                              (line 233)
* gcc_jit_extended_asm_add_input_operand (C function): Adding assembler instructions within a function.
                                                              (line 206)
* gcc_jit_extended_asm_add_output_operand (C function): Adding assembler instructions within a function.
                                                              (line 177)
* gcc_jit_extended_asm_as_object (C function): Adding assembler instructions within a function.
                                                              (line 252)
* gcc_jit_extended_asm_set_inline_flag (C function): Adding assembler instructions within a function.
                                                              (line 171)
* gcc_jit_extended_asm_set_volatile_flag (C function): Adding assembler instructions within a function.
                                                              (line 142)
* gcc_jit_field (C type):                Structures and unions.
                                                              (line  10)
* gcc_jit_field_as_object (C function):  Structures and unions.
                                                              (line  81)
* gcc_jit_function (C type):             Functions.           (line   6)
* GCC_JIT_FUNCTION_ALWAYS_INLINE (C macro): Functions.        (line  44)
* gcc_jit_function_as_object (C function): Functions.         (line  76)
* gcc_jit_function_dump_to_dot (C function): Functions.       (line  86)
* GCC_JIT_FUNCTION_EXPORTED (C macro):   Functions.           (line  24)
* gcc_jit_function_get_address (C function): Function pointers<2>.
                                                              (line  15)
* gcc_jit_function_get_param (C function): Functions.         (line  81)
* gcc_jit_function_get_param_count (C function): Functions.   (line 104)
* gcc_jit_function_get_return_type (C function): Functions.   (line 109)
* GCC_JIT_FUNCTION_IMPORTED (C macro):   Functions.           (line  38)
* GCC_JIT_FUNCTION_INTERNAL (C macro):   Functions.           (line  33)
* gcc_jit_function_kind (C type):        Functions.           (line  19)
* gcc_jit_function_new_block (C function): Blocks.            (line  22)
* gcc_jit_function_new_local (C function): Functions.         (line  91)
* gcc_jit_function_type_get_param_count (C function): Reflection API.
                                                              (line  25)
* gcc_jit_function_type_get_param_type (C function): Reflection API.
                                                              (line  30)
* gcc_jit_function_type_get_return_type (C function): Reflection API.
                                                              (line  20)
* GCC_JIT_GLOBAL_EXPORTED (C macro):     Global variables.    (line  25)
* GCC_JIT_GLOBAL_IMPORTED (C macro):     Global variables.    (line  39)
* GCC_JIT_GLOBAL_INTERNAL (C macro):     Global variables.    (line  32)
* gcc_jit_global_kind (C type):          Global variables.    (line  23)
* gcc_jit_global_set_initializer (C function): Global variables.
                                                              (line  45)
* gcc_jit_global_set_initializer_rvalue (C function): Global variables.
                                                              (line  62)
* gcc_jit_int_option (C type):           Integer options.     (line  12)
* GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL (C macro): Integer options.
                                                              (line  16)
* 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  18)
* gcc_jit_lvalue_as_object (C function): Lvalues.             (line  13)
* gcc_jit_lvalue_as_rvalue (C function): Lvalues.             (line  18)
* gcc_jit_lvalue_get_address (C function): Lvalues.           (line  23)
* gcc_jit_lvalue_get_alignment (C function): Lvalues.         (line 109)
* gcc_jit_lvalue_set_alignment (C function): Lvalues.         (line  95)
* gcc_jit_lvalue_set_link_section (C function): Lvalues.      (line  65)
* gcc_jit_lvalue_set_tls_model (C function): Lvalues.         (line  32)
* gcc_jit_object (C type):               Objects.             (line   6)
* gcc_jit_object_get_context (C function): Objects.           (line  43)
* gcc_jit_object_get_debug_string (C function): Objects.      (line  48)
* gcc_jit_output_kind (C type):          Ahead-of-time compilation.
                                                              (line  28)
* GCC_JIT_OUTPUT_KIND_ASSEMBLER (C macro): Ahead-of-time compilation.
                                                              (line  48)
* GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY (C macro): Ahead-of-time compilation.
                                                              (line  56)
* GCC_JIT_OUTPUT_KIND_EXECUTABLE (C macro): Ahead-of-time compilation.
                                                              (line  60)
* GCC_JIT_OUTPUT_KIND_OBJECT_FILE (C macro): Ahead-of-time compilation.
                                                              (line  52)
* gcc_jit_param (C type):                Params.              (line   6)
* gcc_jit_param_as_lvalue (C function):  Params.              (line  26)
* gcc_jit_param_as_object (C function):  Params.              (line  36)
* gcc_jit_param_as_rvalue (C function):  Params.              (line  31)
* gcc_jit_result (C type):               In-memory compilation.
                                                              (line  16)
* gcc_jit_result_get_code (C function):  In-memory compilation.
                                                              (line  22)
* gcc_jit_result_get_global (C function): In-memory compilation.
                                                              (line  55)
* gcc_jit_result_release (C function):   In-memory compilation.
                                                              (line  95)
* gcc_jit_rvalue (C type):               Rvalues.             (line   6)
* gcc_jit_rvalue_access_field (C function): Working with pointers structs and unions.
                                                              (line  29)
* gcc_jit_rvalue_as_object (C function): Rvalues.             (line  37)
* 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  40)
* 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  12)
* GCC_JIT_STR_OPTION_PROGNAME (C macro): String Options.      (line  20)
* gcc_jit_struct (C type):               Structures and unions.
                                                              (line   6)
* gcc_jit_struct_as_type (C function):   Structures and unions.
                                                              (line 109)
* gcc_jit_struct_get_field (C function): Reflection API.      (line  71)
* gcc_jit_struct_get_field_count (C function): Reflection API.
                                                              (line  76)
* gcc_jit_struct_set_fields (C function): Structures and unions.
                                                              (line 114)
* gcc_jit_timer (C type):                The timing API.      (line 115)
* gcc_jit_timer_new (C function):        The timing API.      (line 117)
* gcc_jit_timer_pop (C function):        The timing API.      (line 184)
* gcc_jit_timer_print (C function):      The timing API.      (line 197)
* gcc_jit_timer_push (C function):       The timing API.      (line 170)
* gcc_jit_timer_release (C function):    The timing API.      (line 128)
* gcc_jit_tls_model (C type):            Lvalues.             (line  40)
* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC (C macro): Lvalues.        (line  46)
* GCC_JIT_TLS_MODEL_INITIAL_EXEC (C macro): Lvalues.          (line  50)
* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC (C macro): Lvalues.         (line  48)
* GCC_JIT_TLS_MODEL_LOCAL_EXEC (C macro): Lvalues.            (line  52)
* GCC_JIT_TLS_MODEL_NONE (C macro):      Lvalues.             (line  42)
* gcc_jit_type (C type):                 Types.               (line   6)
* gcc_jit_type_as_object (C function):   Types.               (line  10)
* gcc_jit_type_dyncast_array (C function): Reflection API.    (line   6)
* gcc_jit_type_dyncast_function_ptr_type (C function): Reflection API.
                                                              (line  15)
* gcc_jit_type_dyncast_vector (C function): Reflection API.   (line  45)
* gcc_jit_type_get_aligned (C function): Pointers const and volatile.
                                                              (line  27)
* gcc_jit_type_get_const (C function):   Pointers const and volatile.
                                                              (line  11)
* gcc_jit_type_get_pointer (C function): Pointers const and volatile.
                                                              (line   6)
* gcc_jit_type_get_size (C function):    Reflection API.      (line 134)
* gcc_jit_type_get_vector (C function):  Vector types.        (line   6)
* gcc_jit_type_get_volatile (C function): Pointers const and volatile.
                                                              (line  16)
* gcc_jit_type_is_bool (C function):     Reflection API.      (line  11)
* gcc_jit_type_is_integral (C function): Reflection API.      (line  35)
* gcc_jit_type_is_pointer (C function):  Reflection API.      (line  39)
* gcc_jit_type_is_struct (C function):   Reflection API.      (line  50)
* gcc_jit_type_unqualified (C function): Reflection API.      (line  65)
* gcc_jit_unary_op (C type):             Unary Operations.    (line  15)
* GCC_JIT_UNARY_OP_ABS (C macro):        Unary Operations.    (line  60)
* GCC_JIT_UNARY_OP_BITWISE_NEGATE (C macro): Unary Operations.
                                                              (line  43)
* GCC_JIT_UNARY_OP_LOGICAL_NEGATE (C macro): Unary Operations.
                                                              (line  52)
* GCC_JIT_UNARY_OP_MINUS (C macro):      Unary Operations.    (line  35)
* gcc_jit_vector_type_get_element_type (C function): Reflection API.
                                                              (line  60)
* gcc_jit_vector_type_get_num_units (C function): Reflection API.
                                                              (line  55)
* gcc_jit_version_major (C function):    Programmatically checking version.
                                                              (line   8)
* gcc_jit_version_minor (C function):    Programmatically checking version.
                                                              (line  13)
* gcc_jit_version_patchlevel (C function): Programmatically checking version.
                                                              (line  18)
* gccjit;;block (C++ class):             Blocks<2>.           (line   6)
* gccjit;;block;;add_assignment (C++ function): Statements<2>.
                                                              (line  16)
* gccjit;;block;;add_assignment_op (C++ function): Statements<2>.
                                                              (line  27)
* gccjit;;block;;add_comment (C++ function): Statements<2>.   (line  47)
* gccjit;;block;;add_eval (C++ function): Statements<2>.      (line   6)
* gccjit;;block;;add_extended_asm (C++ function): Adding assembler instructions within a function<2>.
                                                              (line  68)
* gccjit;;block;;end_with_conditional (C++ function): Statements<2>.
                                                              (line  59)
* gccjit;;block;;end_with_extended_asm_goto (C++ function): Adding assembler instructions within a function<2>.
                                                              (line  81)
* gccjit;;block;;end_with_jump (C++ function): Statements<2>. (line  75)
* gccjit;;block;;end_with_return (C++ function): Statements<2>.
                                                              (line  84)
* gccjit;;block;;end_with_switch (C++ function): Statements<2>.
                                                              (line 109)
* 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;;add_top_level_asm (C++ function): Adding top-level assembler statements<2>.
                                                              (line  10)
* 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  18)
* gccjit;;context;;dump_to_file (C++ function): Debugging<2>. (line   6)
* gccjit;;context;;get_builtin_function (C++ function): Functions<2>.
                                                              (line  23)
* gccjit;;context;;get_first_error (C++ function): Error-handling<3>.
                                                              (line  15)
* gccjit;;context;;get_int_type (C++ function): Standard types<2>.
                                                              (line  12)
* gccjit;;context;;get_int_type<T> (C++ function): Standard types<2>.
                                                              (line  17)
* 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  59)
* gccjit;;context;;new_array_type (C++ function): Pointers const and volatile<2>.
                                                              (line  30)
* gccjit;;context;;new_binary_op (C++ function): Binary Operations<2>.
                                                              (line   6)
* gccjit;;context;;new_bitwise_and (C++ function): Binary Operations<2>.
                                                              (line  42)
* gccjit;;context;;new_bitwise_or (C++ function): Binary Operations<2>.
                                                              (line  50)
* gccjit;;context;;new_bitwise_xor (C++ function): Binary Operations<2>.
                                                              (line  46)
* gccjit;;context;;new_cast (C++ function): Type-coercion<2>. (line   6)
* gccjit;;context;;new_child_context (C++ function): Lifetime-management<2>.
                                                              (line  29)
* gccjit;;context;;new_comparison (C++ function): Comparisons<2>.
                                                              (line   6)
* gccjit;;context;;new_divide (C++ function): Binary Operations<2>.
                                                              (line  34)
* gccjit;;context;;new_eq (C++ function): Comparisons<2>.     (line  21)
* gccjit;;context;;new_field (C++ function): Structures and unions<2>.
                                                              (line  51)
* gccjit;;context;;new_function (C++ function): Functions<2>. (line  11)
* gccjit;;context;;new_ge (C++ function): Comparisons<2>.     (line  41)
* gccjit;;context;;new_global (C++ function): Global variables<2>.
                                                              (line   6)
* gccjit;;context;;new_gt (C++ function): Comparisons<2>.     (line  37)
* gccjit;;context;;new_le (C++ function): Comparisons<2>.     (line  33)
* gccjit;;context;;new_location (C++ function): Source Locations<2>.
                                                              (line  25)
* gccjit;;context;;new_logical_and (C++ function): Binary Operations<2>.
                                                              (line  54)
* gccjit;;context;;new_logical_or (C++ function): Binary Operations<2>.
                                                              (line  58)
* gccjit;;context;;new_lt (C++ function): Comparisons<2>.     (line  29)
* gccjit;;context;;new_minus (C++ function): Unary Operations<2>.
                                                              (line  21)
* gccjit;;context;;new_minus (C++ function) <1>: Binary Operations<2>.
                                                              (line  26)
* gccjit;;context;;new_modulo (C++ function): Binary Operations<2>.
                                                              (line  38)
* gccjit;;context;;new_mult (C++ function): Binary Operations<2>.
                                                              (line  30)
* gccjit;;context;;new_ne (C++ function): Comparisons<2>.     (line  25)
* gccjit;;context;;new_opaque_struct (C++ function): Structures and unions<2>.
                                                              (line  63)
* gccjit;;context;;new_param (C++ function): Params<2>.       (line  10)
* gccjit;;context;;new_plus (C++ function): Binary Operations<2>.
                                                              (line  22)
* gccjit;;context;;new_rvalue (C++ function): Simple expressions<2>.
                                                              (line   6)
* gccjit;;context;;new_rvalue (C++ function) <1>: Simple expressions<2>.
                                                              (line  12)
* gccjit;;context;;new_rvalue (C++ function) <2>: Simple expressions<2>.
                                                              (line  34)
* gccjit;;context;;new_rvalue (C++ function) <3>: Simple expressions<2>.
                                                              (line  41)
* gccjit;;context;;new_rvalue (C++ function) <4>: Simple expressions<2>.
                                                              (line  47)
* gccjit;;context;;new_rvalue (C++ function) <5>: Vector expressions<2>.
                                                              (line   6)
* gccjit;;context;;new_struct_type (C++ function): Structures and unions<2>.
                                                              (line  57)
* gccjit;;context;;new_unary_op (C++ function): Unary Operations<2>.
                                                              (line   6)
* gccjit;;context;;one (C++ function):   Simple expressions<2>.
                                                              (line  26)
* gccjit;;context;;release (C++ function): Lifetime-management<2>.
                                                              (line  17)
* gccjit;;context;;set_bool_allow_unreachable_blocks (C++ function): Boolean options<2>.
                                                              (line  15)
* 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  30)
* 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  18)
* gccjit;;extended_asm (C++ class):      Adding assembler instructions within a function<2>.
                                                              (line   6)
* gccjit;;extended_asm;;add_clobber (C++ function): Adding assembler instructions within a function<2>.
                                                              (line 238)
* gccjit;;extended_asm;;add_input_operand (C++ function): Adding assembler instructions within a function<2>.
                                                              (line 206)
* gccjit;;extended_asm;;add_input_operand (C++ function) <1>: Adding assembler instructions within a function<2>.
                                                              (line 228)
* gccjit;;extended_asm;;add_output_operand (C++ function): Adding assembler instructions within a function<2>.
                                                              (line 169)
* gccjit;;extended_asm;;add_output_operand (C++ function) <1>: Adding assembler instructions within a function<2>.
                                                              (line 196)
* gccjit;;extended_asm;;set_inline_flag (C++ function): Adding assembler instructions within a function<2>.
                                                              (line 163)
* gccjit;;extended_asm;;set_volatile_flag (C++ function): Adding assembler instructions within a function<2>.
                                                              (line 135)
* 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  34)
* gccjit;;function;;get_address (C++ function): Function pointers<3>.
                                                              (line   6)
* gccjit;;function;;get_param (C++ function): Functions<2>.   (line  29)
* gccjit;;function;;new_block (C++ function): Blocks<2>.      (line  25)
* gccjit;;function;;new_local (C++ function): Functions<2>.   (line  39)
* 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  28)
* gccjit;;lvalue;;get_address (C++ function): Lvalues<2>.     (line  15)
* 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  41)
* 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  38)
* 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  48)
* gccjit;;rvalue;;get_type (C++ function): Rvalues<2>.        (line  34)
* gccjit;;rvalue;;operator* (C++ function): Working with pointers structs and unions<2>.
                                                              (line  21)
* 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  21)
* gccjit;;type;;get_const (C++ function): Pointers const and volatile<2>.
                                                              (line  11)
* 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  16)
* 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  60)
* operator- (C++ function) <1>:          Binary Operations<2>.
                                                              (line  69)
* operator! (C++ function):              Unary Operations<2>. (line  70)
* operator!= (C++ function):             Comparisons<2>.      (line  52)
* operator* (C++ function):              Binary Operations<2>.
                                                              (line  74)
* operator/ (C++ function):              Binary Operations<2>.
                                                              (line  79)
* operator& (C++ function):              Binary Operations<2>.
                                                              (line  89)
* operator&& (C++ function):             Binary Operations<2>.
                                                              (line 104)
* operator% (C++ function):              Binary Operations<2>.
                                                              (line  84)
* operator^ (C++ function):              Binary Operations<2>.
                                                              (line  94)
* operator+ (C++ function):              Binary Operations<2>.
                                                              (line  64)
* operator< (C++ function):              Comparisons<2>.      (line  57)
* operator<= (C++ function):             Comparisons<2>.      (line  62)
* operator== (C++ function):             Comparisons<2>.      (line  47)
* operator> (C++ function):              Comparisons<2>.      (line  67)
* operator>= (C++ function):             Comparisons<2>.      (line  72)
* operator| (C++ function):              Binary Operations<2>.
                                                              (line  99)
* operator|| (C++ function):             Binary Operations<2>.
                                                              (line 109)
* 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: Top396
Ref: index doc651
Ref: 0651
Ref: Top-Footnote-18856
Node: Tutorial8893
Ref: intro/index doc8980
Ref: 18980
Ref: intro/index libgccjit8980
Ref: 28980
Ref: intro/index tutorial8980
Ref: 38980
Node: Tutorial part 1 “Hello world”9522
Ref: intro/tutorial01 doc9668
Ref: 49668
Ref: intro/tutorial01 tutorial-part-1-hello-world9668
Ref: 59668
Node: Tutorial part 2 Creating a trivial machine code function14945
Ref: intro/tutorial02 doc15135
Ref: 615135
Ref: intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function15135
Ref: 715135
Node: Error-handling20600
Ref: intro/tutorial02 error-handling20726
Ref: 1820726
Node: Options21629
Ref: intro/tutorial02 options21776
Ref: 1a21776
Node: Full example24372
Ref: intro/tutorial02 full-example24496
Ref: 2024496
Node: Tutorial part 3 Loops and variables28673
Ref: intro/tutorial03 doc28889
Ref: 2128889
Ref: intro/tutorial03 tutorial-part-3-loops-and-variables28889
Ref: 2228889
Node: Expressions lvalues and rvalues30953
Ref: intro/tutorial03 expressions-lvalues-and-rvalues31080
Ref: 2331080
Node: Control flow33286
Ref: intro/tutorial03 control-flow33456
Ref: 2733456
Node: Visualizing the control flow graph38342
Ref: intro/tutorial03 visualizing-the-control-flow-graph38496
Ref: 3238496
Node: Full example<2>39175
Ref: intro/tutorial03 full-example39308
Ref: 3439308
Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter45366
Ref: intro/tutorial04 doc45580
Ref: 3545580
Ref: intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter45580
Ref: 3645580
Node: Our toy interpreter46191
Ref: intro/tutorial04 our-toy-interpreter46343
Ref: 3746343
Node: Compiling to machine code54050
Ref: intro/tutorial04 compiling-to-machine-code54228
Ref: 3854228
Node: Setting things up56267
Ref: intro/tutorial04 setting-things-up56449
Ref: 3a56449
Node: Populating the function60530
Ref: intro/tutorial04 populating-the-function60719
Ref: 3c60719
Node: Verifying the control flow graph68379
Ref: intro/tutorial04 verifying-the-control-flow-graph68572
Ref: 3e68572
Node: Compiling the context69164
Ref: intro/tutorial04 compiling-the-context69376
Ref: 3f69376
Node: Single-stepping through the generated code69968
Ref: intro/tutorial04 single-stepping-through-the-generated-code70176
Ref: 4070176
Node: Examining the generated code72297
Ref: intro/tutorial04 examining-the-generated-code72507
Ref: 4372507
Node: Putting it all together77305
Ref: intro/tutorial04 putting-it-all-together77524
Ref: 4477524
Node: Behind the curtain How does our code get optimized?78365
Ref: intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized78547
Ref: 4578547
Node: Optimizing away stack manipulation84348
Ref: intro/tutorial04 optimizing-away-stack-manipulation84511
Ref: 4684511
Node: Elimination of tail recursion90632
Ref: intro/tutorial04 elimination-of-tail-recursion90795
Ref: 4790795
Node: Tutorial part 5 Implementing an Ahead-of-Time compiler92287
Ref: intro/tutorial05 doc92457
Ref: 4892457
Ref: intro/tutorial05 tutorial-part-5-implementing-an-ahead-of-time-compiler92457
Ref: 4992457
Node: The “brainf” language93310
Ref: intro/tutorial05 the-brainf-language93480
Ref: 4b93480
Node: Converting a brainf script to libgccjit IR96291
Ref: intro/tutorial05 converting-a-brainf-script-to-libgccjit-ir96499
Ref: 4c96499
Node: Compiling a context to a file108107
Ref: intro/tutorial05 compiling-a-context-to-a-file108330
Ref: 4d108330
Node: Other forms of ahead-of-time-compilation115166
Ref: intro/tutorial05 other-forms-of-ahead-of-time-compilation115338
Ref: 4e115338
Node: Topic Reference115698
Ref: topics/index doc115808
Ref: 4f115808
Ref: topics/index topic-reference115808
Ref: 50115808
Node: Compilation contexts116128
Ref: topics/contexts doc116219
Ref: 51116219
Ref: topics/contexts compilation-contexts116219
Ref: 52116219
Ref: topics/contexts c gcc_jit_context116270
Ref: 8116270
Node: Lifetime-management116725
Ref: topics/contexts lifetime-management116826
Ref: 53116826
Ref: topics/contexts c gcc_jit_context_acquire117091
Ref: 9117091
Ref: topics/contexts c gcc_jit_context_release117315
Ref: c117315
Ref: topics/contexts c gcc_jit_context_new_child_context117771
Ref: 54117771
Node: Thread-safety119177
Ref: topics/contexts thread-safety119304
Ref: 55119304
Node: Error-handling<2>119999
Ref: topics/contexts error-handling120116
Ref: 19120116
Ref: topics/contexts id1120116
Ref: 56120116
Ref: topics/contexts c gcc_jit_context_get_first_error121150
Ref: 57121150
Ref: topics/contexts c gcc_jit_context_get_last_error121662
Ref: 58121662
Node: Debugging122006
Ref: topics/contexts debugging122120
Ref: 59122120
Ref: topics/contexts c gcc_jit_context_dump_to_file122153
Ref: 5a122153
Ref: topics/contexts c gcc_jit_context_set_logfile122747
Ref: 5b122747
Ref: topics/contexts c gcc_jit_context_dump_reproducer_to_file124431
Ref: 5d124431
Ref: topics/contexts c gcc_jit_context_enable_dump125613
Ref: 5e125613
Node: Options<2>127155
Ref: topics/contexts options127243
Ref: 5f127243
Node: String Options127761
Ref: topics/contexts string-options127849
Ref: 60127849
Ref: topics/contexts c gcc_jit_context_set_str_option127896
Ref: 61127896
Ref: topics/contexts c gcc_jit_str_option128083
Ref: 62128083
Ref: topics/contexts c GCC_JIT_STR_OPTION_PROGNAME128358
Ref: 63128358
Node: Boolean options128577
Ref: topics/contexts boolean-options128689
Ref: 64128689
Ref: topics/contexts c gcc_jit_context_set_bool_option128738
Ref: 1b128738
Ref: topics/contexts c gcc_jit_bool_option128985
Ref: 65128985
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DEBUGINFO129028
Ref: 42129028
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE129511
Ref: 66129511
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE131453
Ref: 1c131453
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE131915
Ref: 1d131915
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_SUMMARY133033
Ref: 67133033
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING133218
Ref: 68133218
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_SELFCHECK_GC133682
Ref: 6a133682
Ref: topics/contexts c GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES134009
Ref: 69134009
Ref: topics/contexts c gcc_jit_context_set_bool_allow_unreachable_blocks134244
Ref: 6b134244
Ref: topics/contexts c gcc_jit_context_set_bool_use_external_driver134707
Ref: 6d134707
Ref: topics/contexts c gcc_jit_context_set_bool_print_errors_to_stderr135321
Ref: 6f135321
Node: Integer options135740
Ref: topics/contexts integer-options135869
Ref: 71135869
Ref: topics/contexts c gcc_jit_context_set_int_option135918
Ref: 1e135918
Ref: topics/contexts c gcc_jit_int_option136099
Ref: 72136099
Ref: topics/contexts c GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL136200
Ref: 1f136200
Node: Additional command-line options136454
Ref: topics/contexts additional-command-line-options136559
Ref: 73136559
Ref: topics/contexts c gcc_jit_context_add_command_line_option136640
Ref: 74136640
Ref: topics/contexts c gcc_jit_context_add_driver_option137919
Ref: 76137919
Node: Objects139322
Ref: topics/objects doc139427
Ref: 78139427
Ref: topics/objects objects139427
Ref: 79139427
Ref: topics/objects c gcc_jit_object139452
Ref: e139452
Ref: topics/objects c gcc_jit_object_get_context140583
Ref: 7a140583
Ref: topics/objects c gcc_jit_object_get_debug_string140717
Ref: f140717
Node: Types141324
Ref: topics/types doc141420
Ref: 7b141420
Ref: topics/types types141420
Ref: 7c141420
Ref: topics/types c gcc_jit_type141441
Ref: a141441
Ref: topics/types c gcc_jit_type_as_object141524
Ref: d141524
Node: Standard types142513
Ref: topics/types standard-types142608
Ref: 7f142608
Ref: topics/types c gcc_jit_context_get_type142651
Ref: b142651
Ref: topics/types c gcc_jit_context_get_int_type148939
Ref: 80148939
Node: Pointers const and volatile149113
Ref: topics/types pointers-const-and-volatile149229
Ref: 81149229
Ref: topics/types c gcc_jit_type_get_pointer149318
Ref: 7d149318
Ref: topics/types c gcc_jit_type_get_const149450
Ref: 7e149450
Ref: topics/types c gcc_jit_type_get_volatile149585
Ref: 82149585
Ref: topics/types c gcc_jit_context_new_array_type149726
Ref: 83149726
Ref: topics/types c gcc_jit_type_get_aligned149983
Ref: 84149983
Node: Vector types150415
Ref: topics/types vector-types150538
Ref: 86150538
Ref: topics/types c gcc_jit_type_get_vector150577
Ref: 87150577
Node: Structures and unions151755
Ref: topics/types structures-and-unions151873
Ref: 8a151873
Ref: topics/types c gcc_jit_struct151930
Ref: 8b151930
Ref: topics/types c gcc_jit_field152006
Ref: 8c152006
Ref: topics/types c gcc_jit_context_new_field153467
Ref: 8d153467
Ref: topics/types c gcc_jit_context_new_bitfield153911
Ref: 8e153911
Ref: topics/types c gcc_jit_field_as_object154660
Ref: 90154660
Ref: topics/types c gcc_jit_context_new_struct_type154786
Ref: 91154786
Ref: topics/types c gcc_jit_context_new_opaque_struct155229
Ref: 92155229
Ref: topics/types c gcc_jit_struct_as_type155798
Ref: 94155798
Ref: topics/types c gcc_jit_struct_set_fields155927
Ref: 93155927
Ref: topics/types c gcc_jit_context_new_union_type156207
Ref: 95156207
Node: Function pointer types159216
Ref: topics/types function-pointer-types159336
Ref: 96159336
Node: Reflection API159491
Ref: topics/types reflection-api159581
Ref: 98159581
Ref: topics/types c gcc_jit_type_dyncast_array159624
Ref: 99159624
Ref: topics/types c gcc_jit_type_is_bool159790
Ref: 9a159790
Ref: topics/types c gcc_jit_type_dyncast_function_ptr_type159898
Ref: 9b159898
Ref: topics/types c gcc_jit_function_type_get_return_type160062
Ref: 9c160062
Ref: topics/types c gcc_jit_function_type_get_param_count160234
Ref: 9d160234
Ref: topics/types c gcc_jit_function_type_get_param_type160407
Ref: 9e160407
Ref: topics/types c gcc_jit_type_is_integral160612
Ref: 9f160612
Ref: topics/types c gcc_jit_type_is_pointer160729
Ref: a0160729
Ref: topics/types c gcc_jit_type_dyncast_vector160904
Ref: a1160904
Ref: topics/types c gcc_jit_type_is_struct161070
Ref: a2161070
Ref: topics/types c gcc_jit_vector_type_get_num_units161226
Ref: a3161226
Ref: topics/types c gcc_jit_vector_type_get_element_type161396
Ref: a4161396
Ref: topics/types c gcc_jit_type_unqualified161571
Ref: a5161571
Ref: topics/types c gcc_jit_struct_get_field161776
Ref: a6161776
Ref: topics/types c gcc_jit_struct_get_field_count161923
Ref: a7161923
Ref: topics/types c gcc_jit_case163149
Ref: a9163149
Ref: topics/types c gcc_jit_compatible_types163180
Ref: aa163180
Ref: topics/types c gcc_jit_type_get_size163757
Ref: ac163757
Node: Expressions164152
Ref: topics/expressions doc164269
Ref: ad164269
Ref: topics/expressions expressions164269
Ref: ae164269
Node: Rvalues164423
Ref: topics/expressions rvalues164497
Ref: af164497
Ref: topics/expressions c gcc_jit_rvalue164526
Ref: 13164526
Ref: topics/expressions c gcc_jit_rvalue_get_type165188
Ref: b0165188
Ref: topics/expressions c gcc_jit_rvalue_as_object165313
Ref: 14165313
Node: Simple expressions165655
Ref: topics/expressions simple-expressions165752
Ref: b1165752
Ref: topics/expressions c gcc_jit_context_new_rvalue_from_int165807
Ref: 30165807
Ref: topics/expressions c gcc_jit_context_new_rvalue_from_long166067
Ref: b2166067
Ref: topics/expressions c gcc_jit_context_zero166340
Ref: 2b166340
Ref: topics/expressions c gcc_jit_context_one166655
Ref: 2f166655
Ref: topics/expressions c gcc_jit_context_new_rvalue_from_double166968
Ref: 31166968
Ref: topics/expressions c gcc_jit_context_new_rvalue_from_ptr167247
Ref: b3167247
Ref: topics/expressions c gcc_jit_context_null167469
Ref: b4167469
Ref: topics/expressions c gcc_jit_context_new_string_literal167766
Ref: b5167766
Node: Constructor expressions168165
Ref: topics/expressions constructor-expressions168289
Ref: b6168289
Ref: topics/expressions c gcc_jit_context_new_array_constructor169335
Ref: b9169335
Ref: topics/expressions c gcc_jit_context_new_struct_constructor170482
Ref: ba170482
Ref: topics/expressions c gcc_jit_context_new_union_constructor172139
Ref: bb172139
Node: Vector expressions173090
Ref: topics/expressions vector-expressions173212
Ref: bc173212
Ref: topics/expressions c gcc_jit_context_new_rvalue_from_vector173267
Ref: 89173267
Node: Unary Operations173886
Ref: topics/expressions unary-operations174002
Ref: be174002
Ref: topics/expressions c gcc_jit_context_new_unary_op174053
Ref: bf174053
Ref: topics/expressions c gcc_jit_unary_op174386
Ref: c0174386
Ref: topics/expressions c GCC_JIT_UNARY_OP_MINUS175263
Ref: c1175263
Ref: topics/expressions c GCC_JIT_UNARY_OP_BITWISE_NEGATE175379
Ref: c2175379
Ref: topics/expressions c GCC_JIT_UNARY_OP_LOGICAL_NEGATE175540
Ref: c3175540
Ref: topics/expressions c GCC_JIT_UNARY_OP_ABS175689
Ref: c4175689
Node: Binary Operations175822
Ref: topics/expressions binary-operations175931
Ref: c5175931
Ref: topics/expressions c gcc_jit_context_new_binary_op175984
Ref: 12175984
Ref: topics/expressions c gcc_jit_binary_op176341
Ref: c6176341
Ref: topics/expressions c GCC_JIT_BINARY_OP_PLUS178375
Ref: c7178375
Ref: topics/expressions c GCC_JIT_BINARY_OP_MINUS178589
Ref: c8178589
Ref: topics/expressions c GCC_JIT_BINARY_OP_MULT178724
Ref: c9178724
Ref: topics/expressions c GCC_JIT_BINARY_OP_DIVIDE178871
Ref: ca178871
Ref: topics/expressions c GCC_JIT_BINARY_OP_MODULO179230
Ref: cb179230
Ref: topics/expressions c GCC_JIT_BINARY_OP_BITWISE_AND179376
Ref: cc179376
Ref: topics/expressions c GCC_JIT_BINARY_OP_BITWISE_XOR179496
Ref: cd179496
Ref: topics/expressions c GCC_JIT_BINARY_OP_BITWISE_OR179625
Ref: ce179625
Ref: topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_AND179753
Ref: cf179753
Ref: topics/expressions c GCC_JIT_BINARY_OP_LOGICAL_OR179874
Ref: d0179874
Ref: topics/expressions c GCC_JIT_BINARY_OP_LSHIFT179993
Ref: d1179993
Ref: topics/expressions c GCC_JIT_BINARY_OP_RSHIFT180108
Ref: d2180108
Node: Comparisons180224
Ref: topics/expressions comparisons180331
Ref: d4180331
Ref: topics/expressions c gcc_jit_context_new_comparison180372
Ref: 2c180372
Ref: topics/expressions c gcc_jit_comparison180643
Ref: d5180643
Node: Function calls181749
Ref: topics/expressions function-calls181856
Ref: d6181856
Ref: topics/expressions c gcc_jit_context_new_call181903
Ref: d7181903
Ref: topics/expressions c gcc_jit_context_new_call_through_ptr183025
Ref: d9183025
Ref: topics/expressions c gcc_jit_rvalue_set_bool_require_tail_call183560
Ref: da183560
Node: Function pointers184622
Ref: topics/expressions function-pointers184731
Ref: dc184731
Node: Type-coercion185145
Ref: topics/expressions type-coercion185231
Ref: de185231
Ref: topics/expressions c gcc_jit_context_new_cast185276
Ref: df185276
Ref: topics/expressions c gcc_jit_context_new_bitcast185692
Ref: e0185692
Node: Lvalues186286
Ref: topics/expressions lvalues186409
Ref: e2186409
Ref: topics/expressions c gcc_jit_lvalue186438
Ref: 24186438
Ref: topics/expressions c gcc_jit_lvalue_as_object186674
Ref: e3186674
Ref: topics/expressions c gcc_jit_lvalue_as_rvalue186808
Ref: e4186808
Ref: topics/expressions c gcc_jit_lvalue_get_address186942
Ref: e5186942
Ref: topics/expressions c gcc_jit_lvalue_set_tls_model187143
Ref: e6187143
Ref: topics/expressions c gcc_jit_tls_model187406
Ref: e7187406
Ref: topics/expressions c GCC_JIT_TLS_MODEL_NONE187447
Ref: e8187447
Ref: topics/expressions c GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC187527
Ref: e9187527
Ref: topics/expressions c GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC187579
Ref: ea187579
Ref: topics/expressions c GCC_JIT_TLS_MODEL_INITIAL_EXEC187630
Ref: eb187630
Ref: topics/expressions c GCC_JIT_TLS_MODEL_LOCAL_EXEC187680
Ref: ec187680
Ref: topics/expressions c gcc_jit_lvalue_set_link_section188006
Ref: ee188006
Ref: topics/expressions c gcc_jit_lvalue_set_alignment188964
Ref: f1188964
Ref: topics/expressions c gcc_jit_lvalue_get_alignment189345
Ref: f3189345
Node: Global variables189806
Ref: topics/expressions global-variables189869
Ref: f4189869
Ref: topics/expressions c gcc_jit_context_new_global189920
Ref: f5189920
Ref: topics/expressions c gcc_jit_global_kind190552
Ref: f6190552
Ref: topics/expressions c GCC_JIT_GLOBAL_EXPORTED190595
Ref: f7190595
Ref: topics/expressions c GCC_JIT_GLOBAL_INTERNAL190892
Ref: f9190892
Ref: topics/expressions c GCC_JIT_GLOBAL_IMPORTED191195
Ref: fa191195
Ref: topics/expressions c gcc_jit_global_set_initializer191406
Ref: fb191406
Ref: topics/expressions c gcc_jit_global_set_initializer_rvalue192208
Ref: b7192208
Node: Working with pointers structs and unions193512
Ref: topics/expressions working-with-pointers-structs-and-unions193619
Ref: fd193619
Ref: topics/expressions c gcc_jit_rvalue_dereference193716
Ref: fe193716
Ref: topics/expressions c gcc_jit_lvalue_access_field194064
Ref: ff194064
Ref: topics/expressions c gcc_jit_rvalue_access_field194392
Ref: 100194392
Ref: topics/expressions c gcc_jit_rvalue_dereference_field194685
Ref: 101194685
Ref: topics/expressions c gcc_jit_context_new_array_access195059
Ref: d3195059
Node: Creating and using functions195544
Ref: topics/functions doc195676
Ref: 102195676
Ref: topics/functions creating-and-using-functions195676
Ref: 103195676
Node: Params195804
Ref: topics/functions params195896
Ref: 104195896
Ref: topics/functions c gcc_jit_param195923
Ref: 25195923
Ref: topics/functions c gcc_jit_context_new_param196016
Ref: 10196016
Ref: topics/functions c gcc_jit_param_as_lvalue196609
Ref: 105196609
Ref: topics/functions c gcc_jit_param_as_rvalue196738
Ref: 106196738
Ref: topics/functions c gcc_jit_param_as_object196867
Ref: 107196867
Node: Functions196996
Ref: topics/functions functions197103
Ref: 108197103
Ref: topics/functions c gcc_jit_function197136
Ref: 29197136
Ref: topics/functions c gcc_jit_context_new_function197303
Ref: 11197303
Ref: topics/functions c gcc_jit_function_kind197658
Ref: 109197658
Ref: topics/functions c GCC_JIT_FUNCTION_EXPORTED197793
Ref: 10a197793
Ref: topics/functions c GCC_JIT_FUNCTION_INTERNAL198150
Ref: 10b198150
Ref: topics/functions c GCC_JIT_FUNCTION_IMPORTED198346
Ref: 10c198346
Ref: topics/functions c GCC_JIT_FUNCTION_ALWAYS_INLINE198583
Ref: 10d198583
Ref: topics/functions c gcc_jit_context_get_builtin_function199240
Ref: 10e199240
Ref: topics/functions c gcc_jit_function_as_object199994
Ref: 10f199994
Ref: topics/functions c gcc_jit_function_get_param200131
Ref: 110200131
Ref: topics/functions c gcc_jit_function_dump_to_dot200287
Ref: 33200287
Ref: topics/functions c gcc_jit_function_new_local200453
Ref: 26200453
Ref: topics/functions c gcc_jit_function_get_param_count200929
Ref: 111200929
Ref: topics/functions c gcc_jit_function_get_return_type201073
Ref: 112201073
Ref: topics/functions c gcc_jit_case201569
Ref: 113201569
Node: Blocks201600
Ref: topics/functions blocks201711
Ref: 114201711
Ref: topics/functions c gcc_jit_block201738
Ref: 28201738
Ref: topics/functions c gcc_jit_function_new_block202250
Ref: 115202250
Ref: topics/functions c gcc_jit_block_as_object202951
Ref: 116202951
Ref: topics/functions c gcc_jit_block_get_function203077
Ref: 117203077
Node: Statements203216
Ref: topics/functions statements203309
Ref: 118203309
Ref: topics/functions c gcc_jit_block_add_eval203344
Ref: d8203344
Ref: topics/functions c gcc_jit_block_add_assignment203650
Ref: 2a203650
Ref: topics/functions c gcc_jit_block_add_assignment_op203974
Ref: 2e203974
Ref: topics/functions c gcc_jit_block_add_comment204609
Ref: 3d204609
Ref: topics/functions c gcc_jit_block_end_with_conditional205470
Ref: 2d205470
Ref: topics/functions c gcc_jit_block_end_with_jump206004
Ref: 119206004
Ref: topics/functions c gcc_jit_block_end_with_return206274
Ref: 11a206274
Ref: topics/functions c gcc_jit_block_end_with_void_return206580
Ref: 11b206580
Ref: topics/functions c gcc_jit_block_end_with_switch206867
Ref: 11c206867
Ref: topics/functions c gcc_jit_context_new_case208739
Ref: 11e208739
Ref: topics/functions c gcc_jit_case_as_object209279
Ref: 11d209279
Node: Function pointers<2>213647
Ref: topics/function-pointers doc213784
Ref: 121213784
Ref: topics/function-pointers function-pointers213784
Ref: 122213784
Ref: topics/function-pointers c gcc_jit_function_get_address214132
Ref: dd214132
Ref: topics/function-pointers c gcc_jit_context_new_function_ptr_type215438
Ref: 97215438
Node: Source Locations215882
Ref: topics/locations doc216010
Ref: 124216010
Ref: topics/locations source-locations216010
Ref: 125216010
Ref: topics/locations c gcc_jit_location216053
Ref: 3b216053
Ref: topics/locations c gcc_jit_context_new_location216826
Ref: 41216826
Node: Faking it217265
Ref: topics/locations faking-it217330
Ref: 126217330
Node: Compiling a context217989
Ref: topics/compilation doc218122
Ref: 127218122
Ref: topics/compilation compiling-a-context218122
Ref: 128218122
Node: In-memory compilation218612
Ref: topics/compilation in-memory-compilation218726
Ref: 129218726
Ref: topics/compilation c gcc_jit_context_compile218783
Ref: 15218783
Ref: topics/compilation c gcc_jit_result219120
Ref: 16219120
Ref: topics/compilation c gcc_jit_result_get_code219332
Ref: 17219332
Ref: topics/compilation c gcc_jit_result_get_global220914
Ref: f8220914
Ref: topics/compilation c gcc_jit_result_release222384
Ref: 39222384
Node: Ahead-of-time compilation222774
Ref: topics/compilation ahead-of-time-compilation222888
Ref: 12a222888
Ref: topics/compilation c gcc_jit_context_compile_to_file223250
Ref: 4a223250
Ref: topics/compilation c gcc_jit_output_kind223804
Ref: 12b223804
Ref: topics/compilation c GCC_JIT_OUTPUT_KIND_ASSEMBLER224720
Ref: 12c224720
Ref: topics/compilation c GCC_JIT_OUTPUT_KIND_OBJECT_FILE224812
Ref: 12d224812
Ref: topics/compilation c GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY224903
Ref: 12e224903
Ref: topics/compilation c GCC_JIT_OUTPUT_KIND_EXECUTABLE225001
Ref: 12f225001
Node: ABI and API compatibility225090
Ref: topics/compatibility doc225218
Ref: 130225218
Ref: topics/compatibility abi-and-api-compatibility225218
Ref: 131225218
Node: Programmatically checking version226775
Ref: topics/compatibility programmatically-checking-version226897
Ref: 132226897
Ref: topics/compatibility c gcc_jit_version_major227043
Ref: 133227043
Ref: topics/compatibility c gcc_jit_version_minor227178
Ref: 134227178
Ref: topics/compatibility c gcc_jit_version_patchlevel227319
Ref: 135227319
Node: ABI symbol tags227567
Ref: topics/compatibility abi-symbol-tags227689
Ref: 136227689
Node: LIBGCCJIT_ABI_0228377
Ref: topics/compatibility id1228471
Ref: 137228471
Ref: topics/compatibility libgccjit-abi-0228471
Ref: 138228471
Ref: LIBGCCJIT_ABI_0-Footnote-1228859
Node: LIBGCCJIT_ABI_1228924
Ref: topics/compatibility id2229042
Ref: 139229042
Ref: topics/compatibility libgccjit-abi-1229042
Ref: 75229042
Node: LIBGCCJIT_ABI_2229198
Ref: topics/compatibility id3229316
Ref: 13a229316
Ref: topics/compatibility libgccjit-abi-2229316
Ref: 6c229316
Node: LIBGCCJIT_ABI_3229482
Ref: topics/compatibility id4229600
Ref: 13b229600
Ref: topics/compatibility libgccjit-abi-3229600
Ref: 11f229600
Node: LIBGCCJIT_ABI_4229895
Ref: topics/compatibility id5230013
Ref: 13c230013
Ref: topics/compatibility libgccjit-abi-4230013
Ref: 13d230013
Node: LIBGCCJIT_ABI_5230468
Ref: topics/compatibility id6230586
Ref: 145230586
Ref: topics/compatibility libgccjit-abi-5230586
Ref: 6e230586
Node: LIBGCCJIT_ABI_6230747
Ref: topics/compatibility id7230865
Ref: 146230865
Ref: topics/compatibility libgccjit-abi-6230865
Ref: db230865
Node: LIBGCCJIT_ABI_7231023
Ref: topics/compatibility id8231141
Ref: 147231141
Ref: topics/compatibility libgccjit-abi-7231141
Ref: 85231141
Node: LIBGCCJIT_ABI_8231282
Ref: topics/compatibility id9231400
Ref: 148231400
Ref: topics/compatibility libgccjit-abi-8231400
Ref: 88231400
Node: LIBGCCJIT_ABI_9231540
Ref: topics/compatibility id10231659
Ref: 149231659
Ref: topics/compatibility libgccjit-abi-9231659
Ref: 123231659
Node: LIBGCCJIT_ABI_10231806
Ref: topics/compatibility id11231926
Ref: 14a231926
Ref: topics/compatibility libgccjit-abi-10231926
Ref: bd231926
Node: LIBGCCJIT_ABI_11232086
Ref: topics/compatibility id12232207
Ref: 14b232207
Ref: topics/compatibility libgccjit-abi-11232207
Ref: 77232207
Node: LIBGCCJIT_ABI_12232362
Ref: topics/compatibility id13232483
Ref: 14c232483
Ref: topics/compatibility libgccjit-abi-12232483
Ref: 8f232483
Node: LIBGCCJIT_ABI_13232633
Ref: topics/compatibility id14232754
Ref: 14d232754
Ref: topics/compatibility libgccjit-abi-13232754
Ref: 14e232754
Node: LIBGCCJIT_ABI_14233047
Ref: topics/compatibility id15233168
Ref: 14f233168
Ref: topics/compatibility libgccjit-abi-14233168
Ref: fc233168
Node: LIBGCCJIT_ABI_15233320
Ref: topics/compatibility id16233441
Ref: 150233441
Ref: topics/compatibility libgccjit-abi-15233441
Ref: 151233441
Node: LIBGCCJIT_ABI_16234162
Ref: topics/compatibility id17234283
Ref: 15b234283
Ref: topics/compatibility libgccjit-abi-16234283
Ref: a8234283
Node: LIBGCCJIT_ABI_17235361
Ref: topics/compatibility id18235482
Ref: 15c235482
Ref: topics/compatibility libgccjit-abi-17235482
Ref: ed235482
Node: LIBGCCJIT_ABI_18235714
Ref: topics/compatibility id19235835
Ref: 15d235835
Ref: topics/compatibility libgccjit-abi-18235835
Ref: ef235835
Node: LIBGCCJIT_ABI_19236056
Ref: topics/compatibility id20236177
Ref: 15e236177
Ref: topics/compatibility libgccjit-abi-19236177
Ref: b8236177
Node: LIBGCCJIT_ABI_20236627
Ref: topics/compatibility id21236748
Ref: 15f236748
Ref: topics/compatibility libgccjit-abi-20236748
Ref: ab236748
Node: LIBGCCJIT_ABI_21237416
Ref: topics/compatibility id22237537
Ref: 160237537
Ref: topics/compatibility libgccjit-abi-21237537
Ref: e1237537
Node: LIBGCCJIT_ABI_22237760
Ref: topics/compatibility id23237881
Ref: 161237881
Ref: topics/compatibility libgccjit-abi-22237881
Ref: f0237881
Node: LIBGCCJIT_ABI_23238099
Ref: topics/compatibility id24238220
Ref: 162238220
Ref: topics/compatibility libgccjit-abi-23238220
Ref: 70238220
Node: LIBGCCJIT_ABI_24238439
Ref: topics/compatibility id25238535
Ref: 163238535
Ref: topics/compatibility libgccjit-abi-24238535
Ref: f2238535
Node: Performance238803
Ref: topics/performance doc238950
Ref: 164238950
Ref: topics/performance performance238950
Ref: 165238950
Node: The timing API239014
Ref: topics/performance the-timing-api239079
Ref: 166239079
Ref: topics/performance c LIBGCCJIT_HAVE_TIMING_API244432
Ref: 168244432
Ref: topics/performance c gcc_jit_timer244864
Ref: 167244864
Ref: topics/performance c gcc_jit_timer_new244891
Ref: 140244891
Ref: topics/performance c gcc_jit_timer_release245223
Ref: 141245223
Ref: topics/performance c gcc_jit_context_set_timer245586
Ref: 13f245586
Ref: topics/performance c gcc_jit_context_get_timer246260
Ref: 13e246260
Ref: topics/performance c gcc_jit_timer_push246561
Ref: 142246561
Ref: topics/performance c gcc_jit_timer_pop247002
Ref: 143247002
Ref: topics/performance c gcc_jit_timer_print247445
Ref: 144247445
Node: Using Assembly Language with libgccjit247786
Ref: topics/asm doc247899
Ref: 169247899
Ref: topics/asm using-assembly-language-with-libgccjit247899
Ref: 16a247899
Ref: Using Assembly Language with libgccjit-Footnote-1248608
Node: Adding assembler instructions within a function248688
Ref: topics/asm adding-assembler-instructions-within-a-function248859
Ref: 16b248859
Ref: topics/asm c gcc_jit_extended_asm248970
Ref: 120248970
Ref: topics/asm c gcc_jit_block_add_extended_asm251639
Ref: 152251639
Ref: topics/asm c gcc_jit_block_end_with_extended_asm_goto252225
Ref: 153252225
Ref: topics/asm c gcc_jit_extended_asm_set_volatile_flag254711
Ref: 155254711
Ref: topics/asm c gcc_jit_extended_asm_set_inline_flag255974
Ref: 156255974
Ref: topics/asm c gcc_jit_extended_asm_add_output_operand256178
Ref: 157256178
Ref: topics/asm c gcc_jit_extended_asm_add_input_operand257537
Ref: 158257537
Ref: topics/asm c gcc_jit_extended_asm_add_clobber258844
Ref: 159258844
Ref: topics/asm c gcc_jit_extended_asm_as_object259611
Ref: 154259611
Ref: Adding assembler instructions within a function-Footnote-1259802
Ref: Adding assembler instructions within a function-Footnote-2259872
Ref: Adding assembler instructions within a function-Footnote-3259951
Ref: Adding assembler instructions within a function-Footnote-4260028
Ref: Adding assembler instructions within a function-Footnote-5260100
Ref: Adding assembler instructions within a function-Footnote-6260176
Node: Adding top-level assembler statements260270
Ref: topics/asm adding-top-level-assembler-statements260441
Ref: 16c260441
Ref: topics/asm c gcc_jit_context_add_top_level_asm260701
Ref: 15a260701
Node: C++ bindings for libgccjit262072
Ref: cp/index doc262183
Ref: 16d262183
Ref: cp/index c-bindings-for-libgccjit262183
Ref: 16e262183
Ref: C++ bindings for libgccjit-Footnote-1262731
Node: Tutorial<2>262768
Ref: cp/intro/index doc262872
Ref: 16f262872
Ref: cp/intro/index tutorial262872
Ref: 170262872
Node: Tutorial part 1 “Hello world”<2>263315
Ref: cp/intro/tutorial01 doc263470
Ref: 171263470
Ref: cp/intro/tutorial01 tutorial-part-1-hello-world263470
Ref: 172263470
Node: Tutorial part 2 Creating a trivial machine code function<2>268198
Ref: cp/intro/tutorial02 doc268400
Ref: 173268400
Ref: cp/intro/tutorial02 tutorial-part-2-creating-a-trivial-machine-code-function268400
Ref: 174268400
Node: Options<3>273519
Ref: cp/intro/tutorial02 options273652
Ref: 180273652
Node: Full example<3>276109
Ref: cp/intro/tutorial02 full-example276242
Ref: 183276242
Node: Tutorial part 3 Loops and variables<2>279890
Ref: cp/intro/tutorial03 doc280118
Ref: 184280118
Ref: cp/intro/tutorial03 tutorial-part-3-loops-and-variables280118
Ref: 185280118
Node: Expressions lvalues and rvalues<2>282272
Ref: cp/intro/tutorial03 expressions-lvalues-and-rvalues282408
Ref: 186282408
Node: Control flow<2>284693
Ref: cp/intro/tutorial03 control-flow284875
Ref: 18a284875
Node: Visualizing the control flow graph<2>289613
Ref: cp/intro/tutorial03 visualizing-the-control-flow-graph289776
Ref: 193289776
Node: Full example<4>290442
Ref: cp/intro/tutorial03 full-example290581
Ref: 195290581
Node: Tutorial part 4 Adding JIT-compilation to a toy interpreter<2>295542
Ref: cp/intro/tutorial04 doc295702
Ref: 196295702
Ref: cp/intro/tutorial04 tutorial-part-4-adding-jit-compilation-to-a-toy-interpreter295702
Ref: 197295702
Node: Our toy interpreter<2>296586
Ref: cp/intro/tutorial04 our-toy-interpreter296747
Ref: 198296747
Node: Compiling to machine code<2>304346
Ref: cp/intro/tutorial04 compiling-to-machine-code304536
Ref: 199304536
Node: Setting things up<2>306171
Ref: cp/intro/tutorial04 setting-things-up306365
Ref: 19a306365
Node: Populating the function<2>310012
Ref: cp/intro/tutorial04 populating-the-function310213
Ref: 19c310213
Node: Verifying the control flow graph<2>316683
Ref: cp/intro/tutorial04 verifying-the-control-flow-graph316888
Ref: 19e316888
Node: Compiling the context<2>317461
Ref: cp/intro/tutorial04 compiling-the-context317685
Ref: 19f317685
Node: Single-stepping through the generated code<2>318761
Ref: cp/intro/tutorial04 single-stepping-through-the-generated-code318981
Ref: 1a0318981
Node: Examining the generated code<2>321043
Ref: cp/intro/tutorial04 examining-the-generated-code321265
Ref: 1a2321265
Node: Putting it all together<2>325844
Ref: cp/intro/tutorial04 putting-it-all-together326075
Ref: 1a3326075
Node: Behind the curtain How does our code get optimized?<2>326923
Ref: cp/intro/tutorial04 behind-the-curtain-how-does-our-code-get-optimized327114
Ref: 1a4327114
Node: Optimizing away stack manipulation<2>332805
Ref: cp/intro/tutorial04 optimizing-away-stack-manipulation332977
Ref: 1a5332977
Node: Elimination of tail recursion<2>339098
Ref: cp/intro/tutorial04 elimination-of-tail-recursion339270
Ref: 1a6339270
Node: Topic Reference<2>340762
Ref: cp/topics/index doc340866
Ref: 1a7340866
Ref: cp/topics/index topic-reference340866
Ref: 1a8340866
Node: Compilation contexts<2>341237
Ref: cp/topics/contexts doc341337
Ref: 1a9341337
Ref: cp/topics/contexts compilation-contexts341337
Ref: 1aa341337
Ref: cp/topics/contexts _CPPv4N6gccjit7contextE341392
Ref: 175341392
Ref: cp/topics/contexts _CPPv3N6gccjit7contextE341392
Ref: 1ab341392
Ref: cp/topics/contexts _CPPv2N6gccjit7contextE341392
Ref: 1ac341392
Ref: cp/topics/contexts gccjit context341392
Ref: 1ad341392
Node: Lifetime-management<2>341986
Ref: cp/topics/contexts lifetime-management342096
Ref: 1ae342096
Ref: cp/topics/contexts _CPPv4N6gccjit7context7acquireEv342365
Ref: 176342365
Ref: cp/topics/contexts _CPPv3N6gccjit7context7acquireEv342365
Ref: 1af342365
Ref: cp/topics/contexts _CPPv2N6gccjit7context7acquireEv342365
Ref: 1b0342365
Ref: cp/topics/contexts gccjit context acquire342365
Ref: 1b1342365
Ref: cp/topics/contexts _CPPv4N6gccjit7context7releaseEv342621
Ref: 179342621
Ref: cp/topics/contexts _CPPv3N6gccjit7context7releaseEv342621
Ref: 1b2342621
Ref: cp/topics/contexts _CPPv2N6gccjit7context7releaseEv342621
Ref: 1b3342621
Ref: cp/topics/contexts gccjit context release342621
Ref: 1b4342621
Ref: cp/topics/contexts _CPPv4N6gccjit7context17new_child_contextEv343052
Ref: 1b5343052
Ref: cp/topics/contexts _CPPv3N6gccjit7context17new_child_contextEv343052
Ref: 1b6343052
Ref: cp/topics/contexts _CPPv2N6gccjit7context17new_child_contextEv343052
Ref: 1b7343052
Ref: cp/topics/contexts gccjit context new_child_context343052
Ref: 1b8343052
Node: Thread-safety<2>344455
Ref: cp/topics/contexts thread-safety344591
Ref: 1b9344591
Node: Error-handling<3>345295
Ref: cp/topics/contexts error-handling345421
Ref: 1ba345421
Ref: cp/topics/contexts _CPPv4N6gccjit7context15get_first_errorEPN6gccjit7contextE345848
Ref: 1bb345848
Ref: cp/topics/contexts _CPPv3N6gccjit7context15get_first_errorEPN6gccjit7contextE345848
Ref: 1bc345848
Ref: cp/topics/contexts _CPPv2N6gccjit7context15get_first_errorEPN6gccjit7contextE345848
Ref: 1bd345848
Ref: cp/topics/contexts gccjit context get_first_error__gccjit contextP345848
Ref: 1be345848
Node: Debugging<2>346159
Ref: cp/topics/contexts debugging346279
Ref: 1bf346279
Ref: cp/topics/contexts _CPPv4N6gccjit7context12dump_to_fileERKNSt6stringEi346316
Ref: 1c0346316
Ref: cp/topics/contexts _CPPv3N6gccjit7context12dump_to_fileERKNSt6stringEi346316
Ref: 1c1346316
Ref: cp/topics/contexts _CPPv2N6gccjit7context12dump_to_fileERKNSt6stringEi346316
Ref: 1c2346316
Ref: cp/topics/contexts gccjit context dump_to_file__ssCR i346316
Ref: 1c3346316
Ref: cp/topics/contexts _CPPv4N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc346895
Ref: 1c4346895
Ref: cp/topics/contexts _CPPv3N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc346895
Ref: 1c5346895
Ref: cp/topics/contexts _CPPv2N6gccjit7context23dump_reproducer_to_fileEP15gcc_jit_contextPKc346895
Ref: 1c6346895
Ref: cp/topics/contexts gccjit context dump_reproducer_to_file__gcc_jit_contextP cCP346895
Ref: 1c7346895
Node: Options<4>347315
Ref: cp/topics/contexts options347409
Ref: 1c8347409
Node: String Options<2>347638
Ref: cp/topics/contexts string-options347732
Ref: 1c9347732
Ref: cp/topics/contexts _CPPv4N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc347779
Ref: 1ca347779
Ref: cp/topics/contexts _CPPv3N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc347779
Ref: 1cb347779
Ref: cp/topics/contexts _CPPv2N6gccjit7context14set_str_optionE18gcc_jit_str_optionPKc347779
Ref: 1cc347779
Ref: cp/topics/contexts gccjit context set_str_option__gcc_jit_str_option cCP347779
Ref: 1cd347779
Node: Boolean options<2>348080
Ref: cp/topics/contexts boolean-options348201
Ref: 1ce348201
Ref: cp/topics/contexts _CPPv4N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni348250
Ref: 181348250
Ref: cp/topics/contexts _CPPv3N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni348250
Ref: 1cf348250
Ref: cp/topics/contexts _CPPv2N6gccjit7context15set_bool_optionE19gcc_jit_bool_optioni348250
Ref: 1d0348250
Ref: cp/topics/contexts gccjit context set_bool_option__gcc_jit_bool_option i348250
Ref: 1d1348250
Ref: cp/topics/contexts _CPPv4N6gccjit7context33set_bool_allow_unreachable_blocksEi348547
Ref: 1d2348547
Ref: cp/topics/contexts _CPPv3N6gccjit7context33set_bool_allow_unreachable_blocksEi348547
Ref: 1d3348547
Ref: cp/topics/contexts _CPPv2N6gccjit7context33set_bool_allow_unreachable_blocksEi348547
Ref: 1d4348547
Ref: cp/topics/contexts gccjit context set_bool_allow_unreachable_blocks__i348547
Ref: 1d5348547
Ref: cp/topics/contexts _CPPv4N6gccjit7context28set_bool_use_external_driverEi349113
Ref: 1d6349113
Ref: cp/topics/contexts _CPPv3N6gccjit7context28set_bool_use_external_driverEi349113
Ref: 1d7349113
Ref: cp/topics/contexts _CPPv2N6gccjit7context28set_bool_use_external_driverEi349113
Ref: 1d8349113
Ref: cp/topics/contexts gccjit context set_bool_use_external_driver__i349113
Ref: 1d9349113
Node: Integer options<2>349820
Ref: cp/topics/contexts integer-options349958
Ref: 1da349958
Ref: cp/topics/contexts _CPPv4N6gccjit7context14set_int_optionE18gcc_jit_int_optioni350007
Ref: 182350007
Ref: cp/topics/contexts _CPPv3N6gccjit7context14set_int_optionE18gcc_jit_int_optioni350007
Ref: 1db350007
Ref: cp/topics/contexts _CPPv2N6gccjit7context14set_int_optionE18gcc_jit_int_optioni350007
Ref: 1dc350007
Ref: cp/topics/contexts gccjit context set_int_option__gcc_jit_int_option i350007
Ref: 1dd350007
Node: Additional command-line options<2>350302
Ref: cp/topics/contexts additional-command-line-options350413
Ref: 1de350413
Ref: cp/topics/contexts _CPPv4N6gccjit7context23add_command_line_optionEPKc350494
Ref: 1df350494
Ref: cp/topics/contexts _CPPv3N6gccjit7context23add_command_line_optionEPKc350494
Ref: 1e0350494
Ref: cp/topics/contexts _CPPv2N6gccjit7context23add_command_line_optionEPKc350494
Ref: 1e1350494
Ref: cp/topics/contexts gccjit context add_command_line_option__cCP350494
Ref: 1e2350494
Node: Objects<2>350975
Ref: cp/topics/objects doc351092
Ref: 1e3351092
Ref: cp/topics/objects objects351092
Ref: 1e4351092
Ref: cp/topics/objects _CPPv4N6gccjit6objectE351121
Ref: 17a351121
Ref: cp/topics/objects _CPPv3N6gccjit6objectE351121
Ref: 1e5351121
Ref: cp/topics/objects _CPPv2N6gccjit6objectE351121
Ref: 1e6351121
Ref: cp/topics/objects gccjit object351121
Ref: 1e7351121
Ref: cp/topics/objects _CPPv4NK6gccjit6object11get_contextEv351947
Ref: 1e8351947
Ref: cp/topics/objects _CPPv3NK6gccjit6object11get_contextEv351947
Ref: 1e9351947
Ref: cp/topics/objects _CPPv2NK6gccjit6object11get_contextEv351947
Ref: 1ea351947
Ref: cp/topics/objects gccjit object get_contextC351947
Ref: 1eb351947
Ref: cp/topics/objects _CPPv4NK6gccjit6object16get_debug_stringEv352092
Ref: 17b352092
Ref: cp/topics/objects _CPPv3NK6gccjit6object16get_debug_stringEv352092
Ref: 1ec352092
Ref: cp/topics/objects _CPPv2NK6gccjit6object16get_debug_stringEv352092
Ref: 1ed352092
Ref: cp/topics/objects gccjit object get_debug_stringC352092
Ref: 1ee352092
Node: Types<2>352408
Ref: cp/topics/types doc352516
Ref: 1ef352516
Ref: cp/topics/types types352516
Ref: 1f0352516
Ref: cp/topics/types _CPPv4N6gccjit4typeE352541
Ref: 177352541
Ref: cp/topics/types _CPPv3N6gccjit4typeE352541
Ref: 1f1352541
Ref: cp/topics/types _CPPv2N6gccjit4typeE352541
Ref: 1f2352541
Ref: cp/topics/types gccjit type352541
Ref: 1f3352541
Node: Standard types<2>353635
Ref: cp/topics/types standard-types353739
Ref: 1f6353739
Ref: cp/topics/types _CPPv4N6gccjit7context8get_typeE13gcc_jit_types353786
Ref: 178353786
Ref: cp/topics/types _CPPv3N6gccjit7context8get_typeE13gcc_jit_types353786
Ref: 1f7353786
Ref: cp/topics/types _CPPv2N6gccjit7context8get_typeE13gcc_jit_types353786
Ref: 1f8353786
Ref: cp/topics/types gccjit context get_type__gcc_jit_types353786
Ref: 1f9353786
Ref: cp/topics/types _CPPv4N6gccjit7context12get_int_typeE6size_ti354039
Ref: 1fa354039
Ref: cp/topics/types _CPPv3N6gccjit7context12get_int_typeE6size_ti354039
Ref: 1fb354039
Ref: cp/topics/types _CPPv2N6gccjit7context12get_int_typeE6size_ti354039
Ref: 1fc354039
Ref: cp/topics/types gccjit context get_int_type__s i354039
Ref: 1fd354039
Ref: cp/topics/types _CPPv4IEN6gccjit7context12get_int_typeI1TEEN6gccjit4typeEv354218
Ref: 1fe354218
Ref: cp/topics/types _CPPv3IEN6gccjit7context12get_int_typeI1TEEv354218
Ref: 1ff354218
Ref: cp/topics/types _CPPv2IEN6gccjit7context12get_int_typeI1TEEv354218
Ref: 200354218
Node: Pointers const and volatile<2>354522
Ref: cp/topics/types pointers-const-and-volatile354650
Ref: 201354650
Ref: cp/topics/types _CPPv4N6gccjit4type11get_pointerEv354743
Ref: 1f4354743
Ref: cp/topics/types _CPPv3N6gccjit4type11get_pointerEv354743
Ref: 202354743
Ref: cp/topics/types _CPPv2N6gccjit4type11get_pointerEv354743
Ref: 203354743
Ref: cp/topics/types gccjit type get_pointer354743
Ref: 204354743
Ref: cp/topics/types _CPPv4N6gccjit4type9get_constEv354883
Ref: 1f5354883
Ref: cp/topics/types _CPPv3N6gccjit4type9get_constEv354883
Ref: 205354883
Ref: cp/topics/types _CPPv2N6gccjit4type9get_constEv354883
Ref: 206354883
Ref: cp/topics/types gccjit type get_const354883
Ref: 207354883
Ref: cp/topics/types _CPPv4N6gccjit4type12get_volatileEv355026
Ref: 208355026
Ref: cp/topics/types _CPPv3N6gccjit4type12get_volatileEv355026
Ref: 209355026
Ref: cp/topics/types _CPPv2N6gccjit4type12get_volatileEv355026
Ref: 20a355026
Ref: cp/topics/types gccjit type get_volatile355026
Ref: 20b355026
Ref: cp/topics/types _CPPv4N6gccjit4type11get_alignedE6size_t355175
Ref: 20c355175
Ref: cp/topics/types _CPPv3N6gccjit4type11get_alignedE6size_t355175
Ref: 20d355175
Ref: cp/topics/types _CPPv2N6gccjit4type11get_alignedE6size_t355175
Ref: 20e355175
Ref: cp/topics/types gccjit type get_aligned__s355175
Ref: 20f355175
Ref: cp/topics/types _CPPv4N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE355435
Ref: 210355435
Ref: cp/topics/types _CPPv3N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE355435
Ref: 211355435
Ref: cp/topics/types _CPPv2N6gccjit7context14new_array_typeEN6gccjit4typeEiN6gccjit8locationE355435
Ref: 212355435
Ref: cp/topics/types gccjit context new_array_type__gccjit type i gccjit location355435
Ref: 213355435
Node: Vector types<2>355711
Ref: cp/topics/types vector-types355846
Ref: 214355846
Ref: cp/topics/types _CPPv4N6gccjit4type10get_vectorE6size_t355889
Ref: 215355889
Ref: cp/topics/types _CPPv3N6gccjit4type10get_vectorE6size_t355889
Ref: 216355889
Ref: cp/topics/types _CPPv2N6gccjit4type10get_vectorE6size_t355889
Ref: 217355889
Ref: cp/topics/types gccjit type get_vector__s355889
Ref: 218355889
Node: Structures and unions<2>356185
Ref: cp/topics/types structures-and-unions356281
Ref: 219356281
Ref: cp/topics/types _CPPv4N6gccjit7struct_E356342
Ref: 21a356342
Ref: cp/topics/types _CPPv3N6gccjit7struct_E356342
Ref: 21b356342
Ref: cp/topics/types _CPPv2N6gccjit7struct_E356342
Ref: 21c356342
Ref: cp/topics/types gccjit struct_356342
Ref: 21d356342
Ref: cp/topics/types _CPPv4N6gccjit5fieldE356543
Ref: 21e356543
Ref: cp/topics/types _CPPv3N6gccjit5fieldE356543
Ref: 21f356543
Ref: cp/topics/types _CPPv2N6gccjit5fieldE356543
Ref: 220356543
Ref: cp/topics/types gccjit field356543
Ref: 221356543
Ref: cp/topics/types _CPPv4N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE357921
Ref: 222357921
Ref: cp/topics/types _CPPv3N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE357921
Ref: 223357921
Ref: cp/topics/types _CPPv2N6gccjit7context9new_fieldEN6gccjit4typeEPKcN6gccjit8locationE357921
Ref: 224357921
Ref: cp/topics/types gccjit context new_field__gccjit type cCP gccjit location357921
Ref: 225357921
Ref: cp/topics/types _CPPv4N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE358144
Ref: 226358144
Ref: cp/topics/types _CPPv3N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE358144
Ref: 227358144
Ref: cp/topics/types _CPPv2N6gccjit7context15new_struct_typeERKNSt6stringERNSt6vectorI5fieldEEN6gccjit8locationE358144
Ref: 228358144
Ref: cp/topics/types gccjit context new_struct_type__ssCR std vector field R gccjit location358144
Ref: 229358144
Ref: cp/topics/types _CPPv4N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE358404
Ref: 22a358404
Ref: cp/topics/types _CPPv3N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE358404
Ref: 22b358404
Ref: cp/topics/types _CPPv2N6gccjit7context17new_opaque_structERKNSt6stringEN6gccjit8locationE358404
Ref: 22c358404
Ref: cp/topics/types gccjit context new_opaque_struct__ssCR gccjit location358404
Ref: 22d358404
Node: Expressions<2>358816
Ref: cp/topics/expressions doc358945
Ref: 22e358945
Ref: cp/topics/expressions expressions358945
Ref: 22f358945
Node: Rvalues<2>359128
Ref: cp/topics/expressions rvalues359211
Ref: 230359211
Ref: cp/topics/expressions _CPPv4N6gccjit6rvalueE359244
Ref: 17e359244
Ref: cp/topics/expressions _CPPv3N6gccjit6rvalueE359244
Ref: 231359244
Ref: cp/topics/expressions _CPPv2N6gccjit6rvalueE359244
Ref: 232359244
Ref: cp/topics/expressions gccjit rvalue359244
Ref: 233359244
Ref: cp/topics/expressions _CPPv4N6gccjit6rvalue8get_typeEv360031
Ref: 234360031
Ref: cp/topics/expressions _CPPv3N6gccjit6rvalue8get_typeEv360031
Ref: 235360031
Ref: cp/topics/expressions _CPPv2N6gccjit6rvalue8get_typeEv360031
Ref: 236360031
Ref: cp/topics/expressions gccjit rvalue get_type360031
Ref: 237360031
Node: Simple expressions<2>360490
Ref: cp/topics/expressions simple-expressions360591
Ref: 238360591
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEi360646
Ref: 192360646
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEi360646
Ref: 239360646
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEi360646
Ref: 23a360646
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type iC360646
Ref: 23b360646
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEl360904
Ref: 23c360904
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEl360904
Ref: 23d360904
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEl360904
Ref: 23e360904
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type lC360904
Ref: 23f360904
Ref: cp/topics/expressions _CPPv4NK6gccjit7context4zeroEN6gccjit4typeE361164
Ref: 18e361164
Ref: cp/topics/expressions _CPPv3NK6gccjit7context4zeroEN6gccjit4typeE361164
Ref: 240361164
Ref: cp/topics/expressions _CPPv2NK6gccjit7context4zeroEN6gccjit4typeE361164
Ref: 241361164
Ref: cp/topics/expressions gccjit context zero__gccjit typeC361164
Ref: 242361164
Ref: cp/topics/expressions _CPPv4NK6gccjit7context3oneEN6gccjit4typeE361461
Ref: 243361461
Ref: cp/topics/expressions _CPPv3NK6gccjit7context3oneEN6gccjit4typeE361461
Ref: 244361461
Ref: cp/topics/expressions _CPPv2NK6gccjit7context3oneEN6gccjit4typeE361461
Ref: 245361461
Ref: cp/topics/expressions gccjit context one__gccjit typeC361461
Ref: 246361461
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEd361756
Ref: 247361756
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEd361756
Ref: 248361756
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEd361756
Ref: 249361756
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type doubleC361756
Ref: 24a361756
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeEPv362030
Ref: 24b362030
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeEPv362030
Ref: 24c362030
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeEPv362030
Ref: 24d362030
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type voidPC362030
Ref: 24e362030
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueERKNSt6stringE362250
Ref: 24f362250
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueERKNSt6stringE362250
Ref: 250362250
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueERKNSt6stringE362250
Ref: 251362250
Ref: cp/topics/expressions gccjit context new_rvalue__ssCRC362250
Ref: 252362250
Node: Vector expressions<2>362508
Ref: cp/topics/expressions vector-expressions362637
Ref: 253362637
Ref: cp/topics/expressions _CPPv4NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE362692
Ref: 254362692
Ref: cp/topics/expressions _CPPv3NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE362692
Ref: 255362692
Ref: cp/topics/expressions _CPPv2NK6gccjit7context10new_rvalueEN6gccjit4typeENSt6vectorIN6gccjit6rvalueEEE362692
Ref: 256362692
Ref: cp/topics/expressions gccjit context new_rvalue__gccjit type std vector gccjit rvalue C362692
Ref: 257362692
Node: Unary Operations<2>363036
Ref: cp/topics/expressions unary-operations363164
Ref: 258363164
Ref: cp/topics/expressions _CPPv4N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363215
Ref: 259363215
Ref: cp/topics/expressions _CPPv3N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363215
Ref: 25a363215
Ref: cp/topics/expressions _CPPv2N6gccjit7context12new_unary_opE16gcc_jit_unary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363215
Ref: 25b363215
Ref: cp/topics/expressions gccjit context new_unary_op__gcc_jit_unary_op gccjit type gccjit rvalue gccjit location363215
Ref: 25c363215
Ref: cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363750
Ref: 25d363750
Ref: cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363750
Ref: 25e363750
Ref: cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE363750
Ref: 25f363750
Ref: cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit location363750
Ref: 260363750
Ref: cp/topics/expressions _CPPv418new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364099
Ref: 261364099
Ref: cp/topics/expressions _CPPv318new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364099
Ref: 262364099
Ref: cp/topics/expressions _CPPv218new_bitwise_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364099
Ref: 263364099
Ref: cp/topics/expressions new_bitwise_negate__gccjit type gccjit rvalue gccjit location364099
Ref: 264364099
Ref: cp/topics/expressions _CPPv418new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364467
Ref: 265364467
Ref: cp/topics/expressions _CPPv318new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364467
Ref: 266364467
Ref: cp/topics/expressions _CPPv218new_logical_negateN6gccjit4typeEN6gccjit6rvalueEN6gccjit8locationE364467
Ref: 267364467
Ref: cp/topics/expressions new_logical_negate__gccjit type gccjit rvalue gccjit location364467
Ref: 268364467
Ref: cp/topics/expressions _CPPv4miN6gccjit6rvalueE364897
Ref: 269364897
Ref: cp/topics/expressions _CPPv3miN6gccjit6rvalueE364897
Ref: 26a364897
Ref: cp/topics/expressions _CPPv2miN6gccjit6rvalueE364897
Ref: 26b364897
Ref: cp/topics/expressions sub-operator__gccjit rvalue364897
Ref: 26c364897
Ref: cp/topics/expressions _CPPv4coN6gccjit6rvalueE365021
Ref: 26d365021
Ref: cp/topics/expressions _CPPv3coN6gccjit6rvalueE365021
Ref: 26e365021
Ref: cp/topics/expressions _CPPv2coN6gccjit6rvalueE365021
Ref: 26f365021
Ref: cp/topics/expressions inv-operator__gccjit rvalue365021
Ref: 270365021
Ref: cp/topics/expressions _CPPv4ntN6gccjit6rvalueE365143
Ref: 271365143
Ref: cp/topics/expressions _CPPv3ntN6gccjit6rvalueE365143
Ref: 272365143
Ref: cp/topics/expressions _CPPv2ntN6gccjit6rvalueE365143
Ref: 273365143
Ref: cp/topics/expressions not-operator__gccjit rvalue365143
Ref: 274365143
Node: Binary Operations<2>365269
Ref: cp/topics/expressions binary-operations365390
Ref: 275365390
Ref: cp/topics/expressions _CPPv4N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE365443
Ref: 17d365443
Ref: cp/topics/expressions _CPPv3N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE365443
Ref: 276365443
Ref: cp/topics/expressions _CPPv2N6gccjit7context13new_binary_opE17gcc_jit_binary_opN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE365443
Ref: 277365443
Ref: cp/topics/expressions gccjit context new_binary_op__gcc_jit_binary_op gccjit type gccjit rvalue gccjit rvalue gccjit location365443
Ref: 278365443
Ref: cp/topics/expressions _CPPv4N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366015
Ref: 279366015
Ref: cp/topics/expressions _CPPv3N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366015
Ref: 27a366015
Ref: cp/topics/expressions _CPPv2N6gccjit7context8new_plusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366015
Ref: 27b366015
Ref: cp/topics/expressions gccjit context new_plus__gccjit type gccjit rvalue gccjit rvalue gccjit location366015
Ref: 27c366015
Ref: cp/topics/expressions _CPPv4N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366204
Ref: 27d366204
Ref: cp/topics/expressions _CPPv3N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366204
Ref: 27e366204
Ref: cp/topics/expressions _CPPv2N6gccjit7context9new_minusEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366204
Ref: 27f366204
Ref: cp/topics/expressions gccjit context new_minus__gccjit type gccjit rvalue gccjit rvalue gccjit location366204
Ref: 280366204
Ref: cp/topics/expressions _CPPv4N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366394
Ref: 281366394
Ref: cp/topics/expressions _CPPv3N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366394
Ref: 282366394
Ref: cp/topics/expressions _CPPv2N6gccjit7context8new_multEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366394
Ref: 283366394
Ref: cp/topics/expressions gccjit context new_mult__gccjit type gccjit rvalue gccjit rvalue gccjit location366394
Ref: 284366394
Ref: cp/topics/expressions _CPPv4N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366583
Ref: 285366583
Ref: cp/topics/expressions _CPPv3N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366583
Ref: 286366583
Ref: cp/topics/expressions _CPPv2N6gccjit7context10new_divideEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366583
Ref: 287366583
Ref: cp/topics/expressions gccjit context new_divide__gccjit type gccjit rvalue gccjit rvalue gccjit location366583
Ref: 288366583
Ref: cp/topics/expressions _CPPv4N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366774
Ref: 289366774
Ref: cp/topics/expressions _CPPv3N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366774
Ref: 28a366774
Ref: cp/topics/expressions _CPPv2N6gccjit7context10new_moduloEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366774
Ref: 28b366774
Ref: cp/topics/expressions gccjit context new_modulo__gccjit type gccjit rvalue gccjit rvalue gccjit location366774
Ref: 28c366774
Ref: cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366965
Ref: 28d366965
Ref: cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366965
Ref: 28e366965
Ref: cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE366965
Ref: 28f366965
Ref: cp/topics/expressions gccjit context new_bitwise_and__gccjit type gccjit rvalue gccjit rvalue gccjit location366965
Ref: 290366965
Ref: cp/topics/expressions _CPPv4N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367161
Ref: 291367161
Ref: cp/topics/expressions _CPPv3N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367161
Ref: 292367161
Ref: cp/topics/expressions _CPPv2N6gccjit7context15new_bitwise_xorEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367161
Ref: 293367161
Ref: cp/topics/expressions gccjit context new_bitwise_xor__gccjit type gccjit rvalue gccjit rvalue gccjit location367161
Ref: 294367161
Ref: cp/topics/expressions _CPPv4N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367357
Ref: 295367357
Ref: cp/topics/expressions _CPPv3N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367357
Ref: 296367357
Ref: cp/topics/expressions _CPPv2N6gccjit7context14new_bitwise_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367357
Ref: 297367357
Ref: cp/topics/expressions gccjit context new_bitwise_or__gccjit type gccjit rvalue gccjit rvalue gccjit location367357
Ref: 298367357
Ref: cp/topics/expressions _CPPv4N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367552
Ref: 299367552
Ref: cp/topics/expressions _CPPv3N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367552
Ref: 29a367552
Ref: cp/topics/expressions _CPPv2N6gccjit7context15new_logical_andEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367552
Ref: 29b367552
Ref: cp/topics/expressions gccjit context new_logical_and__gccjit type gccjit rvalue gccjit rvalue gccjit location367552
Ref: 29c367552
Ref: cp/topics/expressions _CPPv4N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367748
Ref: 29d367748
Ref: cp/topics/expressions _CPPv3N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367748
Ref: 29e367748
Ref: cp/topics/expressions _CPPv2N6gccjit7context14new_logical_orEN6gccjit4typeEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE367748
Ref: 29f367748
Ref: cp/topics/expressions gccjit context new_logical_or__gccjit type gccjit rvalue gccjit rvalue gccjit location367748
Ref: 2a0367748
Ref: cp/topics/expressions _CPPv4plN6gccjit6rvalueEN6gccjit6rvalueE368009
Ref: 2a1368009
Ref: cp/topics/expressions _CPPv3plN6gccjit6rvalueEN6gccjit6rvalueE368009
Ref: 2a2368009
Ref: cp/topics/expressions _CPPv2plN6gccjit6rvalueEN6gccjit6rvalueE368009
Ref: 2a3368009
Ref: cp/topics/expressions add-operator__gccjit rvalue gccjit rvalue368009
Ref: 2a4368009
Ref: cp/topics/expressions _CPPv4miN6gccjit6rvalueEN6gccjit6rvalueE368151
Ref: 2a5368151
Ref: cp/topics/expressions _CPPv3miN6gccjit6rvalueEN6gccjit6rvalueE368151
Ref: 2a6368151
Ref: cp/topics/expressions _CPPv2miN6gccjit6rvalueEN6gccjit6rvalueE368151
Ref: 2a7368151
Ref: cp/topics/expressions sub-operator__gccjit rvalue gccjit rvalue368151
Ref: 2a8368151
Ref: cp/topics/expressions _CPPv4mlN6gccjit6rvalueEN6gccjit6rvalueE368294
Ref: 2a9368294
Ref: cp/topics/expressions _CPPv3mlN6gccjit6rvalueEN6gccjit6rvalueE368294
Ref: 2aa368294
Ref: cp/topics/expressions _CPPv2mlN6gccjit6rvalueEN6gccjit6rvalueE368294
Ref: 2ab368294
Ref: cp/topics/expressions mul-operator__gccjit rvalue gccjit rvalue368294
Ref: 2ac368294
Ref: cp/topics/expressions _CPPv4dvN6gccjit6rvalueEN6gccjit6rvalueE368437
Ref: 2ad368437
Ref: cp/topics/expressions _CPPv3dvN6gccjit6rvalueEN6gccjit6rvalueE368437
Ref: 2ae368437
Ref: cp/topics/expressions _CPPv2dvN6gccjit6rvalueEN6gccjit6rvalueE368437
Ref: 2af368437
Ref: cp/topics/expressions div-operator__gccjit rvalue gccjit rvalue368437
Ref: 2b0368437
Ref: cp/topics/expressions _CPPv4rmN6gccjit6rvalueEN6gccjit6rvalueE368582
Ref: 2b1368582
Ref: cp/topics/expressions _CPPv3rmN6gccjit6rvalueEN6gccjit6rvalueE368582
Ref: 2b2368582
Ref: cp/topics/expressions _CPPv2rmN6gccjit6rvalueEN6gccjit6rvalueE368582
Ref: 2b3368582
Ref: cp/topics/expressions mod-operator__gccjit rvalue gccjit rvalue368582
Ref: 2b4368582
Ref: cp/topics/expressions _CPPv4anN6gccjit6rvalueEN6gccjit6rvalueE368724
Ref: 2b5368724
Ref: cp/topics/expressions _CPPv3anN6gccjit6rvalueEN6gccjit6rvalueE368724
Ref: 2b6368724
Ref: cp/topics/expressions _CPPv2anN6gccjit6rvalueEN6gccjit6rvalueE368724
Ref: 2b7368724
Ref: cp/topics/expressions and-operator__gccjit rvalue gccjit rvalue368724
Ref: 2b8368724
Ref: cp/topics/expressions _CPPv4eoN6gccjit6rvalueEN6gccjit6rvalueE368864
Ref: 2b9368864
Ref: cp/topics/expressions _CPPv3eoN6gccjit6rvalueEN6gccjit6rvalueE368864
Ref: 2ba368864
Ref: cp/topics/expressions _CPPv2eoN6gccjit6rvalueEN6gccjit6rvalueE368864
Ref: 2bb368864
Ref: cp/topics/expressions xor-operator__gccjit rvalue gccjit rvalue368864
Ref: 2bc368864
Ref: cp/topics/expressions _CPPv4orN6gccjit6rvalueEN6gccjit6rvalueE369004
Ref: 2bd369004
Ref: cp/topics/expressions _CPPv3orN6gccjit6rvalueEN6gccjit6rvalueE369004
Ref: 2be369004
Ref: cp/topics/expressions _CPPv2orN6gccjit6rvalueEN6gccjit6rvalueE369004
Ref: 2bf369004
Ref: cp/topics/expressions or-operator__gccjit rvalue gccjit rvalue369004
Ref: 2c0369004
Ref: cp/topics/expressions _CPPv4aaN6gccjit6rvalueEN6gccjit6rvalueE369144
Ref: 2c1369144
Ref: cp/topics/expressions _CPPv3aaN6gccjit6rvalueEN6gccjit6rvalueE369144
Ref: 2c2369144
Ref: cp/topics/expressions _CPPv2aaN6gccjit6rvalueEN6gccjit6rvalueE369144
Ref: 2c3369144
Ref: cp/topics/expressions sand-operator__gccjit rvalue gccjit rvalue369144
Ref: 2c4369144
Ref: cp/topics/expressions _CPPv4ooN6gccjit6rvalueEN6gccjit6rvalueE369289
Ref: 2c5369289
Ref: cp/topics/expressions _CPPv3ooN6gccjit6rvalueEN6gccjit6rvalueE369289
Ref: 2c6369289
Ref: cp/topics/expressions _CPPv2ooN6gccjit6rvalueEN6gccjit6rvalueE369289
Ref: 2c7369289
Ref: cp/topics/expressions sor-operator__gccjit rvalue gccjit rvalue369289
Ref: 2c8369289
Node: Comparisons<2>369585
Ref: cp/topics/expressions comparisons369704
Ref: 2c9369704
Ref: cp/topics/expressions _CPPv4N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE369745
Ref: 18f369745
Ref: cp/topics/expressions _CPPv3N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE369745
Ref: 2ca369745
Ref: cp/topics/expressions _CPPv2N6gccjit7context14new_comparisonE18gcc_jit_comparisonN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE369745
Ref: 2cb369745
Ref: cp/topics/expressions gccjit context new_comparison__gcc_jit_comparison gccjit rvalue gccjit rvalue gccjit location369745
Ref: 2cc369745
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370296
Ref: 2cd370296
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370296
Ref: 2ce370296
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_eqEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370296
Ref: 2cf370296
Ref: cp/topics/expressions gccjit context new_eq__gccjit rvalue gccjit rvalue gccjit location370296
Ref: 2d0370296
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370457
Ref: 2d1370457
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370457
Ref: 2d2370457
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_neEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370457
Ref: 2d3370457
Ref: cp/topics/expressions gccjit context new_ne__gccjit rvalue gccjit rvalue gccjit location370457
Ref: 2d4370457
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370618
Ref: 2d5370618
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370618
Ref: 2d6370618
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_ltEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370618
Ref: 2d7370618
Ref: cp/topics/expressions gccjit context new_lt__gccjit rvalue gccjit rvalue gccjit location370618
Ref: 2d8370618
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370779
Ref: 2d9370779
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370779
Ref: 2da370779
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_leEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370779
Ref: 2db370779
Ref: cp/topics/expressions gccjit context new_le__gccjit rvalue gccjit rvalue gccjit location370779
Ref: 2dc370779
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370940
Ref: 2dd370940
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370940
Ref: 2de370940
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_gtEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE370940
Ref: 2df370940
Ref: cp/topics/expressions gccjit context new_gt__gccjit rvalue gccjit rvalue gccjit location370940
Ref: 2e0370940
Ref: cp/topics/expressions _CPPv4N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE371101
Ref: 2e1371101
Ref: cp/topics/expressions _CPPv3N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE371101
Ref: 2e2371101
Ref: cp/topics/expressions _CPPv2N6gccjit7context6new_geEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE371101
Ref: 2e3371101
Ref: cp/topics/expressions gccjit context new_ge__gccjit rvalue gccjit rvalue gccjit location371101
Ref: 2e4371101
Ref: cp/topics/expressions _CPPv4eqN6gccjit6rvalueEN6gccjit6rvalueE371328
Ref: 2e5371328
Ref: cp/topics/expressions _CPPv3eqN6gccjit6rvalueEN6gccjit6rvalueE371328
Ref: 2e6371328
Ref: cp/topics/expressions _CPPv2eqN6gccjit6rvalueEN6gccjit6rvalueE371328
Ref: 2e7371328
Ref: cp/topics/expressions eq-operator__gccjit rvalue gccjit rvalue371328
Ref: 2e8371328
Ref: cp/topics/expressions _CPPv4neN6gccjit6rvalueEN6gccjit6rvalueE371491
Ref: 2e9371491
Ref: cp/topics/expressions _CPPv3neN6gccjit6rvalueEN6gccjit6rvalueE371491
Ref: 2ea371491
Ref: cp/topics/expressions _CPPv2neN6gccjit6rvalueEN6gccjit6rvalueE371491
Ref: 2eb371491
Ref: cp/topics/expressions neq-operator__gccjit rvalue gccjit rvalue371491
Ref: 2ec371491
Ref: cp/topics/expressions _CPPv4ltN6gccjit6rvalueEN6gccjit6rvalueE371638
Ref: 2ed371638
Ref: cp/topics/expressions _CPPv3ltN6gccjit6rvalueEN6gccjit6rvalueE371638
Ref: 2ee371638
Ref: cp/topics/expressions _CPPv2ltN6gccjit6rvalueEN6gccjit6rvalueE371638
Ref: 2ef371638
Ref: cp/topics/expressions lt-operator__gccjit rvalue gccjit rvalue371638
Ref: 2f0371638
Ref: cp/topics/expressions _CPPv4leN6gccjit6rvalueEN6gccjit6rvalueE371781
Ref: 2f1371781
Ref: cp/topics/expressions _CPPv3leN6gccjit6rvalueEN6gccjit6rvalueE371781
Ref: 2f2371781
Ref: cp/topics/expressions _CPPv2leN6gccjit6rvalueEN6gccjit6rvalueE371781
Ref: 2f3371781
Ref: cp/topics/expressions lte-operator__gccjit rvalue gccjit rvalue371781
Ref: 2f4371781
Ref: cp/topics/expressions _CPPv4gtN6gccjit6rvalueEN6gccjit6rvalueE371926
Ref: 2f5371926
Ref: cp/topics/expressions _CPPv3gtN6gccjit6rvalueEN6gccjit6rvalueE371926
Ref: 2f6371926
Ref: cp/topics/expressions _CPPv2gtN6gccjit6rvalueEN6gccjit6rvalueE371926
Ref: 2f7371926
Ref: cp/topics/expressions gt-operator__gccjit rvalue gccjit rvalue371926
Ref: 2f8371926
Ref: cp/topics/expressions _CPPv4geN6gccjit6rvalueEN6gccjit6rvalueE372076
Ref: 2f9372076
Ref: cp/topics/expressions _CPPv3geN6gccjit6rvalueEN6gccjit6rvalueE372076
Ref: 2fa372076
Ref: cp/topics/expressions _CPPv2geN6gccjit6rvalueEN6gccjit6rvalueE372076
Ref: 2fb372076
Ref: cp/topics/expressions gte-operator__gccjit rvalue gccjit rvalue372076
Ref: 2fc372076
Node: Function calls<2>372254
Ref: cp/topics/expressions function-calls372373
Ref: 2fd372373
Ref: cp/topics/expressions _CPPv424gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue372420
Ref: 2fe372420
Ref: cp/topics/expressions _CPPv324gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue372420
Ref: 2ff372420
Ref: cp/topics/expressions _CPPv224gcc_jit_context_new_callP15gcc_jit_contextP16gcc_jit_locationP16gcc_jit_functioniPP14gcc_jit_rvalue372420
Ref: 300372420
Ref: cp/topics/expressions gcc_jit_context_new_call__gcc_jit_contextP gcc_jit_locationP gcc_jit_functionP i gcc_jit_rvaluePP372420
Ref: 301372420
Node: Function pointers<3>373389
Ref: cp/topics/expressions function-pointers373510
Ref: 303373510
Ref: cp/topics/expressions _CPPv4N6gccjit8function11get_addressEN6gccjit8locationE373563
Ref: 304373563
Ref: cp/topics/expressions _CPPv3N6gccjit8function11get_addressEN6gccjit8locationE373563
Ref: 305373563
Ref: cp/topics/expressions _CPPv2N6gccjit8function11get_addressEN6gccjit8locationE373563
Ref: 306373563
Ref: cp/topics/expressions gccjit function get_address__gccjit location373563
Ref: 307373563
Node: Type-coercion<2>373765
Ref: cp/topics/expressions type-coercion373860
Ref: 308373860
Ref: cp/topics/expressions _CPPv4N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE373905
Ref: 309373905
Ref: cp/topics/expressions _CPPv3N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE373905
Ref: 30a373905
Ref: cp/topics/expressions _CPPv2N6gccjit7context8new_castEN6gccjit6rvalueEN6gccjit4typeEN6gccjit8locationE373905
Ref: 30b373905
Ref: cp/topics/expressions gccjit context new_cast__gccjit rvalue gccjit type gccjit location373905
Ref: 30c373905
Node: Lvalues<2>374320
Ref: cp/topics/expressions lvalues374455
Ref: 30d374455
Ref: cp/topics/expressions _CPPv4N6gccjit6lvalueE374490
Ref: 187374490
Ref: cp/topics/expressions _CPPv3N6gccjit6lvalueE374490
Ref: 30e374490
Ref: cp/topics/expressions _CPPv2N6gccjit6lvalueE374490
Ref: 30f374490
Ref: cp/topics/expressions gccjit lvalue374490
Ref: 310374490
Ref: cp/topics/expressions _CPPv4N6gccjit6lvalue11get_addressEN6gccjit8locationE374818
Ref: 311374818
Ref: cp/topics/expressions _CPPv3N6gccjit6lvalue11get_addressEN6gccjit8locationE374818
Ref: 312374818
Ref: cp/topics/expressions _CPPv2N6gccjit6lvalue11get_addressEN6gccjit8locationE374818
Ref: 313374818
Ref: cp/topics/expressions gccjit lvalue get_address__gccjit location374818
Ref: 314374818
Node: Global variables<2>375109
Ref: cp/topics/expressions global-variables375178
Ref: 315375178
Ref: cp/topics/expressions _CPPv4N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE375231
Ref: 316375231
Ref: cp/topics/expressions _CPPv3N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE375231
Ref: 317375231
Ref: cp/topics/expressions _CPPv2N6gccjit7context10new_globalE19gcc_jit_global_kindN6gccjit4typeEPKcN6gccjit8locationE375231
Ref: 318375231
Ref: cp/topics/expressions gccjit context new_global__gcc_jit_global_kind gccjit type cCP gccjit location375231
Ref: 319375231
Node: Working with pointers structs and unions<2>375661
Ref: cp/topics/expressions working-with-pointers-structs-and-unions375777
Ref: 31a375777
Ref: cp/topics/expressions _CPPv4N6gccjit6rvalue11dereferenceEN6gccjit8locationE375880
Ref: 31b375880
Ref: cp/topics/expressions _CPPv3N6gccjit6rvalue11dereferenceEN6gccjit8locationE375880
Ref: 31c375880
Ref: cp/topics/expressions _CPPv2N6gccjit6rvalue11dereferenceEN6gccjit8locationE375880
Ref: 31d375880
Ref: cp/topics/expressions gccjit rvalue dereference__gccjit location375880
Ref: 31e375880
Ref: cp/topics/expressions _CPPv4N6gccjit6rvaluemlEv376303
Ref: 31f376303
Ref: cp/topics/expressions _CPPv3N6gccjit6rvaluemlEv376303
Ref: 320376303
Ref: cp/topics/expressions _CPPv2N6gccjit6rvaluemlEv376303
Ref: 321376303
Ref: cp/topics/expressions gccjit rvalue mul-operator376303
Ref: 322376303
Ref: cp/topics/expressions _CPPv4N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376509
Ref: 323376509
Ref: cp/topics/expressions _CPPv3N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376509
Ref: 324376509
Ref: cp/topics/expressions _CPPv2N6gccjit6lvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376509
Ref: 325376509
Ref: cp/topics/expressions gccjit lvalue access_field__gccjit field gccjit location376509
Ref: 326376509
Ref: cp/topics/expressions _CPPv4N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376825
Ref: 327376825
Ref: cp/topics/expressions _CPPv3N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376825
Ref: 328376825
Ref: cp/topics/expressions _CPPv2N6gccjit6rvalue12access_fieldEN6gccjit5fieldEN6gccjit8locationE376825
Ref: 329376825
Ref: cp/topics/expressions gccjit rvalue access_field__gccjit field gccjit location376825
Ref: 32a376825
Ref: cp/topics/expressions _CPPv4N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE377106
Ref: 32b377106
Ref: cp/topics/expressions _CPPv3N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE377106
Ref: 32c377106
Ref: cp/topics/expressions _CPPv2N6gccjit6rvalue17dereference_fieldEN6gccjit5fieldEN6gccjit8locationE377106
Ref: 32d377106
Ref: cp/topics/expressions gccjit rvalue dereference_field__gccjit field gccjit location377106
Ref: 32e377106
Ref: cp/topics/expressions _CPPv4N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE377482
Ref: 32f377482
Ref: cp/topics/expressions _CPPv3N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE377482
Ref: 330377482
Ref: cp/topics/expressions _CPPv2N6gccjit7context16new_array_accessEN6gccjit6rvalueEN6gccjit6rvalueEN6gccjit8locationE377482
Ref: 331377482
Ref: cp/topics/expressions gccjit context new_array_access__gccjit rvalue gccjit rvalue gccjit location377482
Ref: 332377482
Node: Creating and using functions<2>378355
Ref: cp/topics/functions doc378495
Ref: 333378495
Ref: cp/topics/functions creating-and-using-functions378495
Ref: 334378495
Node: Params<2>378674
Ref: cp/topics/functions params378775
Ref: 335378775
Ref: cp/topics/functions _CPPv4N6gccjit5paramE378806
Ref: 188378806
Ref: cp/topics/functions _CPPv3N6gccjit5paramE378806
Ref: 336378806
Ref: cp/topics/functions _CPPv2N6gccjit5paramE378806
Ref: 337378806
Ref: cp/topics/functions gccjit param378806
Ref: 338378806
Ref: cp/topics/functions _CPPv4N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE378902
Ref: 17c378902
Ref: cp/topics/functions _CPPv3N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE378902
Ref: 339378902
Ref: cp/topics/functions _CPPv2N6gccjit7context9new_paramEN6gccjit4typeEPKcN6gccjit8locationE378902
Ref: 33a378902
Ref: cp/topics/functions gccjit context new_param__gccjit type cCP gccjit location378902
Ref: 33b378902
Node: Functions<2>379381
Ref: cp/topics/functions functions379500
Ref: 33c379500
Ref: cp/topics/functions _CPPv4N6gccjit8functionE379537
Ref: 18c379537
Ref: cp/topics/functions _CPPv3N6gccjit8functionE379537
Ref: 33d379537
Ref: cp/topics/functions _CPPv2N6gccjit8functionE379537
Ref: 33e379537
Ref: cp/topics/functions gccjit function379537
Ref: 33f379537
Ref: cp/topics/functions _CPPv4N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE379707
Ref: 340379707
Ref: cp/topics/functions _CPPv3N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE379707
Ref: 341379707
Ref: cp/topics/functions _CPPv2N6gccjit7context12new_functionE21gcc_jit_function_kindN6gccjit4typeEPKcRNSt6vectorI5paramEEiN6gccjit8locationE379707
Ref: 342379707
Ref: cp/topics/functions gccjit context new_function__gcc_jit_function_kind gccjit type cCP std vector param R i gccjit location379707
Ref: 343379707
Ref: cp/topics/functions _CPPv4N6gccjit7context20get_builtin_functionEPKc380190
Ref: 344380190
Ref: cp/topics/functions _CPPv3N6gccjit7context20get_builtin_functionEPKc380190
Ref: 345380190
Ref: cp/topics/functions _CPPv2N6gccjit7context20get_builtin_functionEPKc380190
Ref: 346380190
Ref: cp/topics/functions gccjit context get_builtin_function__cCP380190
Ref: 347380190
Ref: cp/topics/functions _CPPv4NK6gccjit8function9get_paramEi380418
Ref: 348380418
Ref: cp/topics/functions _CPPv3NK6gccjit8function9get_paramEi380418
Ref: 349380418
Ref: cp/topics/functions _CPPv2NK6gccjit8function9get_paramEi380418
Ref: 34a380418
Ref: cp/topics/functions gccjit function get_param__iC380418
Ref: 34b380418
Ref: cp/topics/functions _CPPv4N6gccjit8function11dump_to_dotEPKc380581
Ref: 194380581
Ref: cp/topics/functions _CPPv3N6gccjit8function11dump_to_dotEPKc380581
Ref: 34c380581
Ref: cp/topics/functions _CPPv2N6gccjit8function11dump_to_dotEPKc380581
Ref: 34d380581
Ref: cp/topics/functions gccjit function dump_to_dot__cCP380581
Ref: 34e380581
Ref: cp/topics/functions _CPPv4N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE380738
Ref: 189380738
Ref: cp/topics/functions _CPPv3N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE380738
Ref: 34f380738
Ref: cp/topics/functions _CPPv2N6gccjit8function9new_localEN6gccjit4typeEPKcN6gccjit8locationE380738
Ref: 350380738
Ref: cp/topics/functions gccjit function new_local__gccjit type cCP gccjit location380738
Ref: 351380738
Node: Blocks<2>380992
Ref: cp/topics/functions blocks381115
Ref: 352381115
Ref: cp/topics/functions _CPPv4N6gccjit5blockE381146
Ref: 18b381146
Ref: cp/topics/functions _CPPv3N6gccjit5blockE381146
Ref: 353381146
Ref: cp/topics/functions _CPPv2N6gccjit5blockE381146
Ref: 354381146
Ref: cp/topics/functions gccjit block381146
Ref: 355381146
Ref: cp/topics/functions _CPPv4N6gccjit8function9new_blockEPKc381742
Ref: 356381742
Ref: cp/topics/functions _CPPv3N6gccjit8function9new_blockEPKc381742
Ref: 357381742
Ref: cp/topics/functions _CPPv2N6gccjit8function9new_blockEPKc381742
Ref: 358381742
Ref: cp/topics/functions gccjit function new_block__cCP381742
Ref: 359381742
Node: Statements<2>382083
Ref: cp/topics/functions statements382185
Ref: 35a382185
Ref: cp/topics/functions _CPPv4N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE382224
Ref: 302382224
Ref: cp/topics/functions _CPPv3N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE382224
Ref: 35b382224
Ref: cp/topics/functions _CPPv2N6gccjit5block8add_evalEN6gccjit6rvalueEN6gccjit8locationE382224
Ref: 35c382224
Ref: cp/topics/functions gccjit block add_eval__gccjit rvalue gccjit location382224
Ref: 35d382224
Ref: cp/topics/functions _CPPv4N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE382521
Ref: 18d382521
Ref: cp/topics/functions _CPPv3N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE382521
Ref: 35e382521
Ref: cp/topics/functions _CPPv2N6gccjit5block14add_assignmentEN6gccjit6lvalueEN6gccjit6rvalueEN6gccjit8locationE382521
Ref: 35f382521
Ref: cp/topics/functions gccjit block add_assignment__gccjit lvalue gccjit rvalue gccjit location382521
Ref: 360382521
Ref: cp/topics/functions _CPPv4N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE382835
Ref: 191382835
Ref: cp/topics/functions _CPPv3N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE382835
Ref: 361382835
Ref: cp/topics/functions _CPPv2N6gccjit5block17add_assignment_opEN6gccjit6lvalueE17gcc_jit_binary_opN6gccjit6rvalueEN6gccjit8locationE382835
Ref: 362382835
Ref: cp/topics/functions gccjit block add_assignment_op__gccjit lvalue gcc_jit_binary_op gccjit rvalue gccjit location382835
Ref: 363382835
Ref: cp/topics/functions _CPPv4N6gccjit5block11add_commentEPKcN6gccjit8locationE383397
Ref: 19d383397
Ref: cp/topics/functions _CPPv3N6gccjit5block11add_commentEPKcN6gccjit8locationE383397
Ref: 364383397
Ref: cp/topics/functions _CPPv2N6gccjit5block11add_commentEPKcN6gccjit8locationE383397
Ref: 365383397
Ref: cp/topics/functions gccjit block add_comment__cCP gccjit location383397
Ref: 366383397
Ref: cp/topics/functions _CPPv4N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE383946
Ref: 190383946
Ref: cp/topics/functions _CPPv3N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE383946
Ref: 367383946
Ref: cp/topics/functions _CPPv2N6gccjit5block20end_with_conditionalEN6gccjit6rvalueEN6gccjit5blockEN6gccjit5blockEN6gccjit8locationE383946
Ref: 368383946
Ref: cp/topics/functions gccjit block end_with_conditional__gccjit rvalue gccjit block gccjit block gccjit location383946
Ref: 369383946
Ref: cp/topics/functions _CPPv4N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE384459
Ref: 36a384459
Ref: cp/topics/functions _CPPv3N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE384459
Ref: 36b384459
Ref: cp/topics/functions _CPPv2N6gccjit5block13end_with_jumpEN6gccjit5blockEN6gccjit8locationE384459
Ref: 36c384459
Ref: cp/topics/functions gccjit block end_with_jump__gccjit block gccjit location384459
Ref: 36d384459
Ref: cp/topics/functions _CPPv4N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE384720
Ref: 36e384720
Ref: cp/topics/functions _CPPv3N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE384720
Ref: 36f384720
Ref: cp/topics/functions _CPPv2N6gccjit5block15end_with_returnEN6gccjit6rvalueEN6gccjit8locationE384720
Ref: 370384720
Ref: cp/topics/functions gccjit block end_with_return__gccjit rvalue gccjit location384720
Ref: 371384720
Ref: cp/topics/functions _CPPv4N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE385445
Ref: 372385445
Ref: cp/topics/functions _CPPv3N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE385445
Ref: 373385445
Ref: cp/topics/functions _CPPv2N6gccjit5block15end_with_switchEN6gccjit6rvalueEN6gccjit5blockENSt6vectorIN6gccjit5case_EEEN6gccjit8locationE385445
Ref: 374385445
Ref: cp/topics/functions gccjit block end_with_switch__gccjit rvalue gccjit block std vector gccjit case_ gccjit location385445
Ref: 375385445
Node: Source Locations<2>390439
Ref: cp/topics/locations doc390587
Ref: 376390587
Ref: cp/topics/locations source-locations390587
Ref: 377390587
Ref: cp/topics/locations _CPPv4N6gccjit8locationE390634
Ref: 19b390634
Ref: cp/topics/locations _CPPv3N6gccjit8locationE390634
Ref: 378390634
Ref: cp/topics/locations _CPPv2N6gccjit8locationE390634
Ref: 379390634
Ref: cp/topics/locations gccjit location390634
Ref: 37a390634
Ref: cp/topics/locations _CPPv4N6gccjit7context12new_locationEPKcii391366
Ref: 1a1391366
Ref: cp/topics/locations _CPPv3N6gccjit7context12new_locationEPKcii391366
Ref: 37b391366
Ref: cp/topics/locations _CPPv2N6gccjit7context12new_locationEPKcii391366
Ref: 37c391366
Ref: cp/topics/locations gccjit context new_location__cCP i i391366
Ref: 37d391366
Node: Faking it<2>391650
Ref: cp/topics/locations faking-it391721
Ref: 37e391721
Node: Compiling a context<2>392358
Ref: cp/topics/compilation doc392515
Ref: 37f392515
Ref: cp/topics/compilation compiling-a-context392515
Ref: 380392515
Node: In-memory compilation<2>393067
Ref: cp/topics/compilation in-memory-compilation393190
Ref: 382393190
Ref: cp/topics/compilation _CPPv4N6gccjit7context7compileEv393251
Ref: 17f393251
Ref: cp/topics/compilation _CPPv3N6gccjit7context7compileEv393251
Ref: 383393251
Ref: cp/topics/compilation _CPPv2N6gccjit7context7compileEv393251
Ref: 384393251
Ref: cp/topics/compilation gccjit context compile393251
Ref: 385393251
Node: Ahead-of-time compilation<2>393522
Ref: cp/topics/compilation ahead-of-time-compilation393645
Ref: 386393645
Ref: cp/topics/compilation _CPPv4N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc393924
Ref: 381393924
Ref: cp/topics/compilation _CPPv3N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc393924
Ref: 387393924
Ref: cp/topics/compilation _CPPv2N6gccjit7context15compile_to_fileE19gcc_jit_output_kindPKc393924
Ref: 388393924
Ref: cp/topics/compilation gccjit context compile_to_file__gcc_jit_output_kind cCP393924
Ref: 389393924
Node: Using Assembly Language with libgccjit++394241
Ref: cp/topics/asm doc394370
Ref: 38a394370
Ref: cp/topics/asm using-assembly-language-with-libgccjit394370
Ref: 38b394370
Ref: Using Assembly Language with libgccjit++-Footnote-1395177
Node: Adding assembler instructions within a function<2>395257
Ref: cp/topics/asm adding-assembler-instructions-within-a-function395436
Ref: 38c395436
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asmE395549
Ref: 38d395549
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asmE395549
Ref: 38e395549
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asmE395549
Ref: 38f395549
Ref: cp/topics/asm gccjit extended_asm395549
Ref: 390395549
Ref: cp/topics/asm _CPPv4N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE398005
Ref: 391398005
Ref: cp/topics/asm _CPPv3N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE398005
Ref: 395398005
Ref: cp/topics/asm _CPPv2N6gccjit5block16add_extended_asmERKNSt6stringEN6gccjit8locationE398005
Ref: 396398005
Ref: cp/topics/asm gccjit block add_extended_asm__ssCR gccjit location398005
Ref: 397398005
Ref: cp/topics/asm _CPPv4N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location398605
Ref: 392398605
Ref: cp/topics/asm _CPPv3N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location398605
Ref: 398398605
Ref: cp/topics/asm _CPPv2N6gccjit5block26end_with_extended_asm_gotoERKNSt6stringENSt6vectorI5blockEEP5block8location398605
Ref: 399398605
Ref: cp/topics/asm gccjit block end_with_extended_asm_goto__ssCR std vector block blockP location398605
Ref: 39a398605
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm17set_volatile_flagEb400854
Ref: 39b400854
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm17set_volatile_flagEb400854
Ref: 39c400854
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm17set_volatile_flagEb400854
Ref: 39d400854
Ref: cp/topics/asm gccjit extended_asm set_volatile_flag__b400854
Ref: 39e400854
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm15set_inline_flagEb402010
Ref: 39f402010
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm15set_inline_flagEb402010
Ref: 3a0402010
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm15set_inline_flagEb402010
Ref: 3a1402010
Ref: cp/topics/asm gccjit extended_asm set_inline_flag__b402010
Ref: 3a2402010
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE402228
Ref: 393402228
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE402228
Ref: 3a3402228
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringERKNSt6stringEN6gccjit6lvalueE402228
Ref: 3a4402228
Ref: cp/topics/asm gccjit extended_asm add_output_operand__ssCR ssCR gccjit lvalue402228
Ref: 3a5402228
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE403441
Ref: 3a6403441
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE403441
Ref: 3a7403441
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm18add_output_operandERKNSt6stringEN6gccjit6lvalueE403441
Ref: 3a8403441
Ref: cp/topics/asm gccjit extended_asm add_output_operand__ssCR gccjit lvalue403441
Ref: 3a9403441
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE403832
Ref: 394403832
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE403832
Ref: 3aa403832
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringERKNSt6stringEN6gccjit6rvalueE403832
Ref: 3ab403832
Ref: cp/topics/asm gccjit extended_asm add_input_operand__ssCR ssCR gccjit rvalue403832
Ref: 3ac403832
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE404788
Ref: 3ad404788
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE404788
Ref: 3ae404788
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm17add_input_operandERKNSt6stringEN6gccjit6rvalueE404788
Ref: 3af404788
Ref: cp/topics/asm gccjit extended_asm add_input_operand__ssCR gccjit rvalue404788
Ref: 3b0404788
Ref: cp/topics/asm _CPPv4N6gccjit12extended_asm11add_clobberERKNSt6stringE405174
Ref: 3b1405174
Ref: cp/topics/asm _CPPv3N6gccjit12extended_asm11add_clobberERKNSt6stringE405174
Ref: 3b2405174
Ref: cp/topics/asm _CPPv2N6gccjit12extended_asm11add_clobberERKNSt6stringE405174
Ref: 3b3405174
Ref: cp/topics/asm gccjit extended_asm add_clobber__ssCR405174
Ref: 3b4405174
Ref: Adding assembler instructions within a function<2>-Footnote-1405732
Ref: Adding assembler instructions within a function<2>-Footnote-2405802
Ref: Adding assembler instructions within a function<2>-Footnote-3405881
Ref: Adding assembler instructions within a function<2>-Footnote-4405958
Ref: Adding assembler instructions within a function<2>-Footnote-5406030
Ref: Adding assembler instructions within a function<2>-Footnote-6406106
Node: Adding top-level assembler statements<2>406200
Ref: cp/topics/asm adding-top-level-assembler-statements406379
Ref: 3b5406379
Ref: cp/topics/asm _CPPv4N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE406641
Ref: 3b6406641
Ref: cp/topics/asm _CPPv3N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE406641
Ref: 3b7406641
Ref: cp/topics/asm _CPPv2N6gccjit7context17add_top_level_asmEPKcN6gccjit8locationE406641
Ref: 3b8406641
Ref: cp/topics/asm gccjit context add_top_level_asm__cCP gccjit location406641
Ref: 3b9406641
Node: Internals407848
Ref: internals/index doc407962
Ref: 3ba407962
Ref: internals/index internals407962
Ref: 3bb407962
Node: Working on the JIT library408172
Ref: internals/index working-on-the-jit-library408278
Ref: 3bc408278
Ref: internals/index cmdoption-enable-host-shared409170
Ref: 3bd409170
Ref: internals/index cmdoption-enable-languages409390
Ref: 3be409390
Ref: internals/index cmdoption-disable-bootstrap409927
Ref: 3bf409927
Ref: internals/index cmdoption-enable-checking410227
Ref: 3c0410227
Node: Running the test suite410493
Ref: internals/index running-the-test-suite410629
Ref: 3c1410629
Node: Running under valgrind411687
Ref: internals/index running-under-valgrind411771
Ref: 3c2411771
Ref: Running under valgrind-Footnote-1413347
Ref: Running under valgrind-Footnote-2413376
Ref: Running under valgrind-Footnote-3413432
Node: Environment variables413503
Ref: internals/index environment-variables413628
Ref: 3c3413628
Ref: internals/index envvar-LD_LIBRARY_PATH413789
Ref: 3c4413789
Ref: internals/index envvar-PATH414402
Ref: 3c5414402
Ref: internals/index envvar-LIBRARY_PATH415058
Ref: 3c6415058
Node: Packaging notes416017
Ref: internals/index packaging-notes416146
Ref: 3c7416146
Node: Overview of code structure417523
Ref: internals/index overview-of-code-structure417643
Ref: 3c8417643
Ref: internals/index example-of-log-file434240
Ref: 5c434240
Node: Design notes445331
Ref: internals/index design-notes445454
Ref: 3c9445454
Node: Submitting patches445985
Ref: internals/index submitting-patches446073
Ref: 3ca446073
Ref: Submitting patches-Footnote-1450651
Node: Indices and tables450683
Ref: index indices-and-tables450776
Ref: 3cb450776
Node: Index450858

End Tag Table


Local Variables:
coding: utf-8
End:

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists