[Git][ghc/ghc][wip/24254] Document late plugins

Finley McIlwaine (@FinleyMcIlwaine) gitlab at gitlab.haskell.org
Fri Dec 15 20:24:09 UTC 2023



Finley McIlwaine pushed to branch wip/24254 at Glasgow Haskell Compiler / GHC


Commits:
ebd44d14 by Finley McIlwaine at 2023-12-15T12:23:18-08:00
Document late plugins

- - - - -


4 changed files:

- compiler/GHC/Driver/Plugins.hs
- docs/users_guide/9.10.1-notes.rst
- docs/users_guide/extending_ghc.rst
- testsuite/tests/plugins/late-plugin/LatePlugin.hs


Changes:

=====================================
compiler/GHC/Driver/Plugins.hs
=====================================
@@ -167,6 +167,8 @@ data Plugin = Plugin {
     -- ^ A plugin that runs after interface creation and after late cost centre
     -- insertion. Useful for transformations that should not impact interfaces
     -- or optimization at all.
+    --
+    -- @since 9.10.1
 
   , pluginRecompile :: [CommandLineOption] -> IO PluginRecompile
     -- ^ Specify how the plugin should affect recompilation.


=====================================
docs/users_guide/9.10.1-notes.rst
=====================================
@@ -126,6 +126,9 @@ Compiler
 - The :ghc-flag:`-Wforall-identifier` flag is now deprecated and removed from :ghc-flag:`-Wdefault`,
   as ``forall`` is no longer parsed as an identifier.
 
+- Late plugins have been added. These are plugins which can access and/or modify
+  the core of a module after optimization and after interface creation. See :ghc-ticket:`24254`.
+
 GHCi
 ~~~~
 


=====================================
docs/users_guide/extending_ghc.rst
=====================================
@@ -510,6 +510,58 @@ in a module it compiles:
               return bndr
             printBind _ bndr = return bndr
 
+.. _late-plugins:
+
+Late Plugins
+^^^^^^^^^^^^
+
+If the ``CoreProgram`` of a module is modified in a normal core plugin, the
+modified bindings can end up in unfoldings the interface file for the module.
+This may be undesireable, as the plugin could make changes which affect inlining
+or optimization.
+
+Late plugins can be used to avoid introducing such changes into the interface
+file. Late plugins are a bit different from typical core plugins:
+
+1. They do not run in the ``CoreM`` monad. Instead, they are explicitly passed
+   the ``HscEnv`` and they run in ``IO``.
+2. They are given ``CgGuts`` instead of ``ModGuts``. ``CgGuts`` are a restricted
+   form of ``ModGuts`` intended for code generation. The ``CoreProgram`` held in
+   the ``CgGuts`` given to a late plugin will already be fully optimized.
+3. They must maintain a ``CostCentreState`` and track any cost centres they
+   introduce by adding them to the ``cg_ccs`` field of ``CgGuts``. This is
+   because the automatic collection of cost centres happens before the late
+   plugin stage. If a late plugin does not introduce any cost centres, it may
+   simply return the given cost centre state.
+
+Here is a very simply example of a late plugin that changes the value of a
+binding in a module. If it finds a non-recursive top-level binding named
+``testBinding`` with type ``Int``, it will change its value to the ``Int``
+expression ``111111``.
+
+::
+
+    plugin :: Plugin
+    plugin = defaultPlugin { latePlugin = lateP }
+
+    lateP :: LatePlugin
+    lateP _ _ (cg_guts, cc_state) = do
+        binds' <- editCoreBinding (cg_binds cg_guts)
+        return (cg_guts { cg_binds = binds' }, cc_state)
+
+    editCoreBinding :: CoreProgram -> IO CoreProgram
+    editCoreBinding pgm = pure . go
+      where
+        go :: [CoreBind] -> [CoreBind]
+        go (b@(NonRec v e) : bs)
+          | occNameString (getOccName v) == "testBinding" && exprType e `eqType` intTy =
+              NonRec v (mkUncheckedIntExpr 111111) : bs
+        go (b:bs) = b : go bs
+        go [] = []
+
+Since this is a late plugin, the changed binding value will not end up in the
+interface file.
+
 .. _getting-annotations:
 
 Using Annotations


=====================================
testsuite/tests/plugins/late-plugin/LatePlugin.hs
=====================================
@@ -2,6 +2,7 @@ module LatePlugin where
 
 import Data.Bool
 import GHC.Core
+import GHC.Core.TyCo.Compare
 import GHC.Driver.Monad
 import GHC.Plugins
 import GHC.Types.Avail
@@ -43,7 +44,7 @@ editCoreBinding early modName pgm = do
   where
     go :: [CoreBind] -> [CoreBind]
     go (b@(NonRec v e) : bs)
-      | occNameString (getOccName v) == "testBinding" =
+      | occNameString (getOccName v) == "testBinding" && exprType e `eqType` intTy =
           NonRec v (mkUncheckedIntExpr $ bool 222222 111111 early) : bs
     go (b:bs) = b : go bs
     go [] = []



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ebd44d1455a46c4316094fdaddb0a7962e6733f0

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ebd44d1455a46c4316094fdaddb0a7962e6733f0
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20231215/8c106b14/attachment-0001.html>


More information about the ghc-commits mailing list