From bd93aa1a976dca96267efb36d6d909ff9813a414 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 16 Jun 2015 18:13:44 +0000 Subject: [PATCH] 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 --- gcc/jit/ChangeLog | 46 +++++ gcc/jit/jit-recording.c | 150 +++++++++++++-- gcc/jit/jit-recording.h | 49 ++++- gcc/testsuite/ChangeLog | 8 + gcc/testsuite/jit.dg/all-non-failing-tests.h | 7 + gcc/testsuite/jit.dg/test-debug-strings.c | 190 +++++++++++++++++++ gcc/testsuite/jit.dg/test-quadratic.c | 28 +-- 7 files changed, 447 insertions(+), 31 deletions(-) create mode 100644 gcc/testsuite/jit.dg/test-debug-strings.c diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 0d00f3bcdbf..0ba2fd6cc87 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,49 @@ +2015-06-16 David Malcolm + + 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 * Make-lang.in (jit.install-common): Install headers using INSTALL_DATA. diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 32d7f31a8c3..f379b58ec81 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -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 diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 439e7ce62d9..d3170fecb7c 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 285fcb70518..66101a9d6dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-06-16 David Malcolm + + 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 PR target/56766 diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h index 82ce7368482..f0000cc0c3e 100644 --- a/gcc/testsuite/jit.dg/all-non-failing-tests.h +++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h @@ -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 diff --git a/gcc/testsuite/jit.dg/test-debug-strings.c b/gcc/testsuite/jit.dg/test-debug-strings.c new file mode 100644 index 00000000000..e515a176257 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-debug-strings.c @@ -0,0 +1,190 @@ +#include +#include + +#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. */ +} diff --git a/gcc/testsuite/jit.dg/test-quadratic.c b/gcc/testsuite/jit.dg/test-quadratic.c index 715174c92f0..d83a4fb0571 100644 --- a/gcc/testsuite/jit.dg/test-quadratic.c +++ b/gcc/testsuite/jit.dg/test-quadratic.c @@ -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); } -- 2.30.2