jit: New API entrypoint: gcc_jit_context_dump_reproducer_to_file
gcc/jit/ChangeLog: * docs/cp/topics/contexts.rst (Debugging): Add gccjit::context::dump_reproducer_to_file. * docs/internals/index.rst (Design notes): New section, discussing input validation and gcc_jit_context_dump_reproducer_to_file. * docs/topics/contexts.rst (Debugging): Add gcc_jit_context_dump_reproducer_to_file. * docs/_build/texinfo/libgccjit.texi: Regenerate. * jit-common.h (gcc::jit::dump::get_context): New accessor. * jit-recording.c: Include "hash-map.h". Within namespace ::gcc::jit... (dump::write): Flush each line. (dump::make_location): Pass false for new param "created_by_user". (class allocator): New class. (allocator::~allocator): New function. (allocator::xstrdup_printf): New function. (allocator::xstrdup_printf_va): New function. (class reproducer): New subclass of dump. (reproducer::reproducer): New function. (reproducer::write_params): New function. (reproducer::write_args): New function. (reproducer::make_identifier): New function. (reproducer::make_tmp_identifier): New function. (reproducer::get_identifier): New pair of functions. (reproducer::get_identifier_as_rvalue): New function. (reproducer::get_identifier_as_lvalue): New function. (reproducer::get_identifier_as_type): New function. (reproducer::xstrdup_printf): New function. (recording::context::context): Initialize m_toplevel_ctxt. (recording::context::new_location): Add param created_by_user. (str_option_reproducer_strings): New table of strings. (int_option_reproducer_strings): Likewise. (bool_option_reproducer_strings): Likewise. (get_type_enum_strings): Likewise. (names_of_function_kinds): Likewise. (global_kind_reproducer_strings): Likewise. (unary_op_reproducer_strings): Likewise. (binary_op_reproducer_strings): Likewise. (comparison_reproducer_strings): Likewise. Within namespace ::gcc::jit::recording::... (context::dump_reproducer_to_file): New function. (string::write_reproducer): Likewise. (location::write_reproducer): Likewise. (type::access_as_type): Likewise. (memento_of_get_type::write_reproducer): Likewise. (memento_of_get_pointer::write_reproducer): Likewise. (memento_of_get_const::write_reproducer): Likewise. (memento_of_get_volatile::write_reproducer): Likewise. (array_type::write_reproducer): Likewise. (function_type::write_reproducer): Likewise. (function_type::write_deferred_reproducer): Likewise. (field::write_reproducer): Likewise. (struct_::access_as_type): Likewise. (struct_::write_reproducer): Likewise. (union_::write_reproducer): Likewise. (fields::write_reproducer): Likewise. (rvalue::access_as_rvalue): Likewise. (lvalue::access_as_rvalue): Likewise. (lvalue::access_as_lvalue): Likewise. (param::access_as_rvalue): Likewise. (param::access_as_lvalue): Likewise. (param::write_reproducer): Likewise. (function::write_reproducer): Likewise. (block::write_reproducer): Likewise. (global::write_reproducer): Likewise. (memento_of_new_rvalue_from_const <int>::write_reproducer): Likewise. (memento_of_new_rvalue_from_const <long>::write_reproducer): Likewise. (memento_of_new_rvalue_from_const <double>::write_reproducer): Likewise. (memento_of_new_rvalue_from_const <void *>::write_reproducer): Likewise. (memento_of_new_string_literal::write_reproducer): Likewise. (unary_op::write_reproducer): Likewise. (binary_op::write_reproducer): Likewise. (comparison::write_reproducer): Likewise. (cast::write_reproducer): Likewise. (call::write_reproducer): Likewise. (call_through_ptr::write_reproducer): Likewise. (array_access::write_reproducer): Likewise. (access_field_of_lvalue::write_reproducer): Likewise. (access_field_rvalue::write_reproducer): Likewise. (dereference_field_rvalue::write_reproducer): Likewise. (dereference_rvalue::write_reproducer): Likewise. (get_address_of_lvalue::write_reproducer): Likewise. (local::write_reproducer): Likewise. (eval::write_reproducer): Likewise. (assignment::write_reproducer): Likewise. (assignment_op::write_reproducer): Likewise. (comment::write_reproducer): Likewise. (conditional::write_reproducer): Likewise. (jump::write_reproducer): Likewise. (return_::write_reproducer): Likewise. * jit-recording.h (gcc::jit::reproducer): New forward declararion. Within namespace ::gcc::jit::recording::... (context::new_location): Add "created_by_user" param. (context::dump_reproducer_to_file): New method. (context::m_toplevel_ctxt): New field. (memento::write_reproducer): New pure virtual function. (memento::dyn_cast_location): New virtual function. (string::write_reproducer): (location::location): Add "created_by_user" param. (location::dyn_cast_location): New function. (location::created_by_user): New accessor. (location::write_reproducer): New function. (location::m_created_by_user): New field. (type::access_as_type): New virtual function. (location::write_reproducer): Likewise. (type::access_as_type): Likewise. (memento_of_get_type::write_reproducer): Likewise. (memento_of_get_pointer::write_reproducer): Likewise. (memento_of_get_const::write_reproducer): Likewise. (memento_of_get_volatile::write_reproducer): Likewise. (array_type::write_reproducer): Likewise. (function_type::write_reproducer): Likewise. (function_type::write_deferred_reproducer): Likewise. (field::write_reproducer): Likewise. (struct_::access_as_type): Likewise. (struct_::write_reproducer): Likewise. (union_::write_reproducer): Likewise. (union_::m_fields): Remove stray unused field. (fields::length): New accessor. (fields::get_field): New accessor. (fields::write_reproducer): New function. (rvalue::access_as_rvalue): Likewise. (lvalue::access_as_rvalue): Likewise. (lvalue::access_as_lvalue): Likewise. (param::access_as_rvalue): Likewise. (param::access_as_lvalue): Likewise. (param::write_reproducer): Likewise. (function::write_reproducer): Likewise. (block::write_reproducer): Likewise. (global::write_reproducer): Likewise. (memento_of_new_rvalue_from_const <HOST_TYPE>::write_reproducer): Likewise. (memento_of_new_string_literal::write_reproducer): Likewise. (unary_op::write_reproducer): Likewise. (binary_op::write_reproducer): Likewise. (comparison::write_reproducer): Likewise. (cast::write_reproducer): Likewise. (call::write_reproducer): Likewise. (call_through_ptr::write_reproducer): Likewise. (array_access::write_reproducer): Likewise. (access_field_of_lvalue::write_reproducer): Likewise. (access_field_rvalue::write_reproducer): Likewise. (dereference_field_rvalue::write_reproducer): Likewise. (dereference_rvalue::write_reproducer): Likewise. (get_address_of_lvalue::write_reproducer): Likewise. (local::write_reproducer): Likewise. (eval::write_reproducer): Likewise. (assignment::write_reproducer): Likewise. (assignment_op::write_reproducer): Likewise. (comment::write_reproducer): Likewise. (conditional::write_reproducer): Likewise. (jump::write_reproducer): Likewise. (return_::write_reproducer): Likewise. * libgccjit++.h (gccjit::context::dump_reproducer_to_file): New. * libgccjit.c (gcc_jit_context_new_location): Pass "true" as param "created_by_user". (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. * libgccjit.h (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. * libgccjit.map (gcc_jit_context_dump_reproducer_to_file): New API entrypoint. gcc/testsuite/ChangeLog: * jit.dg/harness.h (set_up_logging): Move string concatenation into... (concat_strings): New function. (dump_reproducer): New function. (test_jit): Call dump_reproducer. * jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer): New function. (jit-dg-test): Delete any generated reproducer from previous runs. Verify that a generated reproducer was created, and verify that it compiles. * jit.dg/test-nested-contexts.c (main): Call gcc_jit_context_dump_reproducer_to_file. From-SVN: r219564
This commit is contained in:
parent
9c80f9197e
commit
86d0ac8876
@ -1,3 +1,171 @@
|
|||||||
|
2015-01-13 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
* docs/cp/topics/contexts.rst (Debugging): Add
|
||||||
|
gccjit::context::dump_reproducer_to_file.
|
||||||
|
* docs/internals/index.rst (Design notes): New section,
|
||||||
|
discussing input validation and
|
||||||
|
gcc_jit_context_dump_reproducer_to_file.
|
||||||
|
* docs/topics/contexts.rst (Debugging): Add
|
||||||
|
gcc_jit_context_dump_reproducer_to_file.
|
||||||
|
* docs/_build/texinfo/libgccjit.texi: Regenerate.
|
||||||
|
* jit-common.h (gcc::jit::dump::get_context): New accessor.
|
||||||
|
* jit-recording.c: Include "hash-map.h".
|
||||||
|
Within namespace ::gcc::jit...
|
||||||
|
(dump::write): Flush each line.
|
||||||
|
(dump::make_location): Pass false for new param "created_by_user".
|
||||||
|
(class allocator): New class.
|
||||||
|
(allocator::~allocator): New function.
|
||||||
|
(allocator::xstrdup_printf): New function.
|
||||||
|
(allocator::xstrdup_printf_va): New function.
|
||||||
|
(class reproducer): New subclass of dump.
|
||||||
|
(reproducer::reproducer): New function.
|
||||||
|
(reproducer::write_params): New function.
|
||||||
|
(reproducer::write_args): New function.
|
||||||
|
(reproducer::make_identifier): New function.
|
||||||
|
(reproducer::make_tmp_identifier): New function.
|
||||||
|
(reproducer::get_identifier): New pair of functions.
|
||||||
|
(reproducer::get_identifier_as_rvalue): New function.
|
||||||
|
(reproducer::get_identifier_as_lvalue): New function.
|
||||||
|
(reproducer::get_identifier_as_type): New function.
|
||||||
|
(reproducer::xstrdup_printf): New function.
|
||||||
|
(recording::context::context): Initialize m_toplevel_ctxt.
|
||||||
|
(recording::context::new_location): Add param created_by_user.
|
||||||
|
(str_option_reproducer_strings): New table of strings.
|
||||||
|
(int_option_reproducer_strings): Likewise.
|
||||||
|
(bool_option_reproducer_strings): Likewise.
|
||||||
|
(get_type_enum_strings): Likewise.
|
||||||
|
(names_of_function_kinds): Likewise.
|
||||||
|
(global_kind_reproducer_strings): Likewise.
|
||||||
|
(unary_op_reproducer_strings): Likewise.
|
||||||
|
(binary_op_reproducer_strings): Likewise.
|
||||||
|
(comparison_reproducer_strings): Likewise.
|
||||||
|
Within namespace ::gcc::jit::recording::...
|
||||||
|
(context::dump_reproducer_to_file): New function.
|
||||||
|
(string::write_reproducer): Likewise.
|
||||||
|
(location::write_reproducer): Likewise.
|
||||||
|
(type::access_as_type): Likewise.
|
||||||
|
(memento_of_get_type::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_pointer::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_const::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_volatile::write_reproducer): Likewise.
|
||||||
|
(array_type::write_reproducer): Likewise.
|
||||||
|
(function_type::write_reproducer): Likewise.
|
||||||
|
(function_type::write_deferred_reproducer): Likewise.
|
||||||
|
(field::write_reproducer): Likewise.
|
||||||
|
(struct_::access_as_type): Likewise.
|
||||||
|
(struct_::write_reproducer): Likewise.
|
||||||
|
(union_::write_reproducer): Likewise.
|
||||||
|
(fields::write_reproducer): Likewise.
|
||||||
|
(rvalue::access_as_rvalue): Likewise.
|
||||||
|
(lvalue::access_as_rvalue): Likewise.
|
||||||
|
(lvalue::access_as_lvalue): Likewise.
|
||||||
|
(param::access_as_rvalue): Likewise.
|
||||||
|
(param::access_as_lvalue): Likewise.
|
||||||
|
(param::write_reproducer): Likewise.
|
||||||
|
(function::write_reproducer): Likewise.
|
||||||
|
(block::write_reproducer): Likewise.
|
||||||
|
(global::write_reproducer): Likewise.
|
||||||
|
(memento_of_new_rvalue_from_const <int>::write_reproducer):
|
||||||
|
Likewise.
|
||||||
|
(memento_of_new_rvalue_from_const <long>::write_reproducer):
|
||||||
|
Likewise.
|
||||||
|
(memento_of_new_rvalue_from_const <double>::write_reproducer):
|
||||||
|
Likewise.
|
||||||
|
(memento_of_new_rvalue_from_const <void *>::write_reproducer):
|
||||||
|
Likewise.
|
||||||
|
(memento_of_new_string_literal::write_reproducer): Likewise.
|
||||||
|
(unary_op::write_reproducer): Likewise.
|
||||||
|
(binary_op::write_reproducer): Likewise.
|
||||||
|
(comparison::write_reproducer): Likewise.
|
||||||
|
(cast::write_reproducer): Likewise.
|
||||||
|
(call::write_reproducer): Likewise.
|
||||||
|
(call_through_ptr::write_reproducer): Likewise.
|
||||||
|
(array_access::write_reproducer): Likewise.
|
||||||
|
(access_field_of_lvalue::write_reproducer): Likewise.
|
||||||
|
(access_field_rvalue::write_reproducer): Likewise.
|
||||||
|
(dereference_field_rvalue::write_reproducer): Likewise.
|
||||||
|
(dereference_rvalue::write_reproducer): Likewise.
|
||||||
|
(get_address_of_lvalue::write_reproducer): Likewise.
|
||||||
|
(local::write_reproducer): Likewise.
|
||||||
|
(eval::write_reproducer): Likewise.
|
||||||
|
(assignment::write_reproducer): Likewise.
|
||||||
|
(assignment_op::write_reproducer): Likewise.
|
||||||
|
(comment::write_reproducer): Likewise.
|
||||||
|
(conditional::write_reproducer): Likewise.
|
||||||
|
(jump::write_reproducer): Likewise.
|
||||||
|
(return_::write_reproducer): Likewise.
|
||||||
|
* jit-recording.h (gcc::jit::reproducer): New forward declararion.
|
||||||
|
Within namespace ::gcc::jit::recording::...
|
||||||
|
(context::new_location): Add "created_by_user" param.
|
||||||
|
(context::dump_reproducer_to_file): New method.
|
||||||
|
(context::m_toplevel_ctxt): New field.
|
||||||
|
(memento::write_reproducer): New pure virtual function.
|
||||||
|
(memento::dyn_cast_location): New virtual function.
|
||||||
|
(string::write_reproducer):
|
||||||
|
(location::location): Add "created_by_user" param.
|
||||||
|
(location::dyn_cast_location): New function.
|
||||||
|
(location::created_by_user): New accessor.
|
||||||
|
(location::write_reproducer): New function.
|
||||||
|
(location::m_created_by_user): New field.
|
||||||
|
(type::access_as_type): New virtual function.
|
||||||
|
(location::write_reproducer): Likewise.
|
||||||
|
(type::access_as_type): Likewise.
|
||||||
|
(memento_of_get_type::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_pointer::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_const::write_reproducer): Likewise.
|
||||||
|
(memento_of_get_volatile::write_reproducer): Likewise.
|
||||||
|
(array_type::write_reproducer): Likewise.
|
||||||
|
(function_type::write_reproducer): Likewise.
|
||||||
|
(function_type::write_deferred_reproducer): Likewise.
|
||||||
|
(field::write_reproducer): Likewise.
|
||||||
|
(struct_::access_as_type): Likewise.
|
||||||
|
(struct_::write_reproducer): Likewise.
|
||||||
|
(union_::write_reproducer): Likewise.
|
||||||
|
(union_::m_fields): Remove stray unused field.
|
||||||
|
(fields::length): New accessor.
|
||||||
|
(fields::get_field): New accessor.
|
||||||
|
(fields::write_reproducer): New function.
|
||||||
|
(rvalue::access_as_rvalue): Likewise.
|
||||||
|
(lvalue::access_as_rvalue): Likewise.
|
||||||
|
(lvalue::access_as_lvalue): Likewise.
|
||||||
|
(param::access_as_rvalue): Likewise.
|
||||||
|
(param::access_as_lvalue): Likewise.
|
||||||
|
(param::write_reproducer): Likewise.
|
||||||
|
(function::write_reproducer): Likewise.
|
||||||
|
(block::write_reproducer): Likewise.
|
||||||
|
(global::write_reproducer): Likewise.
|
||||||
|
(memento_of_new_rvalue_from_const <HOST_TYPE>::write_reproducer):
|
||||||
|
Likewise.
|
||||||
|
(memento_of_new_string_literal::write_reproducer): Likewise.
|
||||||
|
(unary_op::write_reproducer): Likewise.
|
||||||
|
(binary_op::write_reproducer): Likewise.
|
||||||
|
(comparison::write_reproducer): Likewise.
|
||||||
|
(cast::write_reproducer): Likewise.
|
||||||
|
(call::write_reproducer): Likewise.
|
||||||
|
(call_through_ptr::write_reproducer): Likewise.
|
||||||
|
(array_access::write_reproducer): Likewise.
|
||||||
|
(access_field_of_lvalue::write_reproducer): Likewise.
|
||||||
|
(access_field_rvalue::write_reproducer): Likewise.
|
||||||
|
(dereference_field_rvalue::write_reproducer): Likewise.
|
||||||
|
(dereference_rvalue::write_reproducer): Likewise.
|
||||||
|
(get_address_of_lvalue::write_reproducer): Likewise.
|
||||||
|
(local::write_reproducer): Likewise.
|
||||||
|
(eval::write_reproducer): Likewise.
|
||||||
|
(assignment::write_reproducer): Likewise.
|
||||||
|
(assignment_op::write_reproducer): Likewise.
|
||||||
|
(comment::write_reproducer): Likewise.
|
||||||
|
(conditional::write_reproducer): Likewise.
|
||||||
|
(jump::write_reproducer): Likewise.
|
||||||
|
(return_::write_reproducer): Likewise.
|
||||||
|
* libgccjit++.h (gccjit::context::dump_reproducer_to_file): New.
|
||||||
|
* libgccjit.c (gcc_jit_context_new_location): Pass "true" as
|
||||||
|
param "created_by_user".
|
||||||
|
(gcc_jit_context_dump_reproducer_to_file): New API entrypoint.
|
||||||
|
* libgccjit.h (gcc_jit_context_dump_reproducer_to_file): New API
|
||||||
|
entrypoint.
|
||||||
|
* libgccjit.map (gcc_jit_context_dump_reproducer_to_file): New API
|
||||||
|
entrypoint.
|
||||||
|
|
||||||
2015-01-12 David Malcolm <dmalcolm@redhat.com>
|
2015-01-12 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
* jit-recording.c (class gcc::jit::rvalue_usage_validator): New.
|
* jit-recording.c (class gcc::jit::rvalue_usage_validator): New.
|
||||||
|
823
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
823
gcc/jit/docs/_build/texinfo/libgccjit.texi
vendored
File diff suppressed because it is too large
Load Diff
@ -144,6 +144,16 @@ Debugging
|
|||||||
:c:macro:`GCCJIT::BOOL_OPTION_DEBUGINFO` to allow stepping through the
|
:c:macro:`GCCJIT::BOOL_OPTION_DEBUGINFO` to allow stepping through the
|
||||||
code in a debugger.
|
code in a debugger.
|
||||||
|
|
||||||
|
.. function:: void\
|
||||||
|
gccjit::context::dump_reproducer_to_file (gcc_jit_context *ctxt,\
|
||||||
|
const char *path)
|
||||||
|
|
||||||
|
This is a thin wrapper around the C API
|
||||||
|
:c:func:`gcc_jit_context_dump_reproducer_to_file`, and hence works the
|
||||||
|
same way.
|
||||||
|
|
||||||
|
Note that the generated source is C code, not C++; this might be of use
|
||||||
|
for seeing what the C++ bindings are doing at the C level.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
-------
|
||||||
|
@ -277,3 +277,13 @@ generated via this call:
|
|||||||
|
|
||||||
.. literalinclude:: test-hello-world.exe.log.txt
|
.. literalinclude:: test-hello-world.exe.log.txt
|
||||||
:lines: 1-
|
:lines: 1-
|
||||||
|
|
||||||
|
Design notes
|
||||||
|
------------
|
||||||
|
It should not be possible for client code to cause an internal compiler
|
||||||
|
error. If this *does* happen, the root cause should be isolated (perhaps
|
||||||
|
using :c:func:`gcc_jit_context_dump_reproducer_to_file`) and the cause
|
||||||
|
should be rejected via additional checking. The checking ideally should
|
||||||
|
be within the libgccjit API entrypoints in libgccjit.c, since this is as
|
||||||
|
close as possible to the error; failing that, a good place is within
|
||||||
|
``recording::context::validate ()`` in jit-recording.c.
|
||||||
|
@ -218,6 +218,30 @@ current state of a context to the given path, whereas
|
|||||||
:c:func:`gcc_jit_context_set_logfile` enables on-going logging of
|
:c:func:`gcc_jit_context_set_logfile` enables on-going logging of
|
||||||
future activies on a context to the given `FILE *`.
|
future activies on a context to the given `FILE *`.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: void\
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt,\
|
||||||
|
const char *path)
|
||||||
|
|
||||||
|
Write C source code into `path` that can be compiled into a
|
||||||
|
self-contained executable (i.e. with libgccjit as the only dependency).
|
||||||
|
The generated code will attempt to replay the API calls that have been
|
||||||
|
made into the given context.
|
||||||
|
|
||||||
|
This may be useful when debugging the library or client code, for
|
||||||
|
reducing a complicated recipe for reproducing a bug into a simpler
|
||||||
|
form. For example, consider client code that parses some source file
|
||||||
|
into some internal representation, and then walks this IR, calling into
|
||||||
|
libgccjit. If this encounters a bug, a call to
|
||||||
|
`gcc_jit_context_dump_reproducer_to_file` will write out C code for
|
||||||
|
a much simpler executable that performs the equivalent calls into
|
||||||
|
libgccjit, without needing the client code and its data.
|
||||||
|
|
||||||
|
Typically you need to supply :option:`-Wno-unused-variable` when
|
||||||
|
compiling the generated file (since the result of each API call is
|
||||||
|
assigned to a unique variable within the generated C source, and not
|
||||||
|
all are necessarily then used).
|
||||||
|
|
||||||
.. function:: void\
|
.. function:: void\
|
||||||
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\
|
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\
|
||||||
const char *dumpname, \
|
const char *dumpname, \
|
||||||
|
@ -168,6 +168,8 @@ public:
|
|||||||
bool update_locations);
|
bool update_locations);
|
||||||
~dump ();
|
~dump ();
|
||||||
|
|
||||||
|
recording::context &get_context () { return m_ctxt; }
|
||||||
|
|
||||||
void write (const char *fmt, ...)
|
void write (const char *fmt, ...)
|
||||||
GNU_PRINTF(2, 3);
|
GNU_PRINTF(2, 3);
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,7 @@ namespace jit {
|
|||||||
|
|
||||||
class result;
|
class result;
|
||||||
class dump;
|
class dump;
|
||||||
|
class reproducer;
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Recording.
|
Recording.
|
||||||
@ -73,7 +74,8 @@ public:
|
|||||||
location *
|
location *
|
||||||
new_location (const char *filename,
|
new_location (const char *filename,
|
||||||
int line,
|
int line,
|
||||||
int column);
|
int column,
|
||||||
|
bool created_by_user);
|
||||||
|
|
||||||
type *
|
type *
|
||||||
get_type (enum gcc_jit_types type);
|
get_type (enum gcc_jit_types type);
|
||||||
@ -244,6 +246,8 @@ public:
|
|||||||
|
|
||||||
void dump_to_file (const char *path, bool update_locations);
|
void dump_to_file (const char *path, bool update_locations);
|
||||||
|
|
||||||
|
void dump_reproducer_to_file (const char *path);
|
||||||
|
|
||||||
void
|
void
|
||||||
get_all_requested_dumps (vec <recording::requested_dump> *out);
|
get_all_requested_dumps (vec <recording::requested_dump> *out);
|
||||||
|
|
||||||
@ -253,6 +257,10 @@ private:
|
|||||||
private:
|
private:
|
||||||
context *m_parent_ctxt;
|
context *m_parent_ctxt;
|
||||||
|
|
||||||
|
/* The ultimate ancestor of the contexts within a family tree of
|
||||||
|
contexts. This has itself as its own m_toplevel_ctxt. */
|
||||||
|
context *m_toplevel_ctxt;
|
||||||
|
|
||||||
int m_error_count;
|
int m_error_count;
|
||||||
|
|
||||||
char *m_first_error_str;
|
char *m_first_error_str;
|
||||||
@ -314,6 +322,8 @@ public:
|
|||||||
get_debug_string ();
|
get_debug_string ();
|
||||||
|
|
||||||
virtual void write_to_dump (dump &d);
|
virtual void write_to_dump (dump &d);
|
||||||
|
virtual void write_reproducer (reproducer &r) = 0;
|
||||||
|
virtual location *dyn_cast_location () { return NULL; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
memento (context *ctxt)
|
memento (context *ctxt)
|
||||||
@ -355,6 +365,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t m_len;
|
size_t m_len;
|
||||||
@ -364,11 +375,13 @@ private:
|
|||||||
class location : public memento
|
class location : public memento
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
location (context *ctxt, string *filename, int line, int column)
|
location (context *ctxt, string *filename, int line, int column,
|
||||||
|
bool created_by_user)
|
||||||
: memento (ctxt),
|
: memento (ctxt),
|
||||||
m_filename (filename),
|
m_filename (filename),
|
||||||
m_line (line),
|
m_line (line),
|
||||||
m_column (column)
|
m_column (column),
|
||||||
|
m_created_by_user (created_by_user)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void replay_into (replayer *r);
|
void replay_into (replayer *r);
|
||||||
@ -400,13 +413,18 @@ public:
|
|||||||
return static_cast <playback::location *> (m_playback_obj);
|
return static_cast <playback::location *> (m_playback_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location *dyn_cast_location () { return this; }
|
||||||
|
bool created_by_user () const { return m_created_by_user; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string *m_filename;
|
string *m_filename;
|
||||||
int m_line;
|
int m_line;
|
||||||
int m_column;
|
int m_column;
|
||||||
|
bool m_created_by_user;
|
||||||
};
|
};
|
||||||
|
|
||||||
class type : public memento
|
class type : public memento
|
||||||
@ -458,6 +476,8 @@ public:
|
|||||||
return static_cast <playback::type *> (m_playback_obj);
|
return static_cast <playback::type *> (m_playback_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual const char *access_as_type (reproducer &r);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
type (context *ctxt)
|
type (context *ctxt)
|
||||||
: memento (ctxt),
|
: memento (ctxt),
|
||||||
@ -504,6 +524,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum gcc_jit_types m_kind;
|
enum gcc_jit_types m_kind;
|
||||||
@ -531,6 +552,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type *m_other_type;
|
type *m_other_type;
|
||||||
@ -565,6 +587,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type *m_other_type;
|
type *m_other_type;
|
||||||
@ -593,6 +616,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type *m_other_type;
|
type *m_other_type;
|
||||||
@ -623,6 +647,7 @@ class array_type : public type
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location *m_loc;
|
location *m_loc;
|
||||||
@ -657,9 +682,14 @@ public:
|
|||||||
|
|
||||||
string * make_debug_string_with_ptr ();
|
string * make_debug_string_with_ptr ();
|
||||||
|
|
||||||
|
void
|
||||||
|
write_deferred_reproducer (reproducer &r,
|
||||||
|
memento *ptr_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
string * make_debug_string_with (const char *);
|
string * make_debug_string_with (const char *);
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type *m_return_type;
|
type *m_return_type;
|
||||||
@ -698,6 +728,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location *m_loc;
|
location *m_loc;
|
||||||
@ -757,9 +788,11 @@ public:
|
|||||||
|
|
||||||
void replay_into (replayer *r);
|
void replay_into (replayer *r);
|
||||||
|
|
||||||
|
const char *access_as_type (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
};
|
};
|
||||||
|
|
||||||
// memento of struct_::set_fields
|
// memento of struct_::set_fields
|
||||||
@ -774,8 +807,12 @@ public:
|
|||||||
|
|
||||||
void write_to_dump (dump &d);
|
void write_to_dump (dump &d);
|
||||||
|
|
||||||
|
int length () const { return m_fields.length (); }
|
||||||
|
field *get_field (int i) const { return m_fields[i]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
compound_type *m_struct_or_union;
|
compound_type *m_struct_or_union;
|
||||||
@ -793,11 +830,11 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location *m_loc;
|
location *m_loc;
|
||||||
string *m_name;
|
string *m_name;
|
||||||
fields *m_fields;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* An abstract base class for operations that visit all rvalues within an
|
/* An abstract base class for operations that visit all rvalues within an
|
||||||
@ -861,6 +898,8 @@ public:
|
|||||||
/* Dynamic cast. */
|
/* Dynamic cast. */
|
||||||
virtual param *dyn_cast_param () { return NULL; }
|
virtual param *dyn_cast_param () { return NULL; }
|
||||||
|
|
||||||
|
virtual const char *access_as_rvalue (reproducer &r);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
location *m_loc;
|
location *m_loc;
|
||||||
type *m_type;
|
type *m_type;
|
||||||
@ -893,6 +932,9 @@ public:
|
|||||||
|
|
||||||
rvalue *
|
rvalue *
|
||||||
as_rvalue () { return this; }
|
as_rvalue () { return this; }
|
||||||
|
|
||||||
|
const char *access_as_rvalue (reproducer &r);
|
||||||
|
virtual const char *access_as_lvalue (reproducer &r);
|
||||||
};
|
};
|
||||||
|
|
||||||
class param : public lvalue
|
class param : public lvalue
|
||||||
@ -920,8 +962,12 @@ public:
|
|||||||
|
|
||||||
param *dyn_cast_param () { return this; }
|
param *dyn_cast_param () { return this; }
|
||||||
|
|
||||||
|
const char *access_as_rvalue (reproducer &r);
|
||||||
|
const char *access_as_lvalue (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string () { return m_name; }
|
string * make_debug_string () { return m_name; }
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string *m_name;
|
string *m_name;
|
||||||
@ -978,6 +1024,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
location *m_loc;
|
location *m_loc;
|
||||||
@ -1065,6 +1112,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
void replay_into (replayer *r);
|
void replay_into (replayer *r);
|
||||||
|
|
||||||
@ -1103,6 +1151,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string () { return m_name; }
|
string * make_debug_string () { return m_name; }
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum gcc_jit_global_kind m_kind;
|
enum gcc_jit_global_kind m_kind;
|
||||||
@ -1126,6 +1175,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HOST_TYPE m_value;
|
HOST_TYPE m_value;
|
||||||
@ -1146,6 +1196,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string *m_value;
|
string *m_value;
|
||||||
@ -1170,6 +1221,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum gcc_jit_unary_op m_op;
|
enum gcc_jit_unary_op m_op;
|
||||||
@ -1195,6 +1247,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum gcc_jit_binary_op m_op;
|
enum gcc_jit_binary_op m_op;
|
||||||
@ -1221,6 +1274,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum gcc_jit_comparison m_op;
|
enum gcc_jit_comparison m_op;
|
||||||
@ -1245,6 +1299,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
@ -1265,6 +1320,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
function *m_func;
|
function *m_func;
|
||||||
@ -1286,6 +1342,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_fn_ptr;
|
rvalue *m_fn_ptr;
|
||||||
@ -1310,6 +1367,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_ptr;
|
rvalue *m_ptr;
|
||||||
@ -1334,6 +1392,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lvalue *m_lvalue;
|
lvalue *m_lvalue;
|
||||||
@ -1358,6 +1417,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
@ -1382,6 +1442,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
@ -1403,6 +1464,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
@ -1424,6 +1486,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lvalue *m_lvalue;
|
lvalue *m_lvalue;
|
||||||
@ -1448,6 +1511,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string () { return m_name; }
|
string * make_debug_string () { return m_name; }
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
function *m_func;
|
function *m_func;
|
||||||
@ -1495,6 +1559,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
@ -1515,6 +1580,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lvalue *m_lvalue;
|
lvalue *m_lvalue;
|
||||||
@ -1538,6 +1604,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lvalue *m_lvalue;
|
lvalue *m_lvalue;
|
||||||
@ -1558,6 +1625,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string *m_text;
|
string *m_text;
|
||||||
@ -1583,6 +1651,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_boolval;
|
rvalue *m_boolval;
|
||||||
@ -1606,6 +1675,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
block *m_target;
|
block *m_target;
|
||||||
@ -1627,6 +1697,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string * make_debug_string ();
|
string * make_debug_string ();
|
||||||
|
void write_reproducer (reproducer &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rvalue *m_rvalue;
|
rvalue *m_rvalue;
|
||||||
|
@ -106,6 +106,8 @@ namespace gccjit
|
|||||||
int flags,
|
int flags,
|
||||||
int verbosity);
|
int verbosity);
|
||||||
|
|
||||||
|
void dump_reproducer_to_file (const char *path);
|
||||||
|
|
||||||
void set_str_option (enum gcc_jit_str_option opt,
|
void set_str_option (enum gcc_jit_str_option opt,
|
||||||
const char *value);
|
const char *value);
|
||||||
|
|
||||||
@ -558,6 +560,13 @@ context::set_logfile (FILE *logfile,
|
|||||||
verbosity);
|
verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
context::dump_reproducer_to_file (const char *path)
|
||||||
|
{
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (m_inner_ctxt,
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
context::set_str_option (enum gcc_jit_str_option opt,
|
context::set_str_option (enum gcc_jit_str_option opt,
|
||||||
const char *value)
|
const char *value)
|
||||||
|
@ -386,7 +386,7 @@ gcc_jit_context_new_location (gcc_jit_context *ctxt,
|
|||||||
{
|
{
|
||||||
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
|
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
|
||||||
JIT_LOG_FUNC (ctxt->get_logger ());
|
JIT_LOG_FUNC (ctxt->get_logger ());
|
||||||
return (gcc_jit_location *)ctxt->new_location (filename, line, column);
|
return (gcc_jit_location *)ctxt->new_location (filename, line, column, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public entrypoint. See description in libgccjit.h.
|
/* Public entrypoint. See description in libgccjit.h.
|
||||||
@ -2234,6 +2234,22 @@ gcc_jit_context_set_logfile (gcc_jit_context *ctxt,
|
|||||||
ctxt->set_logger (logger);
|
ctxt->set_logger (logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Public entrypoint. See description in libgccjit.h.
|
||||||
|
|
||||||
|
After error-checking, the real work is done by the
|
||||||
|
gcc::jit::recording::context::dump_reproducer_to_file method in
|
||||||
|
jit-recording.c. */
|
||||||
|
|
||||||
|
void
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
|
||||||
|
JIT_LOG_FUNC (ctxt->get_logger ());
|
||||||
|
RETURN_IF_FAIL (path, ctxt, NULL, "NULL path");
|
||||||
|
ctxt->dump_reproducer_to_file (path);
|
||||||
|
}
|
||||||
|
|
||||||
/* Public entrypoint. See description in libgccjit.h.
|
/* Public entrypoint. See description in libgccjit.h.
|
||||||
|
|
||||||
After error-checking, the real work is done by the
|
After error-checking, the real work is done by the
|
||||||
|
@ -1051,6 +1051,24 @@ gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt);
|
|||||||
Implementation support.
|
Implementation support.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
/* Write C source code into "path" that can be compiled into a
|
||||||
|
self-contained executable (i.e. with libgccjit as the only dependency).
|
||||||
|
The generated code will attempt to replay the API calls that have been
|
||||||
|
made into the given context.
|
||||||
|
|
||||||
|
This may be useful when debugging the library or client code, for
|
||||||
|
reducing a complicated recipe for reproducing a bug into a simpler
|
||||||
|
form.
|
||||||
|
|
||||||
|
Typically you need to supply the option "-Wno-unused-variable" when
|
||||||
|
compiling the generated file (since the result of each API call is
|
||||||
|
assigned to a unique variable within the generated C source, and not
|
||||||
|
all are necessarily then used). */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (gcc_jit_context *ctxt,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
/* Enable the dumping of a specific set of internal state from the
|
/* Enable the dumping of a specific set of internal state from the
|
||||||
compilation, capturing the result in-memory as a buffer.
|
compilation, capturing the result in-memory as a buffer.
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
gcc_jit_context_acquire;
|
gcc_jit_context_acquire;
|
||||||
gcc_jit_context_compile;
|
gcc_jit_context_compile;
|
||||||
gcc_jit_context_dump_to_file;
|
gcc_jit_context_dump_to_file;
|
||||||
|
gcc_jit_context_dump_reproducer_to_file;
|
||||||
gcc_jit_context_enable_dump;
|
gcc_jit_context_enable_dump;
|
||||||
gcc_jit_context_get_builtin_function;
|
gcc_jit_context_get_builtin_function;
|
||||||
gcc_jit_context_get_first_error;
|
gcc_jit_context_get_first_error;
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
2015-01-13 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
* jit.dg/harness.h (set_up_logging): Move string concatenation
|
||||||
|
into...
|
||||||
|
(concat_strings): New function.
|
||||||
|
(dump_reproducer): New function.
|
||||||
|
(test_jit): Call dump_reproducer.
|
||||||
|
* jit.dg/jit.exp (is_testcase_meant_to_generate_a_reproducer): New
|
||||||
|
function.
|
||||||
|
(jit-dg-test): Delete any generated reproducer from previous runs.
|
||||||
|
Verify that a generated reproducer was created, and verify that it
|
||||||
|
compiles.
|
||||||
|
* jit.dg/test-nested-contexts.c (main): Call
|
||||||
|
gcc_jit_context_dump_reproducer_to_file.
|
||||||
|
|
||||||
2015-01-13 H.J. Lu <hongjiu.lu@intel.com>
|
2015-01-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* gcc.dg/aru-2.c: Add dg-require-profiling.
|
* gcc.dg/aru-2.c: Add dg-require-profiling.
|
||||||
|
@ -250,6 +250,23 @@ static void set_options (gcc_jit_context *ctxt, const char *argv0)
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Concatenate two strings. The result must be released using "free". */
|
||||||
|
|
||||||
|
char *
|
||||||
|
concat_strings (const char *prefix, const char *suffix)
|
||||||
|
{
|
||||||
|
char *result = (char *)malloc (strlen (prefix) + strlen (suffix) + 1);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
fail ("malloc failure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strcpy (result, prefix);
|
||||||
|
strcpy (result + strlen (prefix), suffix);
|
||||||
|
result[strlen (prefix) + strlen (suffix)] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef TEST_ESCHEWS_TEST_JIT
|
#ifndef TEST_ESCHEWS_TEST_JIT
|
||||||
/* Set up logging to a logfile of the form "test-FOO.exe.log.txt".
|
/* Set up logging to a logfile of the form "test-FOO.exe.log.txt".
|
||||||
|
|
||||||
@ -271,18 +288,9 @@ set_up_logging (gcc_jit_context *ctxt, const char *argv0)
|
|||||||
FILE *logfile = NULL;
|
FILE *logfile = NULL;
|
||||||
|
|
||||||
/* Build a logfile name of the form "test-FOO.exe.log.txt". */
|
/* Build a logfile name of the form "test-FOO.exe.log.txt". */
|
||||||
logfile_name = (char *)malloc (strlen (argv0)
|
logfile_name = concat_strings (argv0, logfile_name_suffix);
|
||||||
+ strlen (logfile_name_suffix)
|
|
||||||
+ 1);
|
|
||||||
if (!logfile_name)
|
if (!logfile_name)
|
||||||
{
|
return NULL;
|
||||||
fail ("malloc failure");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
strcpy (logfile_name, argv0);
|
|
||||||
strcpy (logfile_name + strlen (argv0), logfile_name_suffix);
|
|
||||||
logfile_name[strlen (argv0) + strlen (logfile_name_suffix)] = '\0';
|
|
||||||
|
|
||||||
logfile = fopen (logfile_name, "w");
|
logfile = fopen (logfile_name, "w");
|
||||||
CHECK_NON_NULL (logfile);
|
CHECK_NON_NULL (logfile);
|
||||||
free (logfile_name);
|
free (logfile_name);
|
||||||
@ -293,6 +301,21 @@ set_up_logging (gcc_jit_context *ctxt, const char *argv0)
|
|||||||
return logfile;
|
return logfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Exercise the API entrypoint:
|
||||||
|
gcc_jit_context_dump_reproducer_to_file
|
||||||
|
by calling it on the context, using the path expected by jit.exp. */
|
||||||
|
static void
|
||||||
|
dump_reproducer (gcc_jit_context *ctxt, const char *argv0)
|
||||||
|
{
|
||||||
|
char *reproducer_name;
|
||||||
|
reproducer_name = concat_strings (argv0, ".reproducer.c");
|
||||||
|
if (!reproducer_name)
|
||||||
|
return;
|
||||||
|
note ("%s: writing reproducer to %s", test, reproducer_name);
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (ctxt, reproducer_name);
|
||||||
|
free (reproducer_name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Run one iteration of the test. */
|
/* Run one iteration of the test. */
|
||||||
static void
|
static void
|
||||||
test_jit (const char *argv0, void *user_data)
|
test_jit (const char *argv0, void *user_data)
|
||||||
@ -314,6 +337,8 @@ test_jit (const char *argv0, void *user_data)
|
|||||||
|
|
||||||
create_code (ctxt, user_data);
|
create_code (ctxt, user_data);
|
||||||
|
|
||||||
|
dump_reproducer (ctxt, argv0);
|
||||||
|
|
||||||
/* This actually calls into GCC and runs the build, all
|
/* This actually calls into GCC and runs the build, all
|
||||||
in a mutex for now. */
|
in a mutex for now. */
|
||||||
result = gcc_jit_context_compile (ctxt);
|
result = gcc_jit_context_compile (ctxt);
|
||||||
|
@ -301,6 +301,21 @@ set tests [lsort $tests]
|
|||||||
|
|
||||||
verbose "tests: $tests"
|
verbose "tests: $tests"
|
||||||
|
|
||||||
|
# Is testcase NAME meant to generate a reproducer?
|
||||||
|
proc is_testcase_meant_to_generate_a_reproducer {name} {
|
||||||
|
# We expect most testcases to generate a reproducer.
|
||||||
|
# The exceptions are the tutorials (which don't have a "test-"
|
||||||
|
# prefix), and test-threads.c (which is unique).
|
||||||
|
verbose "is_testcase_meant_to_generate_a_reproducer: $name"
|
||||||
|
if { [string match "*test-*" $name] } {
|
||||||
|
if { [string match "*test-threads.c" $name] } {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# libgloss has found the driver (as "xgcc" or "gcc) and stored
|
# libgloss has found the driver (as "xgcc" or "gcc) and stored
|
||||||
# its full path as GCC_UNDER_TEST.
|
# its full path as GCC_UNDER_TEST.
|
||||||
proc get_path_of_driver {} {
|
proc get_path_of_driver {} {
|
||||||
@ -365,6 +380,14 @@ proc jit-dg-test { prog do_what extra_tool_flags } {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Most of the test cases use gcc_jit_context_dump_reproducer_to_file
|
||||||
|
# as they run to write out a .c file that reproduces their behavior,
|
||||||
|
# exercising that API.
|
||||||
|
set generated_reproducer "${output_file}.reproducer.c"
|
||||||
|
|
||||||
|
# Delete any such generated .c file from a previous run.
|
||||||
|
catch "exec rm -f $generated_reproducer"
|
||||||
|
|
||||||
# Run the test executable, capturing the PASS/FAIL textual output
|
# Run the test executable, capturing the PASS/FAIL textual output
|
||||||
# from the C API, converting it into the Tcl API.
|
# from the C API, converting it into the Tcl API.
|
||||||
|
|
||||||
@ -456,6 +479,54 @@ proc jit-dg-test { prog do_what extra_tool_flags } {
|
|||||||
|
|
||||||
restore_ld_library_path_env_vars
|
restore_ld_library_path_env_vars
|
||||||
|
|
||||||
|
# Most of the test cases use gcc_jit_context_dump_reproducer_to_file
|
||||||
|
# as they run to write out a .c file that reproduces their behavior,
|
||||||
|
# exercising that API.
|
||||||
|
|
||||||
|
if { [is_testcase_meant_to_generate_a_reproducer $name] } {
|
||||||
|
verbose "$name is meant to generate a reproducer"
|
||||||
|
# Verify that a reproducer was generated
|
||||||
|
if { [file exists $generated_reproducer] == 1} {
|
||||||
|
pass "found generated reproducer: $generated_reproducer"
|
||||||
|
set output_file "${generated_reproducer}.exe"
|
||||||
|
# (this overwrites output_file)
|
||||||
|
|
||||||
|
# Try to compile the generated reproducer
|
||||||
|
verbose "compilation_function=$compilation_function"
|
||||||
|
|
||||||
|
# The .c file written by gcc_jit_context_dump_reproducer_to_file
|
||||||
|
# assigns the result of each API call to a unique variable, and not
|
||||||
|
# all are necessarily used, so we need -Wno-unused-variable.
|
||||||
|
set options \
|
||||||
|
"{additional_flags=$extra_tool_flags -Wno-unused-variable}"
|
||||||
|
verbose "options=$options"
|
||||||
|
|
||||||
|
set comp_output2 [$compilation_function $generated_reproducer \
|
||||||
|
$output_file "executable" $options]
|
||||||
|
if ![jit_check_compile "generated reproducer from $name" "initial compilation" \
|
||||||
|
$output_file $comp_output2] then {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# The caller, dg-test, will verify comp_output, which contains
|
||||||
|
# the output from compiling the testcase and will issue a fail
|
||||||
|
# if it's non-empty (e.g. containing warnings, the
|
||||||
|
# "test for excess errors").
|
||||||
|
#
|
||||||
|
# Append the output from compiling the reproducer, so that this is also
|
||||||
|
# verified:
|
||||||
|
append comp_output $comp_output2
|
||||||
|
|
||||||
|
# TODO: we should try to run the built executable
|
||||||
|
# It's not quite a quine, since it embeds ptrs which could change
|
||||||
|
# from run to run.
|
||||||
|
} else {
|
||||||
|
fail "did not find a generated reproducer: $generated_reproducer"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
verbose "$name is not meant to generate a reproducer"
|
||||||
|
}
|
||||||
|
|
||||||
return [list $comp_output $output_file]
|
return [list $comp_output $output_file]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +626,14 @@ main (int argc, char **argv)
|
|||||||
"dump-of-test-nested-contexts-bottom.c",
|
"dump-of-test-nested-contexts-bottom.c",
|
||||||
1);
|
1);
|
||||||
|
|
||||||
|
/* Dump a reproducer for the bottom context.
|
||||||
|
The generated reproducer needs to also regenerate the
|
||||||
|
parent contexts, so this gives us test coverage for
|
||||||
|
that case. */
|
||||||
|
gcc_jit_context_dump_reproducer_to_file (
|
||||||
|
bottom_level.ctxt,
|
||||||
|
"test-nested-contexts.c.exe.reproducer.c");
|
||||||
|
|
||||||
gcc_jit_result *bottom_result =
|
gcc_jit_result *bottom_result =
|
||||||
gcc_jit_context_compile (bottom_level.ctxt);
|
gcc_jit_context_compile (bottom_level.ctxt);
|
||||||
verify_bottom_code (bottom_level.ctxt, bottom_result);
|
verify_bottom_code (bottom_level.ctxt, bottom_result);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user