Skip to content
Snippets Groups Projects
Commit 7c29da9f authored by Finley McIlwaine's avatar Finley McIlwaine
Browse files

Document late plugins

parent be4551ac
No related branches found
No related tags found
No related merge requests found
......@@ -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.
......
......@@ -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
~~~~
......
......@@ -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
......
......@@ -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 [] = []
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment