Commit eb4c16eb by David Malcolm Committed by David Malcolm

New jit API entrypoint: gcc_jit_context_set_logfile

gcc/jit/ChangeLog:
	* Make-lang.in (jit_OBJS): Add jit/jit-logging.o.
	* docs/internals/index.rst (Overview of code structure): Mention
	gcc_jit_context_set_logfile, and embed the example logfile.
	* docs/internals/test-hello-world.exe.log.txt: New file: example
	of a logfile.
	* docs/topics/contexts.rst (Debugging): Add documentation
	for gcc_jit_context_set_logfile.
	* docs/_build/texinfo/libgccjit.texi: Regenerate.
	* dummy-frontend.c: Include "jit-logging.h".
	(jit_langhook_init): Assert that there is an active playback
	context.  If it has a logger, log entry/exit to this function.
	(jit_langhook_write_globals): Likewise.
	* jit-common.h (gcc::jit::logger): New forward declaration.
	* jit-logging.c: New file.
	* jit-logging.h: New file.
	* jit-playback.c: Include "jit-logging.h".
	(gcc::jit::playback::context::context): Initialize the log_user
	base class from the recording context's logger (if any).  Use
	JIT_LOG_SCOPE to log entry/exit from the function body.
	(gcc::jit::playback::context::~context): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	(gcc::jit::playback::build_stmt_list): Likewise.
	(gcc::jit::playback::function::postprocess): Likewise.
	(gcc::jit::playback::context::compile): Likewise.  Log the
	entry/exit to toplev::main and toplev::finalize.  Log the
	fake argv passed to toplev::main.
	(gcc::jit::playback::context::acquire_mutex): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	(gcc::jit::playback::context::release_mutex): Likewise.
	(gcc::jit::playback::context::make_fake_args): Likewise.
	(gcc::jit::playback::context::extract_any_requested_dumps):
	Likewise.
	(gcc::jit::playback::context::convert_to_dso): Likewise. Also,
	log the arguments that the driver is invoked with.
	(gcc::jit::playback::context::dlopen_built_dso): Likewise.  Pass
	the logger to the result object.
	(gcc::jit::playback::context::replay): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	(gcc::jit::playback::context::dump_generated_code): Likewise.
	(gcc::jit::playback::context::handle_locations): Likewise.
	* jit-playback.h (gcc::jit::playback::context): Make this be
	a subclass of gcc::jit::log_user.
	* jit-recording.c: Include "jit-logging.h".
	(gcc::jit::recording::context::context: Initialize the logger to
	NULL for root contexts, or to the parent's logger for child
	contexts.
	(gcc::jit::recording::context::~context): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	(gcc::jit::recording::context::replay_into): Likewise.
	(gcc::jit::recording::context::disassociate_from_playback):
	Likewise.
	(gcc::jit::recording::context::compile): Likewise.
	(recording::context::add_error_va): Likewise.  Also, log the
	error.
	(gcc::jit::recording::context::validate): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	* jit-recording.h: Include "jit-logging.h".
	(gcc::jit::recording::context): Make this be a subclass of
	gcc::jit::log_user.
	* jit-result.c: Include "jit-common.h" and "jit-logging.h".
	(gcc::jit::result::result): Add logger param, recording it.
	Use JIT_LOG_SCOPE to log entry/exit from the function body.
	(gcc::jit::result::~result(): Use JIT_LOG_SCOPE to
	log entry/exit from the function body.
	(gcc::jit::result::get_code): Likewise.
	* jit-result.h (gcc::jit::result): Make this be a subclass of
	gcc::jit::log_user.
	(gcc::jit::result::result): Add logger parameter.
	* libgccjit++.h (gccjit::context::set_logfile): New function.
	* libgccjit.c: Include "jit-logging.h".
	(gcc_jit_context_acquire): Log the context.
	(gcc_jit_context_release): Use JIT_LOG_FUNC to
	log entry/exit from the function body, and log the context.
	(gcc_jit_context_new_child_context): Likewise, logging both
	contexts.
	(gcc_jit_context_new_location): Use JIT_LOG_FUNC to
	log entry/exit from the function body.
	(gcc_jit_context_get_type): Likewise.
	(gcc_jit_context_get_int_type): Likewise.
	(gcc_jit_context_new_array_type): Likewise.
	(gcc_jit_context_new_field): Likewise.
	(gcc_jit_context_new_struct_type): Likewise.
	(gcc_jit_context_new_opaque_struct): Likewise.
	(gcc_jit_struct_set_fields): Likewise.
	(gcc_jit_context_new_union_type): Likewise.
	(gcc_jit_context_new_function_ptr_type): Likewise.
	(gcc_jit_context_new_param): Likewise.
	(gcc_jit_context_new_function): Likewise.
	(gcc_jit_context_get_builtin_function): Likewise.
	(gcc_jit_function_get_param): Likewise.
	(gcc_jit_function_dump_to_dot): Likewise.
	(gcc_jit_function_new_block): Likewise.
	(gcc_jit_context_new_global): Likewise.
	(gcc_jit_context_new_rvalue_from_int): Likewise.
	(gcc_jit_context_zero): Likewise.
	(gcc_jit_context_one): Likewise.
	(gcc_jit_context_new_rvalue_from_double): Likewise.
	(gcc_jit_context_new_rvalue_from_ptr): Likewise.
	(gcc_jit_context_null): Likewise.
	(gcc_jit_context_new_string_literal): Likewise.
	(gcc_jit_context_new_unary_op): Likewise.
	(gcc_jit_context_new_binary_op): Likewise.
	(gcc_jit_context_new_comparison): Likewise.
	(gcc_jit_context_new_call): Likewise.
	(gcc_jit_context_new_call_through_ptr): Likewise.
	(gcc_jit_context_new_cast): Likewise.
	(gcc_jit_context_new_array_access): Likewise.
	(gcc_jit_lvalue_access_field): Likewise.
	(gcc_jit_rvalue_access_field): Likewise.
	(gcc_jit_rvalue_dereference_field): Likewise.
	(gcc_jit_rvalue_dereference): Likewise.
	(gcc_jit_lvalue_get_address): Likewise.
	(gcc_jit_function_new_local): Likewise.
	(gcc_jit_block_add_eval): Likewise.
	(gcc_jit_block_add_assignment): Likewise.
	(gcc_jit_block_add_assignment_op): Likewise.
	(gcc_jit_block_end_with_conditional): Likewise.
	(gcc_jit_block_add_comment): Likewise.
	(gcc_jit_block_end_with_jump): Likewise.
	(gcc_jit_block_end_with_return): Likewise.
	(gcc_jit_block_end_with_void_return): Likewise.
	(gcc_jit_context_set_str_option): Likewise.
	(gcc_jit_context_set_int_option): Likewise.
	(gcc_jit_context_set_bool_option): Likewise.
	(gcc_jit_context_enable_dump): Likewise.
	(gcc_jit_context_compile): Likewise.  Also log the context,
	and the result.
	(gcc_jit_context_dump_to_file): Likewise.
	(gcc_jit_context_set_logfile): New function.
	(gcc_jit_context_get_first_error): Use JIT_LOG_FUNC to
	log entry/exit from the function body.
	(gcc_jit_result_get_code): Likewise.  Also log the fnname)
	and the ptr to be returned.
	(gcc_jit_result_release): Likewise.  Also log the result.
	* libgccjit.h: Include <stdio.h>, since we need FILE *.
	(gcc_jit_context_set_logfile): New declaration.
	* libgccjit.map (gcc_jit_context_set_logfile): New.

gcc/testsuite/ChangeLog:
	* jit.dg/harness.h (set_up_logging): New function.
	(test_jit): Fail if gcc_jit_context_acquire fails.  Call
	set_up_logging on the context, so that every testcase is
	logged to a particular file.
	* jit.dg/test-nested-contexts.c (main): Open a logfile,
	and call gcc_jit_context_set_logfile on the top-level context.

From-SVN: r219357
parent efa7df3c
2015-01-08 David Malcolm <dmalcolm@redhat.com>
* Make-lang.in (jit_OBJS): Add jit/jit-logging.o.
* docs/internals/index.rst (Overview of code structure): Mention
gcc_jit_context_set_logfile, and embed the example logfile.
* docs/internals/test-hello-world.exe.log.txt: New file: example
of a logfile.
* docs/topics/contexts.rst (Debugging): Add documentation
for gcc_jit_context_set_logfile.
* docs/_build/texinfo/libgccjit.texi: Regenerate.
* dummy-frontend.c: Include "jit-logging.h".
(jit_langhook_init): Assert that there is an active playback
context. If it has a logger, log entry/exit to this function.
(jit_langhook_write_globals): Likewise.
* jit-common.h (gcc::jit::logger): New forward declaration.
* jit-logging.c: New file.
* jit-logging.h: New file.
* jit-playback.c: Include "jit-logging.h".
(gcc::jit::playback::context::context): Initialize the log_user
base class from the recording context's logger (if any). Use
JIT_LOG_SCOPE to log entry/exit from the function body.
(gcc::jit::playback::context::~context): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
(gcc::jit::playback::build_stmt_list): Likewise.
(gcc::jit::playback::function::postprocess): Likewise.
(gcc::jit::playback::context::compile): Likewise. Log the
entry/exit to toplev::main and toplev::finalize. Log the
fake argv passed to toplev::main.
(gcc::jit::playback::context::acquire_mutex): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
(gcc::jit::playback::context::release_mutex): Likewise.
(gcc::jit::playback::context::make_fake_args): Likewise.
(gcc::jit::playback::context::extract_any_requested_dumps):
Likewise.
(gcc::jit::playback::context::convert_to_dso): Likewise. Also,
log the arguments that the driver is invoked with.
(gcc::jit::playback::context::dlopen_built_dso): Likewise. Pass
the logger to the result object.
(gcc::jit::playback::context::replay): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
(gcc::jit::playback::context::dump_generated_code): Likewise.
(gcc::jit::playback::context::handle_locations): Likewise.
* jit-playback.h (gcc::jit::playback::context): Make this be
a subclass of gcc::jit::log_user.
* jit-recording.c: Include "jit-logging.h".
(gcc::jit::recording::context::context: Initialize the logger to
NULL for root contexts, or to the parent's logger for child
contexts.
(gcc::jit::recording::context::~context): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
(gcc::jit::recording::context::replay_into): Likewise.
(gcc::jit::recording::context::disassociate_from_playback):
Likewise.
(gcc::jit::recording::context::compile): Likewise.
(recording::context::add_error_va): Likewise. Also, log the
error.
(gcc::jit::recording::context::validate): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
* jit-recording.h: Include "jit-logging.h".
(gcc::jit::recording::context): Make this be a subclass of
gcc::jit::log_user.
* jit-result.c: Include "jit-common.h" and "jit-logging.h".
(gcc::jit::result::result): Add logger param, recording it.
Use JIT_LOG_SCOPE to log entry/exit from the function body.
(gcc::jit::result::~result(): Use JIT_LOG_SCOPE to
log entry/exit from the function body.
(gcc::jit::result::get_code): Likewise.
* jit-result.h (gcc::jit::result): Make this be a subclass of
gcc::jit::log_user.
(gcc::jit::result::result): Add logger parameter.
* libgccjit++.h (gccjit::context::set_logfile): New function.
* libgccjit.c: Include "jit-logging.h".
(gcc_jit_context_acquire): Log the context.
(gcc_jit_context_release): Use JIT_LOG_FUNC to
log entry/exit from the function body, and log the context.
(gcc_jit_context_new_child_context): Likewise, logging both
contexts.
(gcc_jit_context_new_location): Use JIT_LOG_FUNC to
log entry/exit from the function body.
(gcc_jit_context_get_type): Likewise.
(gcc_jit_context_get_int_type): Likewise.
(gcc_jit_context_new_array_type): Likewise.
(gcc_jit_context_new_field): Likewise.
(gcc_jit_context_new_struct_type): Likewise.
(gcc_jit_context_new_opaque_struct): Likewise.
(gcc_jit_struct_set_fields): Likewise.
(gcc_jit_context_new_union_type): Likewise.
(gcc_jit_context_new_function_ptr_type): Likewise.
(gcc_jit_context_new_param): Likewise.
(gcc_jit_context_new_function): Likewise.
(gcc_jit_context_get_builtin_function): Likewise.
(gcc_jit_function_get_param): Likewise.
(gcc_jit_function_dump_to_dot): Likewise.
(gcc_jit_function_new_block): Likewise.
(gcc_jit_context_new_global): Likewise.
(gcc_jit_context_new_rvalue_from_int): Likewise.
(gcc_jit_context_zero): Likewise.
(gcc_jit_context_one): Likewise.
(gcc_jit_context_new_rvalue_from_double): Likewise.
(gcc_jit_context_new_rvalue_from_ptr): Likewise.
(gcc_jit_context_null): Likewise.
(gcc_jit_context_new_string_literal): Likewise.
(gcc_jit_context_new_unary_op): Likewise.
(gcc_jit_context_new_binary_op): Likewise.
(gcc_jit_context_new_comparison): Likewise.
(gcc_jit_context_new_call): Likewise.
(gcc_jit_context_new_call_through_ptr): Likewise.
(gcc_jit_context_new_cast): Likewise.
(gcc_jit_context_new_array_access): Likewise.
(gcc_jit_lvalue_access_field): Likewise.
(gcc_jit_rvalue_access_field): Likewise.
(gcc_jit_rvalue_dereference_field): Likewise.
(gcc_jit_rvalue_dereference): Likewise.
(gcc_jit_lvalue_get_address): Likewise.
(gcc_jit_function_new_local): Likewise.
(gcc_jit_block_add_eval): Likewise.
(gcc_jit_block_add_assignment): Likewise.
(gcc_jit_block_add_assignment_op): Likewise.
(gcc_jit_block_end_with_conditional): Likewise.
(gcc_jit_block_add_comment): Likewise.
(gcc_jit_block_end_with_jump): Likewise.
(gcc_jit_block_end_with_return): Likewise.
(gcc_jit_block_end_with_void_return): Likewise.
(gcc_jit_context_set_str_option): Likewise.
(gcc_jit_context_set_int_option): Likewise.
(gcc_jit_context_set_bool_option): Likewise.
(gcc_jit_context_enable_dump): Likewise.
(gcc_jit_context_compile): Likewise. Also log the context,
and the result.
(gcc_jit_context_dump_to_file): Likewise.
(gcc_jit_context_set_logfile): New function.
(gcc_jit_context_get_first_error): Use JIT_LOG_FUNC to
log entry/exit from the function body.
(gcc_jit_result_get_code): Likewise. Also log the fnname)
and the ptr to be returned.
(gcc_jit_result_release): Likewise. Also log the result.
* libgccjit.h: Include <stdio.h>, since we need FILE *.
(gcc_jit_context_set_logfile): New declaration.
* libgccjit.map (gcc_jit_context_set_logfile): New.
2015-01-07 David Malcolm <dmalcolm@redhat.com>
* jit-recording.h (gcc::jit::recording::type::is_void): New
......
......@@ -62,6 +62,7 @@ jit: $(LIBGCCJIT_FILENAME) \
jit_OBJS = attribs.o \
jit/dummy-frontend.o \
jit/libgccjit.o \
jit/jit-logging.o \
jit/jit-recording.o \
jit/jit-playback.o \
jit/jit-result.o \
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -268,3 +268,12 @@ Here is a high-level summary from ``jit-common.h``:
.. include:: ../../jit-common.h
:start-after: This comment is included by the docs.
:end-before: End of comment for inclusion in the docs. */
.. _example-of-log-file:
Another way to understand the structure of the code is to enable logging,
via :c:func:`gcc_jit_context_set_logfile`. Here is an example of a log
generated via this call:
.. literalinclude:: test-hello-world.exe.log.txt
:lines: 1-
JIT: entering: gcc_jit_context_set_str_option
JIT: exiting: gcc_jit_context_set_str_option
JIT: entering: gcc_jit_context_set_int_option
JIT: exiting: gcc_jit_context_set_int_option
JIT: entering: gcc_jit_context_set_bool_option
JIT: exiting: gcc_jit_context_set_bool_option
JIT: entering: gcc_jit_context_set_bool_option
JIT: exiting: gcc_jit_context_set_bool_option
JIT: entering: gcc_jit_context_set_bool_option
JIT: exiting: gcc_jit_context_set_bool_option
JIT: entering: gcc_jit_context_set_bool_option
JIT: exiting: gcc_jit_context_set_bool_option
JIT: entering: gcc_jit_context_set_bool_option
JIT: exiting: gcc_jit_context_set_bool_option
JIT: entering: gcc_jit_context_get_type
JIT: exiting: gcc_jit_context_get_type
JIT: entering: gcc_jit_context_get_type
JIT: exiting: gcc_jit_context_get_type
JIT: entering: gcc_jit_context_new_param
JIT: exiting: gcc_jit_context_new_param
JIT: entering: gcc_jit_context_new_function
JIT: exiting: gcc_jit_context_new_function
JIT: entering: gcc_jit_context_new_param
JIT: exiting: gcc_jit_context_new_param
JIT: entering: gcc_jit_context_get_type
JIT: exiting: gcc_jit_context_get_type
JIT: entering: gcc_jit_context_new_function
JIT: exiting: gcc_jit_context_new_function
JIT: entering: gcc_jit_context_new_string_literal
JIT: exiting: gcc_jit_context_new_string_literal
JIT: entering: gcc_jit_function_new_block
JIT: exiting: gcc_jit_function_new_block
JIT: entering: gcc_jit_block_add_comment
JIT: exiting: gcc_jit_block_add_comment
JIT: entering: gcc_jit_context_new_call
JIT: exiting: gcc_jit_context_new_call
JIT: entering: gcc_jit_block_add_eval
JIT: exiting: gcc_jit_block_add_eval
JIT: entering: gcc_jit_block_end_with_void_return
JIT: exiting: gcc_jit_block_end_with_void_return
JIT: entering: gcc_jit_context_compile
JIT: compiling ctxt: 0x1283e20
JIT: entering: gcc::jit::result* gcc::jit::recording::context::compile()
JIT: entering: void gcc::jit::recording::context::validate()
JIT: exiting: void gcc::jit::recording::context::validate()
JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: exiting: gcc::jit::playback::context::context(gcc::jit::recording::context*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::compile()
JIT: entering: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: exiting: void gcc::jit::playback::context::make_fake_args(vec<char*>*, const char*, vec<gcc::jit::recording::requested_dump>*)
JIT: entering: void gcc::jit::playback::context::acquire_mutex()
JIT: exiting: void gcc::jit::playback::context::acquire_mutex()
JIT: entering: toplev::main
JIT: argv[0]: ./test-hello-world.c.exe
JIT: argv[1]: /tmp/libgccjit-CKq1M9/fake.c
JIT: argv[2]: -fPIC
JIT: argv[3]: -O3
JIT: argv[4]: -g
JIT: argv[5]: -quiet
JIT: argv[6]: --param
JIT: argv[7]: ggc-min-expand=0
JIT: argv[8]: --param
JIT: argv[9]: ggc-min-heapsize=0
JIT: entering: bool jit_langhook_init()
JIT: exiting: bool jit_langhook_init()
JIT: entering: void gcc::jit::playback::context::replay()
JIT: entering: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*)
JIT: exiting: void gcc::jit::recording::context::replay_into(gcc::jit::replayer*)
JIT: entering: void gcc::jit::recording::context::disassociate_from_playback()
JIT: exiting: void gcc::jit::recording::context::disassociate_from_playback()
JIT: entering: void gcc::jit::playback::context::handle_locations()
JIT: exiting: void gcc::jit::playback::context::handle_locations()
JIT: entering: void gcc::jit::playback::function::build_stmt_list()
JIT: exiting: void gcc::jit::playback::function::build_stmt_list()
JIT: entering: void gcc::jit::playback::function::build_stmt_list()
JIT: exiting: void gcc::jit::playback::function::build_stmt_list()
JIT: entering: void gcc::jit::playback::function::postprocess()
JIT: exiting: void gcc::jit::playback::function::postprocess()
JIT: entering: void gcc::jit::playback::function::postprocess()
JIT: exiting: void gcc::jit::playback::function::postprocess()
JIT: exiting: void gcc::jit::playback::context::replay()
JIT: entering: void jit_langhook_write_globals()
JIT: exiting: void jit_langhook_write_globals()
JIT: exiting: toplev::main
JIT: entering: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*)
JIT: exiting: void gcc::jit::playback::context::extract_any_requested_dumps(vec<gcc::jit::recording::requested_dump>*)
JIT: entering: toplev::finalize
JIT: exiting: toplev::finalize
JIT: entering: void gcc::jit::playback::context::convert_to_dso(const char*)
JIT: argv[0]: x86_64-unknown-linux-gnu-gcc-5.0.0
JIT: argv[1]: -shared
JIT: argv[2]: /tmp/libgccjit-CKq1M9/fake.s
JIT: argv[3]: -o
JIT: argv[4]: /tmp/libgccjit-CKq1M9/fake.so
JIT: argv[5]: -fno-use-linker-plugin
JIT: argv[6]: (null)
JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*)
JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
JIT: entering: gcc::jit::result::result(gcc::jit::logger*, void*)
JIT: exiting: gcc::jit::result::result(gcc::jit::logger*, void*)
JIT: exiting: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso()
JIT: entering: void gcc::jit::playback::context::release_mutex()
JIT: exiting: void gcc::jit::playback::context::release_mutex()
JIT: exiting: gcc::jit::result* gcc::jit::playback::context::compile()
JIT: entering: gcc::jit::playback::context::~context()
JIT: exiting: gcc::jit::playback::context::~context()
JIT: exiting: gcc::jit::result* gcc::jit::recording::context::compile()
JIT: gcc_jit_context_compile: returning (gcc_jit_result *)0x12f75d0
JIT: exiting: gcc_jit_context_compile
JIT: entering: gcc_jit_result_get_code
JIT: locating fnname: hello_world
JIT: entering: void* gcc::jit::result::get_code(const char*)
JIT: exiting: void* gcc::jit::result::get_code(const char*)
JIT: gcc_jit_result_get_code: returning (void *)0x7ff6b8cd87f0
JIT: exiting: gcc_jit_result_get_code
JIT: entering: gcc_jit_context_release
JIT: deleting ctxt: 0x1283e20
JIT: entering: gcc::jit::recording::context::~context()
JIT: exiting: gcc::jit::recording::context::~context()
JIT: exiting: gcc_jit_context_release
JIT: entering: gcc_jit_result_release
JIT: deleting result: 0x12f75d0
JIT: entering: virtual gcc::jit::result::~result()
JIT: exiting: virtual gcc::jit::result::~result()
JIT: exiting: gcc_jit_result_release
JIT: gcc::jit::logger::~logger()
......@@ -153,6 +153,56 @@ Debugging
code in a debugger.
.. function:: void\
gcc_jit_context_set_logfile (gcc_jit_context *ctxt,\
FILE *logfile,\
int flags,\
int verbosity)
To help with debugging; enable ongoing logging of the context's
activity to the given file.
For example, the following will enable logging to stderr.
.. code-block:: c
gcc_jit_context_set_logfile (ctxt, stderr, 0, 0);
Examples of information logged include:
* API calls
* the various steps involved within compilation
* activity on any :c:type:`gcc_jit_result` instances created by
the context
* activity within any child contexts
An example of a log can be seen :ref:`here <example-of-log-file>`,
though the precise format and kinds of information logged is subject
to change.
The caller remains responsible for closing `logfile`, and it must not
be closed until all users are released. In particular, note that
child contexts and :c:type:`gcc_jit_result` instances created by
the context will use the logfile.
There may a performance cost for logging.
You can turn off logging on `ctxt` by passing `NULL` for `logfile`.
Doing so only affects the context; it does not affect child contexts
or :c:type:`gcc_jit_result` instances already created by
the context.
The parameters "flags" and "verbosity" are reserved for future
expansion, and must be zero for now.
To contrast the above: :c:func:`gcc_jit_context_dump_to_file` dumps the
current state of a context to the given path, whereas
:c:func:`gcc_jit_context_set_logfile` enables on-going logging of
future activies on a context to the given `FILE *`.
.. function:: void\
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\
const char *dumpname, \
char **out_ptr)
......
......@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "jit-common.h"
#include "jit-logging.h"
#include "jit-playback.h"
#include <mpfr.h>
......@@ -113,6 +114,9 @@ struct ggc_root_tab jit_root_tab[] =
static bool
jit_langhook_init (void)
{
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
static bool registered_root_tab = false;
if (!registered_root_tab)
{
......@@ -212,6 +216,9 @@ jit_langhook_getdecls (void)
static void
jit_langhook_write_globals (void)
{
gcc_assert (gcc::jit::active_playback_ctxt);
JIT_LOG_SCOPE (gcc::jit::active_playback_ctxt->get_logger ());
/* This is the hook that runs the middle and backends: */
symtab->finalize_compilation_unit ();
}
......
......@@ -97,6 +97,7 @@ namespace jit {
class result;
class dump;
class logger;
class builtins_manager; // declared within jit-builtins.h
class tempdir;
......
/* Internals of libgccjit: logging
Copyright (C) 2014-2015 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
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 "jit-logging.h"
namespace gcc {
namespace jit {
/* Implementation of class gcc::jit::logger. */
/* The constructor for gcc::jit::logger, used by
gcc_jit_context_set_logfile. */
logger::logger (FILE *f_out,
int, /* flags */
int /* verbosity */) :
m_refcount (0),
m_f_out (f_out),
m_indent_level (0),
m_log_refcount_changes (false)
{
}
/* The destructor for gcc::jit::logger, invoked via
the decref method when the refcount hits zero.
Note that we do not close the underlying FILE * (m_f_out). */
logger::~logger ()
{
/* This should be the last message emitted. */
log ("%s", __PRETTY_FUNCTION__);
gcc_assert (m_refcount == 0);
}
/* Increment the reference count of the gcc::jit::logger. */
void
logger::incref (const char *reason)
{
m_refcount++;
if (m_log_refcount_changes)
log ("%s: reason: %s refcount now %i ",
__PRETTY_FUNCTION__, reason, m_refcount);
}
/* Decrement the reference count of the gcc::jit::logger,
deleting it if nothing is referring to it. */
void
logger::decref (const char *reason)
{
gcc_assert (m_refcount > 0);
--m_refcount;
if (m_log_refcount_changes)
log ("%s: reason: %s refcount now %i",
__PRETTY_FUNCTION__, reason, m_refcount);
if (0 == m_refcount)
delete this;
}
/* Write a formatted message to the log, by calling the log_va method. */
void
logger::log (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
log_va (fmt, ap);
va_end (ap);
}
/* Write an indented line to the log file.
We explicitly flush after each line: if something crashes the process,
we want the logfile/stream to contain the most up-to-date hint about the
last thing that was happening, without it being hidden in an in-process
buffer. */
void
logger::log_va (const char *fmt, va_list ap)
{
fprintf (m_f_out, "JIT: ");
for (int i = 0; i < m_indent_level; i++)
fputc (' ', m_f_out);
vfprintf (m_f_out, fmt, ap);
fprintf (m_f_out, "\n");
fflush (m_f_out);
}
/* Record the entry within a particular scope, indenting subsequent
log lines accordingly. */
void
logger::enter_scope (const char *scope_name)
{
log ("entering: %s", scope_name);
m_indent_level += 1;
}
/* Record the exit from a particular scope, restoring the indent level to
before the scope was entered. */
void
logger::exit_scope (const char *scope_name)
{
if (m_indent_level)
m_indent_level -= 1;
else
log ("(mismatching indentation)");
log ("exiting: %s", scope_name);
}
/* Implementation of class gcc::jit::log_user. */
/* The constructor for gcc::jit::log_user. */
log_user::log_user (logger *logger) : m_logger (logger)
{
if (m_logger)
m_logger->incref("log_user ctor");
}
/* The destructor for gcc::jit::log_user. */
log_user::~log_user ()
{
if (m_logger)
m_logger->decref("log_user dtor");
}
/* Set the logger for a gcc::jit::log_user, managing the reference counts
of the old and new logger (either of which might be NULL). */
void
log_user::set_logger (logger *logger)
{
if (logger)
logger->incref ("log_user::set_logger");
if (m_logger)
m_logger->decref ("log_user::set_logger");
m_logger = logger;
}
} // namespace gcc::jit
} // namespace gcc
/* Internals of libgccjit: logging
Copyright (C) 2014-2015 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
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 JIT_LOGGING_H
#define JIT_LOGGING_H
#include "jit-common.h"
namespace gcc {
namespace jit {
/* A gcc::jit::logger encapsulates a logging stream: a way to send
lines of pertinent information to a FILE *. */
class logger
{
public:
logger (FILE *f_out, int flags, int verbosity);
~logger ();
void incref (const char *reason);
void decref (const char *reason);
void log (const char *fmt, ...)
GNU_PRINTF(2, 3);
void log_va (const char *fmt, va_list ap)
GNU_PRINTF(2, 0);
void enter_scope (const char *scope_name);
void exit_scope (const char *scope_name);
private:
int m_refcount;
FILE *m_f_out;
int m_indent_level;
bool m_log_refcount_changes;
};
/* The class gcc::jit::log_scope is an RAII-style class intended to make
it easy to notify a logger about entering and exiting the body of a
given function. */
class log_scope
{
public:
log_scope (logger *logger, const char *name);
~log_scope ();
private:
logger *m_logger;
const char *m_name;
};
/* The constructor for gcc::jit::log_scope.
The normal case is that the logger is NULL, in which case this should
be largely a no-op.
If we do have a logger, notify it that we're entering the given scope.
We also need to hold a reference on it, to avoid a use-after-free
when logging the cleanup of the owner of the logger. */
inline
log_scope::log_scope (logger *logger, const char *name) :
m_logger (logger),
m_name (name)
{
if (m_logger)
{
m_logger->incref ("log_scope ctor");
m_logger->enter_scope (m_name);
}
}
/* The destructor for gcc::jit::log_scope; essentially the opposite of
the constructor. */
inline
log_scope::~log_scope ()
{
if (m_logger)
{
m_logger->exit_scope (m_name);
m_logger->decref ("log_scope dtor");
}
}
/* A gcc::jit::log_user is something that potentially uses a
gcc::jit::logger (which could be NULL).
It is the base class for each of:
- class gcc::jit::recording::context
- class gcc::jit::playback::context
- class gcc::jit::result
The log_user class keeps the reference-count of a logger up-to-date. */
class log_user
{
public:
log_user (logger *logger);
~log_user ();
logger * get_logger () const { return m_logger; }
void set_logger (logger * logger);
void log (const char *fmt, ...)
GNU_PRINTF(2, 3);
void enter_scope (const char *scope_name);
void exit_scope (const char *scope_name);
private:
logger *m_logger;
};
/* A shortcut for calling log from a context/result, handling the common
case where the underlying logger is NULL via a no-op. */
inline void
log_user::log (const char *fmt, ...)
{
if (m_logger)
{
va_list ap;
va_start (ap, fmt);
m_logger->log_va (fmt, ap);
va_end (ap);
}
}
/* A shortcut for recording entry into a scope from a context/result,
handling the common case where the underlying logger is NULL via
a no-op. */
inline void
log_user::enter_scope (const char *scope_name)
{
if (m_logger)
m_logger->enter_scope (scope_name);
}
/* A shortcut for recording exit from a scope from a context/result,
handling the common case where the underlying logger is NULL via
a no-op. */
inline void
log_user::exit_scope (const char *scope_name)
{
if (m_logger)
m_logger->exit_scope (scope_name);
}
} // namespace gcc::jit
} // namespace gcc
/* If the given logger is non-NULL, log entry/exit of this scope to
it, identifying it using __PRETTY_FUNCTION__. */
#define JIT_LOG_SCOPE(LOGGER) \
gcc::jit::log_scope s (LOGGER, __PRETTY_FUNCTION__)
/* If the given logger is non-NULL, log entry/exit of this scope to
it, identifying it using __func__. */
#define JIT_LOG_FUNC(LOGGER) \
gcc::jit::log_scope s (LOGGER, __func__)
#endif /* JIT_LOGGING_H */
......@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h"
#include "jit-common.h"
#include "jit-logging.h"
#include "jit-playback.h"
#include "jit-result.h"
#include "jit-builtins.h"
......@@ -86,11 +87,13 @@ namespace jit {
/* The constructor for gcc::jit::playback::context. */
playback::context::context (recording::context *ctxt)
: m_recording_ctxt (ctxt),
: log_user (ctxt->get_logger ()),
m_recording_ctxt (ctxt),
m_tempdir (NULL),
m_char_array_type_node (NULL),
m_const_char_ptr (NULL)
{
JIT_LOG_SCOPE (get_logger ());
m_functions.create (0);
m_source_files.create (0);
m_cached_locations.create (0);
......@@ -100,6 +103,7 @@ playback::context::context (recording::context *ctxt)
playback::context::~context ()
{
JIT_LOG_SCOPE (get_logger ());
if (m_tempdir)
delete m_tempdir;
m_functions.release ();
......@@ -1219,6 +1223,8 @@ build_stmt_list ()
int i;
block *b;
JIT_LOG_SCOPE (m_ctxt->get_logger ());
FOR_EACH_VEC_ELT (m_blocks, i, b)
{
int j;
......@@ -1244,6 +1250,8 @@ void
playback::function::
postprocess ()
{
JIT_LOG_SCOPE (m_ctxt->get_logger ());
if (m_ctxt->get_bool_option (GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE))
debug_tree (m_stmt_list);
......@@ -1538,6 +1546,8 @@ result *
playback::context::
compile ()
{
JIT_LOG_SCOPE (get_logger ());
const char *ctxt_progname;
result *result_obj = NULL;
......@@ -1572,8 +1582,13 @@ compile ()
/* This runs the compiler. */
toplev toplev (false);
enter_scope ("toplev::main");
if (get_logger ())
for (unsigned i = 0; i < fake_args.length (); i++)
get_logger ()->log ("argv[%i]: %s", i, fake_args[i]);
toplev.main (fake_args.length (),
const_cast <char **> (fake_args.address ()));
exit_scope ("toplev::main");
/* Extracting dumps makes use of the gcc::dump_manager, hence we
need to do it between toplev::main (which creates the dump manager)
......@@ -1581,7 +1596,9 @@ compile ()
extract_any_requested_dumps (&requested_dumps);
/* Clean up the compiler. */
enter_scope ("toplev::finalize");
toplev.finalize ();
exit_scope ("toplev::finalize");
/* Ideally we would release the jit mutex here, but we can't yet since
followup activities use timevars, which are global state. */
......@@ -1622,6 +1639,7 @@ void
playback::context::acquire_mutex ()
{
/* Acquire the big GCC mutex. */
JIT_LOG_SCOPE (get_logger ());
pthread_mutex_lock (&jit_mutex);
gcc_assert (NULL == active_playback_ctxt);
active_playback_ctxt = this;
......@@ -1633,6 +1651,7 @@ void
playback::context::release_mutex ()
{
/* Release the big GCC mutex. */
JIT_LOG_SCOPE (get_logger ());
gcc_assert (active_playback_ctxt == this);
active_playback_ctxt = NULL;
pthread_mutex_unlock (&jit_mutex);
......@@ -1647,6 +1666,8 @@ make_fake_args (vec <char *> *argvec,
const char *ctxt_progname,
vec <recording::requested_dump> *requested_dumps)
{
JIT_LOG_SCOPE (get_logger ());
#define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
#define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
......@@ -1734,6 +1755,8 @@ void
playback::context::
extract_any_requested_dumps (vec <recording::requested_dump> *requested_dumps)
{
JIT_LOG_SCOPE (get_logger ());
int i;
recording::requested_dump *d;
FOR_EACH_VEC_ELT (*requested_dumps, i, d)
......@@ -1819,6 +1842,7 @@ void
playback::context::
convert_to_dso (const char *ctxt_progname)
{
JIT_LOG_SCOPE (get_logger ());
/* Currently this lumps together both assembling and linking into
TV_ASSEMBLE. */
auto_timevar assemble_timevar (TV_ASSEMBLE);
......@@ -1852,6 +1876,10 @@ convert_to_dso (const char *ctxt_progname)
/* pex_one's error-handling requires pname to be non-NULL. */
gcc_assert (ctxt_progname);
if (get_logger ())
for (unsigned i = 0; i < argvec.length (); i++)
get_logger ()->log ("argv[%i]: %s", i, argvec[i]);
errmsg = pex_one (PEX_SEARCH, /* int flags, */
gcc_driver_name,
const_cast <char *const *> (argvec.address ()),
......@@ -1892,6 +1920,7 @@ result *
playback::context::
dlopen_built_dso ()
{
JIT_LOG_SCOPE (get_logger ());
auto_timevar load_timevar (TV_LOAD);
void *handle = NULL;
const char *error = NULL;
......@@ -1906,7 +1935,7 @@ dlopen_built_dso ()
add_error (NULL, "%s", error);
}
if (handle)
result_obj = new result (handle);
result_obj = new result (get_logger (), handle);
else
result_obj = NULL;
......@@ -1923,6 +1952,7 @@ void
playback::context::
replay ()
{
JIT_LOG_SCOPE (get_logger ());
/* Adapted from c-common.c:c_common_nodes_and_builtins. */
tree array_domain_type = build_index_type (size_int (200));
m_char_array_type_node
......@@ -1984,6 +2014,7 @@ void
playback::context::
dump_generated_code ()
{
JIT_LOG_SCOPE (get_logger ());
char buf[4096];
size_t sz;
FILE *f_in = fopen (get_path_s_file (), "r");
......@@ -2069,6 +2100,7 @@ handle_locations ()
imposed by the linemap API.
line_table is a global. */
JIT_LOG_SCOPE (get_logger ());
int i;
source_file *file;
......
......@@ -35,7 +35,7 @@ namespace jit {
namespace playback {
class context
class context : public log_user
{
public:
context (::gcc::jit::recording::context *ctxt);
......
......@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "jit-common.h"
#include "jit-builtins.h"
#include "jit-logging.h"
#include "jit-recording.h"
#include "jit-playback.h"
......@@ -169,7 +170,8 @@ recording::playback_block (recording::block *b)
gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
recording::context::context (context *parent_ctxt)
: m_parent_ctxt (parent_ctxt),
: log_user (NULL),
m_parent_ctxt (parent_ctxt),
m_error_count (0),
m_first_error_str (NULL),
m_owns_first_error_str (false),
......@@ -195,6 +197,7 @@ recording::context::context (context *parent_ctxt)
memcpy (m_bool_options,
parent_ctxt->m_bool_options,
sizeof (m_bool_options));
set_logger (parent_ctxt->get_logger ());
}
else
{
......@@ -211,6 +214,7 @@ recording::context::context (context *parent_ctxt)
recording::context::~context ()
{
JIT_LOG_SCOPE (get_logger ());
int i;
memento *m;
FOR_EACH_VEC_ELT (m_mementos, i, m)
......@@ -245,6 +249,7 @@ recording::context::record (memento *m)
void
recording::context::replay_into (replayer *r)
{
JIT_LOG_SCOPE (get_logger ());
int i;
memento *m;
......@@ -302,6 +307,7 @@ recording::context::replay_into (replayer *r)
void
recording::context::disassociate_from_playback ()
{
JIT_LOG_SCOPE (get_logger ());
int i;
memento *m;
......@@ -904,6 +910,8 @@ recording::context::enable_dump (const char *dumpname,
result *
recording::context::compile ()
{
JIT_LOG_SCOPE (get_logger ());
validate ();
if (errors_occurred ())
......@@ -940,6 +948,8 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
const char *errmsg;
bool has_ownership;
JIT_LOG_SCOPE (get_logger ());
vasprintf (&malloced_msg, fmt, ap);
if (malloced_msg)
{
......@@ -951,6 +961,8 @@ recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
errmsg = "out of memory generating error message";
has_ownership = false;
}
if (get_logger ())
get_logger ()->log ("error %i: %s", m_error_count, errmsg);
const char *ctxt_progname =
get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
......@@ -1060,6 +1072,8 @@ recording::context::get_all_requested_dumps (vec <recording::requested_dump> *ou
void
recording::context::validate ()
{
JIT_LOG_SCOPE (get_logger ());
if (m_parent_ctxt)
m_parent_ctxt->validate ();
......
......@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#define JIT_RECORDING_H
#include "jit-common.h"
#include "jit-logging.h"
namespace gcc {
......@@ -53,7 +54,7 @@ struct requested_dump
};
/* A JIT-compilation context. */
class context
class context : public log_user
{
public:
context (context *parent_ctxt);
......
......@@ -21,6 +21,9 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "jit-common.h"
#include "jit-logging.h"
#include "jit-result.h"
namespace gcc {
......@@ -29,9 +32,11 @@ namespace jit {
/* Constructor for gcc::jit::result. */
result::
result(void *dso_handle)
: m_dso_handle(dso_handle)
result(logger *logger, void *dso_handle) :
log_user (logger),
m_dso_handle (dso_handle)
{
JIT_LOG_SCOPE (get_logger ());
}
/* gcc::jit::result's destructor.
......@@ -40,6 +45,8 @@ result(void *dso_handle)
result::~result()
{
JIT_LOG_SCOPE (get_logger ());
dlclose (m_dso_handle);
}
......@@ -53,6 +60,8 @@ void *
result::
get_code (const char *funcname)
{
JIT_LOG_SCOPE (get_logger ());
void *code;
const char *error;
......
......@@ -26,10 +26,10 @@ namespace gcc {
namespace jit {
/* The result of JIT-compilation. */
class result
class result : public log_user
{
public:
result(void *dso_handle);
result(logger *logger, void *dso_handle);
virtual ~result();
......
......@@ -102,6 +102,10 @@ namespace gccjit
void dump_to_file (const std::string &path,
bool update_locations);
void set_logfile (FILE *logfile,
int flags,
int verbosity);
void set_str_option (enum gcc_jit_str_option opt,
const char *value);
......@@ -541,6 +545,17 @@ context::dump_to_file (const std::string &path,
}
inline void
context::set_logfile (FILE *logfile,
int flags,
int verbosity)
{
gcc_jit_context_set_logfile (m_inner_ctxt,
logfile,
flags,
verbosity);
}
inline void
context::set_str_option (enum gcc_jit_str_option opt,
const char *value)
{
......
......@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef LIBGCCJIT_H
#define LIBGCCJIT_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
......@@ -254,6 +256,19 @@ gcc_jit_context_dump_to_file (gcc_jit_context *ctxt,
const char *path,
int update_locations);
/* To help with debugging; enable ongoing logging of the context's
activity to the given FILE *.
The caller remains responsible for closing "logfile".
Params "flags" and "verbosity" are reserved for future use, and
must both be 0 for now. */
extern void
gcc_jit_context_set_logfile (gcc_jit_context *ctxt,
FILE *logfile,
int flags,
int verbosity);
/* To be called after a compile, this gives the first error message
that occurred on the context.
......
......@@ -65,6 +65,7 @@
gcc_jit_context_release;
gcc_jit_context_set_bool_option;
gcc_jit_context_set_int_option;
gcc_jit_context_set_logfile;
gcc_jit_context_set_str_option;
gcc_jit_context_zero;
gcc_jit_field_as_object;
......
2015-01-08 David Malcolm <dmalcolm@redhat.com>
* jit.dg/harness.h (set_up_logging): New function.
(test_jit): Fail if gcc_jit_context_acquire fails. Call
set_up_logging on the context, so that every testcase is
logged to a particular file.
* jit.dg/test-nested-contexts.c (main): Open a logfile,
and call gcc_jit_context_set_logfile on the top-level context.
2015-01-08 Jakub Jelinek <jakub@redhat.com>
PR target/64338
......
......@@ -251,15 +251,64 @@ static void set_options (gcc_jit_context *ctxt, const char *argv0)
}
#ifndef TEST_ESCHEWS_TEST_JIT
/* Set up logging to a logfile of the form "test-FOO.exe.log.txt".
For example,
SRCDIR/gcc/testsuite/jit.dg/test-hello-world.c
is built as:
BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe
and is logged to
BUILDDIR/gcc/testsuite/jit/test-hello-world.c.exe.log.txt
The logfile must be closed by the caller.
Note that not every testcase enables logging. */
static FILE *
set_up_logging (gcc_jit_context *ctxt, const char *argv0)
{
const char *logfile_name_suffix = ".log.txt";
char *logfile_name = NULL;
FILE *logfile = NULL;
/* Build a logfile name of the form "test-FOO.exe.log.txt". */
logfile_name = (char *)malloc (strlen (argv0)
+ strlen (logfile_name_suffix)
+ 1);
if (!logfile_name)
{
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");
CHECK_NON_NULL (logfile);
free (logfile_name);
if (logfile)
gcc_jit_context_set_logfile (ctxt, logfile, 0, 0);
return logfile;
}
/* Run one iteration of the test. */
static void
test_jit (const char *argv0, void *user_data)
{
gcc_jit_context *ctxt;
FILE *logfile;
gcc_jit_result *result;
ctxt = gcc_jit_context_acquire ();
/* FIXME: error-handling */
if (!ctxt)
{
fail ("gcc_jit_context_acquire failed");
return;
}
logfile = set_up_logging (ctxt, argv0);
set_options (ctxt, argv0);
......@@ -275,6 +324,9 @@ test_jit (const char *argv0, void *user_data)
/* Once we're done with the code, this unloads the built .so file: */
gcc_jit_result_release (result);
if (logfile)
fclose (logfile);
}
#endif /* #ifndef TEST_ESCHEWS_TEST_JIT */
......
......@@ -532,6 +532,10 @@ main (int argc, char **argv)
/* We do the whole thing multiple times to shake out state-management
issues in the underlying code. */
FILE *logfile = fopen ("test-nested-contexts.c.exe.log.txt", "w");
if (!logfile)
fail ("error opening logfile");
for (i = 1; i <= NUM_TOP_ITERATIONS; i++)
{
/* Create the top-level context. */
......@@ -544,6 +548,9 @@ main (int argc, char **argv)
memset (&top_level, 0, sizeof (top_level));
top_level.ctxt = gcc_jit_context_acquire ();
gcc_jit_context_set_logfile (top_level.ctxt,
logfile,
0, 0);
set_options (top_level.ctxt, argv[0]);
make_types (&top_level);
......@@ -635,6 +642,9 @@ main (int argc, char **argv)
gcc_jit_context_release (top_level.ctxt);
}
if (logfile)
fclose (logfile);
totals ();
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment