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>
|
||||
|
||||
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
|
||||
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
|
||||
-------
|
||||
|
|
|
@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "gimplify.h"
|
||||
#include "gcc-driver-name.h"
|
||||
#include "attribs.h"
|
||||
#include "context.h"
|
||||
|
||||
#include "jit-common.h"
|
||||
#include "jit-playback.h"
|
||||
|
@ -1552,6 +1553,26 @@ make_tempdir_path_template ()
|
|||
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:
|
||||
|
||||
- Use the context's options to cconstruct command-line options, and
|
||||
|
@ -1594,14 +1615,25 @@ compile ()
|
|||
if (!ctxt_progname)
|
||||
ctxt_progname = "libgccjit.so";
|
||||
|
||||
auto_vec <const char *> fake_args;
|
||||
make_fake_args (&fake_args, ctxt_progname);
|
||||
auto_vec <recording::requested_dump> requested_dumps;
|
||||
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 ())
|
||||
return NULL;
|
||||
|
||||
/* This runs the compiler. */
|
||||
toplev toplev (false);
|
||||
toplev.main (fake_args.length (),
|
||||
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 ();
|
||||
|
||||
active_playback_ctxt = NULL;
|
||||
|
@ -1645,10 +1677,12 @@ compile ()
|
|||
|
||||
void
|
||||
playback::context::
|
||||
make_fake_args (auto_vec <const char *> *argvec,
|
||||
const char *ctxt_progname)
|
||||
make_fake_args (vec <char *> *argvec,
|
||||
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 (m_path_c_file);
|
||||
|
@ -1707,7 +1741,104 @@ make_fake_args (auto_vec <const char *> *argvec,
|
|||
ADD_ARG ("-fdump-rtl-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_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 ().
|
||||
|
|
|
@ -236,8 +236,16 @@ private:
|
|||
/* Functions for implementing "compile". */
|
||||
|
||||
void
|
||||
make_fake_args (auto_vec <const char *> *argvec,
|
||||
const char *ctxt_progname);
|
||||
make_fake_args (vec <char *> *argvec,
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
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).
|
||||
|
||||
Detect errors within the context, adding errors if any are found. */
|
||||
|
|
|
@ -45,6 +45,13 @@ playback_string (string *str);
|
|||
playback::block *
|
||||
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. */
|
||||
class context
|
||||
{
|
||||
|
@ -191,6 +198,10 @@ public:
|
|||
set_bool_option (enum gcc_jit_bool_option opt,
|
||||
int value);
|
||||
|
||||
void
|
||||
enable_dump (const char *dumpname,
|
||||
char **out_ptr);
|
||||
|
||||
const char *
|
||||
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
|
||||
get_all_requested_dumps (vec <recording::requested_dump> *out);
|
||||
|
||||
private:
|
||||
void validate ();
|
||||
|
||||
|
@ -250,6 +264,9 @@ private:
|
|||
int m_int_options[GCC_JIT_NUM_INT_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. */
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
||||
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 *
|
||||
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
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
gcc_jit_context_acquire;
|
||||
gcc_jit_context_compile;
|
||||
gcc_jit_context_dump_to_file;
|
||||
gcc_jit_context_enable_dump;
|
||||
gcc_jit_context_get_builtin_function;
|
||||
gcc_jit_context_get_first_error;
|
||||
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>
|
||||
|
||||
PR bootstrap/64213
|
||||
|
|
|
@ -84,6 +84,9 @@ static char test[1024];
|
|||
#define 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) \
|
||||
do { \
|
||||
if (COND) \
|
||||
|
@ -110,6 +113,11 @@ extern void
|
|||
check_string_starts_with (const char *actual,
|
||||
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
|
||||
executable. test-combination.c and test-threads.c each combine multiple
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
static char *trig_sincos_dump;
|
||||
static char *trig_statistics_dump;
|
||||
|
||||
static void
|
||||
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))
|
||||
*/
|
||||
|
||||
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_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_4 * 3.0), -1.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
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "harness.h"
|
||||
|
||||
static char *dump_vrp1;
|
||||
|
||||
void
|
||||
create_code (gcc_jit_context *ctxt, void *user_data)
|
||||
{
|
||||
|
@ -22,6 +24,8 @@ create_code (gcc_jit_context *ctxt, void *user_data)
|
|||
}
|
||||
return sum;
|
||||
*/
|
||||
gcc_jit_context_enable_dump (ctxt, "tree-vrp1", &dump_vrp1);
|
||||
|
||||
gcc_jit_type *the_type =
|
||||
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
|
||||
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);
|
||||
note ("loop_test returned: %d", val);
|
||||
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