diff options
Diffstat (limited to 'gcc/jit')
-rw-r--r-- | gcc/jit/ChangeLog | 46 | ||||
-rw-r--r-- | gcc/jit/jit-recording.c | 150 | ||||
-rw-r--r-- | gcc/jit/jit-recording.h | 49 |
3 files changed, 225 insertions, 20 deletions
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index 0d00f3b..0ba2fd6 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -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. diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 32d7f31..f379b58 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 439e7ce..d3170fe 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; |