PR jit/64166: Add API entrypoint gcc_jit_context_enable_dump
gcc/jit/ChangeLog: PR jit/64166 * docs/topics/contexts.rst (Debugging): Add description of gcc_jit_context_enable_dump. * docs/_build/texinfo/libgccjit.texi: Regenerate. * jit-playback.c: Include context.h. (class auto_argvec): New class. (auto_argvec::~auto_argvec): New function. (gcc::jit::playback::context::compile): Convert fake_args to be an auto_argvec, so that it can contain dynamically-allocated strings. Construct a vec of all requested dumps, and pass it to make_fake_args. Extract requested dumps between the calls to toplev::main and toplev::finalize. (gcc::jit::playback::context::make_fake_args): Convert param "argvec" to be a vec <char *>, and gain a "requested_dumps" param. Convert to dynamically-allocated arg strings by converting ADD_ARG to take a copy of the arg, and add ADD_ARG_TAKE_OWNERSHIP for args that are already a copy. Add args for all requested dumps. (gcc::jit::playback::context::extract_any_requested_dumps): New function. (gcc::jit::playback::context::read_dump_file): New function. * jit-playback.h (gcc::jit::playback::context::make_fake_args): Convert param "argvec" to be a vec <char *>, and gain a "requested_dumps" param. (gcc::jit::playback::context::extract_any_requested_dumps): New function. (gcc::jit::playback::context::read_dump_file): New function. * jit-recording.c (gcc::jit::recording::context::enable_dump): New function. (gcc::jit::recording::context::get_all_requested_dumps): New function. * jit-recording.h (gcc::jit::recording::requested_dump): New struct. (gcc::jit::recording::context::enable_dump): New function. (gcc::jit::recording::context::get_all_requested_dumps): New function. (gcc::jit::recording::context::m_requested_dumps): New field. * libgccjit.c (gcc_jit_context_enable_dump): New API entrypoint. * libgccjit.h (gcc_jit_context_enable_dump): New API entrypoint. * libgccjit.map (gcc_jit_context_enable_dump): New API entrypoint. gcc/testsuite/ChangeLog: PR jit/64166 PR jit/64020 * jit.dg/harness.h (CHECK_STRING_CONTAINS): New macro. (check_string_contains): New function. * jit.dg/test-error-unrecognized-dump.c: New file. * jit.dg/test-functions.c (trig_sincos_dump): New variable. (trig_statistics_dump): New variable. (create_test_of_builtin_trig): Enable dumping of "sincos" and "statistics" into "trig_sincos_dump" and "trig_statistics_dump". (verify_test_of_builtin_trig): Verify the sincos and statistics dumps. * jit.dg/test-sum-of-squares.c (dump_vrp1): New variable. (create_code): Enable dumping of "tree-vrp1" into dump_vrp1. (verify_code): Verify the tree-vrp1 dump. From-SVN: r218521
This commit is contained in:
parent
799505ae0c
commit
463366a06a
|
@ -1,3 +1,45 @@
|
||||||
|
2014-12-09 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
PR jit/64166
|
||||||
|
* docs/topics/contexts.rst (Debugging): Add description of
|
||||||
|
gcc_jit_context_enable_dump.
|
||||||
|
* docs/_build/texinfo/libgccjit.texi: Regenerate.
|
||||||
|
* jit-playback.c: Include context.h.
|
||||||
|
(class auto_argvec): New class.
|
||||||
|
(auto_argvec::~auto_argvec): New function.
|
||||||
|
(gcc::jit::playback::context::compile): Convert fake_args to be
|
||||||
|
an auto_argvec, so that it can contain dynamically-allocated
|
||||||
|
strings. Construct a vec of all requested dumps, and pass it to
|
||||||
|
make_fake_args. Extract requested dumps between the calls to
|
||||||
|
toplev::main and toplev::finalize.
|
||||||
|
(gcc::jit::playback::context::make_fake_args): Convert param
|
||||||
|
"argvec" to be a vec <char *>, and gain a "requested_dumps"
|
||||||
|
param. Convert to dynamically-allocated arg strings by converting
|
||||||
|
ADD_ARG to take a copy of the arg, and add ADD_ARG_TAKE_OWNERSHIP
|
||||||
|
for args that are already a copy. Add args for all requested dumps.
|
||||||
|
(gcc::jit::playback::context::extract_any_requested_dumps): New
|
||||||
|
function.
|
||||||
|
(gcc::jit::playback::context::read_dump_file): New function.
|
||||||
|
* jit-playback.h (gcc::jit::playback::context::make_fake_args):
|
||||||
|
Convert param "argvec" to be a vec <char *>, and gain a
|
||||||
|
"requested_dumps" param.
|
||||||
|
(gcc::jit::playback::context::extract_any_requested_dumps): New
|
||||||
|
function.
|
||||||
|
(gcc::jit::playback::context::read_dump_file): New function.
|
||||||
|
* jit-recording.c (gcc::jit::recording::context::enable_dump): New
|
||||||
|
function.
|
||||||
|
(gcc::jit::recording::context::get_all_requested_dumps): New
|
||||||
|
function.
|
||||||
|
* jit-recording.h (gcc::jit::recording::requested_dump): New
|
||||||
|
struct.
|
||||||
|
(gcc::jit::recording::context::enable_dump): New function.
|
||||||
|
(gcc::jit::recording::context::get_all_requested_dumps): New
|
||||||
|
function.
|
||||||
|
(gcc::jit::recording::context::m_requested_dumps): New field.
|
||||||
|
* libgccjit.c (gcc_jit_context_enable_dump): New API entrypoint.
|
||||||
|
* libgccjit.h (gcc_jit_context_enable_dump): New API entrypoint.
|
||||||
|
* libgccjit.map (gcc_jit_context_enable_dump): New API entrypoint.
|
||||||
|
|
||||||
2014-12-09 David Malcolm <dmalcolm@redhat.com>
|
2014-12-09 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
PR jit/64166
|
PR jit/64166
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -152,6 +152,53 @@ Debugging
|
||||||
:macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` to allow stepping through the
|
:macro:`GCC_JIT_BOOL_OPTION_DEBUGINFO` to allow stepping through the
|
||||||
code in a debugger.
|
code in a debugger.
|
||||||
|
|
||||||
|
.. function:: void\
|
||||||
|
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,\
|
||||||
|
const char *dumpname, \
|
||||||
|
char **out_ptr)
|
||||||
|
|
||||||
|
Enable the dumping of a specific set of internal state from the
|
||||||
|
compilation, capturing the result in-memory as a buffer.
|
||||||
|
|
||||||
|
Parameter "dumpname" corresponds to the equivalent gcc command-line
|
||||||
|
option, without the "-fdump-" prefix.
|
||||||
|
For example, to get the equivalent of :option:`-fdump-tree-vrp1`,
|
||||||
|
supply ``"tree-vrp1"``:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
static char *dump_vrp1;
|
||||||
|
|
||||||
|
void
|
||||||
|
create_code (gcc_jit_context *ctxt)
|
||||||
|
{
|
||||||
|
gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
|
||||||
|
/* (other API calls omitted for brevity) */
|
||||||
|
}
|
||||||
|
|
||||||
|
The context directly stores the dumpname as a ``(const char *)``, so
|
||||||
|
the passed string must outlive the context.
|
||||||
|
|
||||||
|
:func:`gcc_jit_context_compile` will capture the dump as a
|
||||||
|
dynamically-allocated buffer, writing it to ``*out_ptr``.
|
||||||
|
|
||||||
|
The caller becomes responsible for calling:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
free (*out_ptr)
|
||||||
|
|
||||||
|
each time that :func:`gcc_jit_context_compile` is called.
|
||||||
|
``*out_ptr`` will be written to, either with the address of a buffer,
|
||||||
|
or with ``NULL`` if an error occurred.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
This API entrypoint is likely to be less stable than the others.
|
||||||
|
In particular, both the precise dumpnames, and the format and content
|
||||||
|
of the dumps are subject to change.
|
||||||
|
|
||||||
|
It exists primarily for writing the library's own test suite.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "gimplify.h"
|
#include "gimplify.h"
|
||||||
#include "gcc-driver-name.h"
|
#include "gcc-driver-name.h"
|
||||||
#include "attribs.h"
|
#include "attribs.h"
|
||||||
|
#include "context.h"
|
||||||
|
|
||||||
#include "jit-common.h"
|
#include "jit-common.h"
|
||||||
#include "jit-playback.h"
|
#include "jit-playback.h"
|
||||||
|
@ -1552,6 +1553,26 @@ make_tempdir_path_template ()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A subclass of auto_vec <char *> that frees all of its elements on
|
||||||
|
deletion. */
|
||||||
|
|
||||||
|
class auto_argvec : public auto_vec <char *>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~auto_argvec ();
|
||||||
|
};
|
||||||
|
|
||||||
|
/* auto_argvec's dtor, freeing all contained strings, automatically
|
||||||
|
chaining up to ~auto_vec <char *>, which frees the internal buffer. */
|
||||||
|
|
||||||
|
auto_argvec::~auto_argvec ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *str;
|
||||||
|
FOR_EACH_VEC_ELT (*this, i, str)
|
||||||
|
free (str);
|
||||||
|
}
|
||||||
|
|
||||||
/* Compile a playback::context:
|
/* Compile a playback::context:
|
||||||
|
|
||||||
- Use the context's options to cconstruct command-line options, and
|
- Use the context's options to cconstruct command-line options, and
|
||||||
|
@ -1594,14 +1615,25 @@ compile ()
|
||||||
if (!ctxt_progname)
|
if (!ctxt_progname)
|
||||||
ctxt_progname = "libgccjit.so";
|
ctxt_progname = "libgccjit.so";
|
||||||
|
|
||||||
auto_vec <const char *> fake_args;
|
auto_vec <recording::requested_dump> requested_dumps;
|
||||||
make_fake_args (&fake_args, ctxt_progname);
|
m_recording_ctxt->get_all_requested_dumps (&requested_dumps);
|
||||||
|
|
||||||
|
auto_argvec fake_args;
|
||||||
|
make_fake_args (&fake_args, ctxt_progname, &requested_dumps);
|
||||||
if (errors_occurred ())
|
if (errors_occurred ())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* This runs the compiler. */
|
||||||
toplev toplev (false);
|
toplev toplev (false);
|
||||||
toplev.main (fake_args.length (),
|
toplev.main (fake_args.length (),
|
||||||
const_cast <char **> (fake_args.address ()));
|
const_cast <char **> (fake_args.address ()));
|
||||||
|
|
||||||
|
/* Extracting dumps makes use of the gcc::dump_manager, hence we
|
||||||
|
need to do it between toplev::main (which creates the dump manager)
|
||||||
|
and toplev::finalize (which deletes it). */
|
||||||
|
extract_any_requested_dumps (&requested_dumps);
|
||||||
|
|
||||||
|
/* Clean up the compiler. */
|
||||||
toplev.finalize ();
|
toplev.finalize ();
|
||||||
|
|
||||||
active_playback_ctxt = NULL;
|
active_playback_ctxt = NULL;
|
||||||
|
@ -1645,10 +1677,12 @@ compile ()
|
||||||
|
|
||||||
void
|
void
|
||||||
playback::context::
|
playback::context::
|
||||||
make_fake_args (auto_vec <const char *> *argvec,
|
make_fake_args (vec <char *> *argvec,
|
||||||
const char *ctxt_progname)
|
const char *ctxt_progname,
|
||||||
|
vec <recording::requested_dump> *requested_dumps)
|
||||||
{
|
{
|
||||||
#define ADD_ARG(arg) argvec->safe_push (arg)
|
#define ADD_ARG(arg) argvec->safe_push (xstrdup (arg))
|
||||||
|
#define ADD_ARG_TAKE_OWNERSHIP(arg) argvec->safe_push (arg)
|
||||||
|
|
||||||
ADD_ARG (ctxt_progname);
|
ADD_ARG (ctxt_progname);
|
||||||
ADD_ARG (m_path_c_file);
|
ADD_ARG (m_path_c_file);
|
||||||
|
@ -1707,7 +1741,104 @@ make_fake_args (auto_vec <const char *> *argvec,
|
||||||
ADD_ARG ("-fdump-rtl-all");
|
ADD_ARG ("-fdump-rtl-all");
|
||||||
ADD_ARG ("-fdump-ipa-all");
|
ADD_ARG ("-fdump-ipa-all");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add "-fdump-" options for any calls to
|
||||||
|
gcc_jit_context_enable_dump. */
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
recording::requested_dump *d;
|
||||||
|
FOR_EACH_VEC_ELT (*requested_dumps, i, d)
|
||||||
|
{
|
||||||
|
char *arg = concat ("-fdump-", d->m_dumpname, NULL);
|
||||||
|
ADD_ARG_TAKE_OWNERSHIP (arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef ADD_ARG
|
#undef ADD_ARG
|
||||||
|
#undef ADD_ARG_TAKE_OWNERSHIP
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The second half of the implementation of gcc_jit_context_enable_dump.
|
||||||
|
Iterate through the requested dumps, reading the underlying files
|
||||||
|
into heap-allocated buffers, writing pointers to the buffers into
|
||||||
|
the char ** pointers provided by client code.
|
||||||
|
Client code is responsible for calling free on the results. */
|
||||||
|
|
||||||
|
void
|
||||||
|
playback::context::
|
||||||
|
extract_any_requested_dumps (vec <recording::requested_dump> *requested_dumps)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
recording::requested_dump *d;
|
||||||
|
FOR_EACH_VEC_ELT (*requested_dumps, i, d)
|
||||||
|
{
|
||||||
|
dump_file_info *dfi;
|
||||||
|
char *filename;
|
||||||
|
char *content;
|
||||||
|
|
||||||
|
dfi = g->get_dumps ()->get_dump_file_info_by_switch (d->m_dumpname);
|
||||||
|
if (!dfi)
|
||||||
|
{
|
||||||
|
add_error (NULL, "unrecognized dump: %s", d->m_dumpname);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = g->get_dumps ()->get_dump_file_name (dfi);
|
||||||
|
content = read_dump_file (filename);
|
||||||
|
*(d->m_out_ptr) = content;
|
||||||
|
free (filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper function for playback::context::extract_any_requested_dumps
|
||||||
|
(itself for use in implementation of gcc_jit_context_enable_dump).
|
||||||
|
|
||||||
|
Attempt to read the complete file at the given path, returning the
|
||||||
|
bytes found there as a buffer.
|
||||||
|
The caller is responsible for calling free on the result.
|
||||||
|
Errors will be reported on the context, and lead to NULL being
|
||||||
|
returned; an out-of-memory error will terminate the process. */
|
||||||
|
|
||||||
|
char *
|
||||||
|
playback::context::read_dump_file (const char *path)
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
size_t total_sz = 0;
|
||||||
|
char buf[4096];
|
||||||
|
size_t sz;
|
||||||
|
FILE *f_in;
|
||||||
|
|
||||||
|
f_in = fopen (path, "r");
|
||||||
|
if (!f_in)
|
||||||
|
{
|
||||||
|
add_error (NULL, "unable to open %s for reading", path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( (sz = fread (buf, 1, sizeof (buf), f_in)) )
|
||||||
|
{
|
||||||
|
size_t old_total_sz = total_sz;
|
||||||
|
total_sz += sz;
|
||||||
|
result = reinterpret_cast <char *> (xrealloc (result, total_sz + 1));
|
||||||
|
memcpy (result + old_total_sz, buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!feof (f_in))
|
||||||
|
{
|
||||||
|
add_error (NULL, "error reading from %s", path);
|
||||||
|
free (result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (f_in);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
result[total_sz] = '\0';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return xstrdup ("");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Part of playback::context::compile ().
|
/* Part of playback::context::compile ().
|
||||||
|
|
|
@ -236,8 +236,16 @@ private:
|
||||||
/* Functions for implementing "compile". */
|
/* Functions for implementing "compile". */
|
||||||
|
|
||||||
void
|
void
|
||||||
make_fake_args (auto_vec <const char *> *argvec,
|
make_fake_args (vec <char *> *argvec,
|
||||||
const char *ctxt_progname);
|
const char *ctxt_progname,
|
||||||
|
vec <recording::requested_dump> *requested_dumps);
|
||||||
|
|
||||||
|
void
|
||||||
|
extract_any_requested_dumps
|
||||||
|
(vec <recording::requested_dump> *requested_dumps);
|
||||||
|
|
||||||
|
char *
|
||||||
|
read_dump_file (const char *path);
|
||||||
|
|
||||||
void
|
void
|
||||||
convert_to_dso (const char *ctxt_progname);
|
convert_to_dso (const char *ctxt_progname);
|
||||||
|
|
|
@ -868,6 +868,27 @@ recording::context::set_bool_option (enum gcc_jit_bool_option opt,
|
||||||
m_bool_options[opt] = value ? true : false;
|
m_bool_options[opt] = value ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add the given dumpname/out_ptr pair to this context's list of requested
|
||||||
|
dumps.
|
||||||
|
|
||||||
|
Implements the post-error-checking part of
|
||||||
|
gcc_jit_context_enable_dump. */
|
||||||
|
|
||||||
|
void
|
||||||
|
recording::context::enable_dump (const char *dumpname,
|
||||||
|
char **out_ptr)
|
||||||
|
{
|
||||||
|
requested_dump d;
|
||||||
|
gcc_assert (dumpname);
|
||||||
|
gcc_assert (out_ptr);
|
||||||
|
|
||||||
|
d.m_dumpname = dumpname;
|
||||||
|
d.m_out_ptr = out_ptr;
|
||||||
|
*out_ptr = NULL;
|
||||||
|
m_requested_dumps.safe_push (d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This mutex guards gcc::jit::recording::context::compile, so that only
|
/* This mutex guards gcc::jit::recording::context::compile, so that only
|
||||||
one thread can be accessing the bulk of GCC's state at once. */
|
one thread can be accessing the bulk of GCC's state at once. */
|
||||||
|
|
||||||
|
@ -1026,6 +1047,19 @@ recording::context::dump_to_file (const char *path, bool update_locations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy the requested dumps within this context and all ancestors into
|
||||||
|
OUT. */
|
||||||
|
|
||||||
|
void
|
||||||
|
recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
|
||||||
|
{
|
||||||
|
if (m_parent_ctxt)
|
||||||
|
m_parent_ctxt->get_all_requested_dumps (out);
|
||||||
|
|
||||||
|
out->reserve (m_requested_dumps.length ());
|
||||||
|
out->splice (m_requested_dumps);
|
||||||
|
}
|
||||||
|
|
||||||
/* This is a pre-compilation check for the context (and any parents).
|
/* This is a pre-compilation check for the context (and any parents).
|
||||||
|
|
||||||
Detect errors within the context, adding errors if any are found. */
|
Detect errors within the context, adding errors if any are found. */
|
||||||
|
|
|
@ -45,6 +45,13 @@ playback_string (string *str);
|
||||||
playback::block *
|
playback::block *
|
||||||
playback_block (block *b);
|
playback_block (block *b);
|
||||||
|
|
||||||
|
/* A recording of a call to gcc_jit_context_enable_dump. */
|
||||||
|
struct requested_dump
|
||||||
|
{
|
||||||
|
const char *m_dumpname;
|
||||||
|
char **m_out_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
/* A JIT-compilation context. */
|
/* A JIT-compilation context. */
|
||||||
class context
|
class context
|
||||||
{
|
{
|
||||||
|
@ -191,6 +198,10 @@ public:
|
||||||
set_bool_option (enum gcc_jit_bool_option opt,
|
set_bool_option (enum gcc_jit_bool_option opt,
|
||||||
int value);
|
int value);
|
||||||
|
|
||||||
|
void
|
||||||
|
enable_dump (const char *dumpname,
|
||||||
|
char **out_ptr);
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
get_str_option (enum gcc_jit_str_option opt) const
|
get_str_option (enum gcc_jit_str_option opt) const
|
||||||
{
|
{
|
||||||
|
@ -235,6 +246,9 @@ public:
|
||||||
|
|
||||||
void dump_to_file (const char *path, bool update_locations);
|
void dump_to_file (const char *path, bool update_locations);
|
||||||
|
|
||||||
|
void
|
||||||
|
get_all_requested_dumps (vec <recording::requested_dump> *out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void validate ();
|
void validate ();
|
||||||
|
|
||||||
|
@ -250,6 +264,9 @@ private:
|
||||||
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
|
int m_int_options[GCC_JIT_NUM_INT_OPTIONS];
|
||||||
bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
|
bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS];
|
||||||
|
|
||||||
|
/* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
|
||||||
|
auto_vec<requested_dump> m_requested_dumps;
|
||||||
|
|
||||||
/* Recorded API usage. */
|
/* Recorded API usage. */
|
||||||
auto_vec<memento *> m_mementos;
|
auto_vec<memento *> m_mementos;
|
||||||
|
|
||||||
|
|
|
@ -2001,6 +2001,24 @@ gcc_jit_context_set_bool_option (gcc_jit_context *ctxt,
|
||||||
ctxt->set_bool_option (opt, value);
|
ctxt->set_bool_option (opt, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Public entrypoint. See description in libgccjit.h.
|
||||||
|
|
||||||
|
After error-checking, the real work is done by the
|
||||||
|
gcc::jit::recording::context::enable_dump method in
|
||||||
|
jit-recording.c. */
|
||||||
|
|
||||||
|
void
|
||||||
|
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
|
||||||
|
const char *dumpname,
|
||||||
|
char **out_ptr)
|
||||||
|
{
|
||||||
|
RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context");
|
||||||
|
RETURN_IF_FAIL (dumpname, ctxt, NULL, "NULL dumpname");
|
||||||
|
RETURN_IF_FAIL (out_ptr, ctxt, NULL, "NULL out_ptr");
|
||||||
|
|
||||||
|
ctxt->enable_dump (dumpname, out_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Public entrypoint. See description in libgccjit.h.
|
/* Public entrypoint. See description in libgccjit.h.
|
||||||
|
|
||||||
After error-checking, the real work is done by the
|
After error-checking, the real work is done by the
|
||||||
|
|
|
@ -985,6 +985,40 @@ gcc_jit_block_end_with_void_return (gcc_jit_block *block,
|
||||||
extern gcc_jit_context *
|
extern gcc_jit_context *
|
||||||
gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt);
|
gcc_jit_context_new_child_context (gcc_jit_context *parent_ctxt);
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
Implementation support.
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/* Enable the dumping of a specific set of internal state from the
|
||||||
|
compilation, capturing the result in-memory as a buffer.
|
||||||
|
|
||||||
|
Parameter "dumpname" corresponds to the equivalent gcc command-line
|
||||||
|
option, without the "-fdump-" prefix.
|
||||||
|
For example, to get the equivalent of "-fdump-tree-vrp1", supply
|
||||||
|
"tree-vrp1".
|
||||||
|
The context directly stores the dumpname as a (const char *), so the
|
||||||
|
passed string must outlive the context.
|
||||||
|
|
||||||
|
gcc_jit_context_compile will capture the dump as a
|
||||||
|
dynamically-allocated buffer, writing it to ``*out_ptr``.
|
||||||
|
|
||||||
|
The caller becomes responsible for calling
|
||||||
|
free (*out_ptr)
|
||||||
|
each time that gcc_jit_context_compile is called. *out_ptr will be
|
||||||
|
written to, either with the address of a buffer, or with NULL if an
|
||||||
|
error occurred.
|
||||||
|
|
||||||
|
This API entrypoint is likely to be less stable than the others.
|
||||||
|
In particular, both the precise dumpnames, and the format and content
|
||||||
|
of the dumps are subject to change.
|
||||||
|
|
||||||
|
It exists primarily for writing the library's own test suite. */
|
||||||
|
|
||||||
|
extern void
|
||||||
|
gcc_jit_context_enable_dump (gcc_jit_context *ctxt,
|
||||||
|
const char *dumpname,
|
||||||
|
char **out_ptr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
gcc_jit_context_acquire;
|
gcc_jit_context_acquire;
|
||||||
gcc_jit_context_compile;
|
gcc_jit_context_compile;
|
||||||
gcc_jit_context_dump_to_file;
|
gcc_jit_context_dump_to_file;
|
||||||
|
gcc_jit_context_enable_dump;
|
||||||
gcc_jit_context_get_builtin_function;
|
gcc_jit_context_get_builtin_function;
|
||||||
gcc_jit_context_get_first_error;
|
gcc_jit_context_get_first_error;
|
||||||
gcc_jit_context_get_type;
|
gcc_jit_context_get_type;
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
|
2014-12-09 David Malcolm <dmalcolm@redhat.com>
|
||||||
|
|
||||||
|
PR jit/64166
|
||||||
|
PR jit/64020
|
||||||
|
* jit.dg/harness.h (CHECK_STRING_CONTAINS): New macro.
|
||||||
|
(check_string_contains): New function.
|
||||||
|
* jit.dg/test-error-unrecognized-dump.c: New file.
|
||||||
|
* jit.dg/test-functions.c (trig_sincos_dump): New variable.
|
||||||
|
(trig_statistics_dump): New variable.
|
||||||
|
(create_test_of_builtin_trig): Enable dumping of "sincos" and
|
||||||
|
"statistics" into "trig_sincos_dump" and "trig_statistics_dump".
|
||||||
|
(verify_test_of_builtin_trig): Verify the sincos and statistics
|
||||||
|
dumps.
|
||||||
|
* jit.dg/test-sum-of-squares.c (dump_vrp1): New variable.
|
||||||
|
(create_code): Enable dumping of "tree-vrp1" into dump_vrp1.
|
||||||
|
(verify_code): Verify the tree-vrp1 dump.
|
||||||
|
|
||||||
2014-12-09 Uros Bizjak <ubizjak@gmail.com>
|
2014-12-09 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
PR bootstrap/64213
|
PR bootstrap/64213
|
||||||
|
|
|
@ -84,6 +84,9 @@ static char test[1024];
|
||||||
#define CHECK_STRING_STARTS_WITH(ACTUAL, EXPECTED_PREFIX) \
|
#define CHECK_STRING_STARTS_WITH(ACTUAL, EXPECTED_PREFIX) \
|
||||||
check_string_starts_with ((ACTUAL), (EXPECTED_PREFIX));
|
check_string_starts_with ((ACTUAL), (EXPECTED_PREFIX));
|
||||||
|
|
||||||
|
#define CHECK_STRING_CONTAINS(ACTUAL, EXPECTED_SUBSTRING) \
|
||||||
|
check_string_contains (#ACTUAL, (ACTUAL), (EXPECTED_SUBSTRING));
|
||||||
|
|
||||||
#define CHECK(COND) \
|
#define CHECK(COND) \
|
||||||
do { \
|
do { \
|
||||||
if (COND) \
|
if (COND) \
|
||||||
|
@ -110,6 +113,11 @@ extern void
|
||||||
check_string_starts_with (const char *actual,
|
check_string_starts_with (const char *actual,
|
||||||
const char *expected_prefix);
|
const char *expected_prefix);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
check_string_contains (const char *name,
|
||||||
|
const char *actual,
|
||||||
|
const char *expected_substring);
|
||||||
|
|
||||||
/* Implement framework needed for turning the testcase hooks into an
|
/* Implement framework needed for turning the testcase hooks into an
|
||||||
executable. test-combination.c and test-threads.c each combine multiple
|
executable. test-combination.c and test-threads.c each combine multiple
|
||||||
testcases into larger testcases, so we have COMBINED_TEST as a way of
|
testcases into larger testcases, so we have COMBINED_TEST as a way of
|
||||||
|
@ -168,6 +176,31 @@ check_string_starts_with (const char *actual,
|
||||||
test, actual, expected_prefix);
|
test, actual, expected_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_string_contains (const char *name,
|
||||||
|
const char *actual,
|
||||||
|
const char *expected_substring)
|
||||||
|
{
|
||||||
|
if (!actual)
|
||||||
|
{
|
||||||
|
fail ("%s: %s: actual: NULL does not contain expected substring: \"%s\"",
|
||||||
|
test, name, expected_substring);
|
||||||
|
fprintf (stderr, "incorrect value\n");
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strstr (actual, expected_substring))
|
||||||
|
{
|
||||||
|
fail ("%s: %s: actual: \"%s\" did not contain expected substring: \"%s\"",
|
||||||
|
test, name, actual, expected_substring);
|
||||||
|
fprintf (stderr, "incorrect value\n");
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
pass ("%s: %s: found substring: \"%s\"",
|
||||||
|
test, name, expected_substring);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_options (gcc_jit_context *ctxt, const char *argv0)
|
static void set_options (gcc_jit_context *ctxt, const char *argv0)
|
||||||
{
|
{
|
||||||
/* Set up options. */
|
/* Set up options. */
|
||||||
|
|
|
@ -167,6 +167,9 @@ create_test_of_builtin_strcmp (gcc_jit_context *ctxt)
|
||||||
gcc_jit_block_end_with_return (initial, NULL, call);
|
gcc_jit_block_end_with_return (initial, NULL, call);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *trig_sincos_dump;
|
||||||
|
static char *trig_statistics_dump;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_test_of_builtin_trig (gcc_jit_context *ctxt)
|
create_test_of_builtin_trig (gcc_jit_context *ctxt)
|
||||||
{
|
{
|
||||||
|
@ -178,6 +181,14 @@ create_test_of_builtin_trig (gcc_jit_context *ctxt)
|
||||||
}
|
}
|
||||||
(in theory, optimizable to sin (2 * theta))
|
(in theory, optimizable to sin (2 * theta))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
gcc_jit_context_enable_dump (ctxt,
|
||||||
|
"tree-sincos",
|
||||||
|
&trig_sincos_dump);
|
||||||
|
gcc_jit_context_enable_dump (ctxt,
|
||||||
|
"statistics",
|
||||||
|
&trig_statistics_dump);
|
||||||
|
|
||||||
gcc_jit_type *double_t =
|
gcc_jit_type *double_t =
|
||||||
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
|
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
|
||||||
|
|
||||||
|
@ -266,6 +277,22 @@ verify_test_of_builtin_trig (gcc_jit_context *ctxt, gcc_jit_result *result)
|
||||||
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_2 ), 0.0);
|
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_2 ), 0.0);
|
||||||
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_4 * 3.0), -1.0);
|
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI_4 * 3.0), -1.0);
|
||||||
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI ), 0.0);
|
CHECK_DOUBLE_VALUE (test_of_builtin_trig (M_PI ), 0.0);
|
||||||
|
|
||||||
|
/* PR jit/64020:
|
||||||
|
The "sincos" pass merges sin/cos calls into the cexpi builtin.
|
||||||
|
Verify that a dump of the "sincos" pass was provided, and that it
|
||||||
|
shows a call to the cexpi builtin on a SSA name of "theta". */
|
||||||
|
CHECK_NON_NULL (trig_sincos_dump);
|
||||||
|
CHECK_STRING_CONTAINS (trig_sincos_dump, " = __builtin_cexpi (theta_");
|
||||||
|
free (trig_sincos_dump);
|
||||||
|
|
||||||
|
/* Similarly, verify that the statistics dump was provided, and that
|
||||||
|
it shows the sincos optimization. */
|
||||||
|
CHECK_NON_NULL (trig_statistics_dump);
|
||||||
|
CHECK_STRING_CONTAINS (
|
||||||
|
trig_statistics_dump,
|
||||||
|
"sincos \"sincos statements inserted\" \"test_of_builtin_trig\" 1");
|
||||||
|
free (trig_statistics_dump);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include "harness.h"
|
#include "harness.h"
|
||||||
|
|
||||||
|
static char *dump_vrp1;
|
||||||
|
|
||||||
void
|
void
|
||||||
create_code (gcc_jit_context *ctxt, void *user_data)
|
create_code (gcc_jit_context *ctxt, void *user_data)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +24,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
*/
|
*/
|
||||||
|
gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
|
||||||
|
|
||||||
gcc_jit_type *the_type =
|
gcc_jit_type *the_type =
|
||||||
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
|
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
|
||||||
gcc_jit_type *return_type = the_type;
|
gcc_jit_type *return_type = the_type;
|
||||||
|
@ -123,4 +127,16 @@ verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
|
||||||
int val = loop_test (10);
|
int val = loop_test (10);
|
||||||
note ("loop_test returned: %d", val);
|
note ("loop_test returned: %d", val);
|
||||||
CHECK_VALUE (val, 285);
|
CHECK_VALUE (val, 285);
|
||||||
|
|
||||||
|
CHECK_NON_NULL (dump_vrp1);
|
||||||
|
/* PR jit/64166
|
||||||
|
An example of using gcc_jit_context_enable_dump to verify a property
|
||||||
|
of the compile.
|
||||||
|
|
||||||
|
In this case, verify that vrp is able to deduce the
|
||||||
|
bounds of the iteration variable. Specifically, verify that some
|
||||||
|
variable is known to be in the range negative infinity to some
|
||||||
|
expression based on param "n" (actually n-1). */
|
||||||
|
CHECK_STRING_CONTAINS (dump_vrp1, ": [-INF, n_");
|
||||||
|
free (dump_vrp1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue