On Thu, 2026-01-08 at 18:54 -0800, Andrew Pinski wrote:
> On Fri, Nov 14, 2025 at 10:33 AM David Malcolm <[email protected]>
> wrote:
> >
> > This patch adds a new "struct compiler_channels" to hold channels
> > relating to the compiler that plugins (or diagnostic sinks) might
> > want
> > to subscribe to events for, accessed from the global gcc::context
> > object, along with a new gcc/topics/ source subdirectory to hold
> > strongly-typed publish/subscribe topics relating to the compiler.
> >
> > For now, there is just one: pass_events_channel, which, if there
> > are any
> > subscribers, issues notifications about passes starting/stopping on
> > particular functions, using topics::pass_events, declared in
> > topics/pass-events.h, but followup patches add more kinds of
> > notification channel.
> >
> > A toy plugin in the testsuite shows how this could be used to build
> > a
> > progress notification UI for the compiler, and a followup patch
> > uses the
> > channel to (optionally) capture CFG information at each stage of
> > optimization in machine-readable form into a SARIF sink.
> >
> > gcc/ChangeLog:
> > * channels.h: New file.
> > * context.cc: Define INCLUDE_LIST. Include "channels.h".
> > (gcc::context::context): Create m_channels.
> > (gcc::context::~context): Delete it.
> > * context.h (struct compiler_channels): New forward decl.
> > (gcc::context::get_channels): New accessor.
> > (gcc::context::m_channels): New field.
> > * passes.cc: Define INCLUDE_LIST. Include "topics/pass-
> > events.h"
> > and "channels.h".
> > (execute_one_pass): If the global context's
> > pass_events_channel
> > has subscribers, publish before_pass and after_pass events
> > to it.
> > * topics/pass-events.h: New file.
> >
> > gcc/testsuite/ChangeLog:
> > * gcc.dg/plugin/plugin.exp: Add
> > progress_notifications_plugin.cc.
> > * gcc.dg/plugin/progress_notifications_plugin.cc: New test
> > plugin.
>
> The only complaint I have is ...
>
> > ---
> > gcc/channels.h | 43 ++++++++++++++
> > gcc/context.cc | 7 ++-
> > gcc/context.h | 12 ++++
> > gcc/passes.cc | 12 ++++
> > gcc/testsuite/gcc.dg/plugin/plugin.exp | 1 +
> > .../plugin/progress_notifications_plugin.cc | 51
> > ++++++++++++++++
> > gcc/topics/pass-events.h | 59
> > +++++++++++++++++++
> > 7 files changed, 184 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/channels.h
> > create mode 100644
> > gcc/testsuite/gcc.dg/plugin/progress_notifications_plugin.cc
> > create mode 100644 gcc/topics/pass-events.h
> >
> > diff --git a/gcc/channels.h b/gcc/channels.h
> > new file mode 100644
> > index 0000000000000..433a1e7fcf62a
> > --- /dev/null
> > +++ b/gcc/channels.h
> > @@ -0,0 +1,43 @@
> > +/* channels.h - Publish/Subscribe channels on compiler-specific
> > topics.
> > + Copyright (C) 2025 Free Software Foundation, Inc.
> > + Contributed by David Malcolm <[email protected]>.
> > +
> > +This file is part of GCC.
> > +
> > +GCC is free software; you can redistribute it and/or modify it
> > under
> > +the terms of the GNU General Public License as published by the
> > Free
> > +Software Foundation; either version 3, or (at your option) any
> > later
> > +version.
> > +
> > +GCC is distributed in the hope that it will be useful, but WITHOUT
> > ANY
> > +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> > License
> > +for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3. If not see
> > +<http://www.gnu.org/licenses/>. */
> > +
> > +#ifndef GCC_CHANNELS_H
> > +#define GCC_CHANNELS_H
> > +
> > +#include "pub-sub.h"
> > +
> > +namespace gcc {
> > +
> > +/* Forward decls of subscribers for the various topics we have
> > + publish/subscribe channels for. */
> > +namespace topics {
> > + namespace pass_events { struct subscriber; }
> > +} // namespace gcc::topics
> > +
> > +/* Publish/subscribe channels on various compiler-specific
> > topics. */
> > +
> > +struct compiler_channels
> > +{
> > + pub_sub::channel<topics::pass_events::subscriber>
> > pass_events_channel;
> > +};
> > +
> > +} // namespace gcc
> > +
> > +#endif /* ! GCC_CHANNELS_H */
> > diff --git a/gcc/context.cc b/gcc/context.cc
> > index f31acc11460eb..cbd7f2bda48e0 100644
> > --- a/gcc/context.cc
> > +++ b/gcc/context.cc
> > @@ -17,6 +17,7 @@ You should have received a copy of the GNU
> > General Public License
> > along with GCC; see the file COPYING3. If not see
> > <http://www.gnu.org/licenses/>. */
> >
> > +#define INCLUDE_LIST
> > #include "config.h"
> > #include "system.h"
> > #include "coretypes.h"
> > @@ -24,12 +25,15 @@ along with GCC; see the file COPYING3. If not
> > see
> > #include "pass_manager.h"
> > #include "dumpfile.h"
> > #include "realmpfr.h"
> > +#include "channels.h"
> >
> > /* The singleton holder of global state: */
> > gcc::context *g;
> >
> > gcc::context::context ()
> > - : m_passes (NULL), m_dumps (new gcc::dump_manager ())
> > +: m_passes (NULL),
> > + m_dumps (new gcc::dump_manager ()),
> > + m_channels (new gcc::compiler_channels ())
> > {
> > have_offload = false;
> > }
> > @@ -38,6 +42,7 @@ gcc::context::~context ()
> > {
> > delete m_passes;
> > delete m_dumps;
> > + delete m_channels;
> >
> > /* Release MPFR caches to avoid Valgrind leak reports. */
> > mpfr_free_cache ();
> > diff --git a/gcc/context.h b/gcc/context.h
> > index 2220e517d0c50..e881d565676d1 100644
> > --- a/gcc/context.h
> > +++ b/gcc/context.h
> > @@ -24,6 +24,7 @@ namespace gcc {
> >
> > class pass_manager;
> > class dump_manager;
> > +struct compiler_channels;
> >
> > /* GCC's internal state can be divided into zero or more
> > "parallel universe" of state; an instance of this class is one
> > such
> > @@ -51,6 +52,15 @@ public:
> >
> > dump_manager *get_dumps () {gcc_assert (m_dumps); return
> > m_dumps; }
> >
> > + /* Publish/subscribe channels for events
> > + on various compiler-specific topics. */
> > + compiler_channels &
> > + get_channels () const
> > + {
> > + gcc_assert (m_channels);
> > + return *m_channels;
> > + }
> > +
> > private:
> > /* Pass-management. */
> > pass_manager *m_passes;
> > @@ -58,6 +68,8 @@ private:
> > /* Dump files. */
> > dump_manager *m_dumps;
> >
> > + compiler_channels *m_channels;
> > +
> > }; // class context
> >
> > } // namespace gcc
> > diff --git a/gcc/passes.cc b/gcc/passes.cc
> > index a33c8d924a52d..440852f12fabf 100644
> > --- a/gcc/passes.cc
> > +++ b/gcc/passes.cc
> > @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not
> > see
> > in the proper order, and counts the time used by each.
> > Error messages and low-level interface to malloc also handled
> > here. */
> >
> > +#define INCLUDE_LIST
> > #include "config.h"
> > #include "system.h"
> > #include "coretypes.h"
> > @@ -63,6 +64,8 @@ along with GCC; see the file COPYING3. If not
> > see
> > #include "diagnostic-core.h" /* for fnotice */
> > #include "stringpool.h"
> > #include "attribs.h"
> > +#include "topics/pass-events.h"
> > +#include "channels.h"
> >
> > /* Reserved TODOs */
> > #define TODO_verify_il (1u << 31)
> > @@ -2575,10 +2578,15 @@ skip_pass (opt_pass *pass)
> > bool
> > execute_one_pass (opt_pass *pass)
> > {
> > + namespace pass_events = gcc::topics::pass_events;
> You have this but then ...
>
> > +
> > unsigned int todo_after = 0;
> >
> > bool gate_status;
> >
> > + if (auto channel = g->get_channels
> > ().pass_events_channel.get_if_active ())
> > + channel->publish (gcc::topics::pass_events::before_pass {pass,
> > cfun});
>
> You write out the fully qualified name here. Should it just be
> pass_events::before_pass ?
Good catch; thanks. I fixed that and have pushed the series to trunk.
> Also maybe we should be able to do:
> ```
> if (auto channel = pass_events_channel_if_active (g))
> ```
> Which is slightly easier to write. Obviously it will be a wrapper for
> `g->get_channels ().pass_events_channel.get_if_active ()`.
Adding this requires a header that includes the topics, the channels,
and the global context, so I decided not to bother.
I verified the bootstrap, regression tests, and some light manually
testing, and have pushed the series as r16-6663-gb34dad6d185a2d through
r16-6666-gf68343c2543ab6.
Thanks
Dave
>
> Thanks,
> Andrew
>
> > +
> > /* IPA passes are executed on whole program, so cfun should be
> > NULL.
> > Other passes need function context set. */
> > if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
> > @@ -2741,6 +2749,10 @@ execute_one_pass (opt_pass *pass)
> >
> > if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
> > report_heap_memory_use ();
> > +
> > + if (auto channel = g->get_channels
> > ().pass_events_channel.get_if_active ())
> > + channel->publish (gcc::topics::pass_events::after_pass {pass,
> > cfun});
> > +
> > return true;
> > }
> >
> > diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp
> > b/gcc/testsuite/gcc.dg/plugin/plugin.exp
> > index 38991e8e6191a..b2812db5890ab 100644
> > --- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
> > +++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
> > @@ -201,6 +201,7 @@ set plugin_test_list [list \
> > cpython-plugin-test-PyList_Append.c \
> > cpython-plugin-test-PyList_New.c \
> > cpython-plugin-test-PyLong_FromLong.c } \
> > + { progress_notifications_plugin.cc } \
> > ]
> >
> > foreach plugin_test $plugin_test_list {
> > diff --git
> > a/gcc/testsuite/gcc.dg/plugin/progress_notifications_plugin.cc
> > b/gcc/testsuite/gcc.dg/plugin/progress_notifications_plugin.cc
> > new file mode 100644
> > index 0000000000000..e1fe2a54820f0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/plugin/progress_notifications_plugin.cc
> > @@ -0,0 +1,51 @@
> > +/* Toy implementation of progress notifications about the
> > compiler,
> > + using gcc::topics::pass_events. */
> > +
> > +#define INCLUDE_LIST
> > +#include "gcc-plugin.h"
> > +#include "config.h"
> > +#include "system.h"
> > +#include "coretypes.h"
> > +#include "tree-pass.h"
> > +#include "diagnostic-core.h"
> > +#include "context.h"
> > +#include "channels.h"
> > +#include "topics/pass-events.h"
> > +
> > +int plugin_is_GPL_compatible;
> > +
> > +namespace pass_events = gcc::topics::pass_events;
> > +
> > +namespace {
> > +
> > +class notification_event_subscriber : public
> > pass_events::subscriber
> > +{
> > +public:
> > + void on_message (const pass_events::before_pass &m) final
> > override
> > + {
> > + if (m.fun)
> > + inform (m.fun->function_start_locus, "starting pass %qs on
> > %qD",
> > + m.pass->name, m.fun->decl);
> > + else
> > + inform (UNKNOWN_LOCATION, "starting pass %qs", m.pass-
> > >name);
> > + }
> > + void on_message (const pass_events::after_pass &m) final
> > override
> > + {
> > + if (m.fun)
> > + inform (m.fun->function_end_locus, "finished pass %qs on
> > %qD",
> > + m.pass->name, m.fun->decl);
> > + else
> > + inform (UNKNOWN_LOCATION, "finished pass %qs", m.pass-
> > >name);
> > + }
> > +} my_event_subscriber;
> > +
> > +} // anonymous namespace
> > +
> > +int
> > +plugin_init (struct plugin_name_args *,
> > + struct plugin_gcc_version *)
> > +{
> > + g->get_channels ().pass_events_channel.add_subscriber
> > (my_event_subscriber);
> > +
> > + return 0;
> > +}
> > diff --git a/gcc/topics/pass-events.h b/gcc/topics/pass-events.h
> > new file mode 100644
> > index 0000000000000..2b072f65bc154
> > --- /dev/null
> > +++ b/gcc/topics/pass-events.h
> > @@ -0,0 +1,59 @@
> > +/* pass-events.h - pub/sub messages about GCC optimization passes.
> > + Copyright (C) 2025 Free Software Foundation, Inc.
> > +
> > +This file is part of GCC.
> > +
> > +GCC is free software; you can redistribute it and/or modify it
> > under
> > +the terms of the GNU General Public License as published by the
> > Free
> > +Software Foundation; either version 3, or (at your option) any
> > later
> > +version.
> > +
> > +GCC is distributed in the hope that it will be useful, but WITHOUT
> > ANY
> > +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> > License
> > +for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3. If not see
> > +<http://www.gnu.org/licenses/>. */
> > +
> > +#ifndef GCC_TOPICS_PASS_EVENTS_H
> > +#define GCC_TOPICS_PASS_EVENTS_H
> > +
> > +#include "pub-sub.h"
> > +
> > +namespace gcc {
> > +namespace topics {
> > +
> > +/* A topic for messages relating to GCC optimization passes. */
> > +
> > +namespace pass_events {
> > +
> > +struct before_pass
> > +{
> > + opt_pass *pass;
> > + function *fun;
> > +};
> > +
> > +struct after_pass
> > +{
> > + opt_pass *pass;
> > + function *fun;
> > +};
> > +
> > +/* Abstract base class for a subscriber to messages about
> > + GCC optimization passes. */
> > +
> > +struct subscriber
> > +{
> > + virtual ~subscriber () = default;
> > +
> > + virtual void on_message (const before_pass &) = 0;
> > + virtual void on_message (const after_pass &) = 0;
> > +};
> > +
> > +} // namespace gcc::topics::pass_events
> > +} // namespace gcc::topics
> > +} // namespace gcc
> > +
> > +#endif /* ! GCC_TOPICS_PASS_EVENTS_H */
> > --
> > 2.26.3
> >
>