Discussion:
[PATCH] Merger of the "dmalcolm/jit" branch
David Malcolm
2014-09-23 18:45:12 UTC
Permalink
I'd like to merge my "dmalcolm/jit" branch into trunk and I wanted to
start a discussion here about what that would take (and maybe get some
code reviewed).

Attached is a (compressed) diff of the branch against trunk (as of
r215090 on 2014-09-09, so a little out-of-date).

As mentioned before, I'm using Sphinx for documentation (and also
checking in autogenerated .texinfo for those who want docs without a
sphinx toolchain installed).

Prebuilt HTML documentation (via Sphinx) can be seen at:
https://dmalcolm.fedorapeople.org/gcc/libgccjit-api-docs/index.html

The API docs currently have this caveat:

"Note that libgccjit is currently of "Alpha" quality; the APIs
are not yet set in stone, and they shouldn’t be used in
production yet."

Do I need to declare a frozen API before this can go in, or is it
acceptable to carry this within the tree as an "experimental" feature?

Bootstrapped&regrtested on x86_64-unknown-linux-gnu (Fedora 20). No
differences found in 16 common .sum files, relative to a control build
of r215090. (adding --enable-host-shared when building with "jit" in
the set of enabled languages).

For some reason "make check" isn't yet running the jit testsuite, and
"make check-jit" doesn't yet work.

That said, "make check-parallel-jit" does work, with the new jit.sum
containing:

=== jit Summary ===

# of expected passes 4301

The attached diff contains ChangeLog.jit entries per-directory (some of
which contain changes that have already been merged, which leads to some
directories that gain a ChangeLog.jit but no other change).

Here's an overall ChangeLog relating to the proposed merger:

ChangeLog:
* ChangeLog.jit: New.
* MAINTAINERS (Various Maintainers): Add myself as jit maintainer.

contrib/ChangeLog:
* ChangeLog.jit: New.
* jit-coverage-report.py: New file: a script to print crude
code-coverage information for the libgccjit API.

gcc/ChangeLog:
* ChangeLog.jit: New.
* ipa-reference.c (ipa_init): Move static bool init_p from here
to...
(ipa_init_p): New file-scope variable, so that it can be reset
when repeatedly invoking the compiler within one process by...
(ipa_reference_c_finalize): New function.
* ipa-reference.h (ipa_reference_c_finalize): New.
* ipa.c (ipa_c_finalize): New.
* main.c (main): Replace invocation of toplev_main with
construction of a toplev instance, and call its "main" method.
* params.c (global_init_params): Add an assert that params_finished is
false.
(params_c_finalize): New.
* params.h (params_c_finalize): New.
* passes.c (execute_ipa_summary_passes): Set "current_pass" before
invoking generate_summary.
(ipa_write_summaries_2): Assign "pass" to "current_pass" global
before calling write_summary hook.
(ipa_write_optimization_summaries_1): Likewise when calling
write_optimization_summary hook.
(ipa_read_summaries_1): Likewise for read_summary hook.
(ipa_read_optimization_summaries_1): Likewise for
read_optimization_summary hook.
* predict.c (predict_c_finalize): New.
* stringpool.c (init_stringpool): Clean up if we're called more
than once.
* symtab.c (symtab_c_finalize): New.
* timevar.c (timevar_init): Ignore repeated calls.
* timevar.def (TV_JIT_REPLAY): New.
(TV_ASSEMBLE): New.
(TV_LINK): New.
(TV_LOAD): New.
* timevar.h (class auto_timevar): New class.
* toplev.c: Include "dwarf2out.h", "ipa-reference.h", "gcse.h".
(general_init): Reset "input_location" to UNKNOWN_LOCATION.
(initialize_rtl): Move static local "initialized_once"
into file scope, and rename to...
(rtl_initialized): New variable.
(do_compile): Remove argument. Move timevar initialization from
here to toplev::start_timevars.
(toplev::toplev, toplev::~toplev, toplev::start_timevars,
toplev::finalize): New functions.
(toplev_main): Rename to...
(toplev::main): ...this.
* toplev.h (class toplev): New class.
(toplev_main): Delete in favor of toplev::main.
* varpool.c (varpool_c_finalize): New.

gcc/java/ChangeLog:
* ChangeLog.jit: New.

gcc/jit/ChangeLog:
* ChangeLog: New.
* ChangeLog.jit: New.
* Make-lang.in: New.
* TODO.rst: New.
* config-lang.in: New.
* docs/Makefile: New.
* docs/_build/texinfo/Makefile: New.
* docs/_build/texinfo/libgccjit.texi: New.
* docs/conf.py: New.
* docs/examples/install-hello-world.c: New.
* docs/examples/tut01-square.c: New.
* docs/examples/tut02-sum-of-squares.c: New.
* docs/examples/tut03-toyvm/Makefile: New.
* docs/examples/tut03-toyvm/factorial.toy: New.
* docs/examples/tut03-toyvm/fibonacci.toy: New.
* docs/examples/tut03-toyvm/toyvm.c: New.
* docs/index.rst: New.
* docs/internals/index.rst: New.
* docs/intro/index.rst: New.
* docs/intro/install.rst: New.
* docs/intro/tutorial01.rst: New.
* docs/intro/tutorial02.rst: New.
* docs/intro/tutorial03.rst: New.
* docs/topics/contexts.rst: New.
* docs/topics/expressions.rst: New.
* docs/topics/functions.rst: New.
* docs/topics/index.rst: New.
* docs/topics/locations.rst: New.
* docs/topics/objects.rst: New.
* docs/topics/results.rst: New.
* docs/topics/types.rst: New.
* dummy-frontend.c: New.
* internal-api.c: New.
* internal-api.h: New.
* jit-builtins.c: New.
* jit-builtins.h: New.
* libgccjit++.h: New.
* libgccjit.c: New.
* libgccjit.h: New.
* libgccjit.map: New.
* libgccjit.pc.in: New.
* notes.txt: New.

gcc/testsuite/ChangeLog:
* ChangeLog.jit: New.
* jit.dg/all-non-failing-tests.h: New.
* jit.dg/harness.h: New.
* jit.dg/jit.exp: New.
* jit.dg/test-accessing-struct.c: New.
* jit.dg/test-accessing-union.c: New.
* jit.dg/test-array-as-pointer.c: New.
* jit.dg/test-arrays.c: New.
* jit.dg/test-calling-external-function.c: New.
* jit.dg/test-calling-function-ptr.c: New.
* jit.dg/test-combination.c: New.
* jit.dg/test-dot-product.c: New.
* jit.dg/test-empty.c: New.
* jit.dg/test-error-adding-to-terminated-block.c: New.
* jit.dg/test-error-array-as-pointer.c: New.
* jit.dg/test-error-bad-cast.c: New.
* jit.dg/test-error-block-in-wrong-function.c: New.
* jit.dg/test-error-call-through-ptr-with-non-function.c: New.
* jit.dg/test-error-call-through-ptr-with-non-pointer.c: New.
* jit.dg/test-error-call-through-ptr-with-not-enough-args.c: New.
* jit.dg/test-error-call-through-ptr-with-too-many-args.c: New.
* jit.dg/test-error-call-with-mismatching-args.c: New.
* jit.dg/test-error-call-with-not-enough-args.c: New.
* jit.dg/test-error-call-with-too-many-args.c: New.
* jit.dg/test-error-dereference-field-of-non-pointer.c: New.
* jit.dg/test-error-dereference-read-of-non-pointer.c: New.
* jit.dg/test-error-index-not-a-numeric-type.c: New.
* jit.dg/test-error-mismatching-types-in-assignment.c: New.
* jit.dg/test-error-mismatching-types-in-call.c: New.
* jit.dg/test-error-missing-return.c: New.
* jit.dg/test-error-null-passed-to-api.c: New.
* jit.dg/test-error-return-within-void-function.c: New.
* jit.dg/test-error-unreachable-block.c: New.
* jit.dg/test-error-unterminated-block.c: New.
* jit.dg/test-error-value-not-a-numeric-type.c: New.
* jit.dg/test-expressions.c: New.
* jit.dg/test-factorial.c: New.
* jit.dg/test-fibonacci.c: New.
* jit.dg/test-functions.c: New.
* jit.dg/test-fuzzer.c: New.
* jit.dg/test-hello-world.c: New.
* jit.dg/test-linked-list.c: New.
* jit.dg/test-nested-contexts.c: New.
* jit.dg/test-nested-loops.c: New.
* jit.dg/test-operator-overloading.cc: New.
* jit.dg/test-quadratic.c: New.
* jit.dg/test-quadratic.cc: New.
* jit.dg/test-reading-struct.c: New.
* jit.dg/test-string-literal.c: New.
* jit.dg/test-sum-of-squares.c: New.
* jit.dg/test-threads.c: New.
* jit.dg/test-types.c: New.
* jit.dg/test-using-global.c: New.
* jit.dg/test-volatile.c: New.

libbacktrace/ChangeLog:
* ChangeLog.jit: New.
libcpp/ChangeLog:
* ChangeLog.jit: New.

libdecnumber/ChangeLog:
* ChangeLog.jit: New.

libiberty/ChangeLog:
* ChangeLog.jit: New.

zlib/ChangeLog:
* ChangeLog.jit: New.
Joseph S. Myers
2014-09-23 23:27:25 UTC
Permalink
Various *_finalize functions are missing comments explaining their
semantics. Also the return type should be on the line before the function
name.

Shouldn't the jit.pdf, jit.install-html etc. Make-lang.in hooks actually
build / install the documentation for this JIT?
+#include "config.h"
+#include "system.h"
+#include "ansidecl.h"
+#include "coretypes.h"
The standard initial includes are config.h, system.h, coretypes.h.
system.h includes libiberty.h which includes ansidecl.h, so direct
ansidecl.h includes shouldn't be needed anywhere.
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
Should start with standard copyright and license header. This applies to
all sources in gcc/jit/.

dump::write, recording::context::add_error_va,
recording::string::from_printf all use fixed-size buffers with vsnprintf
but no apparent reason to assume this can never result in truncation, and
missing API comments (lots of functions are missing such comments ...) to
state either the caller's responsibility to limit the length of the
result, or that the API provides for truncation. Unless there's a
definite reason truncation is needed, dynamic allocation should be used.
A patch was submitted a while back to add xasprintf and xvasprintf to
libiberty - <https://gcc.gnu.org/ml/gcc-patches/2009-11/msg01448.html> and
<https://gcc.gnu.org/ml/gcc-patches/2009-11/msg01449.html> (I don't know
if that's the most recent version), which could be resurrected.

The code for compiling a .s file should:

* use choose_tmpdir from libiberty rather than hardcoding /tmp (or,
better, create the files directly with make_temp_file, and delete them
individual afterwards);

* use libiberty's pexecute to run subprocesses, not "system" (building up
a string to pass to the shell always looks like a security hole, though in
this case it may in fact be safe);

* use the $(target_noncanonical)-gcc-$(version) name for the driver rather
than plain "gcc", to maximise the chance that it is actually the same
compiler the JIT library was built for (I realise you may not actually
depend on it being the same compiler, but that does seem best; in
principle in future it should be possible to load multiple copies of the
JIT library to JIT for different targets, so that code for an offload
accelerator can go through the JIT).

The documentation referring to the dmalcolm/jit branch will of course need
updating to refer to trunk (and GCC 5 and later releases) once this is on
trunk.
--
Joseph S. Myers
joseph-***@public.gmane.org
David Malcolm
2014-09-24 14:29:58 UTC
Permalink
Joseph - thanks for looking through the jit diff.

I plan to fix the issues you raise as a series of separate patches.
Post by Joseph S. Myers
Various *_finalize functions are missing comments explaining their
semantics. Also the return type should be on the line before the function
name.
I've committed the following fix to branch dmalcolm/jit:

Five of the *_c_finalize functions were empty, since their files
contain no state [1][2]. Delete them.

Fix up the formatting of the remaining *_c_finalize functions, and
ensure they have descriptive leading comments.

[1] Most of these lost their state when the symbol_table class was
introduced, in r214422.

[2] predict.c has state in the form of these variables:

static sreal real_zero, real_one, real_almost_one, real_br_prob_base,
real_inv_br_prob_base, real_one_half, real_bb_freq_max;

and, within function estimate_bb_frequencies:

static int real_values_initialized = 0;

but it seems to me that this state doesn't need to be reset between
repeated in-process invocations.

gcc/ChangeLog.jit:
* cgraph.h (cgraphbuild_c_finalize): Delete prototype of empty
function.
(ipa_c_finalize): Likewise.
(predict_c_finalize): Likewise.
(symtab_c_finalize): Likewise.
(varpool_c_finalize): Likewise.

* cgraph.c (cgraph_c_finalize): Add leading comment. Put return
type on line before function name.
* cgraphunit.c (cgraphunit_c_finalize): Likewise.
* dwarf2out.c (dwarf2out_c_finalize): Likewise.
* gcse.c (gcse_c_finalize): Likewise.
* ipa-cp.c (ipa_cp_c_finalize): Likewise.
* ipa-reference.c (ipa_reference_c_finalize): Likewise.

* params.c (params_c_finalize): Update leading comment to match
format of the others mentioned above.

* cgraphbuild.c (cgraphbuild_c_finalize): Delete empty function.
* ipa.c (ipa_c_finalize): Likewise.
* predict.c (predict_c_finalize): Likewise.
* symtab.c (symtab_c_finalize): Likewise.
* varpool.c (varpool_c_finalize): Likewise.

* toplev.c (toplev::finalize): Remove calls to empty functions
cgraphbuild_c_finalize, ipa_c_finalize, predict_c_finalize,
symtab_c_finalize, varpool_c_finalize.
---
gcc/cgraph.c | 6 +++++-
gcc/cgraph.h | 9 ---------
gcc/cgraphbuild.c | 4 ----
gcc/cgraphunit.c | 6 +++++-
gcc/dwarf2out.c | 6 +++++-
gcc/gcse.c | 6 +++++-
gcc/ipa-cp.c | 3 +++
gcc/ipa-reference.c | 6 +++++-
gcc/ipa.c | 4 ----
gcc/params.c | 3 ++-
gcc/predict.c | 4 ----
gcc/symtab.c | 4 ----
gcc/toplev.c | 5 -----
gcc/varpool.c | 4 ----
14 files changed, 30 insertions(+), 40 deletions(-)

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 736dd73..1721634 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -3078,7 +3078,11 @@ gimple_check_call_matching_types (gimple call_stmt, tree callee,
return true;
}

-void cgraph_c_finalize (void)
+/* Reset all state within cgraph.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
+void
+cgraph_c_finalize (void)
{
symtab = NULL;

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c407a3b..fd45e01 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1958,25 +1958,16 @@ void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
/* In cgraphbuild.c */
int compute_call_stmt_bb_frequency (tree, basic_block bb);
void record_references_in_initializer (tree, bool);
-void cgraphbuild_c_finalize (void);

/* In ipa.c */
void cgraph_build_static_cdtor (char which, tree body, int priority);
void ipa_discover_readonly_nonaddressable_vars (void);
-void ipa_c_finalize (void);

/* In ipa-cp.c */
void ipa_cp_c_finalize (void);

-/* In predict.c */
-void predict_c_finalize (void);
-
-/* In symtab.c */
-void symtab_c_finalize (void);
-
/* In varpool.c */
tree ctor_for_folding (tree);
-void varpool_c_finalize (void);

/* Return true when the symbol is real symbol, i.e. it is not inline clone
or abstract function kept for debug info purposes only. */
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index 5610064..96d7015 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -576,7 +576,3 @@ make_pass_remove_cgraph_callee_edges (gcc::context *ctxt)
{
return new pass_remove_cgraph_callee_edges (ctxt);
}
-
-void cgraphbuild_c_finalize (void)
-{
-}
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 1f52d35..9a3834a 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2288,7 +2288,11 @@ symbol_table::finalize_compilation_unit (void)
timevar_pop (TV_CGRAPH);
}

-void cgraphunit_c_finalize (void)
+/* Reset all state within cgraphunit.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
+void
+cgraphunit_c_finalize (void)
{
gcc_assert (cgraph_new_nodes.length () == 0);
cgraph_new_nodes.truncate (0);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5dd7188..6617119 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -24566,7 +24566,11 @@ dwarf2out_finish (const char *filename)
output_indirect_strings ();
}

-void dwarf2out_c_finalize (void)
+/* Reset all state within dwarf2out.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
+void
+dwarf2out_c_finalize (void)
{
last_var_location_insn = NULL;
cached_next_real_insn = NULL;
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 085b1f6..3a59066 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -4288,7 +4288,11 @@ make_pass_rtl_hoist (gcc::context *ctxt)
return new pass_rtl_hoist (ctxt);
}

-void gcse_c_finalize (void)
+/* Reset all state within gcse.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
+void
+gcse_c_finalize (void)
{
test_insn = NULL;
}
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 33a46f2..163ed4b 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -3829,6 +3829,9 @@ make_pass_ipa_cp (gcc::context *ctxt)
return new pass_ipa_cp (ctxt);
}

+/* Reset all state within ipa-cp.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
void
ipa_cp_c_finalize (void)
{
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 39f6cb0..f3af47a 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -1174,7 +1174,11 @@ make_pass_ipa_reference (gcc::context *ctxt)
return new pass_ipa_reference (ctxt);
}

-void ipa_reference_c_finalize (void)
+/* Reset all state within ipa-reference.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */
+
+void
+ipa_reference_c_finalize (void)
{
ipa_init_p = false;
}
diff --git a/gcc/ipa.c b/gcc/ipa.c
index f10e7bd..5afacd8 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -1090,10 +1090,6 @@ make_pass_ipa_cdtor_merge (gcc::context *ctxt)
return new pass_ipa_cdtor_merge (ctxt);
}

-void ipa_c_finalize (void)
-{
-}
-
/* Invalid pointer representing BOTTOM for single user dataflow. */
#define BOTTOM ((cgraph_node *)(size_t) 2)

diff --git a/gcc/params.c b/gcc/params.c
index 2b72c58..7aa96e2 100644
--- a/gcc/params.c
+++ b/gcc/params.c
@@ -84,7 +84,8 @@ finish_params (void)
params_finished = true;
}

-/* Reset all state in params.c. */
+/* Reset all state within params.c so that we can rerun the compiler
+ within the same process. For use by toplev::finalize. */

void
params_c_finalize (void)
diff --git a/gcc/predict.c b/gcc/predict.c
index b0d572f..eb5db2a 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -3237,7 +3237,3 @@ rebuild_frequencies (void)
gcc_unreachable ();
timevar_pop (TV_REBUILD_FREQUENCIES);
}
-
-void predict_c_finalize (void)
-{
-}
diff --git a/gcc/symtab.c b/gcc/symtab.c
index fd9cbac..792b3b5 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1755,10 +1755,6 @@ symtab_node::semantically_equivalent_p (symtab_node *target)
return bb == ba;
}

-void symtab_c_finalize (void)
-{
-}
-
/* Classify symbol symtab node for partitioning. */

enum symbol_partitioning_class
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 37f54ef..58180f4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -2066,15 +2066,10 @@ toplev::finalize (void)
this_target_rtl->target_specific_initialized = false;

cgraph_c_finalize ();
- cgraphbuild_c_finalize ();
cgraphunit_c_finalize ();
dwarf2out_c_finalize ();
gcse_c_finalize ();
- ipa_c_finalize ();
ipa_cp_c_finalize ();
ipa_reference_c_finalize ();
params_c_finalize ();
- predict_c_finalize ();
- symtab_c_finalize ();
- varpool_c_finalize ();
}
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 5b6d76b..72971d6 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -781,7 +781,3 @@ varpool_node::call_for_node_and_aliases (bool (*callback) (varpool_node *,
}
return false;
}
-
-void varpool_c_finalize (void)
-{
-}
--
1.7.11.7
David Malcolm
2014-09-24 16:17:26 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
Should start with standard copyright and license header. This applies to
all sources in gcc/jit/.
[...]

I've committed the following to the dmalcolm/jit branch:

ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

contrib/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

gcc/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

gcc/java/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

gcc/jit/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.
* Make-lang.in: Update copyright.
* config-lang.in: Update copyright.
* docs/examples/install-hello-world.c: Add copyright header.
* docs/examples/tut01-square.c: Likewise.
* docs/examples/tut02-sum-of-squares.c: Likewise.
* docs/examples/tut03-toyvm/toyvm.c: Likewise.
* internal-api.c: Likewise.
* internal-api.h: Likewise.
* libgccjit++.h: Likewise.
* libgccjit.c: Likewise.
* libgccjit.h: Likewise.
* libgccjit.map: Likewise.

gcc/testsuite/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

libbacktrace/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

libcpp/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

libdecnumber/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

libiberty/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.

zlib/ChangeLog.jit:
* ChangeLog.jit: Add copyright footer.
---
ChangeLog.jit | 10 ++++++++++
contrib/ChangeLog.jit | 10 ++++++++++
gcc/ChangeLog.jit | 10 ++++++++++
gcc/java/ChangeLog.jit | 10 ++++++++++
gcc/jit/ChangeLog.jit | 22 ++++++++++++++++++++++
gcc/jit/Make-lang.in | 2 +-
gcc/jit/config-lang.in | 2 +-
gcc/jit/docs/examples/install-hello-world.c | 19 +++++++++++++++++++
gcc/jit/docs/examples/tut01-square.c | 19 +++++++++++++++++++
gcc/jit/docs/examples/tut02-sum-of-squares.c | 19 +++++++++++++++++++
gcc/jit/docs/examples/tut03-toyvm/toyvm.c | 19 ++++++++++++++++++-
gcc/jit/internal-api.c | 20 ++++++++++++++++++++
gcc/jit/internal-api.h | 20 ++++++++++++++++++++
gcc/jit/libgccjit++.h | 19 ++++++++++++++++++-
gcc/jit/libgccjit.c | 21 ++++++++++++++++++++-
gcc/jit/libgccjit.h | 22 +++++++++++++++++++---
gcc/jit/libgccjit.map | 18 ++++++++++++++++++
gcc/testsuite/ChangeLog.jit | 10 ++++++++++
libbacktrace/ChangeLog.jit | 10 ++++++++++
libcpp/ChangeLog.jit | 10 ++++++++++
libdecnumber/ChangeLog.jit | 10 ++++++++++
libiberty/ChangeLog.jit | 10 ++++++++++
zlib/ChangeLog.jit | 10 ++++++++++
23 files changed, 314 insertions(+), 8 deletions(-)

diff --git a/ChangeLog.jit b/ChangeLog.jit
index 5d2db3f..d2c3941 100644
--- a/ChangeLog.jit
+++ b/ChangeLog.jit
@@ -1,3 +1,7 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2014-09-11 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* MAINTAINERS (Various Maintainers): Add myself as jit maintainer.
@@ -6,3 +10,9 @@

* configure.ac: Add --enable-host-shared
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/contrib/ChangeLog.jit b/contrib/ChangeLog.jit
index 79be84d..38a315a 100644
--- a/contrib/ChangeLog.jit
+++ b/contrib/ChangeLog.jit
@@ -1,4 +1,14 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2014-01-23 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* jit-coverage-report.py: New file: a script to print crude
code-coverage information for the libgccjit API.
+
+Copyright (C) 2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/gcc/ChangeLog.jit b/gcc/ChangeLog.jit
index 9771913..29307b1 100644
--- a/gcc/ChangeLog.jit
+++ b/gcc/ChangeLog.jit
@@ -1,5 +1,9 @@
2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

+ * ChangeLog.jit: Add copyright footer.
+
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
* cgraph.h (cgraphbuild_c_finalize): Delete prototype of empty
function.
(ipa_c_finalize): Likewise.
@@ -280,3 +284,9 @@
(toplev_finalize): New.
* varpool.c (varpool_c_finalize): New.

+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/gcc/java/ChangeLog.jit b/gcc/java/ChangeLog.jit
index 50de5bc..e5e7e27 100644
--- a/gcc/java/ChangeLog.jit
+++ b/gcc/java/ChangeLog.jit
@@ -1,4 +1,14 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-11 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* lang.c (java_handle_option): Update for introduction of
gcc::dump_manager.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 4db5e66..f451771 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,19 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+ * Make-lang.in: Update copyright.
+ * config-lang.in: Update copyright.
+ * docs/examples/install-hello-world.c: Add copyright header.
+ * docs/examples/tut01-square.c: Likewise.
+ * docs/examples/tut02-sum-of-squares.c: Likewise.
+ * docs/examples/tut03-toyvm/toyvm.c: Likewise.
+ * internal-api.c: Likewise.
+ * internal-api.h: Likewise.
+ * libgccjit++.h: Likewise.
+ * libgccjit.c: Likewise.
+ * libgccjit.h: Likewise.
+ * libgccjit.map: Likewise.
+
2014-09-23 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* TODO.rst (API): Shift operators are done.
@@ -3062,3 +3078,9 @@
* libgccjit.h: New.
* libgccjit.map: New.
* notes.txt: New.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
index bf017f7..26dd022 100644
--- a/gcc/jit/Make-lang.in
+++ b/gcc/jit/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for libgccjit.so.
-# Copyright (C) 2013 Free Software Foundation, Inc.
+# Copyright (C) 2013-2014 Free Software Foundation, Inc.

#This file is part of GCC.

diff --git a/gcc/jit/config-lang.in b/gcc/jit/config-lang.in
index 7128c3b..b22a5ee 100644
--- a/gcc/jit/config-lang.in
+++ b/gcc/jit/config-lang.in
@@ -1,5 +1,5 @@
# Top level configure fragment for libgccjit.so.
-# Copyright (C) 2013 Free Software Foundation, Inc.
+# Copyright (C) 2013-2014 Free Software Foundation, Inc.

#This file is part of GCC.

diff --git a/gcc/jit/docs/examples/install-hello-world.c b/gcc/jit/docs/examples/install-hello-world.c
index 29afad9..49c9651 100644
--- a/gcc/jit/docs/examples/install-hello-world.c
+++ b/gcc/jit/docs/examples/install-hello-world.c
@@ -1,3 +1,22 @@
+/* Smoketest example for libgccjit.so
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#include <libgccjit.h>

#include <stdlib.h>
diff --git a/gcc/jit/docs/examples/tut01-square.c b/gcc/jit/docs/examples/tut01-square.c
index ea07b92..5eae179 100644
--- a/gcc/jit/docs/examples/tut01-square.c
+++ b/gcc/jit/docs/examples/tut01-square.c
@@ -1,3 +1,22 @@
+/* Usage example for libgccjit.so
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#include <libgccjit.h>

#include <stdlib.h>
diff --git a/gcc/jit/docs/examples/tut02-sum-of-squares.c b/gcc/jit/docs/examples/tut02-sum-of-squares.c
index 1970a36..594230b 100644
--- a/gcc/jit/docs/examples/tut02-sum-of-squares.c
+++ b/gcc/jit/docs/examples/tut02-sum-of-squares.c
@@ -1,3 +1,22 @@
+/* Usage example for libgccjit.so
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#include <libgccjit.h>

#include <stdlib.h>
diff --git a/gcc/jit/docs/examples/tut03-toyvm/toyvm.c b/gcc/jit/docs/examples/tut03-toyvm/toyvm.c
index 8211768..2646fda 100644
--- a/gcc/jit/docs/examples/tut03-toyvm/toyvm.c
+++ b/gcc/jit/docs/examples/tut03-toyvm/toyvm.c
@@ -1,5 +1,22 @@
/* A simple stack-based virtual machine to demonstrate
- JIT-compilation. */
+ JIT-compilation.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */

#include <assert.h>
#include <errno.h>
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index a22cc5c..9e59d92 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -1,3 +1,23 @@
+/* Core of implementation of libgccjit.so
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#include "config.h"
#include "system.h"
#include "ansidecl.h"
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 274b6ca..8054bed 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -1,3 +1,23 @@
+/* Core of implementation of libgccjit.so
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#ifndef INTERNAL_API_H
#define INTERNAL_API_H

diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h
index afcf892..67ed5d5 100644
--- a/gcc/jit/libgccjit++.h
+++ b/gcc/jit/libgccjit++.h
@@ -1,4 +1,21 @@
-/* A C++ API for libgccjit, purely as inline wrapper functions. */
+/* A C++ API for libgccjit, purely as inline wrapper functions.
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */

#ifndef LIBGCCJIT_PLUS_PLUS_H
#define LIBGCCJIT_PLUS_PLUS_H
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 9550d8f..510ed86 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -1,4 +1,23 @@
-/* Implementation of the C API; all wrappers into a C++ API */
+/* Implementation of the C API; all wrappers into the internal C++ API
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#include "config.h"
#include "system.h"
#include "ansidecl.h"
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 0ca1e92..8e03412 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -1,6 +1,22 @@
-/*
- A pure C API to enable client code to embed GCC as a JIT-compiler.
- */
+/* A pure C API to enable client code to embed GCC as a JIT-compiler.
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
#ifndef LIBGCCJIT_H
#define LIBGCCJIT_H

diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 768e010..d4ba7b6 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -1,4 +1,22 @@
# Linker script for libgccjit.so
+# Copyright (C) 2013-2014 Free Software Foundation, Inc.
+# Contributed by David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>.
+#
+# This file is part of GCC.
+#
+# GCC 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, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
{
global:
# Keep this list sorted alphabetically:
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index e882b05..4572c3d 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,7 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2014-09-23 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* jit.dg/test-expressions.c (make_tests_of_binary_ops): Add
@@ -555,3 +559,9 @@
* jit.dg/test-string-literal.c: New.
* jit.dg/test-sum-of-squares.c: New.

+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/libbacktrace/ChangeLog.jit b/libbacktrace/ChangeLog.jit
index fff6241..6b60e3b 100644
--- a/libbacktrace/ChangeLog.jit
+++ b/libbacktrace/ChangeLog.jit
@@ -1,4 +1,14 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-03 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* configure.ac: Add --enable-host-shared.
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/libcpp/ChangeLog.jit b/libcpp/ChangeLog.jit
index 6f497d4..5182b9c 100644
--- a/libcpp/ChangeLog.jit
+++ b/libcpp/ChangeLog.jit
@@ -1,3 +1,7 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-07 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* Makefile.in: Set PICFLAG from configure script; add it to
@@ -10,3 +14,9 @@

* configure.ac: Add --enable-host-shared.
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/libdecnumber/ChangeLog.jit b/libdecnumber/ChangeLog.jit
index 6f497d4..5182b9c 100644
--- a/libdecnumber/ChangeLog.jit
+++ b/libdecnumber/ChangeLog.jit
@@ -1,3 +1,7 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-07 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* Makefile.in: Set PICFLAG from configure script; add it to
@@ -10,3 +14,9 @@

* configure.ac: Add --enable-host-shared.
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/libiberty/ChangeLog.jit b/libiberty/ChangeLog.jit
index 9578e4f..52328e3 100644
--- a/libiberty/ChangeLog.jit
+++ b/libiberty/ChangeLog.jit
@@ -1,4 +1,14 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-03 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* configure.ac: If --enable-host-shared, use -fPIC.
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/zlib/ChangeLog.jit b/zlib/ChangeLog.jit
index 0ffd068..64ba6e1 100644
--- a/zlib/ChangeLog.jit
+++ b/zlib/ChangeLog.jit
@@ -1,3 +1,7 @@
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
+ * ChangeLog.jit: Add copyright footer.
+
2013-10-07 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

* Makefile.am: Add PICFLAG to libz_a_CFLAGS.
@@ -10,3 +14,9 @@

* configure.ac: Add --enable-host-shared.
* configure: Regenerate.
+
+Copyright (C) 2013-2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
--
1.7.11.7
David Malcolm
2014-09-24 16:35:22 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
+#include "config.h"
+#include "system.h"
+#include "ansidecl.h"
+#include "coretypes.h"
The standard initial includes are config.h, system.h, coretypes.h.
system.h includes libiberty.h which includes ansidecl.h, so direct
ansidecl.h includes shouldn't be needed anywhere.
[...]

I've committed the following fix for the above to branch dmalcolm/jit:

gcc/jit/ChangeLog.jit:

* dummy-frontend.c: Update copyright year. Follow standard for
initial includes by removing redundant include of "ansidecl.h".
* internal-api.c: Follow standard for initial includes by removing
redundant include of "ansidecl.h".
* jit-builtins.c: Likewise.
* libgccjit.c: Likewise.
---
gcc/jit/ChangeLog.jit | 9 +++++++++
gcc/jit/dummy-frontend.c | 3 +--
gcc/jit/internal-api.c | 1 -
gcc/jit/jit-builtins.c | 1 -
gcc/jit/libgccjit.c | 1 -
5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index f451771..4ddd3cb 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,14 @@
2014-09-24 David Malcolm <***@redhat.com>

+ * dummy-frontend.c: Update copyright year. Follow standard for
+ initial includes by removing redundant include of "ansidecl.h".
+ * internal-api.c: Follow standard for initial includes by removing
+ redundant include of "ansidecl.h".
+ * jit-builtins.c: Likewise.
+ * libgccjit.c: Likewise.
+
+2014-09-24 David Malcolm <***@redhat.com>
+
* ChangeLog.jit: Add copyright footer.
* Make-lang.in: Update copyright.
* config-lang.in: Update copyright.
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 1b96c91..1d178f9 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -1,5 +1,5 @@
/* jit.c -- Dummy "frontend" for use during JIT-compilation.
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.

This file is part of GCC.

@@ -19,7 +19,6 @@ along with GCC; see the file COPYING3. If not see

#include "config.h"
#include "system.h"
-#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "signop.h"
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 9e59d92..76ada70 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see

#include "config.h"
#include "system.h"
-#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "tree.h"
diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index 160ef20..c4b0f59 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -19,7 +19,6 @@ along with GCC; see the file COPYING3. If not see

#include "config.h"
#include "system.h"
-#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
#include "tree.h"
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 510ed86..cb8321c 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see

#include "config.h"
#include "system.h"
-#include "ansidecl.h"
#include "coretypes.h"
#include "opts.h"
--
1.7.11.7
David Malcolm
2014-09-24 17:50:36 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
dump::write, recording::context::add_error_va,
recording::string::from_printf all use fixed-size buffers with vsnprintf
but no apparent reason to assume this can never result in truncation, and
missing API comments (lots of functions are missing such comments ...) to
state either the caller's responsibility to limit the length of the
result, or that the API provides for truncation. Unless there's a
definite reason truncation is needed, dynamic allocation should be used.
A patch was submitted a while back to add xasprintf and xvasprintf to
libiberty - <https://gcc.gnu.org/ml/gcc-patches/2009-11/msg01448.html> and
<https://gcc.gnu.org/ml/gcc-patches/2009-11/msg01449.html> (I don't know
if that's the most recent version), which could be resurrected.
[...]

The ideal I'm aiming for here is that a well-behaved library should
never abort, so I've rewritten these functions to use vasprintf, and
added error-handling checks to cover the case where malloc returns NULL
within vasprintf.

I believe this fixes the specific issues you pointed out (apart from the
numerous missing API comments, which I'll do it a followup). Note that
there's still a fixed-size buffer within gcc::jit::recording::context,
the field:

char m_first_error_str[1024];

Currently this is populated using strncpy followed by an explicit write
of a truncation byte to make sure, but it *is* another truncation.

Presumably I should address this in a followup, by making that be
dynamically-allocated?
(perhaps by making errors be first-class entities in the API, by
introducing a gcc_jit_error subclass of gcc_jit_object, with a location
field as well as the text message).

Committed to branch dmalcolm/jit:

gcc/jit/ChangeLog.jit:
* internal-api.c (gcc::jit::dump::write): Eliminate fixed-size
buffer "buf" by replacing call to vsnprintf with one to vasprintf
and a free, emitting an error on the dump's context if a malloc
failure occurs.
(gcc::jit::recording::context::add_error_va): Likewise, using
a precanned message if the malloc inside vasprinf fails. Split
local "buf" into "malloced_msg" and "errmsg" to ensure that we
free the message iff we're using one malloc-ed by vasprintf.
(gcc::jit::recording::string::from_printf): Eliminate fixed-size
buffer "buf" by replacing call to vsnprintf with one to vasprintf
and a free, emitting an error on the relevant context if a malloc
failure occurs.
---
gcc/jit/ChangeLog.jit | 15 +++++++++++++++
gcc/jit/internal-api.c | 50 ++++++++++++++++++++++++++++++++++++++------------
2 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 4ddd3cb..3cadaab 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,20 @@
2014-09-24 David Malcolm <***@redhat.com>

+ * internal-api.c (gcc::jit::dump::write): Eliminate fixed-size
+ buffer "buf" by replacing call to vsnprintf with one to vasprintf
+ and a free, emitting an error on the dump's context if a malloc
+ failure occurs.
+ (gcc::jit::recording::context::add_error_va): Likewise, using
+ a precanned message if the malloc inside vasprinf fails. Split
+ local "buf" into "malloced_msg" and "errmsg" to ensure that we
+ free the message iff we're using one malloc-ed by vasprintf.
+ (gcc::jit::recording::string::from_printf): Eliminate fixed-size
+ buffer "buf" by replacing call to vsnprintf with one to vasprintf
+ and a free, emitting an error on the relevant context if a malloc
+ failure occurs.
+
+2014-09-24 David Malcolm <***@redhat.com>
+
* dummy-frontend.c: Update copyright year. Follow standard for
initial includes by removing redundant include of "ansidecl.h".
* internal-api.c: Follow standard for initial includes by removing
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 76ada70..15e9f81 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -95,12 +95,20 @@ dump::~dump ()
void
dump::write (const char *fmt, ...)
{
- char buf[4096];
va_list ap;
+ char *buf = NULL;
+
va_start (ap, fmt);
- vsnprintf (buf, sizeof (buf), fmt, ap);
+ vasprintf (&buf, fmt, ap);
va_end (ap);

+ if (!buf)
+ {
+ m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
+ m_filename);
+ return;
+ }
+
fwrite (buf, strlen (buf), 1, m_file);

/* Update line/column: */
@@ -114,6 +122,8 @@ dump::write (const char *fmt, ...)
else
m_column++;
}
+
+ free (buf);
}

recording::location *
@@ -680,8 +690,14 @@ recording::context::add_error (location *loc, const char *fmt, ...)
void
recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
{
- char buf[1024];
- vsnprintf (buf, sizeof (buf) - 1, fmt, ap);
+ char *malloced_msg;
+ const char *errmsg;
+
+ vasprintf (&malloced_msg, fmt, ap);
+ if (malloced_msg)
+ errmsg = malloced_msg;
+ else
+ errmsg = "out of memory generating error message";

const char *ctxt_progname =
get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
@@ -692,19 +708,21 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
fprintf (stderr, "%s: %s: error: %s\n",
ctxt_progname,
loc->get_debug_string (),
- buf);
+ errmsg);
else
fprintf (stderr, "%s: error: %s\n",
ctxt_progname,
- buf);
+ errmsg);

if (!m_error_count)
{
- strncpy (m_first_error_str, buf, sizeof(m_first_error_str));
+ strncpy (m_first_error_str, errmsg, sizeof(m_first_error_str));
m_first_error_str[sizeof(m_first_error_str) - 1] = '\0';
}

m_error_count++;
+
+ free (malloced_msg);
}

const char *
@@ -797,15 +815,23 @@ recording::string::~string ()
recording::string *
recording::string::from_printf (context *ctxt, const char *fmt, ...)
{
- char buf[4096];
va_list ap;
- va_start (ap, fmt);
-
- vsnprintf (buf, sizeof (buf), fmt, ap);
+ char *buf = NULL;
+ recording::string *result;

+ va_start (ap, fmt);
+ vasprintf (&buf, fmt, ap);
va_end (ap);

- return ctxt->new_string (buf);
+ if (!buf)
+ {
+ ctxt->add_error (NULL, "malloc failure");
+ return NULL;
+ }
+
+ result = ctxt->new_string (buf);
+ free (buf);
+ return result;
}

recording::string *
--
1.7.11.7
Joseph S. Myers
2014-09-24 20:24:34 UTC
Permalink
Post by David Malcolm
The ideal I'm aiming for here is that a well-behaved library should
never abort, so I've rewritten these functions to use vasprintf, and
added error-handling checks to cover the case where malloc returns NULL
within vasprintf.
GCC is designed on the basis of aborting on allocation failures - as is
GMP, which allows custom allocation functions to be specified but still
requires them to exit the program rather than return, longjmp or throw an
exception.
Post by David Malcolm
I believe this fixes the specific issues you pointed out (apart from the
numerous missing API comments, which I'll do it a followup). Note that
there's still a fixed-size buffer within gcc::jit::recording::context,
char m_first_error_str[1024];
Currently this is populated using strncpy followed by an explicit write
of a truncation byte to make sure, but it *is* another truncation.
Presumably I should address this in a followup, by making that be
dynamically-allocated?
Yes. Arbitrary limits should be avoided in GNU.
--
Joseph S. Myers
joseph-***@public.gmane.org
Jeff Law
2014-09-25 04:04:14 UTC
Permalink
Post by Joseph S. Myers
Post by David Malcolm
The ideal I'm aiming for here is that a well-behaved library should
never abort, so I've rewritten these functions to use vasprintf, and
added error-handling checks to cover the case where malloc returns NULL
within vasprintf.
GCC is designed on the basis of aborting on allocation failures - as is
GMP, which allows custom allocation functions to be specified but still
requires them to exit the program rather than return, longjmp or throw an
exception.
But that may be something we need to change if GCC is going to be used
at a JIT in the future. Yea, we'll still have problems of this nature
in libraries that GCC itself might use such as gmp, but that doesn't
mean that we have to perpetuate that practice in GCC itself.
Post by Joseph S. Myers
Post by David Malcolm
Presumably I should address this in a followup, by making that be
dynamically-allocated?
Yes. Arbitrary limits should be avoided in GNU.
Agreed.

jeff
David Malcolm
2014-09-26 14:25:25 UTC
Permalink
Post by Jeff Law
Post by Joseph S. Myers
Post by David Malcolm
The ideal I'm aiming for here is that a well-behaved library should
never abort, so I've rewritten these functions to use vasprintf, and
added error-handling checks to cover the case where malloc returns NULL
within vasprintf.
GCC is designed on the basis of aborting on allocation failures - as is
GMP, which allows custom allocation functions to be specified but still
requires them to exit the program rather than return, longjmp or throw an
exception.
But that may be something we need to change if GCC is going to be used
at a JIT in the future. Yea, we'll still have problems of this nature
in libraries that GCC itself might use such as gmp, but that doesn't
mean that we have to perpetuate that practice in GCC itself.
Post by Joseph S. Myers
Post by David Malcolm
Presumably I should address this in a followup, by making that be
dynamically-allocated?
Yes. Arbitrary limits should be avoided in GNU.
Agreed.
Fixed in the following; committed to branch dmalcolm/jit:

This removes the truncation of overlong error messages in
gcc::jit::recording::context::add_error_va
ensuring that API entrypoint gcc_jit_context_get_first_error reports
them without truncation.

gcc/jit/ChangeLog.jit:
* internal-api.h (gcc::jit::recording::context): Convert field
"m_first_error_str" from a fixed-size buffer to a pointer, and add
a field "m_owns_first_error_str" to determine if we're responsible
for freeing it.
* internal-api.c (gcc::jit::recording::context::context): Update
initializations in ctor for above change.
(gcc::jit::recording::context::~context): Free m_first_error_str
if we own it.
(gcc::jit::recording::context::add_error_va): When capturing the
first error message on a context, rather than copying "errmsg" to
a fixed-size buffer and truncating if oversize, simply store the
pointer to the error message, and flag whether we need to free it.
(gcc::jit::recording::context::get_first_error): Update for change
of "m_first_error_str" from an internal buffer to a pointer.
---
gcc/jit/ChangeLog.jit | 17 +++++++++++++++++
gcc/jit/internal-api.c | 32 ++++++++++++++++++++------------
gcc/jit/internal-api.h | 4 +++-
3 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 9cbba20..ac8f28d 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,20 @@
+2014-09-26 David Malcolm <***@redhat.com>
+
+ * internal-api.h (gcc::jit::recording::context): Convert field
+ "m_first_error_str" from a fixed-size buffer to a pointer, and add
+ a field "m_owns_first_error_str" to determine if we're responsible
+ for freeing it.
+ * internal-api.c (gcc::jit::recording::context::context): Update
+ initializations in ctor for above change.
+ (gcc::jit::recording::context::~context): Free m_first_error_str
+ if we own it.
+ (gcc::jit::recording::context::add_error_va): When capturing the
+ first error message on a context, rather than copying "errmsg" to
+ a fixed-size buffer and truncating if oversize, simply store the
+ pointer to the error message, and flag whether we need to free it.
+ (gcc::jit::recording::context::get_first_error): Update for change
+ of "m_first_error_str" from an internal buffer to a pointer.
+
2014-09-25 David Malcolm <***@redhat.com>

* internal-api.c (gcc::jit::playback::context::compile): Use
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 05ef544..8ef9af9 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -188,14 +188,14 @@ recording::playback_block (recording::block *b)
recording::context::context (context *parent_ctxt)
: m_parent_ctxt (parent_ctxt),
m_error_count (0),
+ m_first_error_str (NULL),
+ m_owns_first_error_str (false),
m_mementos (),
m_compound_types (),
m_functions (),
m_FILE_type (NULL),
m_builtins_manager(NULL)
{
- m_first_error_str[0] = '\0';
-
if (parent_ctxt)
{
/* Inherit options from parent.
@@ -234,6 +234,9 @@ recording::context::~context ()

if (m_builtins_manager)
delete m_builtins_manager;
+
+ if (m_owns_first_error_str)
+ free (m_first_error_str);
}

/* Add the given mememto to the list of those tracked by this
@@ -901,12 +904,19 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
{
char *malloced_msg;
const char *errmsg;
+ bool has_ownership;

vasprintf (&malloced_msg, fmt, ap);
if (malloced_msg)
- errmsg = malloced_msg;
+ {
+ errmsg = malloced_msg;
+ has_ownership = true;
+ }
else
- errmsg = "out of memory generating error message";
+ {
+ errmsg = "out of memory generating error message";
+ has_ownership = false;
+ }

const char *ctxt_progname =
get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
@@ -925,13 +935,14 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)

if (!m_error_count)
{
- strncpy (m_first_error_str, errmsg, sizeof(m_first_error_str));
- m_first_error_str[sizeof(m_first_error_str) - 1] = '\0';
+ m_first_error_str = const_cast <char *> (errmsg);
+ m_owns_first_error_str = has_ownership;
}
+ else
+ if (has_ownership)
+ free (malloced_msg);

m_error_count++;
-
- free (malloced_msg);
}

/* Get the message for the first error that occurred on this context, or
@@ -943,10 +954,7 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
const char *
recording::context::get_first_error () const
{
- if (m_error_count)
- return m_first_error_str;
- else
- return NULL;
+ return m_first_error_str;
}

/* Lazily generate and record a recording::type representing an opaque
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 4603f21..474e7d7 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -378,7 +378,9 @@ private:
context *m_parent_ctxt;

int m_error_count;
- char m_first_error_str[1024];
+
+ char *m_first_error_str;
+ bool m_owns_first_error_str;

const char *m_str_options[GCC_JIT_NUM_STR_OPTIONS];
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
--
1.7.11.7
David Malcolm
2014-09-25 00:58:27 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
missing API comments (lots of functions are missing such comments ...) to
[...]

The following commit adds numerous API comments throughout
internal-api.c and jit-builtins.c. I also renamed some globals to give
them "jit_" prefixes.

Committed to branch dmalcolm/jit:

gcc/jit/ChangeLog.jit:
* dummy-frontend.c (my_walker): Rename to...
(my_ggc_walker): ...this.
(my_root_tab): Rename to...
(jit_root_tab): ...this.
(jit_langhook_init): Update for renaming of "my_root_tab" to
"jit_root_tab".
* internal-api.c: Add descriptive API comments to functions
throughout.
(mutex): Rename to...
(jit_mutex): ...this.
(gcc::jit::recording::context::compile): Update for renaming of
"mutex" to "jit_mutex".
* internal-api.h: Add descriptive API comments to functions
throughout. Add indentation to forward declarations of classes
to indicate inheritance.
* jit-builtins.c: Likewise.
---
gcc/jit/ChangeLog.jit | 19 +
gcc/jit/dummy-frontend.c | 13 +-
gcc/jit/internal-api.c | 1100 ++++++++++++++++++++++++++++++++++++++++++++--
gcc/jit/internal-api.h | 79 ++--
gcc/jit/jit-builtins.c | 28 ++
5 files changed, 1169 insertions(+), 70 deletions(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index 3cadaab..3b33e0d 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,24 @@
2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>

+ * dummy-frontend.c (my_walker): Rename to...
+ (my_ggc_walker): ...this.
+ (my_root_tab): Rename to...
+ (jit_root_tab): ...this.
+ (jit_langhook_init): Update for renaming of "my_root_tab" to
+ "jit_root_tab".
+ * internal-api.c: Add descriptive API comments to functions
+ throughout.
+ (mutex): Rename to...
+ (jit_mutex): ...this.
+ (gcc::jit::recording::context::compile): Update for renaming of
+ "mutex" to "jit_mutex".
+ * internal-api.h: Add descriptive API comments to functions
+ throughout. Add indentation to forward declarations of classes
+ to indicate inheritance.
+ * jit-builtins.c: Likewise.
+
+2014-09-24 David Malcolm <dmalcolm-H+wXaHxf7aLQT0dZR+***@public.gmane.org>
+
* internal-api.c (gcc::jit::dump::write): Eliminate fixed-size
buffer "buf" by replacing call to vsnprintf with one to vasprintf
and a free, emitting an error on the dump's context if a malloc
diff --git a/gcc/jit/dummy-frontend.c b/gcc/jit/dummy-frontend.c
index 1d178f9..eb91191 100644
--- a/gcc/jit/dummy-frontend.c
+++ b/gcc/jit/dummy-frontend.c
@@ -79,7 +79,12 @@ struct GTY(()) language_function
int dummy;
};

-void my_walker (void *)
+/* GC-marking callback for use from jit_root_tab.
+
+ If there's an active playback context, call its marking method
+ so that it can mark any pointers it references. */
+
+static void my_ggc_walker (void *)
{
if (gcc::jit::active_playback_ctxt)
gcc::jit::active_playback_ctxt->gt_ggc_mx ();
@@ -87,10 +92,10 @@ void my_walker (void *)

const char *dummy;

-struct ggc_root_tab my_root_tab[] =
+struct ggc_root_tab jit_root_tab[] =
{
{
- &dummy, 1, 0, my_walker, NULL
+ &dummy, 1, 0, my_ggc_walker, NULL
},
LAST_GGC_ROOT_TAB
};
@@ -106,7 +111,7 @@ jit_langhook_init (void)
static bool registered_root_tab = false;
if (!registered_root_tab)
{
- ggc_register_root_tab (my_root_tab);
+ ggc_register_root_tab (jit_root_tab);
registered_root_tab = true;
}

diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 15e9f81..32fe7cb 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -92,6 +92,11 @@ dump::~dump ()
fclose (m_file);
}

+/* Write the given message to the dump, using printf-formatting
+ conventions, updating the line/column within the dump.
+
+ Emit an error on the context if a failure occurs. */
+
void
dump::write (const char *fmt, ...)
{
@@ -126,6 +131,9 @@ dump::write (const char *fmt, ...)
free (buf);
}

+/* Construct a gcc::jit::recording::location instance for the current
+ location within the dump. */
+
recording::location *
dump::make_location () const
{
@@ -136,6 +144,9 @@ dump::make_location () const
Recording.
**********************************************************************/

+/* Get the playback::location for the given recording::location,
+ handling a NULL input with a NULL output. */
+
playback::location *
recording::playback_location (replayer *r, recording::location *loc)
{
@@ -145,6 +156,9 @@ recording::playback_location (replayer *r, recording::location *loc)
return NULL;
}

+/* Get a const char * for the given recording::string
+ handling a NULL input with a NULL output. */
+
const char *
recording::playback_string (recording::string *str)
{
@@ -154,6 +168,9 @@ recording::playback_string (recording::string *str)
return NULL;
}

+/* Get the playback::block for the given recording::block,
+ handling a NULL input with a NULL output. */
+
playback::block *
recording::playback_block (recording::block *b)
{
@@ -163,7 +180,10 @@ recording::playback_block (recording::block *b)
return NULL;
}

-/* gcc::jit::recording::context:: */
+/* Methods of cc::jit::recording::context. */
+
+/* The constructor for gcc::jit::recording::context, used by
+ gcc_jit_context_acquire and gcc_jit_context_new_child_context. */

recording::context::context (context *parent_ctxt)
: m_parent_ctxt (parent_ctxt),
@@ -200,6 +220,9 @@ recording::context::context (context *parent_ctxt)
memset (m_basic_types, 0, sizeof (m_basic_types));
}

+/* The destructor for gcc::jit::recording::context, implicitly used by
+ gcc_jit_context_release. */
+
recording::context::~context ()
{
int i;
@@ -213,6 +236,10 @@ recording::context::~context ()
delete m_builtins_manager;
}

+/* Add the given mememto to the list of those tracked by this
+ gcc::jit::recording::context, so that e.g. it can be deleted
+ when this context is released. */
+
void
recording::context::record (memento *m)
{
@@ -221,6 +248,8 @@ recording::context::record (memento *m)
m_mementos.safe_push (m);
}

+/* Replay this context (and any parents) into the given replayer. */
+
void
recording::context::replay_into (replayer *r)
{
@@ -293,6 +322,11 @@ recording::context::disassociate_from_playback ()
}
}

+/* Create a recording::string instance and add it to this context's list
+ of mementos.
+
+ This creates a fresh copy of the given 0-terminated buffer. */
+
recording::string *
recording::context::new_string (const char *text)
{
@@ -304,6 +338,12 @@ recording::context::new_string (const char *text)
return result;
}

+/* Create a recording::location instance and add it to this context's
+ list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_location. */
+
recording::location *
recording::context::new_location (const char *filename,
int line,
@@ -317,14 +357,23 @@ recording::context::new_location (const char *filename,
return result;
}

+/* If we haven't seen this enum value yet, create a recording::type
+ instance and add it to this context's list of mementos.
+
+ If we have seen it before, reuse our cached value, so that repeated
+ calls on the context give the same object.
+
+ If we have a parent context, the cache is within the ultimate
+ ancestor context.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_type. */
+
recording::type *
recording::context::get_type (enum gcc_jit_types kind)
{
- /* Cache and reuse the types, so that repeated calls on the context
- give the same object. */
if (!m_basic_types[kind])
{
- /* For basic types, use them from the parent ctxt. */
if (m_parent_ctxt)
m_basic_types[kind] = m_parent_ctxt->get_type (kind);
else
@@ -338,6 +387,13 @@ recording::context::get_type (enum gcc_jit_types kind)
return m_basic_types[kind];
}

+/* Get a recording::type instance for the given size and signedness.
+ This is implemented in terms of recording::context::get_type
+ above.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_int_type. */
+
recording::type *
recording::context::get_int_type (int num_bytes, int is_signed)
{
@@ -375,6 +431,12 @@ recording::context::get_int_type (int num_bytes, int is_signed)
gcc_unreachable ();
}

+/* Create a recording::type instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_array_type. */
+
recording::type *
recording::context::new_array_type (recording::location *loc,
recording::type *element_type,
@@ -395,6 +457,12 @@ recording::context::new_array_type (recording::location *loc,
return result;
}

+/* Create a recording::field instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_field. */
+
recording::field *
recording::context::new_field (recording::location *loc,
recording::type *type,
@@ -406,6 +474,12 @@ recording::context::new_field (recording::location *loc,
return result;
}

+/* Create a recording::struct_ instance and add it to this context's
+ list of mementos and list of compound types.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_struct_type. */
+
recording::struct_ *
recording::context::new_struct_type (recording::location *loc,
const char *name)
@@ -416,6 +490,12 @@ recording::context::new_struct_type (recording::location *loc,
return result;
}

+/* Create a recording::union_ instance and add it to this context's
+ list of mementos and list of compound types.
+
+ Implements the first post-error-checking part of
+ gcc_jit_context_new_union_type. */
+
recording::union_ *
recording::context::new_union_type (recording::location *loc,
const char *name)
@@ -426,6 +506,12 @@ recording::context::new_union_type (recording::location *loc,
return result;
}

+/* Create a recording::type instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_function_ptr_type. */
+
recording::type *
recording::context::new_function_ptr_type (recording::location *, /* unused loc */
recording::type *return_type,
@@ -445,6 +531,12 @@ recording::context::new_function_ptr_type (recording::location *, /* unused loc
return fn_type->get_pointer ();
}

+/* Create a recording::param instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_param. */
+
recording::param *
recording::context::new_param (recording::location *loc,
recording::type *type,
@@ -455,6 +547,12 @@ recording::context::new_param (recording::location *loc,
return result;
}

+/* Create a recording::function instance and add it to this context's list
+ of mementos and list of functions.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_function. */
+
recording::function *
recording::context::new_function (recording::location *loc,
enum gcc_jit_function_kind kind,
@@ -477,6 +575,12 @@ recording::context::new_function (recording::location *loc,
return result;
}

+/* Get a recording::function instance, which is lazily-created and added
+ to the context's lists of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_builtin_function. */
+
recording::function *
recording::context::get_builtin_function (const char *name)
{
@@ -485,6 +589,12 @@ recording::context::get_builtin_function (const char *name)
return m_builtins_manager->get_builtin_function (name);
}

+/* Create a recording::global instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_global. */
+
recording::lvalue *
recording::context::new_global (recording::location *loc,
recording::type *type,
@@ -496,6 +606,12 @@ recording::context::new_global (recording::location *loc,
return result;
}

+/* Create a recording::memento_of_new_rvalue_from_int instance and add
+ it to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_int. */
+
recording::rvalue *
recording::context::new_rvalue_from_int (recording::type *type,
int value)
@@ -506,6 +622,12 @@ recording::context::new_rvalue_from_int (recording::type *type,
return result;
}

+/* Create a recording::memento_of_new_rvalue_from_double instance and
+ add it to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_double. */
+
recording::rvalue *
recording::context::new_rvalue_from_double (recording::type *type,
double value)
@@ -516,6 +638,12 @@ recording::context::new_rvalue_from_double (recording::type *type,
return result;
}

+/* Create a recording::memento_of_new_rvalue_from_ptr instance and add
+ it to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_rvalue_from_ptr. */
+
recording::rvalue *
recording::context::new_rvalue_from_ptr (recording::type *type,
void *value)
@@ -526,6 +654,12 @@ recording::context::new_rvalue_from_ptr (recording::type *type,
return result;
}

+/* Create a recording::memento_of_new_string_literal instance and add it
+ to this context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_string_literal. */
+
recording::rvalue *
recording::context::new_string_literal (const char *value)
{
@@ -535,6 +669,12 @@ recording::context::new_string_literal (const char *value)
return result;
}

+/* Create a recording::unary_op instance and add it to this context's
+ list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_unary_op. */
+
recording::rvalue *
recording::context::new_unary_op (recording::location *loc,
enum gcc_jit_unary_op op,
@@ -547,6 +687,12 @@ recording::context::new_unary_op (recording::location *loc,
return result;
}

+/* Create a recording::binary_op instance and add it to this context's
+ list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_binary_op. */
+
recording::rvalue *
recording::context::new_binary_op (recording::location *loc,
enum gcc_jit_binary_op op,
@@ -560,6 +706,12 @@ recording::context::new_binary_op (recording::location *loc,
return result;
}

+/* Create a recording::comparison instance and add it to this context's
+ list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_comparison. */
+
recording::rvalue *
recording::context::new_comparison (recording::location *loc,
enum gcc_jit_comparison op,
@@ -571,6 +723,12 @@ recording::context::new_comparison (recording::location *loc,
return result;
}

+/* Create a recording::cast instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_cast. */
+
recording::rvalue *
recording::context::new_cast (recording::location *loc,
recording::rvalue *expr,
@@ -581,6 +739,12 @@ recording::context::new_cast (recording::location *loc,
return result;
}

+/* Create a recording::call instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_call. */
+
recording::rvalue *
recording::context::new_call (recording::location *loc,
function *func,
@@ -591,6 +755,12 @@ recording::context::new_call (recording::location *loc,
return result;
}

+/* Create a recording::call_through_ptr instance and add it to this
+ context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_call_through_ptr. */
+
recording::rvalue *
recording::context::new_call_through_ptr (recording::location *loc,
recording::rvalue *fn_ptr,
@@ -602,6 +772,12 @@ recording::context::new_call_through_ptr (recording::location *loc,
return result;
}

+/* Create a recording::array_access instance and add it to this context's list
+ of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_new_array_access. */
+
recording::lvalue *
recording::context::new_array_access (recording::location *loc,
recording::rvalue *ptr,
@@ -612,6 +788,12 @@ recording::context::new_array_access (recording::location *loc,
return result;
}

+/* Set the given string option for this context, or add an error if
+ it's not recognized.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_set_str_option. */
+
void
recording::context::set_str_option (enum gcc_jit_str_option opt,
const char *value)
@@ -625,6 +807,12 @@ recording::context::set_str_option (enum gcc_jit_str_option opt,
m_str_options[opt] = value;
}

+/* Set the given integer option for this context, or add an error if
+ it's not recognized.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_set_int_option. */
+
void
recording::context::set_int_option (enum gcc_jit_int_option opt,
int value)
@@ -638,6 +826,12 @@ recording::context::set_int_option (enum gcc_jit_int_option opt,
m_int_options[opt] = value;
}

+/* Set the given boolean option for this context, or add an error if
+ it's not recognized.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_set_bool_option. */
+
void
recording::context::set_bool_option (enum gcc_jit_bool_option opt,
int value)
@@ -651,7 +845,16 @@ recording::context::set_bool_option (enum gcc_jit_bool_option opt,
m_bool_options[opt] = value ? true : false;
}

-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+/* This mutex guards gcc::jit::recording::context::compile, so that only
+ one thread can be accessing the bulk of GCC's state at once. */
+
+static pthread_mutex_t jit_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Validate this context, and if it passes, compile it within a
+ mutex.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_compile. */

result *
recording::context::compile ()
@@ -662,7 +865,7 @@ recording::context::compile ()
return NULL;

/* Acquire the big GCC mutex. */
- pthread_mutex_lock (&mutex);
+ pthread_mutex_lock (&jit_mutex);
gcc_assert (NULL == ::gcc::jit::active_playback_ctxt);

/* Set up a playback context. */
@@ -673,11 +876,14 @@ recording::context::compile ()

/* Release the big GCC mutex. */
::gcc::jit::active_playback_ctxt = NULL;
- pthread_mutex_unlock (&mutex);
+ pthread_mutex_unlock (&jit_mutex);

return result_obj;
}

+/* Format the given error using printf's conventions, print
+ it to stderr, and add it to the context. */
+
void
recording::context::add_error (location *loc, const char *fmt, ...)
{
@@ -687,6 +893,9 @@ recording::context::add_error (location *loc, const char *fmt, ...)
va_end (ap);
}

+/* Format the given error using printf's conventions, print
+ it to stderr, and add it to the context. */
+
void
recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
{
@@ -725,6 +934,12 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
free (malloced_msg);
}

+/* Get the message for the first error that occurred on this context, or
+ NULL if no errors have occurred on it.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_get_first_error. */
+
const char *
recording::context::get_first_error () const
{
@@ -734,6 +949,12 @@ recording::context::get_first_error () const
return NULL;
}

+/* Lazily generate and record a recording::type representing an opaque
+ struct named "FILE".
+
+ For use if client code tries to dereference the result of
+ get_type (GCC_JIT_TYPE_FILE_PTR). */
+
recording::type *
recording::context::get_opaque_FILE_type ()
{
@@ -742,6 +963,13 @@ recording::context::get_opaque_FILE_type ()
return m_FILE_type;
}

+/* Dump a C-like representation of the given context to the given path.
+ If UPDATE_LOCATIONS is true, update the locations within the
+ context's mementos to point to the dumpfile.
+
+ Implements the post-error-checking part of
+ gcc_jit_context_dump_to_file. */
+
void
recording::context::dump_to_file (const char *path, bool update_locations)
{
@@ -770,6 +998,10 @@ recording::context::dump_to_file (const char *path, bool update_locations)
}
}

+/* This is a pre-compilation check for the context (and any parents).
+
+ Detect errors within the context, adding errors if any are found. */
+
void
recording::context::validate ()
{
@@ -782,7 +1014,15 @@ recording::context::validate ()
fn->validate ();
}

-/* gcc::jit::recording::memento:: */
+/* The implementation of class gcc::jit::recording::memento. */
+
+/* Get a (const char *) debug description of the given memento, by
+ calling the pure-virtual make_debug_string hook, caching the
+ result.
+
+ It is intended that this should only be called in debugging and
+ error-handling paths, so this doesn't need to be particularly
+ optimized. */

const char *
recording::memento::get_debug_string ()
@@ -792,13 +1032,20 @@ recording::memento::get_debug_string ()
return m_debug_string->c_str ();
}

+/* Default implementation of recording::memento::write_to_dump, writing
+ an indented form of the memento's debug string to the dump. */
+
void
recording::memento::write_to_dump (dump &d)
{
d.write(" %s\n", get_debug_string ());
}

-/* gcc::jit::recording::string:: */
+/* The implementation of class gcc::jit::recording::string. */
+
+/* Constructor for gcc::jit::recording::string::string, allocating a
+ copy of the given text using new char[]. */
+
recording::string::string (context *ctxt, const char *text)
: memento (ctxt)
{
@@ -807,11 +1054,20 @@ recording::string::string (context *ctxt, const char *text)
strcpy (m_buffer, text);
}

+/* Destructor for gcc::jit::recording::string::string. */
+
recording::string::~string ()
{
delete[] m_buffer;
}

+/* Function for making gcc::jit::recording::string instances on a
+ context via printf-style formatting.
+
+ It is intended that this should only be called in debugging and
+ error-handling paths, so this doesn't need to be particularly
+ optimized, hence the double-copy of the string is acceptable. */
+
recording::string *
recording::string::from_printf (context *ctxt, const char *fmt, ...)
{
@@ -834,6 +1090,9 @@ recording::string::from_printf (context *ctxt, const char *fmt, ...)
return result;
}

+/* Implementation of recording::memento::make_debug_string for strings,
+ wrapping the given string in quotes and escaping as necessary. */
+
recording::string *
recording::string::make_debug_string ()
{
@@ -870,7 +1129,13 @@ recording::string::make_debug_string ()
return result;
}

-/* gcc::jit::recording::location:: */
+/* The implementation of class gcc::jit::recording::location. */
+
+/* Implementation of recording::memento::replay_into for locations.
+
+ Create a new playback::location and store it into the
+ recording::location's m_playback_obj field. */
+
void
recording::location::replay_into (replayer *r)
{
@@ -880,6 +1145,11 @@ recording::location::replay_into (replayer *r)
m_column);
}

+/* Implementation of recording::memento::make_debug_string for locations,
+ turning them into the usual form:
+ FILENAME:LINE:COLUMN
+ like we do when emitting diagnostics. */
+
recording::string *
recording::location::make_debug_string ()
{
@@ -888,7 +1158,17 @@ recording::location::make_debug_string ()
m_filename->c_str (), m_line, m_column);
}

-/* gcc::jit::recording::type:: */
+/* The implementation of class gcc::jit::recording::type. */
+
+/* Given a type T, get the type T*.
+
+ If this doesn't already exist, generate a new memento_of_get_pointer
+ instance and add it to this type's context's list of mementos.
+
+ Otherwise, use the cached type.
+
+ Implements the post-error-checking part of
+ gcc_jit_type_get_pointer. */

recording::type *
recording::type::get_pointer ()
@@ -901,6 +1181,11 @@ recording::type::get_pointer ()
return m_pointer_to_this_type;
}

+/* Given a type T, get the type const T.
+
+ Implements the post-error-checking part of
+ gcc_jit_type_get_const. */
+
recording::type *
recording::type::get_const ()
{
@@ -909,6 +1194,11 @@ recording::type::get_const ()
return result;
}

+/* Given a type T, get the type volatile T.
+
+ Implements the post-error-checking part of
+ gcc_jit_type_get_volatile. */
+
recording::type *
recording::type::get_volatile ()
{
@@ -917,6 +1207,9 @@ recording::type::get_volatile ()
return result;
}

+/* Implementation of pure virtual hook recording::type::dereference for
+ recording::memento_of_get_type. */
+
recording::type *
recording::memento_of_get_type::dereference ()
{
@@ -961,6 +1254,9 @@ recording::memento_of_get_type::dereference ()
}
}

+/* Implementation of pure virtual hook recording::type::is_int for
+ recording::memento_of_get_type. */
+
bool
recording::memento_of_get_type::is_int () const
{
@@ -1006,6 +1302,9 @@ recording::memento_of_get_type::is_int () const
}
}

+/* Implementation of pure virtual hook recording::type::is_float for
+ recording::memento_of_get_type. */
+
bool
recording::memento_of_get_type::is_float () const
{
@@ -1051,6 +1350,9 @@ recording::memento_of_get_type::is_float () const
}
}

+/* Implementation of pure virtual hook recording::type::is_bool for
+ recording::memento_of_get_type. */
+
bool
recording::memento_of_get_type::is_bool () const
{
@@ -1096,13 +1398,19 @@ recording::memento_of_get_type::is_bool () const
}
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_get_type. */
+
void
recording::memento_of_get_type::replay_into (replayer *r)
{
set_playback_obj (r->get_type (m_kind));
}

-/* gcc::jit::recording::memento_of_get_type:: */
+/* The implementation of class gcc::jit::recording::memento_of_get_type. */
+
+/* Descriptive strings for each of enum gcc_jit_types. */
+
static const char * const get_type_strings[] = {
"void", /* GCC_JIT_TYPE_VOID */
"void *", /* GCC_JIT_TYPE_VOID_PTR */
@@ -1137,13 +1445,23 @@ static const char * const get_type_strings[] = {

};

+/* Implementation of recording::memento::make_debug_string for
+ results of get_type, using a simple table of type names. */
+
recording::string *
recording::memento_of_get_type::make_debug_string ()
{
return m_ctxt->new_string (get_type_strings[m_kind]);
}

-/* gcc::jit::recording::memento_of_get_pointer:: */
+/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
+
+/* Override of default implementation of
+ recording::type::accepts_writes_from for get_pointer.
+
+ Require a pointer type, and allowing writes to
+ (const T *) from a (T*), but not the other way around. */
+
bool
recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
{
@@ -1157,12 +1475,19 @@ recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
->accepts_writes_from (rtype_points_to);
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_get_pointer. */
+
void
recording::memento_of_get_pointer::replay_into (replayer *)
{
set_playback_obj (m_other_type->playback_type ()->get_pointer ());
}

+/* Implementation of recording::memento::make_debug_string for
+ results of get_pointer, adding " *" to the underlying type,
+ with special-casing to handle function pointer types. */
+
recording::string *
recording::memento_of_get_pointer::make_debug_string ()
{
@@ -1176,7 +1501,10 @@ recording::memento_of_get_pointer::make_debug_string ()
"%s *", m_other_type->get_debug_string ());
}

-/* gcc::jit::recording::memento_of_get_const:: */
+/* The implementation of class gcc::jit::recording::memento_of_get_const. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_get_const. */

void
recording::memento_of_get_const::replay_into (replayer *)
@@ -1184,6 +1512,9 @@ recording::memento_of_get_const::replay_into (replayer *)
set_playback_obj (m_other_type->playback_type ()->get_const ());
}

+/* Implementation of recording::memento::make_debug_string for
+ results of get_const, prepending "const ". */
+
recording::string *
recording::memento_of_get_const::make_debug_string ()
{
@@ -1191,7 +1522,10 @@ recording::memento_of_get_const::make_debug_string ()
"const %s", m_other_type->get_debug_string ());
}

-/* gcc::jit::recording::memento_of_get_volatile:: */
+/* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_get_volatile. */

void
recording::memento_of_get_volatile::replay_into (replayer *)
@@ -1199,6 +1533,9 @@ recording::memento_of_get_volatile::replay_into (replayer *)
set_playback_obj (m_other_type->playback_type ()->get_volatile ());
}

+/* Implementation of recording::memento::make_debug_string for
+ results of get_volatile, prepending "volatile ". */
+
recording::string *
recording::memento_of_get_volatile::make_debug_string ()
{
@@ -1206,7 +1543,10 @@ recording::memento_of_get_volatile::make_debug_string ()
"volatile %s", m_other_type->get_debug_string ());
}

-/* gcc::jit::recording::array_type */
+/* The implementation of class gcc::jit::recording::array_type */
+
+/* Implementation of pure virtual hook recording::type::dereference for
+ recording::array_type. */

recording::type *
recording::array_type::dereference ()
@@ -1214,6 +1554,9 @@ recording::array_type::dereference ()
return m_element_type;
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::array_type. */
+
void
recording::array_type::replay_into (replayer *r)
{
@@ -1222,6 +1565,9 @@ recording::array_type::replay_into (replayer *r)
m_num_elements));
}

+/* Implementation of recording::memento::make_debug_string for
+ results of new_array_type. */
+
recording::string *
recording::array_type::make_debug_string ()
{
@@ -1231,7 +1577,10 @@ recording::array_type::make_debug_string ()
m_num_elements);
}

-/* gcc::jit::recording::function_type */
+/* The implementation of class gcc::jit::recording::function_type */
+
+/* Constructor for gcc::jit::recording::function_type. */
+
recording::function_type::function_type (context *ctxt,
type *return_type,
int num_params,
@@ -1246,12 +1595,18 @@ recording::function_type::function_type (context *ctxt,
m_param_types.safe_push (param_types[i]);
}

+/* Implementation of pure virtual hook recording::type::dereference for
+ recording::function_type. */
+
recording::type *
recording::function_type::dereference ()
{
return NULL;
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::function_type. */
+
void
recording::function_type::replay_into (replayer *r)
{
@@ -1268,18 +1623,31 @@ recording::function_type::replay_into (replayer *r)
m_is_variadic));
}

+/* Special-casing for make_debug_string for get_pointer results for
+ handling (one level) of pointers to functions. */
+
recording::string *
recording::function_type::make_debug_string_with_ptr ()
{
return make_debug_string_with ("(*) ");
}

+/* Implementation of recording::memento::make_debug_string for
+ results of new_function_type. */
+
recording::string *
recording::function_type::make_debug_string ()
{
return make_debug_string_with ("");
}

+/* Build a debug string representation of the form:
+
+ RESULT_TYPE INSERT (PARAM_TYPES)
+
+ for use when handling 0 and 1 level of indirection to this
+ function type. */
+
recording::string *
recording::function_type::make_debug_string_with (const char *insert)
{
@@ -1332,7 +1700,11 @@ recording::function_type::make_debug_string_with (const char *insert)
return result;
}

-/* gcc::jit::recording::field:: */
+/* The implementation of class gcc::jit::recording::field. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::field. */
+
void
recording::field::replay_into (replayer *r)
{
@@ -1341,6 +1713,12 @@ recording::field::replay_into (replayer *r)
playback_string (m_name)));
}

+/* Override the default implementation of
+ recording::memento::write_to_dump. Dump each field
+ by dumping a line of the form:
+ TYPE NAME;
+ so that we can build up a struct/union field-byfield. */
+
void
recording::field::write_to_dump (dump &d)
{
@@ -1349,13 +1727,19 @@ recording::field::write_to_dump (dump &d)
m_name->c_str ());
}

+/* Implementation of recording::memento::make_debug_string for
+ results of new_field. */
+
recording::string *
recording::field::make_debug_string ()
{
return m_name;
}

-/* gcc::jit::recording::compound_type */
+/* The implementation of class gcc::jit::recording::compound_type */
+
+/* The constructor for gcc::jit::recording::compound_type. */
+
recording::compound_type::compound_type (context *ctxt,
location *loc,
string *name)
@@ -1366,6 +1750,12 @@ recording::compound_type::compound_type (context *ctxt,
{
}

+/* Set the fields of a compound type.
+
+ Implements the post-error-checking part of
+ gcc_jit_struct_set_fields, and is also used by
+ gcc_jit_context_new_union_type. */
+
void
recording::compound_type::set_fields (location *loc,
int num_fields,
@@ -1378,13 +1768,19 @@ recording::compound_type::set_fields (location *loc,
m_ctxt->record (m_fields);
}

+/* Implementation of pure virtual hook recording::type::dereference for
+ recording::compound_type. */
+
recording::type *
recording::compound_type::dereference ()
{
return NULL; /* not a pointer */
}

-/* gcc::jit::recording::struct_:: */
+/* The implementation of class gcc::jit::recording::struct_. */
+
+/* The constructor for gcc::jit::recording::struct_. */
+
recording::struct_::struct_ (context *ctxt,
location *loc,
string *name)
@@ -1392,6 +1788,9 @@ recording::struct_::struct_ (context *ctxt,
{
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::struct_. */
+
void
recording::struct_::replay_into (replayer *r)
{
@@ -1401,6 +1800,9 @@ recording::struct_::replay_into (replayer *r)
true /* is_struct */));
}

+/* Implementation of recording::memento::make_debug_string for
+ structs. */
+
recording::string *
recording::struct_::make_debug_string ()
{
@@ -1408,7 +1810,10 @@ recording::struct_::make_debug_string ()
"struct %s", get_name ()->c_str ());
}

-/* gcc::jit::recording::union_:: */
+/* The implementation of class gcc::jit::recording::union_. */
+
+/* The constructor for gcc::jit::recording::union_. */
+
recording::union_::union_ (context *ctxt,
location *loc,
string *name)
@@ -1416,6 +1821,9 @@ recording::union_::union_ (context *ctxt,
{
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::union_. */
+
void
recording::union_::replay_into (replayer *r)
{
@@ -1425,6 +1833,9 @@ recording::union_::replay_into (replayer *r)
false /* is_struct */));
}

+/* Implementation of recording::memento::make_debug_string for
+ unions. */
+
recording::string *
recording::union_::make_debug_string ()
{
@@ -1432,7 +1843,10 @@ recording::union_::make_debug_string ()
"union %s", get_name ()->c_str ());
}

-/* gcc::jit::recording::fields:: */
+/* The implementation of class gcc::jit::recording::fields. */
+
+/* The constructor for gcc::jit::recording::fields. */
+
recording::fields::fields (compound_type *struct_or_union,
int num_fields,
field **fields)
@@ -1448,6 +1862,9 @@ recording::fields::fields (compound_type *struct_or_union,
}
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::fields. */
+
void
recording::fields::replay_into (replayer *)
{
@@ -1458,6 +1875,19 @@ recording::fields::replay_into (replayer *)
m_struct_or_union->playback_compound_type ()->set_fields (playback_fields);
}

+/* Override the default implementation of
+ recording::memento::write_to_dump by writing a union/struct
+ declaration of this form:
+
+ struct/union NAME {
+ TYPE_1 NAME_1;
+ TYPE_2 NAME_2;
+ ....
+ TYPE_N NAME_N;
+ };
+
+ to the dump. */
+
void
recording::fields::write_to_dump (dump &d)
{
@@ -1470,6 +1900,9 @@ recording::fields::write_to_dump (dump &d)
d.write ("};\n");
}

+/* Implementation of recording::memento::make_debug_string for
+ field tables. */
+
recording::string *
recording::fields::make_debug_string ()
{
@@ -1477,7 +1910,13 @@ recording::fields::make_debug_string ()
"fields");
}

-/* gcc::jit::recording::rvalue:: */
+/* The implementation of class gcc::jit::recording::rvalue. */
+
+/* Create a recording::access_field_rvalue instance and add it to
+ the rvalue's context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_rvalue_access_field. */

recording::rvalue *
recording::rvalue::access_field (recording::location *loc,
@@ -1489,6 +1928,12 @@ recording::rvalue::access_field (recording::location *loc,
return result;
}

+/* Create a recording::dereference_field_rvalue instance and add it to
+ the rvalue's context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_rvalue_dereference_field. */
+
recording::lvalue *
recording::rvalue::dereference_field (recording::location *loc,
field *field)
@@ -1499,6 +1944,12 @@ recording::rvalue::dereference_field (recording::location *loc,
return result;
}

+/* Create a recording::dereference_rvalue instance and add it to the
+ rvalue's context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_rvalue_dereference. */
+
recording::lvalue *
recording::rvalue::dereference (recording::location *loc)
{
@@ -1508,7 +1959,13 @@ recording::rvalue::dereference (recording::location *loc)
return result;
}

-/* gcc::jit::recording::lvalue:: */
+/* The implementation of class gcc::jit::recording::lvalue. */
+
+/* Create a recording::new_access_field_of_lvalue instance and add it to
+ the lvalue's context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_lvalue_access_field. */

recording::lvalue *
recording::lvalue::access_field (recording::location *loc,
@@ -1520,6 +1977,12 @@ recording::lvalue::access_field (recording::location *loc,
return result;
}

+/* Create a recording::get_address_of_lvalue instance and add it to
+ the lvalue's context's list of mementos.
+
+ Implements the post-error-checking part of
+ gcc_jit_lvalue_get_address. */
+
recording::rvalue *
recording::lvalue::get_address (recording::location *loc)
{
@@ -1529,7 +1992,11 @@ recording::lvalue::get_address (recording::location *loc)
return result;
}

-/* gcc::jit::recording::param:: */
+/* The implementation of class gcc::jit::recording::param. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::param. */
+
void
recording::param::replay_into (replayer *r)
{
@@ -1539,7 +2006,9 @@ recording::param::replay_into (replayer *r)
}


-/* gcc::jit::recording::function:: */
+/* The implementation of class gcc::jit::recording::function. */
+
+/* gcc::jit::recording::function's constructor. */

recording::function::function (context *ctxt,
recording::location *loc,
@@ -1565,6 +2034,9 @@ recording::function::function (context *ctxt,
m_params.safe_push (params[i]);
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::function. */
+
void
recording::function::replay_into (replayer *r)
{
@@ -1585,10 +2057,17 @@ recording::function::replay_into (replayer *r)
m_builtin_id));
}

+/* Create a recording::local instance and add it to
+ the functions's context's list of mementos, and to the function's
+ list of locals.
+
+ Implements the post-error-checking part of
+ gcc_jit_function_new_local. */
+
recording::lvalue *
recording::function::new_local (recording::location *loc,
- type *type,
- const char *name)
+ type *type,
+ const char *name)
{
local *result = new local (this, loc, type, new_string (name));
m_ctxt->record (result);
@@ -1596,6 +2075,13 @@ recording::function::new_local (recording::location *loc,
return result;
}

+/* Create a recording::block instance and add it to
+ the functions's context's list of mementos, and to the function's
+ list of blocks.
+
+ Implements the post-error-checking part of
+ gcc_jit_function_new_block. */
+
recording::block*
recording::function::new_block (const char *name)
{
@@ -1608,6 +2094,12 @@ recording::function::new_block (const char *name)
return result;
}

+/* Override the default implementation of
+ recording::memento::write_to_dump by dumping a C-like
+ representation of the function; either like a prototype
+ for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
+ all other kinds of function. */
+
void
recording::function::write_to_dump (dump &d)
{
@@ -1672,6 +2164,9 @@ recording::function::write_to_dump (dump &d)
}
}

+/* Pre-compilation validation of a function, for those things we can't
+ check until the context is (supposedly) fully-populated. */
+
void
recording::function::validate ()
{
@@ -1743,6 +2238,9 @@ recording::function::validate ()
}
}

+/* Implements the post-error-checking part of
+ gcc_jit_function_dump_to_dot. */
+
void
recording::function::dump_to_dot (const char *path)
{
@@ -1779,13 +2277,23 @@ recording::function::dump_to_dot (const char *path)
fclose (fp);
}

+/* Implementation of recording::memento::make_debug_string for
+ functions. */
+
recording::string *
recording::function::make_debug_string ()
{
return m_name;
}

-/* gcc::jit::recording::block:: */
+/* The implementation of class gcc::jit::recording::block. */
+
+/* Create a recording::eval instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_add_eval. */

void
recording::block::add_eval (recording::location *loc,
@@ -1796,6 +2304,13 @@ recording::block::add_eval (recording::location *loc,
m_statements.safe_push (result);
}

+/* Create a recording::assignment instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_add_assignment. */
+
void
recording::block::add_assignment (recording::location *loc,
recording::lvalue *lvalue,
@@ -1806,6 +2321,13 @@ recording::block::add_assignment (recording::location *loc,
m_statements.safe_push (result);
}

+/* Create a recording::assignment_op instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_add_assignment_op. */
+
void
recording::block::add_assignment_op (recording::location *loc,
recording::lvalue *lvalue,
@@ -1817,6 +2339,13 @@ recording::block::add_assignment_op (recording::location *loc,
m_statements.safe_push (result);
}

+/* Create a recording::comment instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_add_comment. */
+
void
recording::block::add_comment (recording::location *loc,
const char *text)
@@ -1826,6 +2355,13 @@ recording::block::add_comment (recording::location *loc,
m_statements.safe_push (result);
}

+/* Create a recording::end_with_conditional instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_end_with_conditional. */
+
void
recording::block::end_with_conditional (recording::location *loc,
recording::rvalue *boolval,
@@ -1838,6 +2374,13 @@ recording::block::end_with_conditional (recording::location *loc,
m_has_been_terminated = true;
}

+/* Create a recording::end_with_jump instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking part of
+ gcc_jit_block_end_with_jump. */
+
void
recording::block::end_with_jump (recording::location *loc,
recording::block *target)
@@ -1848,6 +2391,14 @@ recording::block::end_with_jump (recording::location *loc,
m_has_been_terminated = true;
}

+/* Create a recording::end_with_return instance and add it to
+ the block's context's list of mementos, and to the block's
+ list of statements.
+
+ Implements the post-error-checking parts of
+ gcc_jit_block_end_with_return and
+ gcc_jit_block_end_with_void_return. */
+
void
recording::block::end_with_return (recording::location *loc,
recording::rvalue *rvalue)
@@ -1861,6 +2412,17 @@ recording::block::end_with_return (recording::location *loc,
m_has_been_terminated = true;
}

+/* Override the default implementation of
+ recording::memento::write_to_dump for blocks by writing
+ an unindented block name as a label, followed by the indented
+ statements:
+
+ BLOCK_NAME:
+ STATEMENT_1;
+ STATEMENT_2;
+ ...
+ STATEMENT_N; */
+
void
recording::block::write_to_dump (dump &d)
{
@@ -1872,6 +2434,8 @@ recording::block::write_to_dump (dump &d)
s->write_to_dump (d);
}

+/* Validate a block by ensuring that it has been terminated. */
+
bool
recording::block::validate ()
{
@@ -1889,6 +2453,9 @@ recording::block::validate ()
return true;
}

+/* Get the source-location of a block by using that of the first
+ statement within it, if any. */
+
recording::location *
recording::block::get_loc () const
{
@@ -1899,6 +2466,8 @@ recording::block::get_loc () const
return NULL;
}

+/* Get the first statement within a block, if any. */
+
recording::statement *
recording::block::get_first_statement () const
{
@@ -1908,6 +2477,8 @@ recording::block::get_first_statement () const
return NULL;
}

+/* Get the last statement within a block, if any. */
+
recording::statement *
recording::block::get_last_statement () const
{
@@ -1917,15 +2488,29 @@ recording::block::get_last_statement () const
return NULL;
}

+/* Assuming that this block has been terminated, get the number of
+ successor blocks, which will be 0, 1 or 2, for return, unconditional
+ jump, and conditional jump respectively.
+ NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
+ is written to NEXT1, and the second (if any) to NEXT2.
+
+ Used when validating functions, and when dumping dot representations
+ of them. */
+
int
recording::block::get_successor_blocks (block **next1, block **next2) const
{
gcc_assert (m_has_been_terminated);
+ gcc_assert (next1);
+ gcc_assert (next2);
statement *last_statement = get_last_statement ();
gcc_assert (last_statement);
return last_statement->get_successor_blocks (next1, next2);
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::block. */
+
void
recording::block::replay_into (replayer *)
{
@@ -1933,6 +2518,9 @@ recording::block::replay_into (replayer *)
->new_block (playback_string (m_name)));
}

+/* Implementation of recording::memento::make_debug_string for
+ blocks. */
+
recording::string *
recording::block::make_debug_string ()
{
@@ -1944,6 +2532,9 @@ recording::block::make_debug_string ()
(void *)this);
}

+/* Dump a block in graphviz form into PP, capturing the block name (if
+ any) and the statements. */
+
void
recording::block::dump_to_dot (pretty_printer *pp)
{
@@ -1974,6 +2565,8 @@ recording::block::dump_to_dot (pretty_printer *pp)
pp_flush (pp);
}

+/* Dump the out-edges of the block in graphviz form into PP. */
+
void
recording::block::dump_edges_to_dot (pretty_printer *pp)
{
@@ -1985,7 +2578,11 @@ recording::block::dump_edges_to_dot (pretty_printer *pp)
m_index, next[i]->m_index);
}

-/* gcc::jit::recording::global:: */
+/* The implementation of class gcc::jit::recording::global. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::global. */
+
void
recording::global::replay_into (replayer *r)
{
@@ -1994,7 +2591,11 @@ recording::global::replay_into (replayer *r)
playback_string (m_name)));
}

-/* gcc::jit::recording::memento_of_new_rvalue_from_int:: */
+/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_int. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_int. */
+
void
recording::memento_of_new_rvalue_from_int::replay_into (replayer *r)
{
@@ -2002,6 +2603,12 @@ recording::memento_of_new_rvalue_from_int::replay_into (replayer *r)
m_value));
}

+/* Implementation of recording::memento::make_debug_string for
+ rvalue_from_int, rendering it as
+ (TYPE)LITERAL
+ e.g.
+ "(int)42". */
+
recording::string *
recording::memento_of_new_rvalue_from_int::make_debug_string ()
{
@@ -2011,7 +2618,11 @@ recording::memento_of_new_rvalue_from_int::make_debug_string ()
m_value);
}

-/* gcc::jit::recording::memento_of_new_rvalue_from_double:: */
+/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_double. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_double. */
+
void
recording::memento_of_new_rvalue_from_double::replay_into (replayer *r)
{
@@ -2019,6 +2630,12 @@ recording::memento_of_new_rvalue_from_double::replay_into (replayer *r)
m_value));
}

+/* Implementation of recording::memento::make_debug_string for
+ rvalue_from_double, rendering it as
+ (TYPE)LITERAL
+ e.g.
+ "(float)42.0". */
+
recording::string *
recording::memento_of_new_rvalue_from_double::make_debug_string ()
{
@@ -2028,7 +2645,11 @@ recording::memento_of_new_rvalue_from_double::make_debug_string ()
m_value);
}

-/* gcc::jit::recording::memento_of_new_rvalue_from_ptr:: */
+/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_ptr. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_rvalue_from_ptr. */
+
void
recording::memento_of_new_rvalue_from_ptr::replay_into (replayer *r)
{
@@ -2036,6 +2657,15 @@ recording::memento_of_new_rvalue_from_ptr::replay_into (replayer *r)
m_value));
}

+/* Implementation of recording::memento::make_debug_string for
+ rvalue_from_ptr, rendering it as
+ (TYPE)HEX
+ e.g.
+ "(int *)0xdeadbeef"
+
+ Zero is rendered as NULL e.g.
+ "(int *)NULL". */
+
recording::string *
recording::memento_of_new_rvalue_from_ptr::make_debug_string ()
{
@@ -2049,13 +2679,20 @@ recording::memento_of_new_rvalue_from_ptr::make_debug_string ()
m_type->get_debug_string ());
}

-/* gcc::jit::recording::memento_of_new_string_literal:: */
+/* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::memento_of_new_string_literal. */
+
void
recording::memento_of_new_string_literal::replay_into (replayer *r)
{
set_playback_obj (r->new_string_literal (m_value->c_str ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ string literals. */
+
recording::string *
recording::memento_of_new_string_literal::make_debug_string ()
{
@@ -2063,7 +2700,11 @@ recording::memento_of_new_string_literal::make_debug_string ()
m_value->get_debug_string ());
}

-/* gcc::jit::recording::unary_op:: */
+/* The implementation of class gcc::jit::recording::unary_op. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::unary_op. */
+
void
recording::unary_op::replay_into (replayer *r)
{
@@ -2073,6 +2714,9 @@ recording::unary_op::replay_into (replayer *r)
m_a->playback_rvalue ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ unary ops. */
+
static const char * const unary_op_strings[] = {
"-", /* GCC_JIT_UNARY_OP_MINUS */
"~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
@@ -2088,7 +2732,11 @@ recording::unary_op::make_debug_string ()
m_a->get_debug_string ());
}

-/* gcc::jit::recording::binary_op:: */
+/* The implementation of class gcc::jit::recording::binary_op. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::binary_op. */
+
void
recording::binary_op::replay_into (replayer *r)
{
@@ -2099,6 +2747,9 @@ recording::binary_op::replay_into (replayer *r)
m_b->playback_rvalue ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ binary ops. */
+
static const char * const binary_op_strings[] = {
"+", /* GCC_JIT_BINARY_OP_PLUS */
"-", /* GCC_JIT_BINARY_OP_MINUS */
@@ -2124,7 +2775,11 @@ recording::binary_op::make_debug_string ()
m_b->get_debug_string ());
}

-/* gcc::jit::recording::comparison:: */
+/* The implementation of class gcc::jit::recording::comparison. */
+
+/* Implementation of recording::memento::make_debug_string for
+ comparisons. */
+
static const char * const comparison_strings[] =
{
"==", /* GCC_JIT_COMPARISON_EQ */
@@ -2145,6 +2800,9 @@ recording::comparison::make_debug_string ()
m_b->get_debug_string ());
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::comparison. */
+
void
recording::comparison::replay_into (replayer *r)
{
@@ -2154,6 +2812,9 @@ recording::comparison::replay_into (replayer *r)
m_b->playback_rvalue ()));
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::cast. */
+
void
recording::cast::replay_into (replayer *r)
{
@@ -2162,6 +2823,9 @@ recording::cast::replay_into (replayer *r)
get_type ()->playback_type ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ casts. */
+
recording::string *
recording::cast::make_debug_string ()
{
@@ -2171,6 +2835,10 @@ recording::cast::make_debug_string ()
m_rvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::call. */
+
+/* The constructor for gcc::jit::recording::call. */
+
recording::call::call (recording::context *ctxt,
recording::location *loc,
recording::function *func,
@@ -2184,6 +2852,9 @@ recording::call::call (recording::context *ctxt,
m_args.safe_push (args[i]);
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::call. */
+
void
recording::call::replay_into (replayer *r)
{
@@ -2197,6 +2868,9 @@ recording::call::replay_into (replayer *r)
playback_args));
}

+/* Implementation of recording::memento::make_debug_string for
+ function calls. */
+
recording::string *
recording::call::make_debug_string ()
{
@@ -2236,6 +2910,10 @@ recording::call::make_debug_string ()
return result;
}

+/* The implementation of class gcc::jit::recording::call_through_ptr. */
+
+/* The constructor for recording::call_through_ptr. */
+
recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
recording::location *loc,
recording::rvalue *fn_ptr,
@@ -2251,6 +2929,9 @@ recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
m_args.safe_push (args[i]);
}

+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::call_through_ptr. */
+
void
recording::call_through_ptr::replay_into (replayer *r)
{
@@ -2264,6 +2945,9 @@ recording::call_through_ptr::replay_into (replayer *r)
playback_args));
}

+/* Implementation of recording::memento::make_debug_string for
+ calls through function ptrs. */
+
recording::string *
recording::call_through_ptr::make_debug_string ()
{
@@ -2303,6 +2987,11 @@ recording::call_through_ptr::make_debug_string ()
return result;
}

+/* The implementation of class gcc::jit::recording::array_access. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::array_access. */
+
void
recording::array_access::replay_into (replayer *r)
{
@@ -2312,6 +3001,9 @@ recording::array_access::replay_into (replayer *r)
m_index->playback_rvalue ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ array accesses. */
+
recording::string *
recording::array_access::make_debug_string ()
{
@@ -2321,6 +3013,11 @@ recording::array_access::make_debug_string ()
m_index->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::access_field_of_lvalue. */
+
void
recording::access_field_of_lvalue::replay_into (replayer *r)
{
@@ -2331,6 +3028,9 @@ recording::access_field_of_lvalue::replay_into (replayer *r)

}

+/* Implementation of recording::memento::make_debug_string for
+ accessing a field of an lvalue. */
+
recording::string *
recording::access_field_of_lvalue::make_debug_string ()
{
@@ -2340,6 +3040,11 @@ recording::access_field_of_lvalue::make_debug_string ()
m_field->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::access_field_rvalue. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::access_field_rvalue. */
+
void
recording::access_field_rvalue::replay_into (replayer *r)
{
@@ -2349,6 +3054,9 @@ recording::access_field_rvalue::replay_into (replayer *r)
m_field->playback_field ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ accessing a field of an rvalue. */
+
recording::string *
recording::access_field_rvalue::make_debug_string ()
{
@@ -2358,6 +3066,12 @@ recording::access_field_rvalue::make_debug_string ()
m_field->get_debug_string ());
}

+/* The implementation of class
+ gcc::jit::recording::dereference_field_rvalue. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::dereference_field_rvalue. */
+
void
recording::dereference_field_rvalue::replay_into (replayer *r)
{
@@ -2367,6 +3081,9 @@ recording::dereference_field_rvalue::replay_into (replayer *r)
m_field->playback_field ()));
}

+/* Implementation of recording::memento::make_debug_string for
+ dereferencing a field of an rvalue. */
+
recording::string *
recording::dereference_field_rvalue::make_debug_string ()
{
@@ -2376,6 +3093,11 @@ recording::dereference_field_rvalue::make_debug_string ()
m_field->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::dereference_rvalue. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::dereference_rvalue. */
+
void
recording::dereference_rvalue::replay_into (replayer *r)
{
@@ -2384,6 +3106,9 @@ recording::dereference_rvalue::replay_into (replayer *r)
dereference (playback_location (r, m_loc)));
}

+/* Implementation of recording::memento::make_debug_string for
+ dereferencing an rvalue. */
+
recording::string *
recording::dereference_rvalue::make_debug_string ()
{
@@ -2392,6 +3117,11 @@ recording::dereference_rvalue::make_debug_string ()
m_rvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::get_address_of_lvalue. */
+
void
recording::get_address_of_lvalue::replay_into (replayer *r)
{
@@ -2400,6 +3130,9 @@ recording::get_address_of_lvalue::replay_into (replayer *r)
get_address (playback_location (r, m_loc)));
}

+/* Implementation of recording::memento::make_debug_string for
+ getting the address of an lvalue. */
+
recording::string *
recording::get_address_of_lvalue::make_debug_string ()
{
@@ -2408,6 +3141,11 @@ recording::get_address_of_lvalue::make_debug_string ()
m_lvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::local. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::local. */
+
void
recording::local::replay_into (replayer *r)
{
@@ -2418,6 +3156,12 @@ recording::local::replay_into (replayer *r)
playback_string (m_name)));
}

+/* Override the default implementation of
+ recording::memento::write_to_dump for locals by writing
+ TYPE NAME;
+ for use at the top of the function body as if it were a
+ declaration. */
+
void
recording::local::write_to_dump (dump &d)
{
@@ -2428,7 +3172,12 @@ recording::local::write_to_dump (dump &d)
get_debug_string ());
}

-// gcc::jit::recording::statement
+/* The implementation of class gcc::jit::recording::statement. */
+
+/* We poison the default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+ since this vfunc must only ever be called on terminator
+ statements. */

int
recording::statement::get_successor_blocks (block **/*out_next1*/,
@@ -2440,6 +3189,11 @@ recording::statement::get_successor_blocks (block **/*out_next1*/,
return 0;
}

+/* Extend the default implementation of
+ recording::memento::write_to_dump for statements by (if requested)
+ updating the location of the statement to the current location in
+ the dumpfile. */
+
void
recording::statement::write_to_dump (dump &d)
{
@@ -2448,6 +3202,11 @@ recording::statement::write_to_dump (dump &d)
m_loc = d.make_location ();
}

+/* The implementation of class gcc::jit::recording::eval. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::eval. */
+
void
recording::eval::replay_into (replayer *r)
{
@@ -2456,6 +3215,9 @@ recording::eval::replay_into (replayer *r)
m_rvalue->playback_rvalue ());
}

+/* Implementation of recording::memento::make_debug_string for
+ an eval statement. */
+
recording::string *
recording::eval::make_debug_string ()
{
@@ -2464,6 +3226,11 @@ recording::eval::make_debug_string ()
m_rvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::assignment. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::assignment. */
+
void
recording::assignment::replay_into (replayer *r)
{
@@ -2473,6 +3240,9 @@ recording::assignment::replay_into (replayer *r)
m_rvalue->playback_rvalue ());
}

+/* Implementation of recording::memento::make_debug_string for
+ an assignment statement. */
+
recording::string *
recording::assignment::make_debug_string ()
{
@@ -2482,6 +3252,11 @@ recording::assignment::make_debug_string ()
m_rvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::assignment_op. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::assignment_op. */
+
void
recording::assignment_op::replay_into (replayer *r)
{
@@ -2501,6 +3276,9 @@ recording::assignment_op::replay_into (replayer *r)
binary_op);
}

+/* Implementation of recording::memento::make_debug_string for
+ an assignment_op statement. */
+
recording::string *
recording::assignment_op::make_debug_string ()
{
@@ -2511,6 +3289,11 @@ recording::assignment_op::make_debug_string ()
m_rvalue->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::comment. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::comment. */
+
void
recording::comment::replay_into (replayer *r)
{
@@ -2519,6 +3302,9 @@ recording::comment::replay_into (replayer *r)
m_text->c_str ());
}

+/* Implementation of recording::memento::make_debug_string for
+ a comment "statement". */
+
recording::string *
recording::comment::make_debug_string ()
{
@@ -2527,6 +3313,11 @@ recording::comment::make_debug_string ()
m_text->c_str ());
}

+/* The implementation of class gcc::jit::recording::conditional. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::conditional. */
+
void
recording::conditional::replay_into (replayer *r)
{
@@ -2537,6 +3328,11 @@ recording::conditional::replay_into (replayer *r)
playback_block (m_on_false));
}

+/* Override the poisoned default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+
+ A conditional jump has 2 successor blocks. */
+
int
recording::conditional::get_successor_blocks (block **out_next1,
block **out_next2) const
@@ -2546,6 +3342,9 @@ recording::conditional::get_successor_blocks (block **out_next1,
return 2;
}

+/* Implementation of recording::memento::make_debug_string for
+ a conditional jump statement. */
+
recording::string *
recording::conditional::make_debug_string ()
{
@@ -2562,6 +3361,11 @@ recording::conditional::make_debug_string ()
m_on_true->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::jump. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::jump. */
+
void
recording::jump::replay_into (replayer *r)
{
@@ -2570,6 +3374,11 @@ recording::jump::replay_into (replayer *r)
m_target->playback_block ());
}

+/* Override the poisoned default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+
+ An unconditional jump has 1 successor block. */
+
int
recording::jump::get_successor_blocks (block **out_next1,
block **/*out_next2*/) const
@@ -2578,6 +3387,9 @@ recording::jump::get_successor_blocks (block **out_next1,
return 1;
}

+/* Implementation of recording::memento::make_debug_string for
+ a unconditional jump statement. */
+
recording::string *
recording::jump::make_debug_string ()
{
@@ -2586,6 +3398,11 @@ recording::jump::make_debug_string ()
m_target->get_debug_string ());
}

+/* The implementation of class gcc::jit::recording::return_. */
+
+/* Implementation of pure virtual hook recording::memento::replay_into
+ for recording::return_. */
+
void
recording::return_::replay_into (replayer *r)
{
@@ -2594,6 +3411,11 @@ recording::return_::replay_into (replayer *r)
m_rvalue ? m_rvalue->playback_rvalue () : NULL);
}

+/* Override the poisoned default implementation of
+ gcc::jit::recording::statement::get_successor_blocks
+
+ A return statement has no successor block. */
+
int
recording::return_::get_successor_blocks (block **/*out_next1*/,
block **/*out_next2*/) const
@@ -2601,6 +3423,9 @@ recording::return_::get_successor_blocks (block **/*out_next1*/,
return 0;
}

+/* Implementation of recording::memento::make_debug_string for
+ a return statement (covers both those with and without rvalues). */
+
recording::string *
recording::return_::make_debug_string ()
{
@@ -2617,6 +3442,8 @@ recording::return_::make_debug_string ()
Playback.
**********************************************************************/

+/* The constructor for gcc::jit::playback::context. */
+
playback::context::context (recording::context *ctxt)
: m_recording_ctxt (ctxt),
m_char_array_type_node (NULL),
@@ -2627,6 +3454,8 @@ playback::context::context (recording::context *ctxt)
m_cached_locations.create (0);
}

+/* The destructor for gcc::jit::playback::context. */
+
playback::context::~context ()
{
if (get_bool_option (GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES))
@@ -2651,6 +3480,12 @@ playback::context::~context ()
m_functions.release ();
}

+/* A playback::context can reference GC-managed pointers. Mark them
+ ("by hand", rather than by gengtype).
+
+ This is called on the active playback context (if any) by the
+ my_ggc_walker hook in the jit_root_table in dummy-frontend.c. */
+
void
playback::context::
gt_ggc_mx ()
@@ -2664,6 +3499,8 @@ gt_ggc_mx ()
}
}

+/* Given an enum gcc_jit_types value, get a "tree" type. */
+
static tree
get_tree_node_for_type (enum gcc_jit_types type_)
{
@@ -2729,6 +3566,9 @@ get_tree_node_for_type (enum gcc_jit_types type_)
return NULL;
}

+/* Construct a playback::type instance (wrapping a tree) for the given
+ enum value. */
+
playback::type *
playback::context::
get_type (enum gcc_jit_types type_)
@@ -2744,6 +3584,9 @@ get_type (enum gcc_jit_types type_)
return new type (type_node);
}

+/* Construct a playback::type instance (wrapping a tree) for the given
+ array type. */
+
playback::type *
playback::context::
new_array_type (playback::location *loc,
@@ -2762,6 +3605,8 @@ new_array_type (playback::location *loc,
return new type (t);
}

+/* Construct a playback::field instance (wrapping a tree). */
+
playback::field *
playback::context::
new_field (location *loc,
@@ -2781,6 +3626,8 @@ new_field (location *loc,
return new field (decl);
}

+/* Construct a playback::compound_type instance (wrapping a tree). */
+
playback::compound_type *
playback::context::
new_compound_type (location *loc,
@@ -2820,6 +3667,9 @@ playback::compound_type::set_fields (const vec<playback::field *> &fields)
layout_type (t);
}

+/* Construct a playback::type instance (wrapping a tree) for a function
+ type. */
+
playback::type *
playback::context::
new_function_type (type *return_type,
@@ -2849,6 +3699,8 @@ new_function_type (type *return_type,
return new type (fn_type);
}

+/* Construct a playback::param instance (wrapping a tree). */
+
playback::param *
playback::context::
new_param (location *loc,
@@ -2865,6 +3717,8 @@ new_param (location *loc,
return new param (this, inner);
}

+/* Construct a playback::function instance. */
+
playback::function *
playback::context::
new_function (location *loc,
@@ -2952,6 +3806,8 @@ new_function (location *loc,
return func;
}

+/* Construct a playback::lvalue instance (wrapping a tree). */
+
playback::lvalue *
playback::context::
new_global (location *loc,
@@ -2973,6 +3829,8 @@ new_global (location *loc,
return new lvalue (this, inner);
}

+/* Construct a playback::rvalue instance (wrapping a tree). */
+
playback::rvalue *
playback::context::
new_rvalue_from_int (type *type,
@@ -2994,6 +3852,8 @@ new_rvalue_from_int (type *type,
}
}

+/* Construct a playback::rvalue instance (wrapping a tree). */
+
playback::rvalue *
playback::context::
new_rvalue_from_double (type *type,
@@ -3022,6 +3882,8 @@ new_rvalue_from_double (type *type,
return new rvalue (this, inner);
}

+/* Construct a playback::rvalue instance (wrapping a tree). */
+
playback::rvalue *
playback::context::
new_rvalue_from_ptr (type *type,
@@ -3033,6 +3895,8 @@ new_rvalue_from_ptr (type *type,
return new rvalue (this, inner);
}

+/* Construct a playback::rvalue instance (wrapping a tree). */
+
playback::rvalue *
playback::context::
new_string_literal (const char *value)
@@ -3049,6 +3913,8 @@ new_string_literal (const char *value)
return new rvalue (this, t_addr);
}

+/* Coerce a tree expression into a boolean tree expression. */
+
tree
playback::context::
as_truth_value (tree expr, location *loc)
@@ -3067,6 +3933,9 @@ as_truth_value (tree expr, location *loc)
return expr;
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ unary op. */
+
playback::rvalue *
playback::context::
new_unary_op (location *loc,
@@ -3114,6 +3983,9 @@ new_unary_op (location *loc,
return new rvalue (this, inner_result);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ binary op. */
+
playback::rvalue *
playback::context::
new_binary_op (location *loc,
@@ -3205,6 +4077,9 @@ new_binary_op (location *loc,
return new rvalue (this, inner_expr);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ comparison. */
+
playback::rvalue *
playback::context::
new_comparison (location *loc,
@@ -3252,6 +4127,9 @@ new_comparison (location *loc,
return new rvalue (this, inner_expr);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ function call. */
+
playback::rvalue *
playback::context::
build_call (location *loc,
@@ -3285,6 +4163,9 @@ build_call (location *loc,
*/
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ call to a specific function. */
+
playback::rvalue *
playback::context::
new_call (location *loc,
@@ -3304,6 +4185,9 @@ new_call (location *loc,
return build_call (loc, fn, args);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ call through a function pointer. */
+
playback::rvalue *
playback::context::
new_call_through_ptr (location *loc,
@@ -3316,6 +4200,8 @@ new_call_through_ptr (location *loc,
return build_call (loc, t_fn_ptr, args);
}

+/* Construct a tree for a cast. */
+
tree
playback::context::build_cast (playback::location *loc,
playback::rvalue *expr,
@@ -3372,6 +4258,9 @@ playback::context::build_cast (playback::location *loc,
}
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ cast. */
+
playback::rvalue *
playback::context::
new_cast (playback::location *loc,
@@ -3385,6 +4274,9 @@ new_cast (playback::location *loc,
return new rvalue (this, t_cast);
}

+/* Construct a playback::lvalue instance (wrapping a tree) for an
+ array access. */
+
playback::lvalue *
playback::context::
new_array_access (location *loc,
@@ -3434,6 +4326,8 @@ new_array_access (location *loc,
}
}

+/* Construct a tree for a field access. */
+
tree
playback::context::
new_field_access (location *loc,
@@ -3457,6 +4351,8 @@ new_field_access (location *loc,
return ref;
}

+/* Construct a tree for a dereference. */
+
tree
playback::context::
new_dereference (tree ptr,
@@ -3471,6 +4367,9 @@ new_dereference (tree ptr,
return datum;
}

+/* Construct a playback::lvalue instance (wrapping a tree) for a
+ field access. */
+
playback::lvalue *
playback::lvalue::
access_field (location *loc,
@@ -3483,6 +4382,9 @@ access_field (location *loc,
return new lvalue (get_context (), ref);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for a
+ field access. */
+
playback::rvalue *
playback::rvalue::
access_field (location *loc,
@@ -3495,6 +4397,9 @@ access_field (location *loc,
return new rvalue (get_context (), ref);
}

+/* Construct a playback::lvalue instance (wrapping a tree) for a
+ dereferenced field access. */
+
playback::lvalue *
playback::rvalue::
dereference_field (location *loc,
@@ -3510,6 +4415,9 @@ dereference_field (location *loc,
return new lvalue (get_context (), ref);
}

+/* Construct a playback::lvalue instance (wrapping a tree) for a
+ dereference. */
+
playback::lvalue *
playback::rvalue::
dereference (location *loc)
@@ -3519,6 +4427,9 @@ dereference (location *loc)
return new lvalue (get_context (), datum);
}

+/* Construct a playback::rvalue instance (wrapping a tree) for an
+ address-lookup. */
+
playback::rvalue *
playback::lvalue::
get_address (location *loc)
@@ -3532,6 +4443,9 @@ get_address (location *loc)
return new rvalue (get_context (), ptr);
}

+/* gcc::jit::playback::wrapper subclasses are GC-managed:
+ allocate them using ggc_internal_cleared_alloc. */
+
void *
playback::wrapper::
operator new (size_t sz)
@@ -3539,6 +4453,8 @@ operator new (size_t sz)
return ggc_internal_cleared_alloc (sz MEM_STAT_INFO);
}

+/* Constructor for gcc:jit::playback::function. */
+
playback::function::
function (context *ctxt,
tree fndecl,
@@ -3564,6 +4480,8 @@ function (context *ctxt,
}
}

+/* Hand-written GC-marking hook for playback functions. */
+
void
playback::function::
gt_ggc_mx ()
@@ -3574,6 +4492,8 @@ gt_ggc_mx ()
gt_ggc_m_9tree_node (m_inner_block);
}

+/* Get the return type of a playback function, in tree form. */
+
tree
playback::function::
get_return_type_as_tree () const
@@ -3581,6 +4501,8 @@ get_return_type_as_tree () const
return TREE_TYPE (TREE_TYPE(m_inner_fndecl));
}

+/* Construct a new local within this playback::function. */
+
playback::lvalue *
playback::function::
new_local (location *loc,
@@ -3603,6 +4525,8 @@ new_local (location *loc,
return new lvalue (m_ctxt, inner);
}

+/* Construct a new block within this playback::function. */
+
playback::block *
playback::function::
new_block (const char *name)
@@ -3614,6 +4538,10 @@ new_block (const char *name)
return result;
}

+/* Build a statement list for the function as a whole out of the
+ lists of statements for the individual blocks, building labels
+ for each block. */
+
void
playback::function::
build_stmt_list ()
@@ -3636,6 +4564,12 @@ build_stmt_list ()
}
}

+/* Finish compiling the given function, potentially running the
+ garbage-collector.
+ The function will have a statement list by now.
+ Amongst other things, this gimplifies the statement list,
+ and calls cgraph_node::finalize_function on the function. */
+
void
playback::function::
postprocess ()
@@ -3692,6 +4626,8 @@ postprocess ()
}
}

+/* Add an eval of the rvalue to the function's statement list. */
+
void
playback::block::
add_eval (location *loc,
@@ -3705,6 +4641,8 @@ add_eval (location *loc,
add_stmt (rvalue->as_tree ());
}

+/* Add an assignment to the function's statement list. */
+
void
playback::block::
add_assignment (location *loc,
@@ -3733,6 +4671,9 @@ add_assignment (location *loc,
add_stmt (stmt);
}

+/* Add a comment to the function's statement list.
+ For now this is done by adding a dummy label. */
+
void
playback::block::
add_comment (location *loc,
@@ -3760,6 +4701,8 @@ add_comment (location *loc,
add_stmt (label_expr);
}

+/* Add a conditional jump statement to the function's statement list. */
+
void
playback::block::
add_conditional (location *loc,
@@ -3792,6 +4735,8 @@ add_conditional (location *loc,
add_stmt (stmt);
}

+/* Add an unconditional jump statement to the function's statement list. */
+
void
playback::block::
add_jump (location *loc,
@@ -3829,6 +4774,8 @@ c_finish_goto_label (location_t loc, tree label)

}

+/* Add a return statement to the function's statement list. */
+
void
playback::block::
add_return (location *loc,
@@ -3857,6 +4804,8 @@ add_return (location *loc,
add_stmt (return_stmt);
}

+/* Constructor for gcc::jit::playback::block. */
+
playback::block::
block (function *func,
const char *name)
@@ -3877,6 +4826,15 @@ block (function *func,
m_label_expr = NULL;
}

+/* Compile a playback::context:
+
+ - Use the context's options to cconstruct command-line options, and
+ call into the rest of GCC (toplev::main).
+ - Assuming it succeeds, we have a .s file; we want a .so file.
+ Invoke another gcc to convert the .s file to a .so file.
+ - dlopen the .so file
+ - Wrap the result up as a playback::result and return it. */
+
result *
playback::context::
compile ()
@@ -4034,6 +4992,12 @@ compile ()
return result_obj;
}

+/* Top-level hook for playing back a recording context.
+
+ This plays back m_recording_ctxt, and, if no errors
+ occurred builds statement lists for and then postprocesses
+ every function in the result. */
+
void
playback::context::
replay ()
@@ -4085,6 +5049,8 @@ replay ()
}
}

+/* Dump the generated .s file to stderr. */
+
void
playback::context::
dump_generated_code ()
@@ -4101,6 +5067,9 @@ dump_generated_code ()
fclose (f_in);
}

+/* qsort comparator for comparing pairs of playback::source_line *,
+ ordering them by line number. */
+
static int
line_comparator (const void *lhs, const void *rhs)
{
@@ -4111,6 +5080,9 @@ line_comparator (const void *lhs, const void *rhs)
return line_lhs->get_line_num () - line_rhs->get_line_num ();
}

+/* qsort comparator for comparing pairs of playback::location *,
+ ordering them by column number. */
+
static int
location_comparator (const void *lhs, const void *rhs)
{
@@ -4121,6 +5093,14 @@ location_comparator (const void *lhs, const void *rhs)
return loc_lhs->get_column_num () - loc_rhs->get_column_num ();
}

+/* Our API allows locations to be created in arbitrary orders, but the
+ linemap API requires locations to be created in ascending order
+ as if we were tokenizing files.
+
+ This hook sorts all of the the locations that have been created, and
+ calls into the linemap API, creating linemap entries in sorted order
+ for our locations. */
+
void
playback::context::
handle_locations ()
@@ -4205,6 +5185,8 @@ handle_locations ()
}
}

+/* We handle errors on a playback::context by adding them to the
+ corresponding recording::context. */

void
playback::context::
@@ -4217,6 +5199,9 @@ add_error (location *loc, const char *fmt, ...)
va_end (ap);
}

+/* We handle errors on a playback::context by adding them to the
+ corresponding recording::context. */
+
void
playback::context::
add_error_va (location *loc, const char *fmt, va_list ap)
@@ -4225,17 +5210,29 @@ add_error_va (location *loc, const char *fmt, va_list ap)
fmt, ap);
}

+/* Constructor for gcc::jit::playback::result. */
+
result::
result(void *dso_handle)
: m_dso_handle(dso_handle)
{
}

+/* gcc::jit::playback::result's destructor.
+
+ Called implicitly by gcc_jit_result_release. */
+
result::~result()
{
dlclose (m_dso_handle);
}

+/* Attempt to locate the given function by name within the
+ playback::result, using dlsym.
+
+ Implements the post-error-checking part of
+ gcc_jit_result_get_code. */
+
void *
result::
get_code (const char *funcname)
@@ -4257,6 +5254,9 @@ get_code (const char *funcname)

/* Dealing with the linemap API. */

+/* Construct a playback::location for a recording::location, if it
+ doesn't exist already. */
+
playback::location *
playback::context::
new_location (recording::location *rloc,
@@ -4273,6 +5273,11 @@ new_location (recording::location *rloc,
return loc;
}

+/* Deferred setting of the location for a given tree, by adding the
+ (tree, playback::location) pair to a list of deferred associations.
+ We will actually set the location on the tree later on once
+ the source_location for the playback::location exists. */
+
void
playback::context::
set_tree_location (tree t, location *loc)
@@ -4282,6 +5287,9 @@ set_tree_location (tree t, location *loc)
}


+/* Construct a playback::source_file for the given source
+ filename, if it doesn't exist already. */
+
playback::source_file *
playback::context::
get_source_file (const char *filename)
@@ -4303,12 +5311,17 @@ get_source_file (const char *filename)
return file;
}

+/* Constructor for gcc::jit::playback::source_file. */
+
playback::source_file::source_file (tree filename) :
m_source_lines (),
m_filename (filename)
{
}

+/* Construct a playback::source_line for the given line
+ within this source file, if one doesn't exist already. */
+
playback::source_line *
playback::source_file::
get_source_line (int line_num)
@@ -4329,6 +5342,8 @@ get_source_line (int line_num)
return line;
}

+/* Constructor for gcc::jit::playback::source_line. */
+
playback::source_line::source_line (source_file *file, int line_num) :
m_locations (),
m_source_file (file),
@@ -4336,6 +5351,10 @@ playback::source_line::source_line (source_file *file, int line_num) :
{
}

+/* Construct a playback::location for the given column
+ within this line of a specific source file, if one doesn't exist
+ already. */
+
playback::location *
playback::source_line::
get_location (recording::location *rloc, int column_num)
@@ -4354,6 +5373,8 @@ get_location (recording::location *rloc, int column_num)
return loc;
}

+/* Constructor for gcc::jit::playback::location. */
+
playback::location::location (recording::location *loc,
source_line *line,
int column_num) :
@@ -4364,6 +5385,9 @@ playback::location::location (recording::location *loc,
{
}

+/* The active gcc::jit::playback::context instance. This is a singleton,
+ guarded by jit_mutex. */
+
playback::context *active_playback_ctxt;

} // namespace gcc::jit
diff --git a/gcc/jit/internal-api.h b/gcc/jit/internal-api.h
index 8054bed..3a4717a 100644
--- a/gcc/jit/internal-api.h
+++ b/gcc/jit/internal-api.h
@@ -97,40 +97,44 @@ class result;
class dump;

namespace recording {
+ /* Indentation indicates inheritance: */
class context;
class builtins_manager; // declared within jit-builtins.h
class memento;
- class string;
- class location;
- class type;
- class function_type;
- class field;
- class compound_type;
- class struct_;
- class union_;
- class fields;
- class function;
- class block;
- class rvalue;
- class lvalue;
- class local;
- class param;
- class statement;
+ class string;
+ class location;
+ class type;
+ class function_type;
+ class compound_type;
+ class struct_;
+ class union_;
+ class field;
+ class fields;
+ class function;
+ class block;
+ class rvalue;
+ class lvalue;
+ class local;
+ class global;
+ class param;
+ class statement;
}

namespace playback {
+ /* Indentation indicates inheritance: */
class context;
- class location;
- class type;
- class field;
- class compound_type;
- class function;
- class block;
- class rvalue;
- class lvalue;
- class param;
- class source_file;
- class source_line;
+ class wrapper;
+ class type;
+ class compound_type;
+ class field;
+ class function;
+ class block;
+ class rvalue;
+ class lvalue;
+ class param;
+ class source_file;
+ class source_line;
+ class location;
}

typedef playback::context replayer;
@@ -397,12 +401,19 @@ public:

void set_playback_obj (void *obj) { m_playback_obj = obj; }

+
+ /* Get the context that owns this object.
+
+ Implements the post-error-checking part of
+ gcc_jit_object_get_context. */
context *get_context () { return m_ctxt; }

memento *
as_object () { return this; }

- /* Debugging hook, for use in generating error messages etc. */
+ /* Debugging hook, for use in generating error messages etc.
+ Implements the post-error-checking part of
+ gcc_jit_object_get_debug_string. */
const char *
get_debug_string ();

@@ -904,6 +915,10 @@ public:
gcc_assert (type_);
}

+ /* Get the recording::type of this rvalue.
+
+ Implements the post-error-checking part of
+ gcc_jit_rvalue_get_type. */
type * get_type () const { return m_type; }

playback::rvalue *
@@ -1015,7 +1030,12 @@ public:
type *get_return_type () const { return m_return_type; }
string * get_name () const { return m_name; }
vec<param *> get_params () const { return m_params; }
+
+ /* Get the given param by index.
+ Implements the post-error-checking part of
+ gcc_jit_function_get_param. */
param *get_param (int i) const { return m_params[i]; }
+
bool is_variadic () const { return m_is_variadic; }

void write_to_dump (dump &d);
@@ -1053,6 +1073,9 @@ public:
{
}

+ /* Get the recording::function containing this block.
+ Implements the post-error-checking part of
+ gcc_jit_block_get_function. */
function *get_function () { return m_func; }

bool has_been_terminated () { return m_has_been_terminated; }
diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index c4b0f59..05cb398 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -61,6 +61,8 @@ static const struct builtin_data builtin_data[] =
};
#undef DEF_BUILTIN

+/* Helper function for find_builtin_by_name. */
+
static bool
matches_builtin (const char *in_name,
const struct builtin_data& bd)
@@ -94,6 +96,10 @@ matches_builtin (const char *in_name,
return false;
}

+/* Locate the built-in function that matches name IN_NAME,
+ writing the result to OUT_ID and returning true if found,
+ or returning false if not found. */
+
static bool
find_builtin_by_name (const char *in_name,
enum built_in_function *out_id)
@@ -123,6 +129,8 @@ find_builtin_by_name (const char *in_name,

// class builtins_manager

+/* Constructor for gcc::jit::recording::builtins_manager. */
+
builtins_manager::builtins_manager (context *ctxt)
: m_ctxt (ctxt)
{
@@ -130,6 +138,10 @@ builtins_manager::builtins_manager (context *ctxt)
memset (m_builtin_functions, 0, sizeof (m_builtin_functions));
}

+/* Locate a builtin function by name.
+ Create a recording::function of the appropriate type, reusing them
+ if they've already been seen. */
+
function *
builtins_manager::get_builtin_function (const char *name)
{
@@ -154,6 +166,8 @@ builtins_manager::get_builtin_function (const char *name)
return m_builtin_functions[builtin_id];
}

+/* Create the recording::function for a given builtin function, by ID. */
+
function *
builtins_manager::make_builtin_function (enum built_in_function builtin_id)
{
@@ -191,6 +205,9 @@ builtins_manager::make_builtin_function (enum built_in_function builtin_id)
return result;
}

+/* Get the recording::type for a given type of builtin function,
+ by ID, creating it if it doesn't already exist. */
+
type *
builtins_manager::get_type (enum jit_builtin_type type_id)
{
@@ -199,6 +216,8 @@ builtins_manager::get_type (enum jit_builtin_type type_id)
return m_types[type_id];
}

+/* Create the recording::type for a given type of builtin function. */
+
type *
builtins_manager::make_type (enum jit_builtin_type type_id)
{
@@ -275,6 +294,11 @@ builtins_manager::make_type (enum jit_builtin_type type_id)
}
}

+/* Create the recording::type for a given primitive type within the
+ builtin system.
+
+ Only some types are currently supported. */
+
type*
builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
{
@@ -343,6 +367,8 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
}
}

+/* Create the recording::function_type for a given function type
+ signature. */

function_type *
builtins_manager::make_fn_type (enum jit_builtin_type,
@@ -382,6 +408,8 @@ builtins_manager::make_fn_type (enum jit_builtin_type,
return result;
}

+/* Handler for DEF_POINTER_TYPE within builtins_manager::make_type. */
+
type *
builtins_manager::make_ptr_type (enum jit_builtin_type,
enum jit_builtin_type other_type_id)
--
1.7.11.7
David Malcolm
2014-09-25 16:03:04 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
* use choose_tmpdir from libiberty rather than hardcoding /tmp (or,
better, create the files directly with make_temp_file, and delete them
individual afterwards);
[...]

I believe that a tempdir is better than creating individual tempfiles:
for debugging all this it's handy to have dumpfiles, and if they're
enabled, they're written out relative to the supposed source file.
So if we have
SOME_PATH_TO/fake.c
we get e.g.
SOME_PATH_TO/fake.c.016t.ssa
and so on. The simplest way to clean this all up seems to be to put
everything related to a compile in a tempdir, and to create that tempdir
as securely as we can. The tempdir is deleted in the destructor for
the playback::context (unless GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES
has been set).

So I went with the choose_tmpdir approach, to avoid hardcoding "/tmp/",
although it wasn't previously exposed in liberty.h.

I've committed the following to branch dmalcolm/jit:

Expose choose_tmpdir and use it when building tmpdir for jit
compilation:

Fix the return type of libiberty's choose_tmpdir.

Expose it in libiberty.h

Use it within the JIT's playback::context::compile when building the
tempdir to avoid hardcoding "/tmp/".

gcc/jit/ChangeLog.jit:
* internal-api.c (make_tempdir_path_template): New.
(gcc::jit::playback::context::compile): Call
make_tempdir_path_template to make m_path_template, rather than
hardcoding "/tmp/" within "/tmp/libgccjit-XXXXXX".

include/ChangeLog.jit:
* libiberty.h (choose_tmpdir): New prototype.
* ChangeLog.jit: New.

libiberty/ChangeLog.jit:
* choose-temp.c (choose_tmpdir): Remove now-redundant local
copy of prototype.
* functions.texi: Regenerate.
* make-temp-file.c (choose_tmpdir): Convert return type from
char * to const char * - given that this returns a pointer to
a memoized allocation, the caller must not touch it.
---
gcc/jit/ChangeLog.jit | 7 +++++++
gcc/jit/internal-api.c | 40 +++++++++++++++++++++++++++++++++++++++-
include/ChangeLog.jit | 11 +++++++++++
include/libiberty.h | 5 +++++
libiberty/ChangeLog.jit | 9 +++++++++
libiberty/choose-temp.c | 1 -
libiberty/functions.texi | 13 ++++++-------
libiberty/make-temp-file.c | 4 ++--
8 files changed, 79 insertions(+), 11 deletions(-)
create mode 100644 include/ChangeLog.jit

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index b4700e4..d66203a 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,10 @@
+2014-09-25 David Malcolm <***@redhat.com>
+
+ * internal-api.c (make_tempdir_path_template): New.
+ (gcc::jit::playback::context::compile): Call
+ make_tempdir_path_template to make m_path_template, rather than
+ hardcoding "/tmp/" within "/tmp/libgccjit-XXXXXX".
+
2014-09-24 David Malcolm <***@redhat.com>

* docs/internals/index.rst ("Overview of code structure"): Add
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 32fe7cb..50fd83b 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -4826,6 +4826,44 @@ block (function *func,
m_label_expr = NULL;
}

+/* Construct a tempdir path template suitable for use by mkdtemp
+ e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in
+ libiberty's choose_tempdir rather than hardcoding "/tmp/".
+
+ The memory is allocated using malloc and must be freed.
+ Aborts the process if allocation fails. */
+
+static char *
+make_tempdir_path_template ()
+{
+ const char *tmpdir_buf;
+ size_t tmpdir_len;
+ const char *file_template_buf;
+ size_t file_template_len;
+ char *result;
+
+ /* The result of choose_tmpdir is a cached buffer within libiberty, so
+ we must *not* free it. */
+ tmpdir_buf = choose_tmpdir ();
+
+ /* choose_tmpdir aborts on malloc failure. */
+ gcc_assert (tmpdir_buf);
+
+ tmpdir_len = strlen (tmpdir_buf);
+ /* tmpdir_buf should now have a dir separator as the final byte. */
+ gcc_assert (tmpdir_len > 0);
+ gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR);
+
+ file_template_buf = "libgccjit-XXXXXX";
+ file_template_len = strlen (file_template_buf);
+
+ result = XNEWVEC (char, tmpdir_len + file_template_len + 1);
+ strcpy (result, tmpdir_buf);
+ strcpy (result + tmpdir_len, file_template_buf);
+
+ return result;
+}
+
/* Compile a playback::context:

- Use the context's options to cconstruct command-line options, and
@@ -4845,7 +4883,7 @@ compile ()
const char *fake_args[20];
unsigned int num_args;

- m_path_template = xstrdup ("/tmp/libgccjit-XXXXXX");
+ m_path_template = make_tempdir_path_template ();
if (!m_path_template)
return NULL;

diff --git a/include/ChangeLog.jit b/include/ChangeLog.jit
new file mode 100644
index 0000000..84acd33
--- /dev/null
+++ b/include/ChangeLog.jit
@@ -0,0 +1,11 @@
+2014-09-25 David Malcolm <***@redhat.com>
+
+ * libiberty.h (choose_tmpdir): New prototype.
+ * ChangeLog.jit: New.
+
+
+Copyright (C) 2014 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/include/libiberty.h b/include/libiberty.h
index 56b8b43..7802501 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -227,6 +227,11 @@ extern char *make_relative_prefix (const char *, const char *,
extern char *make_relative_prefix_ignore_links (const char *, const char *,
const char *) ATTRIBUTE_MALLOC;

+/* Returns a pointer to a directory path suitable for creating temporary
+ files in. */
+
+extern const char *choose_tmpdir (void) ATTRIBUTE_RETURNS_NONNULL;
+
/* Choose a temporary directory to use for scratch files. */

extern char *choose_temp_base (void) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
diff --git a/libiberty/ChangeLog.jit b/libiberty/ChangeLog.jit
index 52328e3..5b64f80 100644
--- a/libiberty/ChangeLog.jit
+++ b/libiberty/ChangeLog.jit
@@ -1,3 +1,12 @@
+2014-09-25 David Malcolm <***@redhat.com>
+
+ * choose-temp.c (choose_tmpdir): Remove now-redundant local
+ copy of prototype.
+ * functions.texi: Regenerate.
+ * make-temp-file.c (choose_tmpdir): Convert return type from
+ char * to const char * - given that this returns a pointer to
+ a memoized allocation, the caller must not touch it.
+
2014-09-24 David Malcolm <***@redhat.com>

* ChangeLog.jit: Add copyright footer.
diff --git a/libiberty/choose-temp.c b/libiberty/choose-temp.c
index 0a454cf..8e1e84b 100644
--- a/libiberty/choose-temp.c
+++ b/libiberty/choose-temp.c
@@ -34,7 +34,6 @@ Boston, MA 02110-1301, USA. */
#endif

#include "libiberty.h"
-extern char *choose_tmpdir (void);

/* Name of temporary file.
mktemp requires 6 trailing X's. */
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index 9323ff9..387aee0 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -125,7 +125,7 @@ Uses @code{malloc} to allocate storage for @var{nelem} objects of

@end deftypefn

-@c choose-temp.c:46
+@c choose-temp.c:45
@deftypefn Extension char* choose_temp_base (void)

Return a prefix for temporary file names or @code{NULL} if unable to
@@ -139,7 +139,7 @@ not recommended.
@end deftypefn

@c make-temp-file.c:96
-@deftypefn Replacement char* choose_tmpdir ()
+@deftypefn Replacement const char* choose_tmpdir ()

Returns a pointer to a directory path suitable for creating temporary
files in.
@@ -160,9 +160,8 @@ number of seconds used.
@dots{}, @code{NULL})

Concatenate zero or more of strings and return the result in freshly
-@code{xmalloc}ed memory. Returns @code{NULL} if insufficient memory is
-available. The argument list is terminated by the first @code{NULL}
-pointer encountered. Pointers to empty strings are ignored.
+@code{xmalloc}ed memory. The argument list is terminated by the first
+@code{NULL} pointer encountered. Pointers to empty strings are ignored.

@end deftypefn

@@ -528,7 +527,7 @@ nineteen EBCDIC varying characters is tested; exercise caution.)
@end ftable
@end defvr

-@c hashtab.c:336
+@c hashtab.c:328
@deftypefn Supplemental htab_t htab_create_typed_alloc (size_t @var{size}, @
htab_hash @var{hash_f}, htab_eq @var{eq_f}, htab_del @var{del_f}, @
htab_alloc @var{alloc_tab_f}, htab_alloc @var{alloc_f}, @
@@ -1163,7 +1162,7 @@ control over the state of the random number generator.

@end deftypefn

-@c concat.c:174
+@c concat.c:160
@deftypefn Extension char* reconcat (char *@var{optr}, const char *@var{s1}, @
@dots{}, @code{NULL})

diff --git a/libiberty/make-temp-file.c b/libiberty/make-temp-file.c
index 7b74f81..244cc23 100644
--- a/libiberty/make-temp-file.c
+++ b/libiberty/make-temp-file.c
@@ -93,7 +93,7 @@ static char *memoized_tmpdir;

/*

-@deftypefn Replacement char* choose_tmpdir ()
+@deftypefn Replacement const char* choose_tmpdir ()

Returns a pointer to a directory path suitable for creating temporary
files in.
@@ -102,7 +102,7 @@ files in.

*/

-char *
+const char *
choose_tmpdir (void)
{
if (!memoized_tmpdir)
--
1.7.11.7
David Malcolm
2014-09-25 17:29:31 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
[...]
Post by Joseph S. Myers
* use libiberty's pexecute to run subprocesses, not "system" (building up
a string to pass to the shell always looks like a security hole, though in
this case it may in fact be safe);
[...]

libiberty.h has this deprecation comment about pexecute:

/* pexecute and pwait are the old pexecute interface, still here for
backward compatibility. Don't use these for new code. Instead,
use pex_init/pex_run/pex_get_status/pex_free, or pex_one. */

so I used pex_one when eliminating the "system" callsite.

Committed to branch dmalcolm/jit:

gcc/jit/ChangeLog.jit:
* internal-api.c (gcc::jit::playback::context::compile): Use
pex_one rather than system when invoking "gcc" to go from a .s
file to a .so file.
---
gcc/jit/ChangeLog.jit | 6 ++++++
gcc/jit/internal-api.c | 46 +++++++++++++++++++++++++++++++++++++---------
2 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index d66203a..9cbba20 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,11 @@
2014-09-25 David Malcolm <***@redhat.com>

+ * internal-api.c (gcc::jit::playback::context::compile): Use
+ pex_one rather than system when invoking "gcc" to go from a .s
+ file to a .so file.
+
+2014-09-25 David Malcolm <***@redhat.com>
+
* internal-api.c (make_tempdir_path_template): New.
(gcc::jit::playback::context::compile): Call
make_tempdir_path_template to make m_path_template, rather than
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 50fd83b..05ef544 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -4992,18 +4992,46 @@ compile ()
We could reuse parts of gcc/gcc.c to do this.
For now, just use the /usr/bin/gcc on the system...
*/
- /* FIXME: totally faking it for now, not even using pex */
{
auto_timevar assemble_timevar (TV_ASSEMBLE);
+ const char *errmsg;
+ const char *argv[6];
+ int exit_status = 0;
+ int err = 0;
+
+ argv[0] = "gcc";
+ argv[1] = "-shared";
+ /* The input: assembler. */
+ argv[2] = m_path_s_file;
+ /* The output: shared library. */
+ argv[3] = "-o";
+ argv[4] = m_path_so_file;
+ /* pex argv arrays are NULL-terminated. */
+ argv[5] = NULL;
+
+ errmsg = pex_one (PEX_SEARCH, /* int flags, */
+ "gcc", /* const char *executable */
+ const_cast<char * const *> (argv),
+ ctxt_progname, /* const char *pname */
+ NULL, /* const char *outname */
+ NULL, /* const char *errname */
+ &exit_status, /* int *status */
+ &err); /* int *err*/
+ if (errmsg)
+ {
+ add_error (NULL, "error invoking gcc harness: %s", errmsg);
+ return NULL;
+ }

- char cmd[1024];
- snprintf (cmd, 1024, "gcc -shared %s -o %s",
- m_path_s_file, m_path_so_file);
- if (0)
- printf ("cmd: %s\n", cmd);
- int ret = system (cmd);
- if (ret)
- return NULL;
+ /* pex_one can return a NULL errmsg when the executable wasn't
+ found (or doesn't exist), so trap these cases also. */
+ if (exit_status || err)
+ {
+ add_error (NULL,
+ "error invoking gcc harness: exit_status: %i err: %i",
+ exit_status, err);
+ return NULL;
+ }
}

// TODO: split out assembles vs linker
--
1.7.11.7
David Malcolm
2014-09-25 20:29:35 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
[...]
Post by Joseph S. Myers
* use the $(target_noncanonical)-gcc-$(version) name for the driver rather
than plain "gcc", to maximise the chance that it is actually the same
compiler the JIT library was built for (I realise you may not actually
depend on it being the same compiler, but that does seem best; in
principle in future it should be possible to load multiple copies of the
JIT library to JIT for different targets, so that code for an offload
accelerator can go through the JIT).
[...]

Should this have the $(exeext) suffix seen in Makefile.in?
$(target_noncanonical)-gcc-$(version)$(exeext)

The attached patch does this, by generating a new gcc-harness-name.h
and using that name in internal-api.c when invoking the harness.

That said, I haven't applied this to my branch yet, since it requires
the name to be findable on $PATH. Hence the user needs to
(A) build and install the driver, and
(B) $PATH needs to be updated accordingly.

(A) is a minor extra hurdle when developing. In my prebuilt RPM
packages I haven't actually been shipping the driver, just the libs,
relying on a sufficiently compatible harness around. That may be just
a side-effect of this not yet being in trunk.

As for (B), would it make sense to "bake in" the path to the binary into
the pex invocation, and hence to turn off PEX_SEARCH? If so, presumably
I need to somehow expand the Makefile's value of $(bindir) into
internal-api.c, right? (I tried this in configure.ac, but merely got
"$(exec_prefix)/bin" iirc).

A better long-term approach to this would be to extract the spec
machinery from gcc.c (perhaps into a "libdriver.a"?) and run it directly
from the jit library - but that's a rather involved patch, I suspect.

[...]
Post by Joseph S. Myers
[...] in
principle in future it should be possible to load multiple copies of the
JIT library to JIT for different targets, so that code for an offload
accelerator can go through the JIT).
I had a mini-brainstorm about JIT and accelerator support; here goes...
(Big caveat: the last time I hacked on GPUs was 12 years ago in my
past life as a game developer, when people were publishing papers on
using them for general compute purposes, iirc)

I wonder if the appropriate approach here is to have a single library
with multiple plugin backends e.g. one for the CPU, one for each GPU
family, with the ability to load multiple "backends" at once.

Unfortunately, "backend" is horribly overloaded here - I mean basically
all of gcc here, everything other than the libgccjit.h API seen by
client code.

In this model libgccjit.h and .c become the only real part of the library,
with all of the classes becoming abstract interfaces, with gcc_jit_context
implemented by the plugins.

The embedded copy of the bulk of gcc becomes the jit-plugin, and exposes
only a very narrow API to the main library, with almost all of the names
hidden from the linker.

That way you could have something like (assuming x86_64-unknown-linux
host cpu/os):

+-----------+ +------------+
|client code|----|libgccjit.so|
+-----------+ +------------+
|
| +-------------------------------+
|----|jit-plugin-x86_64-unknown-linux|
| +-------------------------------+
|
| +---------------------------+
|----|jit-plugin-some-accelerator|
| +---------------------------+
|
| +---------------------------------+
|----|jit-plugin-some-other-accelerator|
| +---------------------------------+
etc

I believe this would allow us to have multiple copies of gcc linked into
one process at once, each with their own idea of what their single
target is, whilst having a single "libgccjit.so" to avoid issues where
e.g. one client library want to use libgccjit.so for CPU-targetted
compilation, another wants it for GPU work.

Client code sends its code to a gcc_jit_context, which builds
optimized code for the appropriate CPU/accelerator that it's associated
with. One consistent API across CPU and all accelerators.

The execution model would need refining a bit; currently a
gcc_jit_result merely hands us a void* to be cast to the appropriate
type. We'd need to do some extra work to get it to be runnable on the
GPU presumably.

(Yes I know this is feature creep, I'm thinking about gcc 6.0 or later,
fwiw. But maybe it's doable without breaking the current client API).

[...]


Thoughts?
Dave

gcc/ChangeLog.jit:
* configure: Regenerate.
* configure.ac: Add generation of "gcc-harness-name.h".

gcc/jit/ChangeLog.jit:
* internal-api.c: Include "gcc-harness-name.h".
(gcc::jit::playback::context::compile): Run the executable named
GCC_HARNESS_NAME, rather than hardcoding "gcc".
---
gcc/configure | 6 ++++++
gcc/configure.ac | 6 ++++++
gcc/jit/internal-api.c | 6 ++++--
3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/configure b/gcc/configure
index c1922ac..8f2b8e7 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28148,6 +28148,12 @@ _ACEOF

fi

+# Generate gcc-harness-name.h containing GCC_HARNESS_NAME for the benefit
+# of jit/internal-api.c.
+cat > gcc-harness-name.h <<EOF
+#define GCC_HARNESS_NAME "${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}"
+EOF
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)

diff --git a/gcc/configure.ac b/gcc/configure.ac
index 6164cc2..01d35f2 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5675,6 +5675,12 @@ if test x"${LINKER_HASH_STYLE}" != x; then
[The linker hash style])
fi

+# Generate gcc-harness-name.h containing GCC_HARNESS_NAME for the benefit
+# of jit/internal-api.c.
+cat > gcc-harness-name.h <<EOF
+#define GCC_HARNESS_NAME "${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}"
+EOF
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)

diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 05ef544..e589642 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "print-tree.h"
#include "gimplify.h"
+#include "gcc-harness-name.h"

#include <pthread.h>

@@ -4998,8 +4999,9 @@ compile ()
const char *argv[6];
int exit_status = 0;
int err = 0;
+ const char *executable = GCC_HARNESS_NAME;

- argv[0] = "gcc";
+ argv[0] = executable;
argv[1] = "-shared";
/* The input: assembler. */
argv[2] = m_path_s_file;
@@ -5010,7 +5012,7 @@ compile ()
argv[5] = NULL;

errmsg = pex_one (PEX_SEARCH, /* int flags, */
- "gcc", /* const char *executable */
+ executable,
const_cast<char * const *> (argv),
ctxt_progname, /* const char *pname */
NULL, /* const char *outname */
--
1.8.5.3
Joseph S. Myers
2014-09-26 21:55:44 UTC
Permalink
Post by David Malcolm
Should this have the $(exeext) suffix seen in Makefile.in?
$(target_noncanonical)-gcc-$(version)$(exeext)
Depends on whether that's needed for the pex code to find it.
Post by David Malcolm
As for (B), would it make sense to "bake in" the path to the binary into
the pex invocation, and hence to turn off PEX_SEARCH? If so, presumably
I need to somehow expand the Makefile's value of $(bindir) into
internal-api.c, right? (I tried this in configure.ac, but merely got
"$(exec_prefix)/bin" iirc).
An installation must be relocatable. Thus, you can't just hardcode
looking in the configured prefix; you'd need to locate it relative to
libgccjit.so in some way (i.e. using make_relative_prefix, but I don't
know offhand how libgccjit.so would locate itself).
Post by David Malcolm
A better long-term approach to this would be to extract the spec
machinery from gcc.c (perhaps into a "libdriver.a"?) and run it directly
from the jit library - but that's a rather involved patch, I suspect.
And you'd still need libgccjit.so to locate itself for proper
relocatability in finding other pieces such as assembler and linker.
Post by David Malcolm
I wonder if the appropriate approach here is to have a single library
with multiple plugin backends e.g. one for the CPU, one for each GPU
family, with the ability to load multiple "backends" at once.
If you can get that working, sure.
Post by David Malcolm
Unfortunately, "backend" is horribly overloaded here - I mean basically
all of gcc here, everything other than the libgccjit.h API seen by
client code.
(Though preferably as much as possible could be shared, i.e. properly
define the parts of GCC that need building separately for each target and
limit them as much as possible. Joern's multi-target patches from 2010
that selectively built parts of GCC using namespaces while sharing others
without an obvious clear separation seemed very fragile. For something
robust you either build everything separately for each target, or have a
well-defined separation between bits needing building separately and bits
that can be built once and ways to avoid non-obvious target dependencies
in bits built once.)
--
Joseph S. Myers
***@codesourcery.com
David Malcolm
2014-10-07 14:26:55 UTC
Permalink
Post by Joseph S. Myers
Post by David Malcolm
Should this have the $(exeext) suffix seen in Makefile.in?
$(target_noncanonical)-gcc-$(version)$(exeext)
Depends on whether that's needed for the pex code to find it.
Post by David Malcolm
As for (B), would it make sense to "bake in" the path to the binary into
the pex invocation, and hence to turn off PEX_SEARCH? If so, presumably
I need to somehow expand the Makefile's value of $(bindir) into
internal-api.c, right? (I tried this in configure.ac, but merely got
"$(exec_prefix)/bin" iirc).
An installation must be relocatable. Thus, you can't just hardcode
looking in the configured prefix; you'd need to locate it relative to
libgccjit.so in some way (i.e. using make_relative_prefix, but I don't
know offhand how libgccjit.so would locate itself).
Post by David Malcolm
A better long-term approach to this would be to extract the spec
machinery from gcc.c (perhaps into a "libdriver.a"?) and run it directly
from the jit library - but that's a rather involved patch, I suspect.
And you'd still need libgccjit.so to locate itself for proper
relocatability in finding other pieces such as assembler and linker.
Post by David Malcolm
I wonder if the appropriate approach here is to have a single library
with multiple plugin backends e.g. one for the CPU, one for each GPU
family, with the ability to load multiple "backends" at once.
If you can get that working, sure.
Post by David Malcolm
Unfortunately, "backend" is horribly overloaded here - I mean basically
all of gcc here, everything other than the libgccjit.h API seen by
client code.
(Though preferably as much as possible could be shared, i.e. properly
define the parts of GCC that need building separately for each target and
limit them as much as possible. Joern's multi-target patches from 2010
that selectively built parts of GCC using namespaces while sharing others
without an obvious clear separation seemed very fragile. For something
robust you either build everything separately for each target, or have a
well-defined separation between bits needing building separately and bits
that can be built once and ways to avoid non-obvious target dependencies
in bits built once.)
I've been experimenting with directly embedding the gcc.c driver code
in-process, but that patch was getting unwieldy, so for now, I'm going
with the simpler approach: just call the driver out-of-process,
specifying the full installed name:
$(target_noncanonical)-gcc-$(version)$(exeext)
as expanded at configuration time, requiring it to be on the PATH.

Hopefully this addresses the last of the concerns raised in your initial
review; I'll do some more testing and then try to resubmit to the list
(I'm also thinking about breaking up internal-api.c/h, as they've become
rather large, into jit-recording/jit-playback.c/h)

Committed to branch dmalcolm/jit:

gcc/ChangeLog.jit:
* Makefile.in (site.exp): When constructing site.exp, add a line
to set "bindir".
* configure.ac: Generate a gcc-driver-name.h file containing
GCC_DRIVER_NAME for the benefit of jit/internal-api.c.
* configure: Regenerate.

gcc/jit/ChangeLog.jit:
* docs/internals/index.rst
(Using a working copy without installing): Rename to...
(Using a working copy without installing every time): ...this, and
update to reflect the need to have installed the driver binary
when running directly from a build directory.
(Running the test suite): Add PATH setting to the example.
* docs/intro/install.rst ("Hello world"): Likewise.
* internal-api.c: Include new autogenerated header
"gcc-driver-name.h".
(gcc::jit::playback::context::compile): Rather than looking for a
"gcc" on the path, look for GCC_DRIVER_NAME from gcc-driver-name.h,
as created by the configure script, so that we are using one for
the correct target.

gcc/testsuite/ChangeLog.jit:
* jit.dg/jit.exp (jit-dg-test): Prepend the installed bindir to
the PATH before invoking built binaries using the library, so that
the library can find the driver. Restore the PATH immediately
afterwards.
---
gcc/ChangeLog.jit | 8 +++++
gcc/Makefile.in | 1 +
gcc/configure | 6 ++++
gcc/configure.ac | 6 ++++
gcc/jit/ChangeLog.jit | 16 ++++++++++
gcc/jit/docs/internals/index.rst | 64 ++++++++++++++++++++++++++++++++++++----
gcc/jit/docs/intro/install.rst | 36 ++++++++++++++--------
gcc/jit/internal-api.c | 10 +++++--
gcc/testsuite/ChangeLog.jit | 7 +++++
gcc/testsuite/jit.dg/jit.exp | 14 +++++++++
10 files changed, 147 insertions(+), 21 deletions(-)

diff --git a/gcc/ChangeLog.jit b/gcc/ChangeLog.jit
index e71f7c4..ca73c04 100644
--- a/gcc/ChangeLog.jit
+++ b/gcc/ChangeLog.jit
@@ -1,3 +1,11 @@
+2014-10-07 David Malcolm <***@redhat.com>
+
+ * Makefile.in (site.exp): When constructing site.exp, add a line
+ to set "bindir".
+ * configure.ac: Generate a gcc-driver-name.h file containing
+ GCC_DRIVER_NAME for the benefit of jit/internal-api.c.
+ * configure: Regenerate.
+
2014-10-03 David Malcolm <***@redhat.com>

* diagnostic.c (diagnostic_finish): Free the memory for
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 069a6e8..f5e3d4c 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3504,6 +3504,7 @@ site.exp: ./config.status Makefile
@echo "# add them to the last section" >> ./site.tmp
@echo "set rootme \"`${PWD_COMMAND}`\"" >> ./site.tmp
@echo "set srcdir \"`cd ${srcdir}; ${PWD_COMMAND}`\"" >> ./site.tmp
+ @echo "set bindir \"`cd ${bindir}; ${PWD_COMMAND}`\"" >> ./site.tmp
@echo "set host_triplet $(host)" >> ./site.tmp
@echo "set build_triplet $(build)" >> ./site.tmp
@echo "set target_triplet $(target)" >> ./site.tmp
diff --git a/gcc/configure b/gcc/configure
index b943c20..8ec141f 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28190,6 +28190,12 @@ _ACEOF

fi

+# Generate gcc-driver-name.h containing GCC_DRIVER_NAME for the benefit
+# of jit/internal-api.c.
+cat > gcc-driver-name.h <<EOF
+#define GCC_DRIVER_NAME "${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}"
+EOF
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)

diff --git a/gcc/configure.ac b/gcc/configure.ac
index 7319f1c..62e5ad7 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5679,6 +5679,12 @@ if test x"${LINKER_HASH_STYLE}" != x; then
[The linker hash style])
fi

+# Generate gcc-driver-name.h containing GCC_DRIVER_NAME for the benefit
+# of jit/internal-api.c.
+cat > gcc-driver-name.h <<EOF
+#define GCC_DRIVER_NAME "${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}"
+EOF
+
# Configure the subdirectories
# AC_CONFIG_SUBDIRS($subdirs)

diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index ac8f28d..07438b9 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,3 +1,19 @@
+2014-10-07 David Malcolm <***@redhat.com>
+
+ * docs/internals/index.rst
+ (Using a working copy without installing): Rename to...
+ (Using a working copy without installing every time): ...this, and
+ update to reflect the need to have installed the driver binary
+ when running directly from a build directory.
+ (Running the test suite): Add PATH setting to the example.
+ * docs/intro/install.rst ("Hello world"): Likewise.
+ * internal-api.c: Include new autogenerated header
+ "gcc-driver-name.h".
+ (gcc::jit::playback::context::compile): Rather than looking for a
+ "gcc" on the path, look for GCC_DRIVER_NAME from gcc-driver-name.h,
+ as created by the configure script, so that we are using one for
+ the correct target.
+
2014-09-26 David Malcolm <***@redhat.com>

* internal-api.h (gcc::jit::recording::context): Convert field
diff --git a/gcc/jit/docs/internals/index.rst b/gcc/jit/docs/internals/index.rst
index 9765862..7823b12 100644
--- a/gcc/jit/docs/internals/index.rst
+++ b/gcc/jit/docs/internals/index.rst
@@ -18,17 +18,66 @@
Internals
=========

-Using a working copy without installing
----------------------------------------
+Using a working copy without installing every time
+--------------------------------------------------
When directly working on the library you can avoid needing to install to
-test changes.
+test every change.
+
+You need to do a ``make install`` of the ``gcc`` subdirectory to install
+the driver binary (the top-level ``gcc`` binary). This is used internally
+by the library for converting from .s assembler files to .so shared
+libraries. Specifically, it looks for an executable on the ``$PATH`` with
+a name expanded by the ``configure`` script from
+``${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}``,
+such as ``x86_64-unknown-linux-gnu-gcc-5.0.0``.
+
+For example, if you configured with a prefix of ``$PREFIX`` like this:
+
+.. code-block:: bash
+
+ mkdir build
+ mkdir install
+ PREFIX=$(pwd)/install
+ cd build
+ ../src/configure \
+ --enable-host-shared \
+ --enable-languages=jit \
+ --disable-bootstrap \
+ --enable-checking=release \
+ --prefix=$PREFIX
+
+then you can install (once) to ensure that ``$PREFIX/bin/`` is populated:
+
+.. code-block:: console
+
+ [build]$ ll ../install/bin/*gcc*
+ -rwxr-xr-x. 3 david david 2733458 Oct 6 14:25 ../install/bin/gcc
+ -rwxr-xr-x. 2 david david 136921 Oct 6 14:25 ../install/bin/gcc-ar
+ -rwxr-xr-x. 2 david david 136857 Oct 6 14:25 ../install/bin/gcc-nm
+ -rwxr-xr-x. 2 david david 136869 Oct 6 14:25 ../install/bin/gcc-ranlib
+ -rwxr-xr-x. 3 david david 2733458 Oct 6 14:25 ../install/bin/x86_64-unknown-linux-gnu-gcc
+ -rwxr-xr-x. 3 david david 2733458 Oct 6 14:25 ../install/bin/x86_64-unknown-linux-gnu-gcc-5.0.0
+ -rwxr-xr-x. 2 david david 136921 Oct 6 14:25 ../install/bin/x86_64-unknown-linux-gnu-gcc-ar
+ -rwxr-xr-x. 2 david david 136857 Oct 6 14:25 ../install/bin/x86_64-unknown-linux-gnu-gcc-nm
+ -rwxr-xr-x. 2 david david 136869 Oct 6 14:25 ../install/bin/x86_64-unknown-linux-gnu-gcc-ranlib
+
+Note the presence above of ``../install/bin/x86_64-unknown-linux-gnu-gcc``.

When building code using the API you need to ensure that ``-I`` points to
the directory containing ``libgccjit.h`` and ``-L`` points to the
directory containing the built library.

-You'll need to manually set ``LD_LIBRARY_PATH`` to the directory containing
-``libgccjit.so`` when running binaries (or debugging them).
+When running binaries (or debugging them), you'll need to manually set
+``LD_LIBRARY_PATH`` to the directory containing ``libgccjit.so``, and
+``PATH`` needs to contain the path to the installed binaries.
+
+and then you can run from a built (but not installed) copy:
+
+.. code-block:: console
+
+ [gcc]$ PATH=../../install/bin:$PATH LD_LIBRARY_PATH=. ./testsuite/jit/test-factorial.exe
+
+without needing to reinstall everything for every tweak to the library.

Running the test suite
----------------------
@@ -68,7 +117,10 @@ and once a test has been compiled, you can debug it directly:

.. code-block:: console

- [gcc] $ LD_LIBRARY_PATH=. gdb testsuite/jit/test-factorial.exe
+ [gcc] $ PATH=../../install/bin:$PATH \
+ LD_LIBRARY_PATH=. \
+ gdb --args \
+ testsuite/jit/test-factorial.exe


Overview of code structure
diff --git a/gcc/jit/docs/intro/install.rst b/gcc/jit/docs/intro/install.rst
index 0e14db0..a0641b7 100644
--- a/gcc/jit/docs/intro/install.rst
+++ b/gcc/jit/docs/intro/install.rst
@@ -189,17 +189,6 @@ specify the compilation and linkage flags:
-o jit-hello-world \
$(pkg-config libgccjit --cflags --libs)

-and ensure that `LD_LIBRARY_PATH` is set appropriate when running the
-built program, so that it can locate and dynamically link against
-`libgccjit.so`:
-
-.. code-block:: console
-
- # Run the built program:
- $ export LD_LIBRARY_PATH=$PREFIX/lib
- $ ./jit-hello-world
- hello world
-
This is equivalent to handcoding the include and library paths with `-I`
and `-L` and specifying `-lgccjit` (i.e. linkage against libgccjit):

@@ -211,5 +200,28 @@ and `-L` and specifying `-lgccjit` (i.e. linkage against libgccjit):
-lgccjit \
-I$PREFIX/include -L$PREFIX/lib

- $ LD_LIBRARY_PATH=$PREFIX/lib ./jit-hello-world
+When running the built test program against a locally-built tree, two
+environment variables need to be set up:
+
+* `LD_LIBRARY_PATH` needs to be set up appropriately so that the dynamic
+ linker can locate the `libgccjit.so`
+
+* `PATH` needs to include the `bin` subdirectory below the installation
+ prefix, so that the library can locate a driver binary. This is used
+ internally by the library for converting from .s assembler files to
+ .so shared libraries.
+
+ ..
+ Specifically, it looks for a name expanded from
+ ``${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}`` on the
+ ``$PATH``, such as ``x86_64-unknown-linux-gnu-gcc-5.0.0``).
+
+For example, if you configured with a prefix of ``$PREFIX`` like above,
+you need an invocation like this:
+
+.. code-block:: console
+
+ $ LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH \
+ PATH=$PREFIX/bin:$PATH \
+ ./jit-hello-world
hello world
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 8ef9af9..6849403 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "print-tree.h"
#include "gimplify.h"
+#include "gcc-driver-name.h"

#include <pthread.h>

@@ -4998,7 +4999,9 @@ compile ()
/* Gross hacks follow:
We have a .s file; we want a .so file.
We could reuse parts of gcc/gcc.c to do this.
- For now, just use the /usr/bin/gcc on the system...
+ For now, just use the driver binary from the install, as
+ named in gcc-driver-name.h
+ e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0".
*/
{
auto_timevar assemble_timevar (TV_ASSEMBLE);
@@ -5006,8 +5009,9 @@ compile ()
const char *argv[6];
int exit_status = 0;
int err = 0;
+ const char *gcc_driver_name = GCC_DRIVER_NAME;

- argv[0] = "gcc";
+ argv[0] = gcc_driver_name;
argv[1] = "-shared";
/* The input: assembler. */
argv[2] = m_path_s_file;
@@ -5018,7 +5022,7 @@ compile ()
argv[5] = NULL;

errmsg = pex_one (PEX_SEARCH, /* int flags, */
- "gcc", /* const char *executable */
+ gcc_driver_name,
const_cast<char * const *> (argv),
ctxt_progname, /* const char *pname */
NULL, /* const char *outname */
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index 4572c3d..798f7c9 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,3 +1,10 @@
+2014-10-07 David Malcolm <***@redhat.com>
+
+ * jit.dg/jit.exp (jit-dg-test): Prepend the installed bindir to
+ the PATH before invoking built binaries using the library, so that
+ the library can find the driver. Restore the PATH immediately
+ afterwards.
+
2014-09-24 David Malcolm <***@redhat.com>

* ChangeLog.jit: Add copyright footer.
diff --git a/gcc/testsuite/jit.dg/jit.exp b/gcc/testsuite/jit.dg/jit.exp
index 7986185..4672063 100644
--- a/gcc/testsuite/jit.dg/jit.exp
+++ b/gcc/testsuite/jit.dg/jit.exp
@@ -92,12 +92,26 @@ proc jit-dg-test { prog do_what extra_tool_flags } {
#
unsetenv GCC_EXEC_PREFIX

+ # libgccjit uses the driver to convert .s files to .so libraries
+ # via its *installed* name, the expansion of:
+ # ${target_noncanonical}-gcc-${gcc_BASEVER}${exeext}
+ # e.g. "x86_64-unknown-linux-gnu-gcc-5.0.0"
+ # looking for it on PATH. Hence we need to prepend the installation
+ # bindir to PATH when running the tests
+ global env
+ global bindir
+ set old_path $env(PATH)
+ setenv "PATH" $bindir:$env(PATH)
+
# dejagnu.exp's host_execute has code to scrape out test results
# from the DejaGnu C API and bring back into the tcl world, so we
# use that to invoke the built code:
set result [host_execute $output_file]
verbose "result: $result"

+ # Restore PATH
+ setenv "PATH" $old_path
+
restore_ld_library_path_env_vars
}
--
1.7.11.7
David Malcolm
2014-09-26 20:27:31 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
[...]
Post by Joseph S. Myers
* use libiberty's pexecute to run subprocesses, not "system" (building up
a string to pass to the shell always looks like a security hole, though in
this case it may in fact be safe);
* use the $(target_noncanonical)-gcc-$(version) name for the driver rather
than plain "gcc", to maximise the chance that it is actually the same
compiler the JIT library was built for (I realise you may not actually
depend on it being the same compiler, but that does seem best; in
principle in future it should be possible to load multiple copies of the
JIT library to JIT for different targets, so that code for an offload
accelerator can go through the JIT).
[...]

The JIT generates assembler, but needs to generate a shared library.
Currently it invokes a "gcc" driver binary to go from .s to .so

I had the idea of turning the driver code in gcc.c into a library
and using it directly, in-process.

This experiment renames "main" in gcc.c to "driver_main" for use by
the insides of the JIT library, adding a gcc-main.c with a "main" that
simply calls "driver_main" (rather like how we have main.c calling
toplev_main for use by cc1 etc).

I can then call driver_main from inside the JIT library, and call a
new "driver_finalize" function to try to cleanup state in gcc.c enough
to support repeated calls.

I have to set LIBRARY_PATH so that the "ln" invocation can find -lgcc
and -lgcc_s:

LD_LIBRARY_PATH=. \
LIBRARY_PATH=../../install/lib/gcc/x86_64-unknown-linux-gnu/5.0.0:../../install/lib \
gdb --args \
testsuite/jit/test-factorial.exe

I also pass -fno-use-linker-plugin to driver_main to stop path issues
locating that.

This works for 5 or 6 in-process iterations, but eventually dies with:
test-factorial.exe: error trying to exec 'ld': execvp: Argument list too long

LIBRARY_PATH in the process' environment gets crazily long; what I think
is happening is that gcc.c uses getenv("LIBRARY_PATH"), processes the result
somewhat, then uses putenv("LIBRARY_PATH"), leading to (I think) an
exponential explosion in the length of LIBRARY_PATH in the process's env
(and the eventual failure seen above).

Other than that... my simple testcase seems to work.

In crude perftesting it currently seems to be slightly *slower*; e.g.:

Using driver_main, buggily:
assemble JIT code : 0.00 ( 0%) usr 0.04 (80%) sys 0.18 (49%) wall 0 kB ( 0%) ggc
TOTAL : 0.16 0.05 0.37 2348 kB

Using a subprocess:
assemble JIT code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.15 (48%) wall 0 kB ( 0%) ggc
TOTAL : 0.14 0.02 0.31 2348 kB

Perhaps this is because of the env accumulation bug above, or maybe I'm
doing an apples-to-oranges comparison somewhere.

Not committing this; just posting it for discussion and archival.

gcc/ChangeLog.jit:
* Makefile.in (GCC_OBJS): Add gcc-main.o.
* gcc/gcc-main.c: New file, implementing just a "main".
* gcc.c (main): Rename to...
(driver_main): ...this.
(driver_finalize): New function.
* gcc.h (driver_main): New prototype.
(driver_finalize): Likewise.

gcc/jit/ChangeLog.jit:
* Make-lang.in (jit_OBJS): Add gcc.o so that we can use
driver_main, and jitspec.o to provide implementations of functions
needed by it. Put .o files on individual lines, sorted
alphabetically.
(LIBGCCJIT_FILENAME): Add $(EXTRA_GCC_OBJS) $(EXTRA_GCC_LIBS) to
the linkage line (and deps), so that we can pick up the
config's implementation of "host_detect_local_cpu", which is
needed by gcc.o.
* internal-api.c: Include gcc.h.
(gcc::jit::playback::context::compile): Rewrite invocation of
assembler and linker to simply call into driver_main in-process,
rather than invoking "gcc". Keep the old code around for now
for performance testing.
* jitspec.c: New file, providing implementations of functions
and variables needed by gcc.o: functions lang_specific_driver
and lang_specific_pre_link, and variable
lang_specific_extra_outfiles.
* notes.txt: Show the invocation of driver_main and
driver_finalize.
---
gcc/Makefile.in | 2 +-
gcc/gcc-main.c | 31 +++++++++++++++++++++++++++++++
gcc/gcc.c | 20 +++++++++++++++++---
gcc/gcc.h | 7 +++++++
gcc/jit/Make-lang.in | 11 +++++++++--
gcc/jit/internal-api.c | 38 +++++++++++++++++++++++++++++++++-----
gcc/jit/jitspec.c | 42 ++++++++++++++++++++++++++++++++++++++++++
gcc/jit/notes.txt | 11 +++++++++--
8 files changed, 149 insertions(+), 13 deletions(-)
create mode 100644 gcc/gcc-main.c
create mode 100644 gcc/jit/jitspec.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f56fa96..151d967 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1140,7 +1140,7 @@ CXX_TARGET_OBJS=@cxx_target_objs@
FORTRAN_TARGET_OBJS=@fortran_target_objs@

# Object files for gcc many-languages driver.
-GCC_OBJS = gcc.o ggc-none.o
+GCC_OBJS = gcc.o gcc-main.o ggc-none.o

c-family-warn = $(STRICT_WARN)

diff --git a/gcc/gcc-main.c b/gcc/gcc-main.c
new file mode 100644
index 0000000..923d746
--- /dev/null
+++ b/gcc/gcc-main.c
@@ -0,0 +1,31 @@
+/* Compiler driver program that can handle many languages.
+ Copyright (C) 1987-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "gcc.h"
+
+extern int main (int, char **);
+
+int
+main (int argc, char **argv)
+{
+ return driver_main (argc, argv);
+}
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..0d9de35 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -6369,10 +6369,8 @@ compare_files (char *cmpfile[])
return ret;
}

-extern int main (int, char **);
-
int
-main (int argc, char **argv)
+driver_main (int argc, char **argv)
{
size_t i;
int value;
@@ -8776,3 +8774,19 @@ convert_white_space (char *orig)
else
return orig;
}
+
+void
+driver_finalize (void)
+{
+ params_c_finalize ();
+
+ user_specs_head = NULL;
+ user_specs_tail = NULL;
+
+ mdswitches = NULL;
+ n_mdswitches = 0;
+
+ switches = NULL;
+ n_switches = 0;
+ n_switches_alloc = 0;
+}
diff --git a/gcc/gcc.h b/gcc/gcc.h
index c4a27a8..7c4b680 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -55,4 +55,11 @@ extern int lang_specific_extra_outfiles;

extern const char **outfiles;

+/* Entrypoint to the driver. */
+extern int driver_main (int argc, char **argv);
+
+/* Clean up state, for those that want to call the driver multiple times
+ in one process. */
+extern void driver_finalize (void);
+
#endif /* ! GCC_GCC_H */
diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
index 26dd022..03b7839 100644
--- a/gcc/jit/Make-lang.in
+++ b/gcc/jit/Make-lang.in
@@ -56,8 +56,13 @@ jit: $(LIBGCCJIT_FILENAME) $(LIBGCCJIT_SYMLINK) $(LIBGCCJIT_LINKER_NAME_SYMLINK)
# Tell GNU make to ignore these if they exist.
.PHONY: jit

-jit_OBJS = attribs.o jit/dummy-frontend.o jit/libgccjit.o jit/internal-api.o \
- jit/jit-builtins.o
+jit_OBJS = attribs.o \
+ gcc.o \
+ jit/dummy-frontend.o \
+ jit/internal-api.o \
+ jit/jit-builtins.o \
+ jit/jitspec.o \
+ jit/libgccjit.o

# Use strict warnings for this front end.
jit-warn = $(STRICT_WARN)
@@ -65,12 +70,14 @@ jit-warn = $(STRICT_WARN)
# We avoid using $(BACKEND) from Makefile.in in order to avoid pulling
# in main.o
$(LIBGCCJIT_FILENAME): $(jit_OBJS) \
+ $(EXTRA_GCC_OBJS) $(EXTRA_GCC_LIBS) \
libbackend.a libcommon-target.a libcommon.a \
$(CPPLIB) $(LIBDECNUMBER) \
$(LIBDEPS) $(srcdir)/jit/libgccjit.map
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ -shared \
$(jit_OBJS) libbackend.a libcommon-target.a libcommon.a \
$(CPPLIB) $(LIBDECNUMBER) $(LIBS) $(BACKENDLIBS) \
+ $(EXTRA_GCC_OBJS) $(EXTRA_GCC_LIBS) \
-Wl,--version-script=$(srcdir)/jit/libgccjit.map \
-Wl,-soname,$(LIBGCCJIT_SONAME)

diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 8ef9af9..3fe543b 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "print-tree.h"
#include "gimplify.h"
+#include "gcc.h"

#include <pthread.h>

@@ -4995,11 +4996,37 @@ compile ()
if (get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE))
dump_generated_code ();

- /* Gross hacks follow:
- We have a .s file; we want a .so file.
- We could reuse parts of gcc/gcc.c to do this.
- For now, just use the /usr/bin/gcc on the system...
- */
+ /* We have a .s file; we want a .so file. */
+#if 1
+ /*
+ Directly use the driver code in-process to invoke the appropriate
+ assembler and linker. */
+ {
+ auto_timevar assemble_timevar (TV_ASSEMBLE);
+ const char *argv[7];
+ int result;
+
+ argv[0] = fake_args[0];
+ argv[1] = "-shared";
+ /* The input: assembler. */
+ argv[2] = m_path_s_file;
+ /* The output: shared library. */
+ argv[3] = "-o";
+ argv[4] = m_path_so_file;
+ argv[5] = "-fno-use-linker-plugin";
+ argv[6] = "-v";
+
+ result = driver_main (7, const_cast <char **> (argv));
+ driver_finalize ();
+
+ if (result)
+ {
+ add_error (NULL, "error invoking gcc driver");
+ return NULL;
+ }
+ }
+#else
+ /* Invoke another gcc. */
{
auto_timevar assemble_timevar (TV_ASSEMBLE);
const char *errmsg;
@@ -5041,6 +5068,7 @@ compile ()
return NULL;
}
}
+#endif

// TODO: split out assembles vs linker

diff --git a/gcc/jit/jitspec.c b/gcc/jit/jitspec.c
new file mode 100644
index 0000000..62f5153
--- /dev/null
+++ b/gcc/jit/jitspec.c
@@ -0,0 +1,42 @@
+/* jitspec.c -- Specific flags and argument handling for the driver
+ Copyright (C) 2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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 GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "gcc.h"
+#include "opts.h"
+
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options ATTRIBUTE_UNUSED,
+ unsigned int *in_decoded_options_count ATTRIBUTE_UNUSED,
+ int *in_added_libraries ATTRIBUTE_UNUSED)
+{
+ /* empty for the jit. */
+}
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link (void) /* Not used for jit. */
+{
+ return 0;
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for jit. */
diff --git a/gcc/jit/notes.txt b/gcc/jit/notes.txt
index 54dca8f..daf58a1 100644
--- a/gcc/jit/notes.txt
+++ b/gcc/jit/notes.txt
@@ -60,9 +60,16 @@ Client Code . Generated . libgccjit.so
. . . . (the middle─end and backend)
. . . . ↓
. . <───────────────────────────── end of toplev::main
- . . │ RELEASE MUTEX .
. . │ . .
- . . │ Convert assembler to DSO
+ . . V . .
+ . . --> Convert assembler to DSO:
+ . . driver_main ()
+ . . invocation of "as"
+ . . invocation of "ld"
+ . . driver_finalize ()
+ . . <----
+ . . │ . .
+ . . │ RELEASE MUTEX .
. . │ . .
. . │ Load DSO .
<─────────────────────────── . .
--
1.8.5.3
David Malcolm
2014-10-02 16:12:27 UTC
Permalink
On Tue, 2014-09-23 at 23:27 +0000, Joseph S. Myers wrote:
[...]
Post by Joseph S. Myers
Shouldn't the jit.pdf, jit.install-html etc. Make-lang.in hooks actually
build / install the documentation for this JIT?
[...]

I've committed the following to the branch dmalcolm/jit:

This patch implements the documentation targets:
* jit.info
* jit.install-info
* jit.dvi
* jit.pdf
* jit.install-pdf
* jit.install-html
* jit.html
within jit/Make-lang.in, and adds detection of "sphinx-build" to the gcc
configure script.

It uses sphinx (if available) to generate the HTML jit documentation, with
texinfo as a fallback, and texinfo for the other formats.

gcc/ChangeLog.jit:
* configure.ac (doc_build_sys): New variable, set to "sphinx" if
sphinx is installed, falling back to "texinfo" otherwise.
* configure: Regenerate.
* Makefile.in (doc_build_sys): New.

gcc/jit/ChangeLog.jit:
* Make-lang.in (jit.info): Implement.
(jit.install-info): Implement.
(jit.dvi): Implement.
(jit.pdf): Implement in terms of new target "jit.texinfo.pdf".
(jit.install-pdf): Likewise for new target
"jit.texinfo.install-pdf".
(jit.install-html): Implement in terms of
"jit.$(doc_build_sys).install-html" to redirect to new targets
"jit.sphinx.install-html" or "jit.texinfo.install-html".
(jit.html): Implement in terms of "jit.$(doc_build_sys).html" to
redirect to new targets "jit.sphinx.html" or "jit.texinfo.html".
(JIT_TEXI_FILES): New variable.
(jit.texinfo.html): New target.
(jit.texinfo.install-html): New target.
(jit.texinfo.pdf): New target.
(jit.texinfo.install-pdf): New target.
(SPHINX_BUILD_DIR): New variable.
(jit.sphinx.html): New target.
(jit_htmldir): New variable.
(jit.sphinx.install-html): New target.
(jit.sphinx.pdf): New target.
---
gcc/Makefile.in | 5 ++
gcc/configure | 46 +++++++++++++++-
gcc/configure.ac | 4 ++
gcc/jit/Make-lang.in | 148 ++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 194 insertions(+), 9 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f56fa96..ae2c6e5 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -310,6 +310,11 @@ write_entries_to_file = $(shell rm -f $(2) || :) $(shell touch $(2)) \
$(shell expr $(range) + $(write_entries_to_file_split) - 1), $(1))" \
| tr ' ' '\012' >> $(2)))

+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# configure sets "doc_build_sys" to "sphinx" or "texinfo" accordingly
+doc_build_sys=@doc_build_sys@
+
# --------
# UNSORTED
# --------
diff --git a/gcc/configure b/gcc/configure
index c1922ac..0eccf67 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -743,6 +743,7 @@ CXXDEPMODE
DEPDIR
am__leading_dot
CXXCPP
+doc_build_sys
AR
NM
BISON
@@ -8062,6 +8063,47 @@ fi

fi

+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# Set "doc_build_sys" to "sphinx" or "texinfo" accordingly.
+# Extract the first word of "sphinx-build", so it can be a program name with args.
+set dummy sphinx-build; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_doc_build_sys+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$doc_build_sys"; then
+ ac_cv_prog_doc_build_sys="$doc_build_sys" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_doc_build_sys="sphinx"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_doc_build_sys" && ac_cv_prog_doc_build_sys="texinfo"
+fi
+fi
+doc_build_sys=$ac_cv_prog_doc_build_sys
+if test -n "$doc_build_sys"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doc_build_sys" >&5
+$as_echo "$doc_build_sys" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+

# --------------------
# Checks for C headers
@@ -18035,7 +18077,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18038 "configure"
+#line 18080 "configure"
#include "confdefs.h"

#if HAVE_DLFCN_H
@@ -18141,7 +18183,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18144 "configure"
+#line 18186 "configure"
#include "confdefs.h"

#if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 6164cc2..5b78b65 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -972,6 +972,10 @@ else
AC_CHECK_PROG(AR, ar, ar, ${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing ar)
fi

+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# Set "doc_build_sys" to "sphinx" or "texinfo" accordingly.
+AC_CHECK_PROG(doc_build_sys, sphinx-build, sphinx, texinfo)

# --------------------
# Checks for C headers
diff --git a/gcc/jit/Make-lang.in b/gcc/jit/Make-lang.in
index 26dd022..e79d5d0 100644
--- a/gcc/jit/Make-lang.in
+++ b/gcc/jit/Make-lang.in
@@ -86,13 +86,147 @@ $(LIBGCCJIT_LINKER_NAME_SYMLINK): $(LIBGCCJIT_SONAME_SYMLINK)
jit.all.cross:
jit.start.encap:
jit.rest.encap:
-jit.info:
-jit.install-info:
-jit.dvi:
-jit.pdf:
-jit.install-pdf:
-jit.install-html:
-jit.html:
+
+# Documentation build hooks.
+#
+# The documentation can be built using the texinfo toolchain, or
+# the sphinx toolchain
+#
+# The jit documentation is authored using Sphinx, which has numerous
+# advantages over Texinfo, including:
+#
+# * much faster
+#
+# * use of CSS and JS to provide less of a 1990s feel in the generated
+# HTML.
+#
+# * sane, stable HTML page and anchor names
+#
+# * sane HTML navigation: ability to move forward and back in the HTML
+# at every node to read the HTML like a book
+#
+# * syntax-coloring of examples
+#
+# * the ability to "include" fragments of code inline. This is used
+# heavily by the jit docs, so that the example code is shared by both
+# the test suite and the documentation to ensure that the examples
+# appearing in the docs actually compile and work
+#
+# Sphinx is not a "blessed" dependency, and so a prebuilt libgccjit.texinfo
+# file built by Sphinx is checked into the source tree to avoid requiring
+# everyone to have Sphinx installed.
+#
+# This prebuilt libgccjit.texinfo has the "include" fragments "baked in",
+# and so contains the content from the sphinx toolchain, but lacks the
+# syntax-coloring, and the generated HTML is (IMHO) greatly inferior to
+# that generated by Sphinx.
+
+# These targets redirect HTML creation and installation to either
+# jit.sphinx.(install-)html or jit.texinfo.(install-)html.
+jit.html: jit.$(doc_build_sys).html
+jit.install-html: jit.$(doc_build_sys).install-html
+
+# For now, use texinfo for pdf, since the sphinx latex toolchain currently
+# fails for me deep inside pdflatex (see notes below)
+jit.pdf: jit.texinfo.pdf
+jit.install-pdf: jit.texinfo.install-pdf
+
+# Hooks for building docs using texinfo
+JIT_TEXI_FILES = $(srcdir)/jit/docs/_build/texinfo/libgccjit.texi
+
+jit.info: doc/libgccjit.info
+doc/libgccjit.info: $(JIT_TEXI_FILES)
+ if test "x$(BUILD_INFO)" = xinfo; then \
+ rm -f doc/libgccjit.info*; \
+ $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+ -I $(gcc_docdir)/include -o $@ $<; \
+ else true; fi
+
+jit.install-info: $(DESTDIR)$(infodir)/libgccjit.info
+
+jit.dvi: doc/libgccjit.dvi
+doc/libgccjit.dvi: $(JIT_TEXI_FILES)
+ $(TEXI2DVI) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+jit.texinfo.html: $(build_htmldir)/jit/index.html
+
+$(build_htmldir)/jit/index.html: $(srcdir)/jit/docs/_build/texinfo/libgccjit.texi
+ $(mkinstalldirs) $(@D)
+ rm -f $(@D)/*
+ $(TEXI2HTML) -I $(gcc_docdir)/include -I $(srcdir)/jit -o $(@D) $<
+
+jit.texinfo.install-html: jit.texinfo.html
+ @$(NORMAL_INSTALL)
+ test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
+ @for p in $(build_htmldir)/jit; do \
+ if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
+ f=$(html__strip_dir) \
+ if test -d "$$d$$p"; then \
+ echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+ echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
+ else \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
+ fi; \
+ done
+
+jit.texinfo.pdf: doc/libgccjit.pdf
+
+doc/libgccjit.pdf: $(JIT_TEXI_FILES)
+ $(TEXI2PDF) -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+jit.texinfo.install-pdf: doc/libgccjit.pdf
+ @$(NORMAL_INSTALL)
+ test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
+ @for p in doc/libgccjit.pdf; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(pdf__strip_dir) \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \
+ done
+
+# Hooks for building docs using the Sphinx toolchain:
+
+SPHINX_BUILD_DIR=jit/sphinx-build
+
+jit.sphinx.html:
+ mkdir -p $(SPHINX_BUILD_DIR)
+ (cd $(srcdir)/jit/docs && \
+ make html BUILDDIR=$(PWD)/$(SPHINX_BUILD_DIR) )
+
+jit_htmldir=$(htmldir)/jit
+
+jit.sphinx.install-html: jit.sphinx.html
+ @$(NORMAL_INSTALL)
+ test -z "$(jit_htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(jit_htmldir)"
+ @for f in $(shell cd $(SPHINX_BUILD_DIR)/html && find) ; do \
+ if test -f $(SPHINX_BUILD_DIR)/html/"$$f"; then \
+ $(INSTALL_DATA) $(SPHINX_BUILD_DIR)/html/"$$f" $(DESTDIR)$(jit_htmldir)/"$$f"; \
+ else \
+ mkdir $(DESTDIR)$(jit_htmldir)/"$$f"; \
+ fi; \
+ done
+
+# (This one is currently failing deep inside pdflatex for me;
+# see https://bugzilla.redhat.com/show_bug.cgi?id=1148845 )
+jit.sphinx.pdf: $(SPHINX_BUILD_DIR)/latex/libgccjit.pdf
+$(SPHINX_BUILD_DIR)/latex/libgccjit.pdf:
+ mkdir -p $(SPHINX_BUILD_DIR)
+ (cd $(srcdir)/jit/docs && \
+ make latexpdf BUILDDIR=$(PWD)/$(SPHINX_BUILD_DIR) )
+
+jit.sphinx.install-pdf: $(SPHINX_BUILD_DIR)/latex/libgccjit.pdf
+ @$(NORMAL_INSTALL)
+ test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
+ @for p in $(SPHINX_BUILD_DIR)/latex/libgccjit.pdf; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(pdf__strip_dir) \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \
+ done
+
jit.srcinfo:
jit.srcextra:
--
1.7.11.7
Loading...