[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, ¶m_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