]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Implement a coroutine language debug dump
authorArsen Arsenović <arsen@aarsen.me>
Thu, 5 Sep 2024 17:53:07 +0000 (19:53 +0200)
committerArsen Arsenović <arsen@gcc.gnu.org>
Tue, 10 Dec 2024 15:43:39 +0000 (16:43 +0100)
This provides to people working on coroutines, as well as writing tests
for coroutines, a way to have insight into the results and inputs of the
coroutine transformation passes, which is quite essential to
understanding what happens in the coroutine transformation.  Currently,
the information dumped is the pre-transform function (which is not
otherwise available), the generated ramp function, the generated frame
type, the transformed actor/resumer, and the destroyer stub.

While debugging this, I've also encountered a minor bug in
c-pretty-print.cc, where it tried to check DECL_REGISTER of DECLs that
did not support it.  I've added a check for that.

Similary, I found one in pp_cxx_template_parameter, where TREE_TYPE was
called on the list cell the template parameter was in rather than on the
parameter itself.  I've fixed that.

And, lastly, there appeared to be no way to pretty-print a FIELD_DECL,
so I added support to cxx_pretty_printer::declaration for it (by reusing
the VAR_DECL path).

Co-authored-by: Iain Sandoe <iain@sandoe.co.uk>
gcc/c-family/ChangeLog:

* c-pretty-print.cc (c_pretty_printer::storage_class_specifier):
Check that we're looking at a PARM_DECL or VAR_DECL before
looking at DECL_REGISTER.

gcc/cp/ChangeLog:

* coroutines.cc (dump_record_fields): New helper.  Iterates a
RECORD_TYPEs TYPE_FIELDS and pretty-prints them.
(dmp_str): New.  The lang-coro dump stream.
(coro_dump_id): New.  ID of the lang-coro dump.
(coro_dump_flags): New.  Flags passed to the lang-coro dump.
(coro_maybe_dump_initial_function): New helper.  Prints, if
dumping is enabled, the fndecl passed to it as the original
function.
(coro_maybe_dump_ramp): New.  Prints the ramp function passed to
it, if dumping is enabled.
(coro_maybe_dump_transformed_functions): New.
(cp_coroutine_transform::apply_transforms): Initialize the
lang-coro dump.  Call coro_maybe_dump_initial_function on the
original function, as well as coro_maybe_dump_ramp, after the
transformation into the ramp is finished.
(cp_coroutine_transform::finish_transforms): Call
coro_maybe_dump_transformed_functions on the built actor and
destroy.
* cp-objcp-common.cc (cp_register_dumps): Register the coroutine
dump.
* cp-tree.h (coro_dump_id): Declare as extern.
* cxx-pretty-print.cc (pp_cxx_template_parameter): Don't call
TREE_TYPE on a TREE_LIST cell.
(cxx_pretty_printer::declaration): Handle FIELD_DECL similar to
VAR_DECL.

gcc/ChangeLog:

* dumpfile.cc (FIRST_ME_AUTO_NUMBERED_DUMP): Bump to 6 for sake
of the coroutine dump.

gcc/c-family/c-pretty-print.cc
gcc/cp/coroutines.cc
gcc/cp/cp-objcp-common.cc
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.cc
gcc/dumpfile.cc

index b772d8d8ae2bacfeafae53485906ed7bb9073862..c48336f88295502bec0df1f6499388f09ac326cf 100644 (file)
@@ -753,7 +753,8 @@ c_pretty_printer::storage_class_specifier (tree t)
     pp_c_ws_string (this, "typedef");
   else if (DECL_P (t))
     {
-      if (DECL_REGISTER (t))
+      if ((TREE_CODE (t) == PARM_DECL || VAR_P (t))
+         && DECL_REGISTER (t))
        pp_c_ws_string (this, "register");
       else if (TREE_STATIC (t) && VAR_P (t))
        pp_c_ws_string (this, "static");
index 7585229d94ab5818c575cc6c5a448af7825d2874..242afbe9a251d8fc6e12efc10121066ca412edff 100644 (file)
@@ -34,6 +34,123 @@ along with GCC; see the file COPYING3.  If not see
 #include "hash-map.h"
 #include "coroutines.h"
 
+/* ================= Debug. ================= */
+
+#include "langhooks.h"
+#include "cxx-pretty-print.h"
+
+/* Walk through the fields of the type TYP and print them to the pretty printer
+   PP.  */
+
+static void
+dump_record_fields (cxx_pretty_printer *pp, tree typ)
+{
+  pp->type_id (typ);
+  pp_newline_and_indent (pp, 2);
+  pp_left_brace (pp);
+  pp_indentation (pp) += 2;
+
+  /* We'll be on a new line, we don't need padding.  */
+  pp->set_padding (pp_none);
+
+  for (tree tmp = TYPE_FIELDS (typ); tmp; tmp = DECL_CHAIN (tmp))
+    {
+      pp_newline_and_indent (pp, 0);
+      pp->declaration (tmp);
+    }
+
+  pp_newline_and_indent (pp, -2);
+  pp_right_brace (pp);
+  pp_newline_and_indent (pp, -2);
+}
+
+/* The lang-coro stream.  */
+static FILE *dmp_str = NULL;
+
+/* ID of the lang-coro dump. */
+int coro_dump_id;
+
+/* Flags passed to the lang-coro dump.  */
+static dump_flags_t coro_dump_flags;
+
+/* Pretty print the function FNDECL, which ought to be a coroutine before
+   co_await expansion, into the lang-coro dump, if it is enabled.  */
+
+static void
+coro_maybe_dump_initial_function (tree fndecl)
+{
+  if (!dmp_str)
+    return;
+
+  bool lambda_p = LAMBDA_TYPE_P (DECL_CONTEXT (fndecl));
+  fprintf (dmp_str, "%s %s original:\n",
+          (lambda_p ? "Lambda" : "Function"),
+           lang_hooks.decl_printable_name (fndecl, 2));
+
+  cxx_pretty_printer pp;
+  pp.set_output_stream (dmp_str);
+  pp.flags = coro_dump_flags;
+  pp.declaration (fndecl);
+  pp_newline_and_flush (&pp);
+}
+
+/* Pretty print the RAMP function to the lang-coro dump, if it is enabled.  */
+
+static void
+coro_maybe_dump_ramp (tree ramp)
+{
+  if (!dmp_str)
+    return;
+
+  cxx_pretty_printer pp;
+  pp.set_output_stream (dmp_str);
+  pp.flags = coro_dump_flags;
+
+  pp_string (&pp, "Ramp function:");
+  pp_newline_and_indent (&pp, 0);
+  pp.declaration (ramp);
+  pp_newline_and_flush (&pp);
+}
+
+/* For a given ACTOR and DESTROY, if lang-coro dumping is enabled, pretty-print
+   their contents to the lang-coro dump.  */
+
+static void
+coro_maybe_dump_transformed_functions (tree actor, tree destroy)
+{
+  if (!dmp_str)
+    return;
+
+  cxx_pretty_printer pp;
+  pp.set_output_stream (dmp_str);
+  pp.flags = coro_dump_flags;
+
+  if (!actor || actor == error_mark_node)
+    {
+      pp_string (&pp, "Transform failed");
+      pp_newline_and_flush (&pp);
+      return;
+    }
+
+  tree frame = TREE_TYPE (TREE_TYPE (DECL_ARGUMENTS (actor)));
+  pp_string (&pp, "Frame type:");
+  pp_newline (&pp);
+  dump_record_fields (&pp, frame);
+  pp_newline_and_flush (&pp);
+
+  pp_string (&pp, "Actor/resumer:");
+  pp_newline (&pp);
+  pp.declaration (actor);
+  pp_newline_and_flush (&pp);
+
+  pp_string (&pp, "Destroyer:");
+  pp_newline (&pp);
+  pp.declaration (destroy);
+  pp_newline_and_flush (&pp);
+}
+
+/* ================= END Debug. ================= */
+
 static bool coro_promise_type_found_p (tree, location_t);
 
 /* GCC C++ coroutines implementation.
@@ -5226,6 +5343,10 @@ cp_coroutine_transform::~cp_coroutine_transform ()
 void
 cp_coroutine_transform::apply_transforms ()
 {
+  if (dmp_str == NULL)
+    dmp_str = dump_begin (coro_dump_id, &coro_dump_flags);
+
+  coro_maybe_dump_initial_function (orig_fn_decl);
 
   coroutine_body
     = split_coroutine_body_from_ramp (orig_fn_decl);
@@ -5273,6 +5394,7 @@ cp_coroutine_transform::apply_transforms ()
   frame_type = finish_struct (frame_type, NULL_TREE);
 
   valid_coroutine = build_ramp_function ();
+  coro_maybe_dump_ramp (orig_fn_decl);
 }
 
 /* Having analysed and collected the necessary data we are now in a position
@@ -5291,6 +5413,8 @@ cp_coroutine_transform::finish_transforms ()
 
   current_function_decl = destroyer;
   build_destroy_fn (fn_start, frame_type, destroyer, resumer, inline_p);
+
+  coro_maybe_dump_transformed_functions (resumer, destroyer);
 }
 
 #include "gt-cp-coroutines.h"
index 1e7c205674671b7db54f643c19460d991fbe2c25..6ae021f07b038cd48ffb4d9142393f568327034b 100644 (file)
@@ -610,6 +610,8 @@ cp_register_dumps (gcc::dump_manager *dumps)
 
   raw_dump_id = dumps->dump_register
     (".raw", "lang-raw", "lang-raw", DK_lang, OPTGROUP_NONE, false);
+  coro_dump_id = dumps->dump_register
+    (".coro", "lang-coro", "lang-coro", DK_lang, OPTGROUP_NONE, false);
 }
 
 void
index 5f0529530b9479951f408dbdbc97b5912cdb06fd..c5e0fc5c440d19ad22a290ed7bd67150f136b75a 100644 (file)
@@ -6755,6 +6755,7 @@ extern cp_parameter_declarator *no_parameters;
 extern int class_dump_id;
 extern int module_dump_id;
 extern int raw_dump_id;
+extern int coro_dump_id;
 
 /* Whether the current context is manifestly constant-evaluated.
    Used by the constexpr machinery to control folding of
index 4bbbb01b517b61d9825feb7c084ed26bc572123e..4104c6863c7d7d915d96392b70bfdf53237e38cd 100644 (file)
@@ -2294,7 +2294,7 @@ pp_cxx_template_parameter (cxx_pretty_printer *pp, tree t)
     {
     case TYPE_DECL:
       pp_cxx_ws_string (pp, "class");
-      if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (t)))
+      if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parameter)))
        pp_cxx_ws_string (pp, "...");
       if (DECL_NAME (parameter))
        pp_cxx_tree_identifier (pp, DECL_NAME (parameter));
@@ -2480,6 +2480,7 @@ cxx_pretty_printer::declaration (tree t)
       }
   else switch (TREE_CODE (t))
     {
+    case FIELD_DECL:
     case VAR_DECL:
     case TYPE_DECL:
       pp_cxx_simple_declaration (this, t);
index 06a607cf56071535a7ee6ae765d0082223f635e2..f1f1b79e2e1d529530f44c5ac36b1075990d7ec9 100644 (file)
@@ -107,7 +107,7 @@ static struct dump_file_info dump_files[TDI_end] =
   DUMP_FILE_INFO (".lto-stream-out", "ipa-lto-stream-out", DK_ipa, 0),
   DUMP_FILE_INFO (".profile-report", "profile-report", DK_ipa, 0),
 #define FIRST_AUTO_NUMBERED_DUMP 1
-#define FIRST_ME_AUTO_NUMBERED_DUMP 5
+#define FIRST_ME_AUTO_NUMBERED_DUMP 6
 
   DUMP_FILE_INFO (NULL, "lang-all", DK_lang, 0),
   DUMP_FILE_INFO (NULL, "tree-all", DK_tree, 0),