On January 15, 2015 9:05:59 PM CET, David Malcolm <dmalc...@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.

>"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 <dmalc...@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 <dmalc...@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 <dmalc...@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 <dmalc...@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 <dmalc...@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


Reply via email to