https://gcc.gnu.org/g:07e74798b93c256bea3a91895d3517223a58da61
commit r15-3431-g07e74798b93c256bea3a91895d3517223a58da61 Author: David Malcolm <dmalc...@redhat.com> Date: Tue Sep 3 15:11:06 2024 -0400 pretty-print: split up pretty_printer::format into subroutines The body of pretty_printer::format is almost 500 lines long, mostly comprising two distinct phases. This patch splits it up so that there are explicit subroutines for the two different phases, reducing the scope of various locals, and making it easier to e.g. put a breakpoint on phase 2. No functional change intended. gcc/ChangeLog: * pretty-print-markup.h (pp_markup::context::context): Drop params "buf" and "chunk_idx", initializing m_buf from pp. (pp_markup::context::m_chunk_idx): Drop field. * pretty-print.cc (pretty_printer::format): Convert param from a text_info * to a text_info &. Split out phase 1 and phase 2 into subroutines... (format_phase_1): New, from pretty_printer::format. (format_phase_2): Likewise. * pretty-print.h (pretty_printer::format): Convert param from a text_info * to a text_info &. (pp_format): Update for above change. Assert that text_info is non-null. Signed-off-by: David Malcolm <dmalc...@redhat.com> Diff: --- gcc/pretty-print-markup.h | 6 +- gcc/pretty-print.cc | 232 +++++++++++++++++++++++++--------------------- gcc/pretty-print.h | 5 +- 3 files changed, 131 insertions(+), 112 deletions(-) diff --git a/gcc/pretty-print-markup.h b/gcc/pretty-print-markup.h index ce2c5e9dbbe9..de9e4bda6ade 100644 --- a/gcc/pretty-print-markup.h +++ b/gcc/pretty-print-markup.h @@ -30,13 +30,10 @@ class context { public: context (pretty_printer &pp, - output_buffer &buf, - unsigned chunk_idx, bool "ed, pp_token_list *formatted_token_list) : m_pp (pp), - m_buf (buf), - m_chunk_idx (chunk_idx), + m_buf (*pp_buffer (&pp)), m_quoted (quoted), m_formatted_token_list (formatted_token_list) { @@ -52,7 +49,6 @@ public: pretty_printer &m_pp; output_buffer &m_buf; - unsigned m_chunk_idx; bool &m_quoted; pp_token_list *m_formatted_token_list; }; diff --git a/gcc/pretty-print.cc b/gcc/pretty-print.cc index 115f376c4512..998e06e155f7 100644 --- a/gcc/pretty-print.cc +++ b/gcc/pretty-print.cc @@ -1589,35 +1589,79 @@ push_back_any_text (pp_token_list *tok_list, Phase 3 is in pp_output_formatted_text, which pops the pp_formatted_chunks instance. */ +static void +format_phase_1 (const text_info &text, + obstack &chunk_obstack, + pp_token_list **args, + pp_token_list ***formatters); + +static void +format_phase_2 (pretty_printer *pp, + text_info &text, + obstack &chunk_obstack, + pp_token_list ***formatters); + void -pretty_printer::format (text_info *text) +pretty_printer::format (text_info &text) { - output_buffer * const buffer = m_buffer; + pp_formatted_chunks *new_chunk_array = m_buffer->push_formatted_chunks (); + pp_token_list **args = new_chunk_array->m_args; - unsigned int chunk = 0, argno; pp_token_list **formatters[PP_NL_ARGMAX]; - - pp_formatted_chunks *new_chunk_array = buffer->push_formatted_chunks (); - pp_token_list **args = new_chunk_array->m_args; + memset (formatters, 0, sizeof formatters); /* Formatting phase 1: split up TEXT->format_spec into chunks in pp_buffer (PP)->args[]. Even-numbered chunks are to be output verbatim, odd-numbered chunks are format specifiers. %m, %%, %<, %>, %} and %' are replaced with the appropriate text at this point. */ + format_phase_1 (text, m_buffer->m_chunk_obstack, args, formatters); - memset (formatters, 0, sizeof formatters); + /* Note that you can debug the state of the chunk arrays here using + (gdb) call m_buffer->cur_chunk_array->dump() + which, given e.g. "foo: %s bar: %s" might print: + 0: [TEXT("foo: ")] + 1: [TEXT("s")] + 2: [TEXT(" bar: ")] + 3: [TEXT("s")] + */ + + /* Set output to the argument obstack, and switch line-wrapping and + prefixing off. */ + m_buffer->m_obstack = &m_buffer->m_chunk_obstack; + const int old_line_length = m_buffer->m_line_length; + const pp_wrapping_mode_t old_wrapping_mode = pp_set_verbatim_wrapping (this); + + format_phase_2 (this, text, m_buffer->m_chunk_obstack, formatters); + + /* If the client supplied a postprocessing object, call its "handle" + hook here. */ + if (m_format_postprocessor) + m_format_postprocessor->handle (this); + + /* Revert to normal obstack and wrapping mode. */ + m_buffer->m_obstack = &m_buffer->m_formatted_obstack; + m_buffer->m_line_length = old_line_length; + pp_wrapping_mode (this) = old_wrapping_mode; + clear_state (); +} +static void +format_phase_1 (const text_info &text, + obstack &chunk_obstack, + pp_token_list **args, + pp_token_list ***formatters) +{ + unsigned chunk = 0; unsigned int curarg = 0; bool any_unnumbered = false, any_numbered = false; pp_token_list *cur_token_list; - args[chunk++] = cur_token_list - = pp_token_list::make (buffer->m_chunk_obstack); - for (const char *p = text->m_format_spec; *p; ) + args[chunk++] = cur_token_list = pp_token_list::make (chunk_obstack); + for (const char *p = text.m_format_spec; *p; ) { while (*p != '\0' && *p != '%') { - obstack_1grow (&buffer->m_chunk_obstack, *p); + obstack_1grow (&chunk_obstack, *p); p++; } @@ -1630,13 +1674,13 @@ pretty_printer::format (text_info *text) gcc_unreachable (); case '%': - obstack_1grow (&buffer->m_chunk_obstack, '%'); + obstack_1grow (&chunk_obstack, '%'); p++; continue; case '<': { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); cur_token_list->push_back<pp_token_begin_quote> (); p++; continue; @@ -1644,14 +1688,14 @@ pretty_printer::format (text_info *text) case '>': { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); cur_token_list->push_back<pp_token_end_quote> (); p++; continue; } case '\'': { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); cur_token_list->push_back<pp_token_end_quote> (); p++; } @@ -1659,7 +1703,7 @@ pretty_printer::format (text_info *text) case '}': { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); cur_token_list->push_back<pp_token_end_url> (); p++; } @@ -1667,7 +1711,7 @@ pretty_printer::format (text_info *text) case 'R': { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); cur_token_list->push_back<pp_token_end_color> (); p++; continue; @@ -1675,22 +1719,22 @@ pretty_printer::format (text_info *text) case 'm': { - const char *errstr = xstrerror (text->m_err_no); - obstack_grow (&buffer->m_chunk_obstack, errstr, strlen (errstr)); + const char *errstr = xstrerror (text.m_err_no); + obstack_grow (&chunk_obstack, errstr, strlen (errstr)); } p++; continue; default: /* Handled in phase 2. Terminate the plain chunk here. */ - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); break; } /* Start a new token list for the formatting args. */ - args[chunk] = cur_token_list - = pp_token_list::make (buffer->m_chunk_obstack); + args[chunk] = cur_token_list = pp_token_list::make (chunk_obstack); + unsigned argno; if (ISDIGIT (*p)) { char *end; @@ -1713,7 +1757,7 @@ pretty_printer::format (text_info *text) formatters[argno] = &args[chunk++]; do { - obstack_1grow (&buffer->m_chunk_obstack, *p); + obstack_1grow (&chunk_obstack, *p); p++; } while (strchr ("qwlzt+#", p[-1])); @@ -1726,7 +1770,7 @@ pretty_printer::format (text_info *text) { do { - obstack_1grow (&buffer->m_chunk_obstack, *p); + obstack_1grow (&chunk_obstack, *p); p++; } while (ISDIGIT (p[-1])); @@ -1735,7 +1779,7 @@ pretty_printer::format (text_info *text) else { gcc_assert (*p == '*'); - obstack_1grow (&buffer->m_chunk_obstack, '*'); + obstack_1grow (&chunk_obstack, '*'); p++; if (ISDIGIT (*p)) @@ -1757,48 +1801,40 @@ pretty_printer::format (text_info *text) curarg++; } gcc_assert (*p == 's'); - obstack_1grow (&buffer->m_chunk_obstack, 's'); + obstack_1grow (&chunk_obstack, 's'); p++; } } if (*p == '\0') { - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + push_back_any_text (cur_token_list, &chunk_obstack); break; } - obstack_1grow (&buffer->m_chunk_obstack, '\0'); - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + obstack_1grow (&chunk_obstack, '\0'); + push_back_any_text (cur_token_list, &chunk_obstack); /* Start a new token list for the next (non-formatted) text. */ gcc_assert (chunk < PP_NL_ARGMAX * 2); - args[chunk++] = cur_token_list - = pp_token_list::make (buffer->m_chunk_obstack); + args[chunk++] = cur_token_list = pp_token_list::make (chunk_obstack); } - obstack_1grow (&buffer->m_chunk_obstack, '\0'); - push_back_any_text (cur_token_list, &buffer->m_chunk_obstack); + obstack_1grow (&chunk_obstack, '\0'); + push_back_any_text (cur_token_list, &chunk_obstack); gcc_assert (chunk < PP_NL_ARGMAX * 2); args[chunk] = nullptr; +} - /* Set output to the argument obstack, and switch line-wrapping and - prefixing off. */ - buffer->m_obstack = &buffer->m_chunk_obstack; - const int old_line_length = buffer->m_line_length; - const pp_wrapping_mode_t old_wrapping_mode = pp_set_verbatim_wrapping (this); - - /* Note that you can debug the state of the chunk arrays here using - (gdb) call buffer->cur_chunk_array->dump() - which, given e.g. "foo: %s bar: %s" might print: - 0: [TEXT("foo: ")] - 1: [TEXT("s")] - 2: [TEXT(" bar: ")] - 3: [TEXT("s")] - */ - - /* Second phase. Replace each formatter with the formatted text it - corresponds to. */ +/* Second phase. Replace each formatter with pp_tokens for the formatted + text it corresponds to, consuming va_args from TEXT->m_args_ptr. */ +static void +format_phase_2 (pretty_printer *pp, + text_info &text, + obstack &chunk_obstack, + pp_token_list ***formatters) +{ + unsigned argno; for (argno = 0; formatters[argno]; argno++) { int precision = 0; @@ -1807,8 +1843,6 @@ pretty_printer::format (text_info *text) bool hash = false; bool quote = false; - const char *p; - /* We expect a single text token containing the formatter. */ pp_token_list *tok_list = *(formatters[argno]); gcc_assert (tok_list); @@ -1817,11 +1851,12 @@ pretty_printer::format (text_info *text) /* Accumulate the value of the formatted text into here. */ pp_token_list *formatted_tok_list - = pp_token_list::make (buffer->m_chunk_obstack); + = pp_token_list::make (chunk_obstack); /* We do not attempt to enforce any ordering on the modifier characters. */ + const char *p; for (p = as_a <pp_token_text *> (tok_list->m_first)->m_value.get ();; p++) { switch (*p) @@ -1869,7 +1904,7 @@ pretty_printer::format (text_info *text) if (quote) { - push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack); + push_back_any_text (formatted_tok_list, &chunk_obstack); formatted_tok_list->push_back<pp_token_begin_quote> (); } @@ -1877,7 +1912,7 @@ pretty_printer::format (text_info *text) { case 'r': { - const char *color = va_arg (*text->m_args_ptr, const char *); + const char *color = va_arg (*text.m_args_ptr, const char *); formatted_tok_list->push_back<pp_token_begin_color> (label_text::borrow (color)); } @@ -1888,13 +1923,13 @@ pretty_printer::format (text_info *text) /* When quoting, print alphanumeric, punctuation, and the space character unchanged, and all others in hexadecimal with the "\x" prefix. Otherwise print them all unchanged. */ - int chr = va_arg (*text->m_args_ptr, int); + int chr = va_arg (*text.m_args_ptr, int); if (ISPRINT (chr) || !quote) - pp_character (this, chr); + pp_character (pp, chr); else { const char str [2] = { chr, '\0' }; - pp_quoted_string (this, str, 1); + pp_quoted_string (pp, str, 1); } break; } @@ -1902,57 +1937,57 @@ pretty_printer::format (text_info *text) case 'd': case 'i': if (wide) - pp_wide_integer (this, va_arg (*text->m_args_ptr, HOST_WIDE_INT)); + pp_wide_integer (pp, va_arg (*text.m_args_ptr, HOST_WIDE_INT)); else - pp_integer_with_precision (this, *text->m_args_ptr, precision, + pp_integer_with_precision (pp, *text.m_args_ptr, precision, int, "d"); break; case 'o': if (wide) - pp_scalar (this, "%" HOST_WIDE_INT_PRINT "o", - va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT)); + pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o", + va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT)); else - pp_integer_with_precision (this, *text->m_args_ptr, precision, + pp_integer_with_precision (pp, *text.m_args_ptr, precision, unsigned, "o"); break; case 's': if (quote) - pp_quoted_string (this, va_arg (*text->m_args_ptr, const char *)); + pp_quoted_string (pp, va_arg (*text.m_args_ptr, const char *)); else - pp_string (this, va_arg (*text->m_args_ptr, const char *)); + pp_string (pp, va_arg (*text.m_args_ptr, const char *)); break; case 'p': - pp_pointer (this, va_arg (*text->m_args_ptr, void *)); + pp_pointer (pp, va_arg (*text.m_args_ptr, void *)); break; case 'u': if (wide) - pp_scalar (this, HOST_WIDE_INT_PRINT_UNSIGNED, - va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT)); + pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED, + va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT)); else - pp_integer_with_precision (this, *text->m_args_ptr, precision, + pp_integer_with_precision (pp, *text.m_args_ptr, precision, unsigned, "u"); break; case 'f': - pp_double (this, va_arg (*text->m_args_ptr, double)); + pp_double (pp, va_arg (*text.m_args_ptr, double)); break; case 'Z': { - int *v = va_arg (*text->m_args_ptr, int *); - unsigned len = va_arg (*text->m_args_ptr, unsigned); + int *v = va_arg (*text.m_args_ptr, int *); + unsigned len = va_arg (*text.m_args_ptr, unsigned); for (unsigned i = 0; i < len; ++i) { - pp_scalar (this, "%i", v[i]); + pp_scalar (pp, "%i", v[i]); if (i < len - 1) { - pp_comma (this); - pp_space (this); + pp_comma (pp); + pp_space (pp); } } break; @@ -1960,10 +1995,10 @@ pretty_printer::format (text_info *text) case 'x': if (wide) - pp_scalar (this, HOST_WIDE_INT_PRINT_HEX, - va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT)); + pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, + va_arg (*text.m_args_ptr, unsigned HOST_WIDE_INT)); else - pp_integer_with_precision (this, *text->m_args_ptr, precision, + pp_integer_with_precision (pp, *text.m_args_ptr, precision, unsigned, "x"); break; @@ -1988,21 +2023,21 @@ pretty_printer::format (text_info *text) gcc_assert (*p == '*'); p++; gcc_assert (*p == 's'); - n = va_arg (*text->m_args_ptr, int); + n = va_arg (*text.m_args_ptr, int); /* This consumes a second entry in the formatters array. */ gcc_assert (formatters[argno] == formatters[argno+1]); argno++; } - s = va_arg (*text->m_args_ptr, const char *); + s = va_arg (*text.m_args_ptr, const char *); /* Append the lesser of precision and strlen (s) characters from the array (which need not be a nul-terminated string). Negative precision is treated as if it were omitted. */ size_t len = n < 0 ? strlen (s) : strnlen (s, n); - pp_append_text (this, s, s + len); + pp_append_text (pp, s, s + len); } break; @@ -2010,7 +2045,7 @@ pretty_printer::format (text_info *text) { /* diagnostic_event_id_t *. */ diagnostic_event_id_ptr event_id - = va_arg (*text->m_args_ptr, diagnostic_event_id_ptr); + = va_arg (*text.m_args_ptr, diagnostic_event_id_ptr); gcc_assert (event_id->known_p ()); formatted_tok_list->push_back<pp_token_event_id> (*event_id); } @@ -2018,7 +2053,7 @@ pretty_printer::format (text_info *text) case '{': { - const char *url = va_arg (*text->m_args_ptr, const char *); + const char *url = va_arg (*text.m_args_ptr, const char *); formatted_tok_list->push_back<pp_token_begin_url> (label_text::borrow (url)); } @@ -2026,9 +2061,8 @@ pretty_printer::format (text_info *text) case 'e': { - pp_element *element - = va_arg (*text->m_args_ptr, pp_element *); - pp_markup::context ctxt (*this, *buffer, chunk, + pp_element *element = va_arg (*text.m_args_ptr, pp_element *); + pp_markup::context ctxt (*pp, quote, /* by reference */ formatted_tok_list); element->add_to_phase_2 (ctxt); @@ -2037,29 +2071,28 @@ pretty_printer::format (text_info *text) default: { - bool ok; - /* Call the format decoder. Pass the address of "quote" so that format decoders can potentially disable printing of the closing quote (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family of frontends). */ - gcc_assert (pp_format_decoder (this)); + printer_fn format_decoder = pp_format_decoder (pp); + gcc_assert (format_decoder); gcc_assert (formatted_tok_list); - ok = m_format_decoder (this, text, p, - precision, wide, plus, hash, "e, - *formatted_tok_list); + bool ok = format_decoder (pp, &text, p, + precision, wide, plus, hash, "e, + *formatted_tok_list); gcc_assert (ok); } } if (quote) { - push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack); + push_back_any_text (formatted_tok_list, &chunk_obstack); formatted_tok_list->push_back<pp_token_end_quote> (); } - push_back_any_text (formatted_tok_list, &buffer->m_chunk_obstack); + push_back_any_text (formatted_tok_list, &chunk_obstack); delete *formatters[argno]; *formatters[argno] = formatted_tok_list; } @@ -2067,17 +2100,6 @@ pretty_printer::format (text_info *text) if (CHECKING_P) for (; argno < PP_NL_ARGMAX; argno++) gcc_assert (!formatters[argno]); - - /* If the client supplied a postprocessing object, call its "handle" - hook here. */ - if (m_format_postprocessor) - m_format_postprocessor->handle (this); - - /* Revert to normal obstack and wrapping mode. */ - buffer->m_obstack = &buffer->m_formatted_obstack; - buffer->m_line_length = old_line_length; - pp_wrapping_mode (this) = old_wrapping_mode; - clear_state (); } struct auto_obstack diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h index 14a6c53a4ac0..b5ded5cdd5e0 100644 --- a/gcc/pretty-print.h +++ b/gcc/pretty-print.h @@ -282,7 +282,7 @@ public: void emit_prefix (); - void format (text_info *text); + void format (text_info &text); void maybe_space (); @@ -579,7 +579,8 @@ extern void pp_flush (pretty_printer *); extern void pp_really_flush (pretty_printer *); inline void pp_format (pretty_printer *pp, text_info *text) { - pp->format (text); + gcc_assert (text); + pp->format (*text); } extern void pp_output_formatted_text (pretty_printer *, const urlifier * = nullptr);