On Fri, Jan 16, 2015 at 7:47 PM, David Malcolm <dmalc...@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 <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. > > 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 <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, ¶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 <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 >> >> >