[PATCH] Re: Stage 3 RFC: using "jit" for ahead-of-time compilation

Richard Biener richard.guenther@gmail.com
Mon Jan 19 10:26:00 GMT 2015


On Fri, Jan 16, 2015 at 7:47 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Thu, 2015-01-15 at 22:50 +0100, Richard Biener wrote:
>> On January 15, 2015 9:05:59 PM CET, David Malcolm <dmalcolm@redhat.com> wrote:
>> >Release managers: given that this only touches the jit, and that the
>> >jit
>> >is off by default, any objections if I go ahead and commit this?
>> >It's a late-breaking feature, but the jit as a whole is new, and
>> >I think the following is a big win, so I'd like to proceed with this in
>> >stage 3 (i.e. in the next 24 hours).  There are docs and testcases.
>> >
>> >New jit API entrypoint: gcc_jit_context_compile_to_file
>> >
>> >This patch adds a way to use libgccjit for ahead-of-time compilation.
>> >I noticed that given the postprocessing steps the jit has to take to
>> >turn the .s file into in-memory code (invoke driver to convert to
>> >a .so and then dlopen), that it's not much of a leap to support
>> >compiling the .s file into objects, dynamic libraries, and executables.
>> >
>> >Doing so seems like a big win from a feature standpoint: people with
>> >pre-existing frontend code who want a backend can then plug in
>> >libgccjit
>> >and have a compiler, without needing to write it as a GCC frontend, or
>> >use LLVM.
>>
>> Note that you should make them aware of our runtime license with
>> respect to the eligible compilation process.  Which means this is not
>> a way to implement proprietary front ends.
>>
>> Richard.
>
> IANAL, but as I understand things, the runtime license is an additional
> grant of rights that covers certain components of GCC that bear the GCC
> Runtime Library Exception, allowing them to be used in certain
> additional ways beyond regular GPLv3-compliance.
>
> libgccjit doesn't have that exception; it's GPLv3.
>
> Perhaps an argument could be made for libgccjit to have the exception,
> if the FSF think that that would better serve the FSF's mission; right
> now, I'm merely trying to provide a technical means to modularity.
>
> Assuming the above is correct, anything linked against it needs to be
> GPLv3-compatible.  Hence any such frontend linked against libgccjit
> would need to be GPLv3-compatible.
>
> Attached is a patch (on top of the proposed one below), to clarify the
> wording in the new tutorial a little, to remind people that such linking
> needs to be license-compatible (without actually spelling out what the
> license is, though it's visible at the top of the public header file,
> libgccjit.h, as GPLv3 or later without the runtime library exception).
>
> Are the combined patches OK by you?

Yes.

Thanks,
Richard.

> Thanks
> Dave
>
>
>> >"jit" becomes something of a misnomer for this use-case.
>> >
>> >As an experiment, I used this technique to add a compiler for the
>> >language I'll refer to as "brainf" (ahem), and wrote this up for the
>> >libgccjit tutorial (it's all in the patch); prebuilt HTML can be seen
>> >at:
>> >https://dmalcolm.fedorapeople.org/gcc/libgccjit-api-docs-wip/intro/tutorial05.html
>> >
>> >The main things that are missing are:
>> > * specifying libraries to link against (Uli had some ideas about this)
>> >  * cross-compilation support (needs some deeper work, especially the
>> >    test suite, so deferrable to gcc 6, I guess)
>> >but the feature is useful with the patch as-is.
>> >
>> >The new test cases take jit.sum's # of expected passes
>> >from 7514 to 7571.
>> >
>> >gcc/jit/ChangeLog:
>> >     * docs/cp/topics/results.rst: Rename to...
>> >     * docs/cp/topics/compilation.rst: ...this, and add section on
>> >     ahead-of-time compilation.
>> >     * docs/cp/topics/index.rst: Update for renaming of results.rst
>> >     to compilation.rst.
>> >     * docs/examples/emit-alphabet.bf: New file, a sample "brainf"
>> >     script.
>> >     * docs/examples/tut05-bf.c: New file, implementing a compiler
>> >     for "brainf".
>> >     * docs/internals/test-hello-world.exe.log.txt: Update to reflect
>> >     changes to logger output.
>> >     * docs/intro/index.rst: Add tutorial05.rst
>> >     * docs/intro/tutorial05.rst: New file.
>> >     * docs/topics/results.rst: Rename to...
>> >     * docs/topics/compilation.rst: ...this, and add section on
>> >     ahead-of-time compilation.
>> >     * docs/topics/index.rst: Update for renaming of results.rst to
>> >     compilation.rst.
>> >     * jit-playback.c (gcc::jit::playback::context::compile): Convert
>> >     return type from result * to void.  Move the code to convert to
>> >     dso and dlopen the result to a new pure virtual "postprocess"
>> >     method.
>> >     (gcc::jit::playback::compile_to_memory::compile_to_memory): New
>> >     function.
>> >     (gcc::jit::playback::compile_to_memory::postprocess): New
>> >     function, based on playback::context::compile.
>> >     (gcc::jit::playback::compile_to_file::compile_to_file): New
>> >     function.
>> >     (gcc::jit::playback::compile_to_file::postprocess): New function.
>> >     (gcc::jit::playback::compile_to_file::copy_file): New function.
>> >     (gcc::jit::playback::context::convert_to_dso): Move internals
>> >     to...
>> >     (gcc::jit::playback::context::invoke_driver): New method.  Add
>> >     "-shared" and "-c" options to driver's argv as needed.
>> >     * jit-playback.h: Include "timevar.h".
>> >     (gcc::jit::playback::context::compile): Convert return type from
>> >     result * to void.
>> >     (gcc::jit::playback::context::postprocess): New pure virtual
>> >     function, making this an abstract base class.
>> >     (gcc::jit::playback::context::get_tempdir): New accessor.
>> >     (gcc::jit::playback::context::invoke_driver): New function.
>> >     (class gcc::jit::playback::compile_to_memory): New subclass of
>> >     playback::context.
>> >     (class gcc::jit::playback::compile_to_file): Likewise.
>> >     * jit-recording.c (gcc::jit::recording::context::compile): Use a
>> >     playback::compile_to_memory, and extract its result.
>> >     (gcc::jit::recording::context::compile_to_file): New function.
>> >     * jit-recording.h (gcc::jit::recording::context::compile_to_file):
>> >     New function.
>> >     * libgccjit++.h (gccjit::context::compile_to_file): New method.
>> >     * libgccjit.c (gcc_jit_context_compile): Update log message to
>> >     clarify that this is an in-memory compile.
>> >     (gcc_jit_context_compile_to_file): New function.
>> >     * libgccjit.h (gcc_jit_context): Clarify that you can compile
>> >     a context more than once, and that you can compile to a file
>> >     as well as to memory.
>> >     (gcc_jit_result): Clarify that this is the result of an
>> >     in-memory compilation.
>> >     (gcc_jit_context_compile): Clarify that you can compile, and that
>> >     this is an in-memory compilation.
>> >     (enum gcc_jit_output_kind): New enum.
>> >     (gcc_jit_context_compile_to_file): New function.
>> >     (gcc_jit_context_enable_dump): Clarify comment to cover both forms
>> >     of compilation.
>> >     * libgccjit.map (gcc_jit_context_compile_to_file): New API
>> >     entrypoint.
>> >     * notes.txt: Update to show the playback::context::postprocess
>> >     virtual function.
>> >
>> >gcc/testsuite/ChangeLog:
>> >     * jit.dg/harness.h: Include <unistd.h>.
>> >     (CHECK_NO_ERRORS): New.
>> >     (verify_code): Wrap prototype in #ifndef TEST_COMPILING_TO_FILE.
>> >     (test_jit): Support new macro TEST_COMPILING_TO_FILE for exercising
>> >     gcc_jit_context_compile_to_file.
>> >     * jit.dg/jit.exp (fixed_host_execute): Fix the code for passing on
>> >     args to the spawned executable.
>> >     (jit-expand-vars): New function.
>> >     (jit-exe-params): New variable.
>> >     (dg-jit-set-exe-params): New function.
>> >     (jit-dg-test): Detect testcases that use
>> >     jit-verify-compile-to-file and call jit-setup-compile-to-file.
>> >     Set arguments of spawned process to jit-exe-params.
>> >     (jit-get-output-filename): New function.
>> >     (jit-setup-compile-to-file): New function.
>> >     (jit-verify-compile-to-file): New function.
>> >     (jit-run-executable): New function.
>> >     (jit-verify-executable): New function.
>> >     * jit.dg/test-compile-to-assembler.c: New testcase.
>> >     * jit.dg/test-compile-to-dynamic-library.c: New testcase.
>> >     * jit.dg/test-compile-to-executable.c: New testcase.
>> >     * jit.dg/test-compile-to-object.c: New testcase.
>> >---
>> > gcc/jit/docs/cp/topics/compilation.rst             |  58 +++
>> > gcc/jit/docs/cp/topics/index.rst                   |   4 +-
>> > gcc/jit/docs/cp/topics/results.rst                 |  48 ---
>> > gcc/jit/docs/examples/emit-alphabet.bf             |  17 +
>> >gcc/jit/docs/examples/tut05-bf.c                   | 446
>> >+++++++++++++++++++++
>> > .../docs/internals/test-hello-world.exe.log.txt    |  48 ++-
>> > gcc/jit/docs/intro/index.rst                       |   3 +-
>> > gcc/jit/docs/intro/tutorial05.rst                  | 253 ++++++++++++
>> > gcc/jit/docs/topics/compilation.rst                | 199 +++++++++
>> > gcc/jit/docs/topics/index.rst                      |   4 +-
>> > gcc/jit/docs/topics/results.rst                    | 127 ------
>> >gcc/jit/jit-playback.c                             | 308 +++++++++++++-
>> > gcc/jit/jit-playback.h                             |  54 ++-
>> > gcc/jit/jit-recording.c                            |  40 +-
>> > gcc/jit/jit-recording.h                            |   4 +
>> > gcc/jit/libgccjit++.h                              |  12 +
>> > gcc/jit/libgccjit.c                                |  31 +-
>> > gcc/jit/libgccjit.h                                |  58 ++-
>> > gcc/jit/libgccjit.map                              |   1 +
>> > gcc/jit/notes.txt                                  |  13 +-
>> > gcc/testsuite/jit.dg/harness.h                     |  29 +-
>> > gcc/testsuite/jit.dg/jit.exp                       | 209 +++++++++-
>> > gcc/testsuite/jit.dg/test-compile-to-assembler.c   |  65 +++
>> > .../jit.dg/test-compile-to-dynamic-library.c       |  65 +++
>> > gcc/testsuite/jit.dg/test-compile-to-executable.c  | 110 +++++
>> > gcc/testsuite/jit.dg/test-compile-to-object.c      |  65 +++
>> > 26 files changed, 2026 insertions(+), 245 deletions(-)
>> > create mode 100644 gcc/jit/docs/cp/topics/compilation.rst
>> > delete mode 100644 gcc/jit/docs/cp/topics/results.rst
>> > create mode 100644 gcc/jit/docs/examples/emit-alphabet.bf
>> > create mode 100644 gcc/jit/docs/examples/tut05-bf.c
>> > create mode 100644 gcc/jit/docs/intro/tutorial05.rst
>> > create mode 100644 gcc/jit/docs/topics/compilation.rst
>> > delete mode 100644 gcc/jit/docs/topics/results.rst
>> > create mode 100644 gcc/testsuite/jit.dg/test-compile-to-assembler.c
>> >create mode 100644
>> >gcc/testsuite/jit.dg/test-compile-to-dynamic-library.c
>> > create mode 100644 gcc/testsuite/jit.dg/test-compile-to-executable.c
>> > create mode 100644 gcc/testsuite/jit.dg/test-compile-to-object.c
>> >
>> >diff --git a/gcc/jit/docs/cp/topics/compilation.rst
>> >b/gcc/jit/docs/cp/topics/compilation.rst
>> >new file mode 100644
>> >index 0000000..05917e8
>> >--- /dev/null
>> >+++ b/gcc/jit/docs/cp/topics/compilation.rst
>> >@@ -0,0 +1,58 @@
>> >+.. Copyright (C) 2014-2015 Free Software Foundation, Inc.
>> >+   Originally contributed by David Malcolm <dmalcolm@redhat.com>
>> >+
>> >+   This 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 of the License, or
>> >+   (at your option) any later version.
>> >+
>> >+   This program 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 this program.  If not, see
>> >+   <http://www.gnu.org/licenses/>.
>> >+
>> >+.. default-domain:: cpp
>> >+
>> >+Compiling a context
>> >+===================
>> >+
>> >+Once populated, a :class:`gccjit::context` can be compiled to
>> >+machine code, either in-memory via :func:`gccjit::context::compile` or
>> >+to disk via :func:`gccjit::context::compile_to_file`.
>> >+
>> >+You can compile a context multiple times (using either form of
>> >+compilation), although any errors that occur on the context will
>> >+prevent any future compilation of that context.
>> >+
>> >+In-memory compilation
>> >+*********************
>> >+
>> >+.. function:: gcc_jit_result *\
>> >+              gccjit::context::compile ()
>> >+
>> >+   This calls into GCC and builds the code, returning a
>> >+   `gcc_jit_result *`.
>> >+
>> >+   This is a thin wrapper around the
>> >+   :c:func:`gcc_jit_context_compile` API entrypoint.
>> >+
>> >+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 :func:`gccjit::context::compile_to_file` method.
>> >+
>> >+.. function:: void \
>> >+              gccjit::context::compile_to_file (enum
>> >gcc_jit_output_kind,\
>> >+                                                const char
>> >*output_path)
>> >+
>> >+   Compile the :class:`gccjit::context` to a file of the given
>> >+   kind.
>> >+
>> >+   This is a thin wrapper around the
>> >+   :c:func:`gcc_jit_context_compile_to_file` API entrypoint.
>> >diff --git a/gcc/jit/docs/cp/topics/index.rst
>> >b/gcc/jit/docs/cp/topics/index.rst
>> >index a129137..4ebb623 100644
>> >--- a/gcc/jit/docs/cp/topics/index.rst
>> >+++ b/gcc/jit/docs/cp/topics/index.rst
>> >@@ -1,4 +1,4 @@
>> >-.. Copyright (C) 2014 Free Software Foundation, Inc.
>> >+.. Copyright (C) 2014-2015 Free Software Foundation, Inc.
>> >    Originally contributed by David Malcolm <dmalcolm@redhat.com>
>> >
>> >    This is free software: you can redistribute it and/or modify it
>> >@@ -27,4 +27,4 @@ Topic Reference
>> >    expressions.rst
>> >    functions.rst
>> >    locations.rst
>> >-   results.rst
>> >+   compilation.rst
>> >diff --git a/gcc/jit/docs/cp/topics/results.rst
>> >b/gcc/jit/docs/cp/topics/results.rst
>> >deleted file mode 100644
>> >index 18200ac..0000000
>> >--- a/gcc/jit/docs/cp/topics/results.rst
>> >+++ /dev/null
>> >@@ -1,48 +0,0 @@
>> >-.. Copyright (C) 2014 Free Software Foundation, Inc.
>> >-   Originally contributed by David Malcolm <dmalcolm@redhat.com>
>> >-
>> >-   This 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 of the License, or
>> >-   (at your option) any later version.
>> >-
>> >-   This program 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 this program.  If not, see
>> >-   <http://www.gnu.org/licenses/>.
>> >-
>> >-.. default-domain:: cpp
>> >-
>> >-Compilation results
>> >-===================
>> >-
>> >-.. type:: gcc_jit_result
>> >-
>> >-  A `gcc_jit_result` encapsulates the result of compiling a context.
>> >-
>> >-.. function:: gcc_jit_result *\
>> >-              gccjit::context::compile ()
>> >-
>> >-   This calls into GCC and builds the code, returning a
>> >-   `gcc_jit_result *`.
>> >-
>> >-
>> >-.. function:: void *\
>> >-              gcc_jit_result_get_code (gcc_jit_result *result,\
>> >-                                       const char *funcname)
>> >-
>> >-   Locate a given function within the built machine code.
>> >-   This will need to be cast to a function pointer of the
>> >-   correct type before it can be called.
>> >-
>> >-
>> >-.. 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.
>> >diff --git a/gcc/jit/docs/examples/emit-alphabet.bf
>> >b/gcc/jit/docs/examples/emit-alphabet.bf
>> >new file mode 100644
>> >index 0000000..6863273
>> >--- /dev/null
>> >+++ b/gcc/jit/docs/examples/emit-alphabet.bf
>> >@@ -0,0 +1,17 @@
>> >+[
>> >+  Emit the uppercase alphabet
>> >+]
>> >+
>> >+cell 0 = 26
>> >+++++++++++++++++++++++++++
>> >+
>> >+cell 1 = 65
>> >+>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<
>> >+
>> >+while cell#0 != 0
>> >+[
>> >+ >
>> >+ .      emit cell#1
>> >+ +      increment cell@1
>> >+ <-     decrement cell@0
>> >+]
>> >diff --git a/gcc/jit/docs/examples/tut05-bf.c
>> >b/gcc/jit/docs/examples/tut05-bf.c
>> >new file mode 100644
>> >index 0000000..f948ede
>> >--- /dev/null
>> >+++ b/gcc/jit/docs/examples/tut05-bf.c
>> >@@ -0,0 +1,446 @@
>> >+/* A compiler for the "bf" language.  */
>> >+
>> >+#include <stdlib.h>
>> >+#include <string.h>
>> >+#include <errno.h>
>> >+
>> >+#include "libgccjit.h"
>> >+
>> >+/* 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;
>> >+}
>> >+
>> >+#define MAX_OPEN_PARENS 16
>> >+
>> >+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;
>> >+}
>> >+
>> >+/* Entrypoint to the compiler.  */
>> >+
>> >+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;
>> >+}
>> >+
>> >+/* Use the built compiler to compile the example to an executable:
>> >+
>> >+     { dg-jit-set-exe-params
>> >SRCDIR/gcc/jit/docs/examples/emit-alphabet.bf emit-alphabet.bf.exe }
>> >+
>> >+   Then run the executable, and verify that it emits the alphabet:
>> >+
>> >+     { dg-final { jit-run-executable emit-alphabet.bf.exe
>> >"ABCDEFGHIJKLMNOPQRSTUVWXYZ" } } */
>> >diff --git a/gcc/jit/docs/internals/test-hello-world.exe.log.txt
>> >b/gcc/jit/docs/internals/test-hello-world.exe.log.txt
>> >index 113dc35..205b6b4 100644
>> >--- a/gcc/jit/docs/internals/test-hello-world.exe.log.txt
>> >+++ b/gcc/jit/docs/internals/test-hello-world.exe.log.txt
>> >@@ -38,14 +38,20 @@ 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:  compiling ctxt: 0x1283e20
>> >+JIT:  in-memory compile of ctxt: 0x1283e20
>> >JIT:  entering: gcc::jit::result*
>> >gcc::jit::recording::context::compile()
>> > 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::result*
>> >gcc::jit::playback::context::compile()
>> >+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()
>> >@@ -86,29 +92,37 @@ 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:     entering: void jit_langhook_write_globals()
>> >+JIT:      entering: void
>> >gcc::jit::playback::context::write_global_decls_1()
>> >+JIT:      exiting: void
>> >gcc::jit::playback::context::write_global_decls_1()
>> >+JIT:      entering: void
>> >gcc::jit::playback::context::write_global_decls_2()
>> >+JIT:      exiting: void
>> >gcc::jit::playback::context::write_global_decls_2()
>> > JIT:     exiting: void jit_langhook_write_globals()
>> > 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: void
>> >gcc::jit::playback::context::convert_to_dso(const char*)
>> >-JIT:     argv[0]: x86_64-unknown-linux-gnu-gcc-5.0.0
>> >-JIT:     argv[1]: -shared
>> >-JIT:     argv[2]: /tmp/libgccjit-CKq1M9/fake.s
>> >-JIT:     argv[3]: -o
>> >-JIT:     argv[4]: /tmp/libgccjit-CKq1M9/fake.so
>> >-JIT:     argv[5]: -fno-use-linker-plugin
>> >-JIT:     argv[6]: (null)
>> >-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:    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:       argv[0]: x86_64-unknown-linux-gnu-gcc-5.0.0
>> >+JIT:       argv[1]: -shared
>> >+JIT:       argv[2]: /tmp/libgccjit-CKq1M9/fake.s
>> >+JIT:       argv[3]: -o
>> >+JIT:       argv[4]: /tmp/libgccjit-CKq1M9/fake.so
>> >+JIT:       argv[5]: -fno-use-linker-plugin
>> >+JIT:       argv[6]: (null)
>> >+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: gcc::jit::result*
>> >gcc::jit::playback::context::compile()
>> >+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()
>> >diff --git a/gcc/jit/docs/intro/index.rst
>> >b/gcc/jit/docs/intro/index.rst
>> >index d3bcec9..0f51777 100644
>> >--- a/gcc/jit/docs/intro/index.rst
>> >+++ b/gcc/jit/docs/intro/index.rst
>> >@@ -1,4 +1,4 @@
>> >-.. Copyright (C) 2014 Free Software Foundation, Inc.
>> >+.. Copyright (C) 2014-2015 Free Software Foundation, Inc.
>> >    Originally contributed by David Malcolm <dmalcolm@redhat.com>
>> >
>> >    This is free software: you can redistribute it and/or modify it
>> >@@ -25,3 +25,4 @@ Tutorial
>> >    tutorial02.rst
>> >    tutorial03.rst
>> >    tutorial04.rst
>> >+   tutorial05.rst
>> >diff --git a/gcc/jit/docs/intro/tutorial05.rst
>> >b/gcc/jit/docs/intro/tutorial05.rst
>> >new file mode 100644
>> >index 0000000..865a550
>> >--- /dev/null
>> >+++ b/gcc/jit/docs/intro/tutorial05.rst
>> >@@ -0,0 +1,253 @@
>> >+.. Copyright (C) 2015 Free Software Foundation, Inc.
>> >+   Originally contributed by David Malcolm <dmalcolm@redhat.com>
>> >+
>> >+   This 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 of the License, or
>> >+   (at your option) any later version.
>> >+
>> >+   This program 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 this program.  If not, see
>> >+   <http://www.gnu.org/licenses/>.
>> >+
>> >+Tutorial part 5: Implementing an Ahead-of-Time compiler
>> >+-------------------------------------------------------
>> >+
>> >+If you have a pre-existing language frontend, 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 compil
>>
>>
>



More information about the Gcc-patches mailing list