PR jit/66539: Add parentheses as needed to gcc_jit_object_get_debug_string
gcc/jit/ChangeLog: PR jit/66539 * jit-recording.c: Within namespace gcc::jit::recording:: (rvalue::get_debug_string_parens): New function. (binary_op::make_debug_string): Update to mimic C precedence rules. (binary_op_precedence): New array. (binary_op::get_precedence): New function. (comparison::make_debug_string): Update to mimic C precedence rules. (comparison_precedence): New array. (comparison::get_precedence): New function. (cast::make_debug_string): Update to mimic C precedence rules. (call::make_debug_string): Likewise. (call_through_ptr::make_debug_string): Likewise. (array_access::make_debug_string): Likewise. (access_field_of_lvalue::make_debug_string): Likewise. (access_field_rvalue::make_debug_string): Likewise. (dereference_field_rvalue::make_debug_string): Likewise. (dereference_rvalue::make_debug_string): Likewise. (get_address_of_lvalue::make_debug_string): Likewise. * jit-recording.h: Within namespace gcc::jit::recording:: (precedence): New enum. (rvalue::rvalue): Initialize field "m_parenthesized_string". (rvalue::get_debug_string_parens): New method. (rvalue::get_precedence): New pure virtual function. (rvalue::m_parenthesized_string): New field. (param::get_precedence): New function. (global::get_precedence): New function. (memento_of_new_rvalue_from_const::get_precedence): New function. (memento_of_new_string_literal::get_precedence): New function. (unary_op::get_precedence): New function. (binary_op::get_precedence): New function. (comparison::get_precedence): New function. (cast::get_precedence): New function. (call::get_precedence): New function. (call_through_ptr::get_precedence): New function. (array_access::get_precedence): New function. (access_field_of_lvalue::get_precedence): New function. (access_field_rvalue::get_precedence): New function. (dereference_field_rvalue::get_precedence): New function. (dereference_rvalue::get_precedence): New function. (get_address_of_lvalue::get_precedence): New function. (local::get_precedence): New function. gcc/testsuite/ChangeLog: PR jit/66539 * jit.dg/all-non-failing-tests.h: Add test-debug-strings.c. * jit.dg/test-debug-strings.c: New test case. * jit.dg/test-quadratic.c (make_calc_discriminant): Verify that the discriminant has a sane debug string. From-SVN: r224531
This commit is contained in:
parent
0dc3cba1bd
commit
bd93aa1a97
|
@ -1,3 +1,49 @@
|
|||
2015-06-16 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR jit/66539
|
||||
* jit-recording.c: Within namespace gcc::jit::recording::
|
||||
(rvalue::get_debug_string_parens): New function.
|
||||
(binary_op::make_debug_string): Update to mimic C precedence
|
||||
rules.
|
||||
(binary_op_precedence): New array.
|
||||
(binary_op::get_precedence): New function.
|
||||
(comparison::make_debug_string): Update to mimic C precedence
|
||||
rules.
|
||||
(comparison_precedence): New array.
|
||||
(comparison::get_precedence): New function.
|
||||
(cast::make_debug_string): Update to mimic C precedence rules.
|
||||
(call::make_debug_string): Likewise.
|
||||
(call_through_ptr::make_debug_string): Likewise.
|
||||
(array_access::make_debug_string): Likewise.
|
||||
(access_field_of_lvalue::make_debug_string): Likewise.
|
||||
(access_field_rvalue::make_debug_string): Likewise.
|
||||
(dereference_field_rvalue::make_debug_string): Likewise.
|
||||
(dereference_rvalue::make_debug_string): Likewise.
|
||||
(get_address_of_lvalue::make_debug_string): Likewise.
|
||||
* jit-recording.h: Within namespace gcc::jit::recording::
|
||||
(precedence): New enum.
|
||||
(rvalue::rvalue): Initialize field "m_parenthesized_string".
|
||||
(rvalue::get_debug_string_parens): New method.
|
||||
(rvalue::get_precedence): New pure virtual function.
|
||||
(rvalue::m_parenthesized_string): New field.
|
||||
(param::get_precedence): New function.
|
||||
(global::get_precedence): New function.
|
||||
(memento_of_new_rvalue_from_const::get_precedence): New function.
|
||||
(memento_of_new_string_literal::get_precedence): New function.
|
||||
(unary_op::get_precedence): New function.
|
||||
(binary_op::get_precedence): New function.
|
||||
(comparison::get_precedence): New function.
|
||||
(cast::get_precedence): New function.
|
||||
(call::get_precedence): New function.
|
||||
(call_through_ptr::get_precedence): New function.
|
||||
(array_access::get_precedence): New function.
|
||||
(access_field_of_lvalue::get_precedence): New function.
|
||||
(access_field_rvalue::get_precedence): New function.
|
||||
(dereference_field_rvalue::get_precedence): New function.
|
||||
(dereference_rvalue::get_precedence): New function.
|
||||
(get_address_of_lvalue::get_precedence): New function.
|
||||
(local::get_precedence): New function.
|
||||
|
||||
2015-06-09 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* Make-lang.in (jit.install-common): Install headers using INSTALL_DATA.
|
||||
|
|
|
@ -3021,6 +3021,63 @@ recording::rvalue::access_as_rvalue (reproducer &r)
|
|||
return r.get_identifier (this);
|
||||
}
|
||||
|
||||
/* Return a debug string for the given rvalue, wrapping it in parentheses
|
||||
if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
|
||||
stronger precedence that this rvalue's precedence.
|
||||
|
||||
For example, given:
|
||||
|
||||
MULT
|
||||
/ \
|
||||
PLUS MINUS
|
||||
/ \ / \
|
||||
A B C D
|
||||
|
||||
we want to emit:
|
||||
|
||||
(A + B) * (C - D)
|
||||
|
||||
since MULT has strong precedence than PLUS and MINUS, whereas for:
|
||||
|
||||
PLUS
|
||||
/ \
|
||||
MULT DIVIDE
|
||||
/ \ / \
|
||||
A B C D
|
||||
|
||||
we can simply emit:
|
||||
|
||||
A * B + C / D
|
||||
|
||||
since PLUS has weaker precedence than MULT and DIVIDE. */
|
||||
|
||||
const char *
|
||||
recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
|
||||
{
|
||||
enum precedence this_prec = get_precedence ();
|
||||
|
||||
/* If this_prec has stronger precedence than outer_prec, we don't
|
||||
need to wrap this in parens within the outer debug string.
|
||||
Stronger precedences occur earlier than weaker within the enum,
|
||||
so this is a less than test. Equal precedences don't need
|
||||
parentheses. */
|
||||
if (this_prec <= outer_prec)
|
||||
return get_debug_string();
|
||||
|
||||
/* Otherwise, we need parentheses. */
|
||||
|
||||
/* Lazily-build and cache m_parenthesized_string. */
|
||||
if (!m_parenthesized_string)
|
||||
{
|
||||
const char *debug_string = get_debug_string ();
|
||||
m_parenthesized_string = string::from_printf (get_context (),
|
||||
"(%s)",
|
||||
debug_string);
|
||||
}
|
||||
gcc_assert (m_parenthesized_string);
|
||||
return m_parenthesized_string->c_str ();
|
||||
}
|
||||
|
||||
|
||||
/* The implementation of class gcc::jit::recording::lvalue. */
|
||||
|
||||
|
@ -4251,11 +4308,12 @@ static const char * const binary_op_strings[] = {
|
|||
recording::string *
|
||||
recording::binary_op::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s %s %s",
|
||||
m_a->get_debug_string (),
|
||||
m_a->get_debug_string_parens (prec),
|
||||
binary_op_strings[m_op],
|
||||
m_b->get_debug_string ());
|
||||
m_b->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
static const char * const binary_op_reproducer_strings[] = {
|
||||
|
@ -4295,6 +4353,31 @@ recording::binary_op::write_reproducer (reproducer &r)
|
|||
r.get_identifier_as_rvalue (m_b));
|
||||
}
|
||||
|
||||
namespace recording {
|
||||
static const enum precedence binary_op_precedence[] = {
|
||||
PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
|
||||
PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
|
||||
|
||||
PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
|
||||
PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
|
||||
PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
|
||||
|
||||
PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
|
||||
PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
|
||||
PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
|
||||
PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
|
||||
PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
|
||||
PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
|
||||
PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
|
||||
};
|
||||
} /* namespace recording */
|
||||
|
||||
enum recording::precedence
|
||||
recording::binary_op::get_precedence () const
|
||||
{
|
||||
return binary_op_precedence[m_op];
|
||||
}
|
||||
|
||||
/* The implementation of class gcc::jit::recording::comparison. */
|
||||
|
||||
/* Implementation of recording::memento::make_debug_string for
|
||||
|
@ -4313,11 +4396,12 @@ static const char * const comparison_strings[] =
|
|||
recording::string *
|
||||
recording::comparison::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s %s %s",
|
||||
m_a->get_debug_string (),
|
||||
m_a->get_debug_string_parens (prec),
|
||||
comparison_strings[m_op],
|
||||
m_b->get_debug_string ());
|
||||
m_b->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
/* A table of enum gcc_jit_comparison values expressed in string
|
||||
|
@ -4375,6 +4459,25 @@ recording::comparison::visit_children (rvalue_visitor *v)
|
|||
v->visit (m_b);
|
||||
}
|
||||
|
||||
namespace recording {
|
||||
static const enum precedence comparison_precedence[] =
|
||||
{
|
||||
PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
|
||||
PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
|
||||
|
||||
PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
|
||||
PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
|
||||
PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
|
||||
PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
|
||||
};
|
||||
} /* namespace recording */
|
||||
|
||||
enum recording::precedence
|
||||
recording::comparison::get_precedence () const
|
||||
{
|
||||
return comparison_precedence[m_op];
|
||||
}
|
||||
|
||||
/* Implementation of pure virtual hook recording::memento::replay_into
|
||||
for recording::cast. */
|
||||
|
||||
|
@ -4400,10 +4503,11 @@ recording::cast::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::cast::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"(%s)%s",
|
||||
get_type ()->get_debug_string (),
|
||||
m_rvalue->get_debug_string ());
|
||||
m_rvalue->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
/* Implementation of recording::memento::write_reproducer for casts. */
|
||||
|
@ -4473,12 +4577,13 @@ recording::call::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::call::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
/* First, build a buffer for the arguments. */
|
||||
/* Calculate length of said buffer. */
|
||||
size_t sz = 1; /* nil terminator */
|
||||
for (unsigned i = 0; i< m_args.length (); i++)
|
||||
{
|
||||
sz += strlen (m_args[i]->get_debug_string ());
|
||||
sz += strlen (m_args[i]->get_debug_string_parens (prec));
|
||||
sz += 2; /* ", " separator */
|
||||
}
|
||||
|
||||
|
@ -4488,8 +4593,8 @@ recording::call::make_debug_string ()
|
|||
|
||||
for (unsigned i = 0; i< m_args.length (); i++)
|
||||
{
|
||||
strcpy (argbuf + len, m_args[i]->get_debug_string ());
|
||||
len += strlen (m_args[i]->get_debug_string ());
|
||||
strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
|
||||
len += strlen (m_args[i]->get_debug_string_parens (prec));
|
||||
if (i + 1 < m_args.length ())
|
||||
{
|
||||
strcpy (argbuf + len, ", ");
|
||||
|
@ -4586,12 +4691,13 @@ recording::call_through_ptr::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::call_through_ptr::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
/* First, build a buffer for the arguments. */
|
||||
/* Calculate length of said buffer. */
|
||||
size_t sz = 1; /* nil terminator */
|
||||
for (unsigned i = 0; i< m_args.length (); i++)
|
||||
{
|
||||
sz += strlen (m_args[i]->get_debug_string ());
|
||||
sz += strlen (m_args[i]->get_debug_string_parens (prec));
|
||||
sz += 2; /* ", " separator */
|
||||
}
|
||||
|
||||
|
@ -4601,8 +4707,8 @@ recording::call_through_ptr::make_debug_string ()
|
|||
|
||||
for (unsigned i = 0; i< m_args.length (); i++)
|
||||
{
|
||||
strcpy (argbuf + len, m_args[i]->get_debug_string ());
|
||||
len += strlen (m_args[i]->get_debug_string ());
|
||||
strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
|
||||
len += strlen (m_args[i]->get_debug_string_parens (prec));
|
||||
if (i + 1 < m_args.length ())
|
||||
{
|
||||
strcpy (argbuf + len, ", ");
|
||||
|
@ -4614,7 +4720,7 @@ recording::call_through_ptr::make_debug_string ()
|
|||
/* ...and use it to get the string for the call as a whole. */
|
||||
string *result = string::from_printf (m_ctxt,
|
||||
"%s (%s)",
|
||||
m_fn_ptr->get_debug_string (),
|
||||
m_fn_ptr->get_debug_string_parens (prec),
|
||||
argbuf);
|
||||
|
||||
delete[] argbuf;
|
||||
|
@ -4680,10 +4786,11 @@ recording::array_access::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::array_access::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s[%s]",
|
||||
m_ptr->get_debug_string (),
|
||||
m_index->get_debug_string ());
|
||||
m_ptr->get_debug_string_parens (prec),
|
||||
m_index->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
/* Implementation of recording::memento::write_reproducer for
|
||||
|
@ -4735,9 +4842,10 @@ recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::access_field_of_lvalue::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s.%s",
|
||||
m_lvalue->get_debug_string (),
|
||||
m_lvalue->get_debug_string_parens (prec),
|
||||
m_field->get_debug_string ());
|
||||
}
|
||||
|
||||
|
@ -4787,9 +4895,10 @@ recording::access_field_rvalue::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::access_field_rvalue::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s.%s",
|
||||
m_rvalue->get_debug_string (),
|
||||
m_rvalue->get_debug_string_parens (prec),
|
||||
m_field->get_debug_string ());
|
||||
}
|
||||
|
||||
|
@ -4840,9 +4949,10 @@ recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::dereference_field_rvalue::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"%s->%s",
|
||||
m_rvalue->get_debug_string (),
|
||||
m_rvalue->get_debug_string_parens (prec),
|
||||
m_field->get_debug_string ());
|
||||
}
|
||||
|
||||
|
@ -4891,9 +5001,10 @@ recording::dereference_rvalue::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::dereference_rvalue::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"*%s",
|
||||
m_rvalue->get_debug_string ());
|
||||
m_rvalue->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
/* Implementation of recording::memento::write_reproducer for
|
||||
|
@ -4939,9 +5050,10 @@ recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
|
|||
recording::string *
|
||||
recording::get_address_of_lvalue::make_debug_string ()
|
||||
{
|
||||
enum precedence prec = get_precedence ();
|
||||
return string::from_printf (m_ctxt,
|
||||
"&%s",
|
||||
m_lvalue->get_debug_string ());
|
||||
m_lvalue->get_debug_string_parens (prec));
|
||||
}
|
||||
|
||||
/* Implementation of recording::memento::write_reproducer for
|
||||
|
|
|
@ -858,6 +858,27 @@ class rvalue_visitor
|
|||
virtual void visit (rvalue *rvalue) = 0;
|
||||
};
|
||||
|
||||
/* When generating debug strings for rvalues we mimic C, so we need to
|
||||
mimic C's precedence levels when handling compound expressions.
|
||||
These are in order from strongest precedence to weakest. */
|
||||
enum precedence
|
||||
{
|
||||
PRECEDENCE_PRIMARY,
|
||||
PRECEDENCE_POSTFIX,
|
||||
PRECEDENCE_UNARY,
|
||||
PRECEDENCE_CAST,
|
||||
PRECEDENCE_MULTIPLICATIVE,
|
||||
PRECEDENCE_ADDITIVE,
|
||||
PRECEDENCE_SHIFT,
|
||||
PRECEDENCE_RELATIONAL,
|
||||
PRECEDENCE_EQUALITY,
|
||||
PRECEDENCE_BITWISE_AND,
|
||||
PRECEDENCE_BITWISE_XOR,
|
||||
PRECEDENCE_BITWISE_IOR,
|
||||
PRECEDENCE_LOGICAL_AND,
|
||||
PRECEDENCE_LOGICAL_OR
|
||||
};
|
||||
|
||||
class rvalue : public memento
|
||||
{
|
||||
public:
|
||||
|
@ -867,7 +888,8 @@ public:
|
|||
: memento (ctxt),
|
||||
m_loc (loc),
|
||||
m_type (type_),
|
||||
m_scope (NULL)
|
||||
m_scope (NULL),
|
||||
m_parenthesized_string (NULL)
|
||||
{
|
||||
gcc_assert (type_);
|
||||
}
|
||||
|
@ -909,12 +931,20 @@ public:
|
|||
|
||||
virtual const char *access_as_rvalue (reproducer &r);
|
||||
|
||||
/* Get the debug string, wrapped in parentheses. */
|
||||
const char *
|
||||
get_debug_string_parens (enum precedence outer_prec);
|
||||
|
||||
private:
|
||||
virtual enum precedence get_precedence () const = 0;
|
||||
|
||||
protected:
|
||||
location *m_loc;
|
||||
type *m_type;
|
||||
|
||||
private:
|
||||
function *m_scope; /* NULL for globals, non-NULL for locals/params */
|
||||
string *m_parenthesized_string;
|
||||
};
|
||||
|
||||
class lvalue : public rvalue
|
||||
|
@ -977,6 +1007,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string () { return m_name; }
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; }
|
||||
|
||||
private:
|
||||
string *m_name;
|
||||
|
@ -1161,6 +1192,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string () { return m_name; }
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; }
|
||||
|
||||
private:
|
||||
enum gcc_jit_global_kind m_kind;
|
||||
|
@ -1185,6 +1217,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; }
|
||||
|
||||
private:
|
||||
HOST_TYPE m_value;
|
||||
|
@ -1206,6 +1239,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; }
|
||||
|
||||
private:
|
||||
string *m_value;
|
||||
|
@ -1231,6 +1265,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const {return PRECEDENCE_UNARY;}
|
||||
|
||||
private:
|
||||
enum gcc_jit_unary_op m_op;
|
||||
|
@ -1257,6 +1292,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const;
|
||||
|
||||
private:
|
||||
enum gcc_jit_binary_op m_op;
|
||||
|
@ -1284,6 +1320,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const;
|
||||
|
||||
private:
|
||||
enum gcc_jit_comparison m_op;
|
||||
|
@ -1309,6 +1346,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_CAST; }
|
||||
|
||||
private:
|
||||
rvalue *m_rvalue;
|
||||
|
@ -1330,6 +1368,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
function *m_func;
|
||||
|
@ -1352,6 +1391,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
rvalue *m_fn_ptr;
|
||||
|
@ -1377,6 +1417,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
rvalue *m_ptr;
|
||||
|
@ -1402,6 +1443,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
lvalue *m_lvalue;
|
||||
|
@ -1427,6 +1469,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
rvalue *m_rvalue;
|
||||
|
@ -1452,6 +1495,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; }
|
||||
|
||||
private:
|
||||
rvalue *m_rvalue;
|
||||
|
@ -1474,6 +1518,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_UNARY; }
|
||||
|
||||
private:
|
||||
rvalue *m_rvalue;
|
||||
|
@ -1496,6 +1541,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string ();
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_UNARY; }
|
||||
|
||||
private:
|
||||
lvalue *m_lvalue;
|
||||
|
@ -1521,6 +1567,7 @@ public:
|
|||
private:
|
||||
string * make_debug_string () { return m_name; }
|
||||
void write_reproducer (reproducer &r);
|
||||
enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; }
|
||||
|
||||
private:
|
||||
function *m_func;
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2015-06-16 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR jit/66539
|
||||
* jit.dg/all-non-failing-tests.h: Add test-debug-strings.c.
|
||||
* jit.dg/test-debug-strings.c: New test case.
|
||||
* jit.dg/test-quadratic.c (make_calc_discriminant): Verify that
|
||||
the discriminant has a sane debug string.
|
||||
|
||||
2015-06-16 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/56766
|
||||
|
|
|
@ -64,6 +64,13 @@
|
|||
#undef create_code
|
||||
#undef verify_code
|
||||
|
||||
/* test-debug-strings.c */
|
||||
#define create_code create_code_debug_strings
|
||||
#define verify_code verify_code_debug_strings
|
||||
#include "test-debug-strings.c"
|
||||
#undef create_code
|
||||
#undef verify_code
|
||||
|
||||
/* test-dot-product.c */
|
||||
#define create_code create_code_dot_product
|
||||
#define verify_code verify_code_dot_product
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libgccjit.h"
|
||||
|
||||
#include "harness.h"
|
||||
|
||||
/* Build various compound expressions, and verify that they have sane debug
|
||||
strings. */
|
||||
void
|
||||
create_code (gcc_jit_context *ctxt, void *user_data)
|
||||
{
|
||||
/* Make a singly-linked list type:
|
||||
struct node
|
||||
{
|
||||
struct node *next;
|
||||
int value;
|
||||
};
|
||||
*/
|
||||
gcc_jit_type *t_int =
|
||||
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
|
||||
gcc_jit_struct *t_node =
|
||||
gcc_jit_context_new_opaque_struct (ctxt, NULL, "node");
|
||||
gcc_jit_type *t_node_ptr =
|
||||
gcc_jit_type_get_pointer (gcc_jit_struct_as_type (t_node));
|
||||
gcc_jit_field *f_next =
|
||||
gcc_jit_context_new_field (ctxt, NULL, t_node_ptr, "next");
|
||||
gcc_jit_field *f_value =
|
||||
gcc_jit_context_new_field (ctxt, NULL, t_int, "value");
|
||||
gcc_jit_field *fields[] = {f_next, f_value};
|
||||
gcc_jit_struct_set_fields (t_node, NULL, 2, fields);
|
||||
|
||||
/* Create a dummy function so that we have locals/params to build
|
||||
expressions with. */
|
||||
gcc_jit_type *t_void =
|
||||
gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
|
||||
gcc_jit_function *fn =
|
||||
gcc_jit_context_new_function (ctxt, NULL,
|
||||
GCC_JIT_FUNCTION_EXPORTED,
|
||||
t_void,
|
||||
"test_debug_strings",
|
||||
0, NULL, 0);
|
||||
gcc_jit_rvalue *ptr =
|
||||
gcc_jit_lvalue_as_rvalue (
|
||||
gcc_jit_function_new_local (fn,
|
||||
NULL,
|
||||
t_node_ptr,
|
||||
"ptr"));
|
||||
gcc_jit_rvalue *a =
|
||||
gcc_jit_lvalue_as_rvalue (
|
||||
gcc_jit_function_new_local (fn, NULL, t_int, "a"));
|
||||
gcc_jit_rvalue *b =
|
||||
gcc_jit_lvalue_as_rvalue (
|
||||
gcc_jit_function_new_local (fn, NULL, t_int, "b"));
|
||||
gcc_jit_rvalue *c =
|
||||
gcc_jit_lvalue_as_rvalue (
|
||||
gcc_jit_function_new_local (fn, NULL, t_int, "c"));
|
||||
gcc_jit_rvalue *d =
|
||||
gcc_jit_lvalue_as_rvalue (
|
||||
gcc_jit_function_new_local (fn, NULL, t_int, "d"));
|
||||
|
||||
#define CHECK_RVALUE_DEBUG_STRING(RVALUE, EXPECTED) \
|
||||
CHECK_STRING_VALUE ( \
|
||||
gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (RVALUE)), \
|
||||
(EXPECTED))
|
||||
|
||||
#define CHECK_LVALUE_DEBUG_STRING(LVALUE, EXPECTED) \
|
||||
CHECK_STRING_VALUE ( \
|
||||
gcc_jit_object_get_debug_string (gcc_jit_lvalue_as_object (LVALUE)), \
|
||||
(EXPECTED))
|
||||
|
||||
/* Verify various simple compound expressions. */
|
||||
{
|
||||
CHECK_RVALUE_DEBUG_STRING (ptr, "ptr");
|
||||
|
||||
gcc_jit_lvalue *deref =
|
||||
gcc_jit_rvalue_dereference_field (ptr,
|
||||
NULL,
|
||||
f_value);
|
||||
CHECK_LVALUE_DEBUG_STRING (deref, "ptr->value");
|
||||
|
||||
gcc_jit_rvalue *deref_as_rvalue = gcc_jit_lvalue_as_rvalue (deref);
|
||||
|
||||
#define BINOP(OP, A, B) \
|
||||
gcc_jit_context_new_binary_op (ctxt, NULL, \
|
||||
GCC_JIT_BINARY_OP_##OP, t_int, (A), (B))
|
||||
#define COMPARISON(OP, A, B) \
|
||||
gcc_jit_context_new_comparison (ctxt, NULL, \
|
||||
GCC_JIT_COMPARISON_##OP,(A), (B))
|
||||
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (PLUS, deref_as_rvalue, deref_as_rvalue),
|
||||
"ptr->value + ptr->value");
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (MULT, deref_as_rvalue, deref_as_rvalue),
|
||||
"ptr->value * ptr->value");
|
||||
|
||||
/* Multiplication has higher precedence in C than addition, so this
|
||||
dump shouldn't contain parentheses. */
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (PLUS,
|
||||
BINOP (MULT, a, b),
|
||||
BINOP (MULT, c, d)),
|
||||
"a * b + c * d");
|
||||
|
||||
/* ...but this one should. */
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (MULT,
|
||||
BINOP (PLUS, a, b),
|
||||
BINOP (PLUS, c, d)),
|
||||
"(a + b) * (c + d)");
|
||||
|
||||
/* Equal precedences don't need parentheses. */
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (MULT,
|
||||
BINOP (MULT, a, b),
|
||||
BINOP (MULT, c, d)),
|
||||
"a * b * c * d");
|
||||
|
||||
/* Comparisons and logical ops. */
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
COMPARISON (LT, a, b),
|
||||
"a < b");
|
||||
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (LOGICAL_AND,
|
||||
COMPARISON (LT, a, b),
|
||||
COMPARISON (GT, c, d)),
|
||||
"a < b && c > d");
|
||||
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (LOGICAL_AND,
|
||||
BINOP (LOGICAL_OR,
|
||||
COMPARISON (LT, a, b),
|
||||
COMPARISON (LT, a, c)),
|
||||
BINOP (LOGICAL_OR,
|
||||
COMPARISON (GT, d, b),
|
||||
COMPARISON (GT, d, c))),
|
||||
"(a < b || a < c) && (d > b || d > c)");
|
||||
|
||||
CHECK_RVALUE_DEBUG_STRING (
|
||||
BINOP (LOGICAL_OR,
|
||||
BINOP (LOGICAL_AND,
|
||||
COMPARISON (LT, a, b),
|
||||
COMPARISON (LT, a, c)),
|
||||
BINOP (LOGICAL_AND,
|
||||
COMPARISON (GT, d, b),
|
||||
COMPARISON (GT, d, c))),
|
||||
"a < b && a < c || d > b && d > c");
|
||||
|
||||
#undef BINOP
|
||||
#undef COMPARISON
|
||||
}
|
||||
|
||||
/* PR jit/66539 "Missing parentheses in jit dumps".
|
||||
Construct the equivalent of
|
||||
((cast)ptr->next)->next
|
||||
and verify that the appropriate parentheses appear in the debug
|
||||
string. */
|
||||
{
|
||||
/* "ptr->next". */
|
||||
gcc_jit_lvalue *inner_deref =
|
||||
gcc_jit_rvalue_dereference_field (ptr,
|
||||
NULL,
|
||||
f_next);
|
||||
/* "((node *)ptr->next)"; the cast is redundant, purely
|
||||
to exercise dumping. */
|
||||
gcc_jit_rvalue *test_cast =
|
||||
gcc_jit_context_new_cast (ctxt, NULL,
|
||||
gcc_jit_lvalue_as_rvalue (inner_deref),
|
||||
t_node_ptr);
|
||||
/* "((node *)ptr->next)->next". */
|
||||
gcc_jit_lvalue *outer_deref =
|
||||
gcc_jit_rvalue_dereference_field (test_cast, /* gcc_jit_rvalue *ptr */
|
||||
NULL, /* gcc_jit_location *loc */
|
||||
f_next); /* gcc_jit_field *field */
|
||||
CHECK_LVALUE_DEBUG_STRING (outer_deref,
|
||||
"((struct node *)ptr->next)->next");
|
||||
}
|
||||
|
||||
#undef CHECK_LVALUE_DEBUG_STRING
|
||||
}
|
||||
|
||||
void
|
||||
verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
|
||||
{
|
||||
CHECK_NON_NULL (result);
|
||||
/* We don't actually build any functions above;
|
||||
nothing more to verify. */
|
||||
}
|
|
@ -176,16 +176,8 @@ make_calc_discriminant (struct quadratic_test *testcase)
|
|||
gcc_jit_param_as_rvalue (param_q),
|
||||
NULL, testcase->c));
|
||||
|
||||
gcc_jit_block_add_assignment (
|
||||
blk, NULL,
|
||||
|
||||
/* q->discriminant =... */
|
||||
gcc_jit_rvalue_dereference_field (
|
||||
gcc_jit_param_as_rvalue (param_q),
|
||||
NULL,
|
||||
testcase->discriminant),
|
||||
|
||||
/* (q->b * q->b) - (4 * q->a * q->c) */
|
||||
/* (q->b * q->b) - (4 * q->a * q->c) */
|
||||
gcc_jit_rvalue *rhs =
|
||||
gcc_jit_context_new_binary_op (
|
||||
testcase->ctxt, NULL,
|
||||
GCC_JIT_BINARY_OP_MINUS,
|
||||
|
@ -213,7 +205,21 @@ make_calc_discriminant (struct quadratic_test *testcase)
|
|||
testcase->ctxt, NULL,
|
||||
GCC_JIT_BINARY_OP_MULT,
|
||||
testcase->numeric_type,
|
||||
q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */
|
||||
q_a, q_c)));
|
||||
|
||||
CHECK_STRING_VALUE (
|
||||
gcc_jit_object_get_debug_string (gcc_jit_rvalue_as_object (rhs)),
|
||||
"q->b * q->b - (double)4 * q->a * q->c");
|
||||
|
||||
gcc_jit_block_add_assignment (
|
||||
blk, NULL,
|
||||
|
||||
/* q->discriminant =... */
|
||||
gcc_jit_rvalue_dereference_field (
|
||||
gcc_jit_param_as_rvalue (param_q),
|
||||
NULL,
|
||||
testcase->discriminant),
|
||||
rhs);
|
||||
|
||||
gcc_jit_block_end_with_void_return (blk, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue