From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27542 invoked by alias); 15 Jan 2015 21:50:23 -0000 Mailing-List: contact jit-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Subscribe: Sender: jit-owner@gcc.gnu.org Received: (qmail 27516 invoked by uid 89); 15 Jan 2015 21:50:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.98.5 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.2 required=5.0 tests=AWL,BAYES_99,BAYES_999,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=no version=3.3.2 X-Spam-Status: No, score=0.2 required=5.0 tests=AWL,BAYES_99,BAYES_999,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=no version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wi0-f172.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=user-agent:in-reply-to:references:mime-version :content-transfer-encoding:content-type:subject:from:date:to :message-id; bh=/ygKjykF7h63UfceLB00i0+aKkpMHLymYoCcHGiXg5k=; b=WXSoZH8S12aCz8dEerytdQms0EM3pjU67M95xlb27fBqpQuqBNWLYOo3odMqE1PaQl 2Vsw+OacYymhncP9DTs13zSrpFJ8dQiukCtxgM57bb36Oty9fYJDczO1xTL6JJAsXfOc 2Cz3rzEOIHhIrL8puRuqJQuVCMcx79JTSXMKxZ61ytECrgIwMvBOU7wlRzWq//nqc+hK NrHlV5nTM87M6lmwnwvnwL1cG4wQLwHxoLsoOnwutBpDnTXRHIkps/lD2ZJvcCQl27o9 faUptoegJgkB2vbtH2ozk74LEtrqRkx7hRcrlO4VL1Rr9V+BDdwV4713IeYGKVwgmbmT 0awA== X-Received: by 10.180.208.79 with SMTP id mc15mr118607wic.34.1421358614586; Thu, 15 Jan 2015 13:50:14 -0800 (PST) User-Agent: K-9 Mail for Android In-Reply-To: <1421352359-26729-1-git-send-email-dmalcolm@redhat.com> References: <1421352359-26729-1-git-send-email-dmalcolm@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Subject: Re: Stage 3 RFC: using "jit" for ahead-of-time compilation From: Richard Biener Date: Thu, 01 Jan 2015 00:00:00 -0000 To: David Malcolm ,jit@gcc.gnu.org,gcc-patches@gcc.gnu.org,Jakub Jelinek ,Joseph Myers Message-ID: <7ACAA3E6-6CBB-4F60-98C4-DBA0EB3C344A@gmail.com> X-SW-Source: 2015-q1/txt/msg00021.txt.bz2 On January 15, 2015 9:05:59 PM CET, David Malcolm 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 . > (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 >+ >+ 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 >+ . >+ >+.. 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 > > 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 >- >- 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 >- . >- >-.. 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 >+#include >+#include >+ >+#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*) >JIT: exiting: void >gcc::jit::playback::context::extract_any_requested_dumps(vec*) > 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 > > 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 >+ >+ 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 >+ . >+ >+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