wiki:NewPlugins

Version 48 (modified by nomeata, 21 months ago) (diff)

Fix link

See also the section on Compiler Plugins in GHC's User's Guide.

New Plugins work

Plugins are a new feature in GHC 7.2.1 that allows users to write compiler passes (for things like optimizations) over GHC's internal intermediate language, Core.

GHC understands the -fplugin and -fplugin-arg options. You essentially install plugins for GHC by cabal installing them, as they expose a module implementing an interface, and then calling GHC in the form of:

$ ghc -fplugin=Some.Plugin.Module -fplugin-opt=Some.Plugin.Module:no-fizzbuzz a.hs

Some.Plugin.Module should export a symbol named 'plugin' - see the following repositories for examples that do Common Subexpression Elimination, turn Haskell into a strict language, and implement a loop unroller:

https://github.com/thoughtpolice/cse-ghc-plugin

https://github.com/thoughtpolice/strict-ghc-plugin

https://github.com/thoughtpolice/unroll-ghc-plugin

Basic overview of the plugins API for Core

Modules can be loaded by GHC as compiler plugins by exposing a declaration called 'plugin' of type Plugin, which is an ADT containing a function that installs a pass into the Core pipeline.

module Some.Plugin.Module (plugin) where
import GhcPlugins

plugin :: Plugin
plugin = defaultPlugin {
  installCoreToDos = install
}


-- type CommandLineOption = String

install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install _options passes = do
  ...


We can think of CoreToDo as being a type synonym for (Core -> Core) - that is, the install function just inserts its own CoreToDo into the list of compiler passes. For example, the CSE pass actually couples a simplification pass, followed by CSE itself into the front of the compilation pipeline:

module CSE.Plugin where

...

install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install _ xs = return $ CoreDoPasses [defaultGentleSimplToDo, cse] : xs
  where cse = CoreDoPluginPass "Common Subexpression Elimination" (bindsOnlyPass cseProgram)

cseProgram :: [CoreBind] -> CoreM [CoreBind]
cseProgram binds = do
  ...

More specifically, a CoreToDo describes some sort of particular pass over a Core program that can be invoked as many times as you like. For reference, defaultGentlSimplToDo is constructed using CoreDoSimplify. In this case, cse_pass is constructed using CoreDoPluginsPass, which takes a name and a function of type ModGuts -> CoreM ModGuts - ModGuts is a type that represents the 1 module GHC is compiling at any time. You normally want to manipulate the field mg_binds of a ModGuts, which contains all the top-level bindings for the module.

bindsOnlyPass is a function that merely lifts a function over binders to a function over ModGuts. It's the simple case where nothing else from the ModGuts is needed.

More details on plugins for end-users can be found in the users guide.

The Future

Plugins for Cmm

Aside from manipulating the core language, we would also like to manipulate the C-- representation GHC generates for modules too.

TODO fixme

Rough API possibilities

TODO fixme