@@ -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 \
@@ -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-
new file mode 100644
@@ -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()
@@ -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;
new file mode 100644
@@ -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
new file mode 100644
@@ -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 */
@@ -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)
{
@@ -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;
}
@@ -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;
@@ -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;