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
This commit is contained in:
David Malcolm 2015-01-08 19:41:07 +00:00 committed by David Malcolm
parent efa7df3c62
commit eb4c16eb84
23 changed files with 1544 additions and 401 deletions

View File

@ -1,3 +1,143 @@
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

View File

@ -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 \

File diff suppressed because it is too large Load Diff

View File

@ -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-

View File

@ -0,0 +1,126 @@
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()

View File

@ -152,6 +152,56 @@ Debugging
:macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` to allow stepping through the
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, \

View File

@ -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 ();
}

View File

@ -97,6 +97,7 @@ namespace jit {
class result;
class dump;
class logger;
class builtins_manager; // declared within jit-builtins.h
class tempdir;

168
gcc/jit/jit-logging.c Normal file
View File

@ -0,0 +1,168 @@
/* 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

191
gcc/jit/jit-logging.h Normal file
View File

@ -0,0 +1,191 @@
/* 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 */

View File

@ -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;

View File

@ -35,7 +35,7 @@ namespace jit {
namespace playback {
class context
class context : public log_user
{
public:
context (::gcc::jit::recording::context *ctxt);

View File

@ -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 ();

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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);
@ -540,6 +544,17 @@ context::dump_to_file (const std::string &path,
update_locations);
}
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)

View File

@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "libgccjit.h"
#include "jit-common.h"
#include "jit-logging.h"
#include "jit-recording.h"
#include "jit-result.h"
@ -323,7 +324,9 @@ compatible_types (gcc::jit::recording::type *ltype,
gcc_jit_context *
gcc_jit_context_acquire (void)
{
return new gcc_jit_context (NULL);
gcc_jit_context *ctxt = new gcc_jit_context (NULL);
ctxt->log ("new top-level ctxt: %p", (void *)ctxt);
return ctxt;
}
/* Public entrypoint for releasing a gcc_jit_context.
@ -333,6 +336,9 @@ gcc_jit_context_acquire (void)
void
gcc_jit_context_release (gcc_jit_context *ctxt)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL ctxt");
JIT_LOG_FUNC (ctxt->get_logger ());
ctxt->log ("deleting ctxt: %p", (void *)ctxt);
delete ctxt;
}
@ -345,7 +351,12 @@ gcc_jit_context_release (gcc_jit_context *ctxt)
gcc_jit_context *
gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt)
{
return new gcc_jit_context (parent_ctxt);
RETURN_NULL_IF_FAIL (parent_ctxt, NULL, NULL, "NULL parent ctxt");
JIT_LOG_FUNC (parent_ctxt->get_logger ());
parent_ctxt->log ("parent_ctxt: %p", (void *)parent_ctxt);
gcc_jit_context *child_ctxt = new gcc_jit_context (parent_ctxt);
child_ctxt->log ("new child_ctxt: %p", (void *)child_ctxt);
return child_ctxt;
}
/* Public entrypoint. See description in libgccjit.h.
@ -361,7 +372,7 @@ gcc_jit_context_new_location (gcc_jit_context *ctxt,
int column)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
return (gcc_jit_location *)ctxt->new_location (filename, line, column);
}
@ -404,6 +415,7 @@ gcc_jit_context_get_type (gcc_jit_context *ctxt,
enum gcc_jit_types type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_PRINTF1 (
(type >= GCC_JIT_TYPE_VOID
&& type <= GCC_JIT_TYPE_FILE_PTR),
@ -425,6 +437,7 @@ gcc_jit_context_get_int_type (gcc_jit_context *ctxt,
int num_bytes, int is_signed)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (num_bytes >= 0, ctxt, NULL, "negative size");
return (gcc_jit_type *)ctxt->get_int_type (num_bytes, is_signed);
@ -485,6 +498,7 @@ gcc_jit_context_new_array_type (gcc_jit_context *ctxt,
int num_elements)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (element_type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (num_elements >= 0, ctxt, NULL, "negative size");
@ -507,6 +521,7 @@ gcc_jit_context_new_field (gcc_jit_context *ctxt,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
@ -543,6 +558,7 @@ gcc_jit_context_new_struct_type (gcc_jit_context *ctxt,
gcc_jit_field **fields)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
if (num_fields)
@ -578,6 +594,7 @@ gcc_jit_context_new_opaque_struct (gcc_jit_context *ctxt,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
@ -611,8 +628,9 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
gcc_jit_field **fields)
{
RETURN_IF_FAIL (struct_type, NULL, loc, "NULL struct_type");
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = struct_type->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL_PRINTF1 (
NULL == struct_type->get_fields (), ctxt, loc,
"%s already has had fields set",
@ -649,6 +667,7 @@ gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
gcc_jit_field **fields)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
if (num_fields)
@ -687,6 +706,7 @@ gcc_jit_context_new_function_ptr_type (gcc_jit_context *ctxt,
int is_variadic)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (return_type, ctxt, loc, "NULL return_type");
RETURN_NULL_IF_FAIL (
@ -720,6 +740,7 @@ gcc_jit_context_new_param (gcc_jit_context *ctxt,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
@ -785,6 +806,7 @@ gcc_jit_context_new_function (gcc_jit_context *ctxt,
int is_variadic)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL_PRINTF1 (
((kind >= GCC_JIT_FUNCTION_EXPORTED)
@ -846,6 +868,7 @@ gcc_jit_context_get_builtin_function (gcc_jit_context *ctxt,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (name, ctxt, NULL, "NULL name");
return static_cast <gcc_jit_function *> (ctxt->get_builtin_function (name));
@ -876,6 +899,7 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
{
RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
gcc::jit::recording::context *ctxt = func->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (index >= 0, ctxt, NULL, "negative index");
int num_params = func->get_params ().length ();
RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
@ -900,6 +924,7 @@ gcc_jit_function_dump_to_dot (gcc_jit_function *func,
{
RETURN_IF_FAIL (func, NULL, NULL, "NULL function");
gcc::jit::recording::context *ctxt = func->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_IF_FAIL (path, ctxt, NULL, "NULL path");
func->dump_to_dot (path);
@ -916,6 +941,7 @@ gcc_jit_function_new_block (gcc_jit_function *func,
const char *name)
{
RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function");
JIT_LOG_FUNC (func->get_context ()->get_logger ());
RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED,
func->get_context (), NULL,
"cannot add block to an imported function");
@ -965,6 +991,7 @@ gcc_jit_context_new_global (gcc_jit_context *ctxt,
const char *name)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
RETURN_NULL_IF_FAIL (name, ctxt, loc, "NULL name");
@ -1050,6 +1077,7 @@ gcc_jit_context_new_rvalue_from_int (gcc_jit_context *ctxt,
int value)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
return (gcc_jit_rvalue *)ctxt->new_rvalue_from_int (numeric_type, value);
@ -1066,6 +1094,7 @@ gcc_jit_context_zero (gcc_jit_context *ctxt,
gcc_jit_type *numeric_type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 0);
@ -1082,6 +1111,7 @@ gcc_jit_context_one (gcc_jit_context *ctxt,
gcc_jit_type *numeric_type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
return gcc_jit_context_new_rvalue_from_int (ctxt, numeric_type, 1);
@ -1099,6 +1129,7 @@ gcc_jit_context_new_rvalue_from_double (gcc_jit_context *ctxt,
double value)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE (ctxt, numeric_type);
return (gcc_jit_rvalue *)ctxt->new_rvalue_from_double (numeric_type, value);
@ -1116,6 +1147,7 @@ gcc_jit_context_new_rvalue_from_ptr (gcc_jit_context *ctxt,
void *value)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type");
RETURN_NULL_IF_FAIL_PRINTF1 (
pointer_type->is_pointer (),
@ -1137,6 +1169,7 @@ gcc_jit_context_null (gcc_jit_context *ctxt,
gcc_jit_type *pointer_type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (pointer_type, ctxt, NULL, "NULL type");
RETURN_NULL_IF_FAIL_PRINTF1 (
pointer_type->is_pointer (),
@ -1158,6 +1191,7 @@ gcc_jit_context_new_string_literal (gcc_jit_context *ctxt,
const char *value)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_NULL_IF_FAIL (value, ctxt, NULL, "NULL value");
return (gcc_jit_rvalue *)ctxt->new_string_literal (value);
@ -1177,6 +1211,7 @@ gcc_jit_context_new_unary_op (gcc_jit_context *ctxt,
gcc_jit_rvalue *rvalue)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL_PRINTF1 (
(op >= GCC_JIT_UNARY_OP_MINUS
@ -1215,6 +1250,7 @@ gcc_jit_context_new_binary_op (gcc_jit_context *ctxt,
gcc_jit_rvalue *a, gcc_jit_rvalue *b)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL_PRINTF1 (
valid_binary_op_p (op),
@ -1250,6 +1286,7 @@ gcc_jit_context_new_comparison (gcc_jit_context *ctxt,
gcc_jit_rvalue *a, gcc_jit_rvalue *b)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL_PRINTF1 (
(op >= GCC_JIT_COMPARISON_EQ
@ -1285,6 +1322,7 @@ gcc_jit_context_new_call (gcc_jit_context *ctxt,
int numargs , gcc_jit_rvalue **args)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (func, ctxt, loc, "NULL function");
if (numargs)
@ -1357,6 +1395,7 @@ gcc_jit_context_new_call_through_ptr (gcc_jit_context *ctxt,
int numargs, gcc_jit_rvalue **args)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (fn_ptr, ctxt, loc, "NULL fn_ptr");
if (numargs)
@ -1486,6 +1525,7 @@ gcc_jit_context_new_cast (gcc_jit_context *ctxt,
gcc_jit_type *type)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_NULL_IF_FAIL (type, ctxt, loc, "NULL type");
@ -1513,6 +1553,7 @@ gcc_jit_context_new_array_access (gcc_jit_context *ctxt,
gcc_jit_rvalue *index)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, loc, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (ptr, ctxt, loc, "NULL ptr");
RETURN_NULL_IF_FAIL (index, ctxt, loc, "NULL index");
@ -1572,8 +1613,9 @@ gcc_jit_lvalue_access_field (gcc_jit_lvalue *struct_,
gcc_jit_field *field)
{
RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct");
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = struct_->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field");
RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc,
"field %s has not been placed in a struct",
@ -1594,8 +1636,9 @@ gcc_jit_rvalue_access_field (gcc_jit_rvalue *struct_,
gcc_jit_field *field)
{
RETURN_NULL_IF_FAIL (struct_, NULL, loc, "NULL struct");
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = struct_->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (field, ctxt, loc, "NULL field");
RETURN_NULL_IF_FAIL_PRINTF1 (field->get_container (), field->m_ctxt, loc,
"field %s has not been placed in a struct",
@ -1616,6 +1659,7 @@ gcc_jit_rvalue_dereference_field (gcc_jit_rvalue *ptr,
gcc_jit_field *field)
{
RETURN_NULL_IF_FAIL (ptr, NULL, loc, "NULL ptr");
JIT_LOG_FUNC (ptr->get_context ()->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (field, NULL, loc, "NULL field");
gcc::jit::recording::type *underlying_type =
@ -1652,6 +1696,7 @@ gcc_jit_rvalue_dereference (gcc_jit_rvalue *rvalue,
gcc_jit_location *loc)
{
RETURN_NULL_IF_FAIL (rvalue, NULL, loc, "NULL rvalue");
JIT_LOG_FUNC (rvalue->get_context ()->get_logger ());
/* LOC can be NULL. */
gcc::jit::recording::type *underlying_type =
@ -1684,6 +1729,7 @@ gcc_jit_lvalue_get_address (gcc_jit_lvalue *lvalue,
gcc_jit_location *loc)
{
RETURN_NULL_IF_FAIL (lvalue, NULL, loc, "NULL lvalue");
JIT_LOG_FUNC (lvalue->get_context ()->get_logger ());
/* LOC can be NULL. */
return (gcc_jit_rvalue *)lvalue->get_address (loc);
@ -1701,8 +1747,9 @@ gcc_jit_function_new_local (gcc_jit_function *func,
const char *name)
{
RETURN_NULL_IF_FAIL (func, NULL, loc, "NULL function");
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = func->m_ctxt;
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_NULL_IF_FAIL (func->get_kind () != GCC_JIT_FUNCTION_IMPORTED,
ctxt, loc,
"Cannot add locals to an imported function");
@ -1723,8 +1770,9 @@ gcc_jit_block_add_eval (gcc_jit_block *block,
gcc_jit_rvalue *rvalue)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
return block->add_eval (loc, rvalue);
@ -1743,8 +1791,9 @@ gcc_jit_block_add_assignment (gcc_jit_block *block,
gcc_jit_rvalue *rvalue)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue");
RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
@ -1775,8 +1824,9 @@ gcc_jit_block_add_assignment_op (gcc_jit_block *block,
gcc_jit_rvalue *rvalue)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (lvalue, ctxt, loc, "NULL lvalue");
RETURN_IF_FAIL_PRINTF1 (
valid_binary_op_p (op),
@ -1814,8 +1864,9 @@ gcc_jit_block_end_with_conditional (gcc_jit_block *block,
gcc_jit_block *on_false)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (boolval, ctxt, loc, "NULL boolval");
RETURN_IF_FAIL_PRINTF2 (
is_bool (boolval), ctxt, loc,
@ -1860,8 +1911,9 @@ gcc_jit_block_add_comment (gcc_jit_block *block,
const char *text)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (text, ctxt, loc, "NULL text");
block->add_comment (loc, text);
@ -1879,8 +1931,9 @@ gcc_jit_block_end_with_jump (gcc_jit_block *block,
gcc_jit_block *target)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
RETURN_IF_FAIL (target, ctxt, loc, "NULL target");
RETURN_IF_FAIL_PRINTF4 (
block->get_function () == target->get_function (),
@ -1908,8 +1961,9 @@ gcc_jit_block_end_with_return (gcc_jit_block *block,
gcc_jit_rvalue *rvalue)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
gcc::jit::recording::function *func = block->get_function ();
RETURN_IF_FAIL (rvalue, ctxt, loc, "NULL rvalue");
RETURN_IF_FAIL_PRINTF4 (
@ -1938,8 +1992,9 @@ gcc_jit_block_end_with_void_return (gcc_jit_block *block,
gcc_jit_location *loc)
{
RETURN_IF_NOT_VALID_BLOCK (block, loc);
/* LOC can be NULL. */
gcc::jit::recording::context *ctxt = block->get_context ();
JIT_LOG_FUNC (ctxt->get_logger ());
/* LOC can be NULL. */
gcc::jit::recording::function *func = block->get_function ();
RETURN_IF_FAIL_PRINTF2 (
func->get_return_type () == ctxt->get_type (GCC_JIT_TYPE_VOID),
@ -1968,6 +2023,7 @@ gcc_jit_context_set_str_option (gcc_jit_context *ctxt,
const char *value)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* opt is checked by the inner function.
value can be NULL. */
@ -1986,6 +2042,7 @@ gcc_jit_context_set_int_option (gcc_jit_context *ctxt,
int value)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* opt is checked by the inner function. */
ctxt->set_int_option (opt, value);
@ -2003,6 +2060,7 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
int value)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
/* opt is checked by the inner function. */
ctxt->set_bool_option (opt, value);
@ -2020,6 +2078,7 @@ gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
char **out_ptr)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_IF_FAIL (dumpname, ctxt, NULL, "NULL dumpname");
RETURN_IF_FAIL (out_ptr, ctxt, NULL, "NULL out_ptr");
@ -2037,7 +2096,16 @@ gcc_jit_context_compile (gcc_jit_context *ctxt)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
return (gcc_jit_result *)ctxt->compile ();
JIT_LOG_FUNC (ctxt->get_logger ());
ctxt->log ("compiling ctxt: %p", (void *)ctxt);
gcc_jit_result *result = (gcc_jit_result *)ctxt->compile ();
ctxt->log ("%s: returning (gcc_jit_result *)%p",
__func__, (void *)result);
return result;
}
/* Public entrypoint. See description in libgccjit.h.
@ -2052,10 +2120,32 @@ gcc_jit_context_dump_to_file (gcc_jit_context *ctxt,
int update_locations)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_IF_FAIL (path, ctxt, NULL, "NULL path");
ctxt->dump_to_file (path, update_locations);
}
/* Public entrypoint. See description in libgccjit.h. */
void
gcc_jit_context_set_logfile (gcc_jit_context *ctxt,
FILE *logfile,
int flags,
int verbosity)
{
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
RETURN_IF_FAIL ((flags == 0), ctxt, NULL, "flags must be 0 for now");
RETURN_IF_FAIL ((verbosity == 0), ctxt, NULL, "verbosity must be 0 for now");
gcc::jit::logger *logger;
if (logfile)
logger = new gcc::jit::logger (logfile, flags, verbosity);
else
logger = NULL;
ctxt->set_logger (logger);
}
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@ -2066,6 +2156,7 @@ const char *
gcc_jit_context_get_first_error (gcc_jit_context *ctxt)
{
RETURN_NULL_IF_FAIL (ctxt, NULL, NULL, "NULL context");
JIT_LOG_FUNC (ctxt->get_logger ());
return ctxt->get_first_error ();
}
@ -2080,9 +2171,14 @@ gcc_jit_result_get_code (gcc_jit_result *result,
const char *fnname)
{
RETURN_NULL_IF_FAIL (result, NULL, NULL, "NULL result");
JIT_LOG_FUNC (result->get_logger ());
RETURN_NULL_IF_FAIL (fnname, NULL, NULL, "NULL fnname");
return result->get_code (fnname);
result->log ("locating fnname: %s", fnname);
void *code = result->get_code (fnname);
result->log ("%s: returning (void *)%p", __func__, code);
return code;
}
/* Public entrypoint. See description in libgccjit.h.
@ -2094,6 +2190,7 @@ void
gcc_jit_result_release (gcc_jit_result *result)
{
RETURN_IF_FAIL (result, NULL, NULL, "NULL result");
JIT_LOG_FUNC (result->get_logger ());
result->log ("deleting result: %p", (void *)result);
delete result;
}

View File

@ -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.

View File

@ -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;

View File

@ -1,3 +1,12 @@
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

View File

@ -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 */

View File

@ -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;