Ticket #3843: ghc_plugins_support_2010_11_19.2.dpatch

File ghc_plugins_support_2010_11_19.2.dpatch, 34.0 KB (added by thoughtpolice, 3 years ago)

Patch implementing support for compiler plugins; dated 2010-11-19

Line 
11 patch for repository /home/a/src/ghc-head:
2
3Fri Nov 19 21:11:23 CST 2010  austin seipp <as@hacks.yi.org>
4  * Implement support for writing and loading plugins for GHC
5  Based on Max Bolingbroke's original patch for implementing plugin support in GHC,
6  which can be gotten from here: http://hackage.haskell.org/trac/ghc/ticket/3843
7 
8  A little bit of the linker interface changed and the simplifier interface changed
9  inbetween now and then. This patch brings most of the work Max did up to date although
10  there may be a few loose ends. The interface for plugins that rewrite core hasn't changed
11  (that is, most people will be writing passes of type [CoreBind] -> CoreM [CoreBind])
12 
13  Plugins are registered the same way as they were previously: plugin modules provide an installation
14  function of type [CoreToDo] -> CoreM [CoreToDo]
15 
16  Changes:
17   * -plg and -P flags replaced by -fplugin and -fplugin-arg (consistent with what GCC uses)
18 
19
20
21New patches:
22
23[Implement support for writing and loading plugins for GHC
24austin seipp <as@hacks.yi.org>**20101120031123
25 Ignore-this: 69e032420d3611fde37b6704b3e13c15
26 Based on Max Bolingbroke's original patch for implementing plugin support in GHC,
27 which can be gotten from here: http://hackage.haskell.org/trac/ghc/ticket/3843
28 
29 A little bit of the linker interface changed and the simplifier interface changed
30 inbetween now and then. This patch brings most of the work Max did up to date although
31 there may be a few loose ends. The interface for plugins that rewrite core hasn't changed
32 (that is, most people will be writing passes of type [CoreBind] -> CoreM [CoreBind])
33 
34 Plugins are registered the same way as they were previously: plugin modules provide an installation
35 function of type [CoreToDo] -> CoreM [CoreToDo]
36 
37 Changes:
38  * -plg and -P flags replaced by -fplugin and -fplugin-arg (consistent with what GCC uses)
39 
40] {
41hunk ./compiler/basicTypes/Module.lhs 42
42         dphSeqPackageId,
43         dphParPackageId,
44        mainPackageId,
45-
46+        thisGhcPackageId,
47+       
48        -- * The Module type
49        Module,
50        modulePackageId, moduleName,
51hunk ./compiler/basicTypes/Module.lhs 351
52 integerPackageId, primPackageId,
53   basePackageId, rtsPackageId,
54   thPackageId, dphSeqPackageId, dphParPackageId,
55-  mainPackageId  :: PackageId
56+  mainPackageId, thisGhcPackageId  :: PackageId
57 primPackageId      = fsToPackageId (fsLit "ghc-prim")
58 integerPackageId   = fsToPackageId (fsLit cIntegerLibrary)
59 basePackageId      = fsToPackageId (fsLit "base")
60hunk ./compiler/basicTypes/Module.lhs 359
61 thPackageId        = fsToPackageId (fsLit "template-haskell")
62 dphSeqPackageId    = fsToPackageId (fsLit "dph-seq")
63 dphParPackageId    = fsToPackageId (fsLit "dph-par")
64+thisGhcPackageId   = fsToPackageId (fsLit ("ghc-" ++ cProjectVersion))
65 
66 -- | This is the package Id for the current program.  It is the default
67 -- package Id if you don't specify a package name.  We don't add this prefix
68hunk ./compiler/ghc.cabal.in 325
69         ErrUtils
70         Finder
71         GHC
72+        Plugins
73+        GHCPlugins
74+        LoadPlugins
75+        DynamicLoading
76         HeaderInfo
77         HscMain
78         HscStats
79hunk ./compiler/ghci/Linker.lhs 18
80                linkExpr, unload, withExtendedLinkEnv,
81                 extendLinkEnv, deleteFromLinkEnv,
82                 extendLoadedPkgs,
83-               linkPackages,initDynLinker,
84-                dataConInfoPtrToName
85+               linkPackages,initDynLinker,linkModule,
86+                dataConInfoPtrToName, lessUnsafeCoerce
87        ) where
88 
89 #include "HsVersions.h"
90hunk ./compiler/ghci/Linker.lhs 58
91 import FastString
92 import Config
93 
94+import GHC.Exts (unsafeCoerce#)
95+
96 -- Standard libraries
97 import Control.Monad
98 
99hunk ./compiler/ghci/Linker.lhs 262
100 -- Throws a 'ProgramError' if loading fails or the name cannot be found.
101 getHValue :: HscEnv -> Name -> IO HValue
102 getHValue hsc_env name = do
103+  initDynLinker (hsc_dflags hsc_env)
104   pls <- modifyMVar v_PersistentLinkerState $ \pls -> do
105            if (isExternalName name) then do
106              (pls', ok) <- linkDependencies hsc_env pls noSrcSpan [nameModule name]
107hunk ./compiler/ghci/Linker.lhs 276
108                  -> SrcSpan -> [Module]
109                  -> IO (PersistentLinkerState, SuccessFlag)
110 linkDependencies hsc_env pls span needed_mods = do
111+--   initDynLinker (hsc_dflags hsc_env)
112    let hpt = hsc_HPT hsc_env
113        dflags = hsc_dflags hsc_env
114        -- The interpreter and dynamic linker can only handle object code built
115hunk ./compiler/ghci/Linker.lhs 696
116            adjust_ul _ _ = panic "adjust_ul"
117 \end{code}
118 
119+%************************************************************************
120+%*                                                                     *
121+              Loading a single module
122+%*                                                                     *
123+%************************************************************************
124+\begin{code}
125+
126+-- | Link a single module
127+linkModule :: HscEnv -> Module -> IO ()
128+linkModule hsc_env mod = do
129+  initDynLinker (hsc_dflags hsc_env)
130+  modifyMVar v_PersistentLinkerState $ \pls -> do
131+    (pls', ok) <- linkDependencies hsc_env pls noSrcSpan [mod]
132+    if (failed ok) then ghcError (ProgramError "")
133+      else return (pls',())
134+
135+-- | Coerce a value as usual, but:
136+--
137+-- 1) Evaluate it immediately to get a segfault early if the coercion was wrong
138+--
139+-- 2) Wrap it in some debug messages at verbosity 3 or higher so we can see what happened
140+--    if it /does/ segfault
141+lessUnsafeCoerce :: DynFlags -> String -> a -> IO b
142+lessUnsafeCoerce dflags context what = do
143+    debugTraceMsg dflags 3 $ (ptext $ sLit "Coercing a value in") <+> (text context) <> (ptext $ sLit "...")
144+    output <- evaluate (unsafeCoerce# what)
145+    debugTraceMsg dflags 3 $ ptext $ sLit "Successfully evaluated coercion"
146+    return output
147+
148+
149+
150+\end{code}
151 
152 %************************************************************************
153 %*                                                                     *
154hunk ./compiler/ghci/Linker.lhs 1029
155 linkPackages dflags new_pkgs = do
156   -- It's probably not safe to try to load packages concurrently, so we take
157   -- a lock.
158+  initDynLinker dflags
159   modifyMVar_ v_PersistentLinkerState $ \pls -> do
160     linkPackages' dflags new_pkgs pls
161 
162hunk ./compiler/main/DynFlags.hs 139
163    | Opt_D_dump_occur_anal
164    | Opt_D_dump_parsed
165    | Opt_D_dump_rn
166+   | Opt_D_dump_core_pipeline -- TODO FIXME: dump after simplifier stats
167    | Opt_D_dump_simpl
168    | Opt_D_dump_simpl_iterations
169    | Opt_D_dump_simpl_phases
170hunk ./compiler/main/DynFlags.hs 446
171 
172   hpcDir                :: String,      -- ^ Path to store the .mix files
173 
174+  -- Plugins
175+  pluginModNames        :: [ModuleName],
176+  pluginModNameOpts     :: [(ModuleName,String)],
177+
178   -- options for particular phases
179   opt_L                 :: [String],
180   opt_P                 :: [String],
181hunk ./compiler/main/DynFlags.hs 686
182         hcSuf                   = phaseInputExt HCc,
183         hiSuf                   = "hi",
184 
185+        pluginModNames          = [],
186+        pluginModNameOpts       = [],
187+
188         outputFile              = Nothing,
189         outputHi                = Nothing,
190         dynLibLoader            = SystemDependent,
191hunk ./compiler/main/DynFlags.hs 899
192 setOutputFile f d = d{ outputFile = f}
193 setOutputHi   f d = d{ outputHi   = f}
194 
195+addPluginModuleName :: String -> DynFlags -> DynFlags
196+addPluginModuleName name d = d { pluginModNames = (mkModuleName name) : (pluginModNames d) }
197+
198+addPluginModuleNameOption :: String -> DynFlags -> DynFlags
199+addPluginModuleNameOption optflag d = d { pluginModNameOpts = (mkModuleName m, option) : (pluginModNameOpts d) }
200+  where (m, rest) = break (== ':') optflag
201+        option = case rest of
202+          [] -> "" -- should probably signal an error
203+          (_:plug_opt) -> plug_opt -- ignore the ':' from break
204+
205 parseDynLibLoaderMode f d =
206  case splitAt 8 f of
207    ("deploy", "")       -> d{ dynLibLoader = Deployable }
208hunk ./compiler/main/DynFlags.hs 1252
209   , Flag "ddump-occur-anal"        (setDumpFlag Opt_D_dump_occur_anal)
210   , Flag "ddump-parsed"            (setDumpFlag Opt_D_dump_parsed)
211   , Flag "ddump-rn"                (setDumpFlag Opt_D_dump_rn)
212+  , Flag "ddump-core-pipeline"     (setDumpFlag Opt_D_dump_core_pipeline)
213   , Flag "ddump-simpl"             (setDumpFlag Opt_D_dump_simpl)
214   , Flag "ddump-simpl-iterations"  (setDumpFlag Opt_D_dump_simpl_iterations)
215   , Flag "ddump-simpl-phases"      (OptPrefix setDumpSimplPhases)
216hunk ./compiler/main/DynFlags.hs 1309
217   , Flag "Wnot"   (NoArg (do { mapM_ unSetDynFlag minusWallOpts
218                              ; deprecate "Use -w instead" }))
219   , Flag "w"      (NoArg (mapM_ unSetDynFlag minuswRemovesOpts))
220-
221+       
222+        ------ Plugin flags ------------------------------------------------
223+  , Flag "fplugin"     (hasArg addPluginModuleName)
224+  , Flag "fplugin-opt" (hasArg addPluginModuleNameOption)
225+   
226         ------ Optimisation flags ------------------------------------------
227   , Flag "O"      (noArg (setOptLevel 1))
228   , Flag "Onot"   (noArgDF (setOptLevel 0) "Use -O0 instead")
229addfile ./compiler/main/DynamicLoading.hs
230hunk ./compiler/main/DynamicLoading.hs 1
231+-- | Dynamically lookup up values from modules and loading them.
232+module DynamicLoading (
233+#ifdef GHCI
234+        -- * Force loading information
235+        forceLoadModuleInterfaces,
236+        forceLoadNameModuleInterface,
237+        forceLoadTyCon,
238+       
239+        -- * Finding names
240+        lookupRdrNameInModule,
241+       
242+        -- * Loading values
243+        getValueSafely,
244+        lessUnsafeCoerce
245+#endif
246+    ) where
247+
248+#ifdef GHCI
249+import Linker           ( linkModule, getHValue, lessUnsafeCoerce )
250+import OccName          ( occNameSpace )
251+import Name             ( nameOccName )
252+import SrcLoc           ( noSrcSpan )
253+import Finder           ( findImportedModule, cannotFindModule )
254+import DriverPhases     ( HscSource(HsSrcFile) )
255+import TcRnDriver       ( getModuleExports )
256+import TcRnMonad        ( initTc, initIfaceTcRn )
257+import LoadIface        ( loadUserInterface )
258+import RdrName          ( RdrName, Provenance(..), ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..),
259+                          mkGlobalRdrEnv, lookupGRE_RdrName, gre_name, rdrNameSpace )
260+import RnNames          ( gresFromAvails )
261+import PrelNames        ( iNTERACTIVE )
262+
263+import HscTypes         ( HscEnv(..), FindResult(..), lookupTypeHscEnv )
264+import TypeRep          ( TyThing(..), pprTyThingCategory )
265+import Type             ( Type, coreEqType )
266+import TyCon            ( TyCon )
267+import Name             ( Name, nameModule_maybe )
268+import Id               ( idType )
269+import Module           ( Module, ModuleName )
270+import Panic            ( GhcException(..), throwGhcException )
271+import FastString
272+import Outputable
273+
274+import Data.Maybe        ( mapMaybe )
275+
276+
277+-- | Force the interfaces for the given modules to be loaded. The 'SDoc' parameter is used
278+-- for debugging (@-ddump-if-trace@) only: it is shown as the reason why the module is being loaded.
279+forceLoadModuleInterfaces :: HscEnv -> SDoc -> [Module] -> IO ()
280+forceLoadModuleInterfaces hsc_env doc modules
281+    = (initTc hsc_env HsSrcFile False iNTERACTIVE $ initIfaceTcRn $ mapM_ (loadUserInterface False doc) modules) >> return ()
282+
283+-- | Force the interface for the module containing the name to be loaded. The 'SDoc' parameter is used
284+-- for debugging (@-ddump-if-trace@) only: it is shown as the reason why the module is being loaded.
285+forceLoadNameModuleInterface :: HscEnv -> SDoc -> Name -> IO ()
286+forceLoadNameModuleInterface hsc_env reason name = do
287+    let name_modules = mapMaybe nameModule_maybe [name]
288+    forceLoadModuleInterfaces hsc_env reason name_modules
289+
290+-- | Load the 'TyCon' associated with the given name, come hell or high water. Fails if:
291+--
292+-- * The interface could not be loaded
293+-- * The name is not that of a 'TyCon'
294+-- * The name did not exist in the loaded module
295+forceLoadTyCon :: HscEnv -> Name -> IO TyCon
296+forceLoadTyCon hsc_env con_name = do
297+    forceLoadNameModuleInterface hsc_env (ptext (sLit "contains a name used in an invocation of loadTyConTy")) con_name
298+   
299+    mb_con_thing <- lookupTypeHscEnv hsc_env con_name
300+    case mb_con_thing of
301+        Nothing -> throwCmdLineErrorS $ missingTyThingError con_name
302+        Just (ATyCon tycon) -> return tycon
303+        Just con_thing -> throwCmdLineErrorS $ wrongTyThingError con_name con_thing
304+
305+-- | Loads the value corresponding to a 'Name' if that value has the given 'Type'. This only provides limited safety
306+-- in that it is up to the user to ensure that that type corresponds to the type you try to use the return value at!
307+--
308+-- If the value found was not of the correct type, returns @Nothing@. Any other condition results in an exception:
309+--
310+-- * If we could not load the names module
311+-- * If the thing being loaded is not a value
312+-- * If the Name does not exist in the module
313+-- * If the link failed
314+
315+getValueSafely :: HscEnv -> Name -> Type -> IO (Maybe a)
316+getValueSafely hsc_env val_name expected_type = do
317+    forceLoadNameModuleInterface hsc_env (ptext (sLit "contains a name used in an invocation of getValueSafely")) val_name
318+   
319+    -- Now look up the names for the value and type constructor in the type environment
320+    mb_val_thing <- lookupTypeHscEnv hsc_env val_name
321+    case mb_val_thing of
322+        Nothing -> throwCmdLineErrorS $ missingTyThingError val_name
323+        Just (AnId id) -> do
324+            -- Check the value type in the interface against the type recovered from the type constructor
325+            -- before finally casting the value to the type we assume corresponds to that constructor
326+            if expected_type `coreEqType` idType id
327+             then do
328+                -- Link in the module that contains the value, if it has such a module
329+                case nameModule_maybe val_name of
330+                    Just mod -> do linkModule hsc_env mod
331+                                   return ()
332+                    Nothing ->  return ()
333+                -- Find the value that we just linked in and cast it given that we have proved it's type
334+                hval <- getHValue hsc_env val_name
335+                value <- lessUnsafeCoerce (hsc_dflags hsc_env) "getValueSafely" hval
336+                return $ Just value
337+             else return Nothing
338+        Just val_thing -> throwCmdLineErrorS $ wrongTyThingError val_name val_thing
339+
340+-- | Finds the 'Name' corresponding to the given 'RdrName' in the context of the 'ModuleName'. Returns @Nothing@ if no
341+-- such 'Name' could be found. Any other condition results in an exception:
342+--
343+-- * If the module could not be found
344+-- * If we could not determine the imports of the module
345+lookupRdrNameInModule :: HscEnv -> ModuleName -> RdrName -> IO (Maybe Name)
346+lookupRdrNameInModule hsc_env mod_name rdr_name = do
347+    -- First find the package the module resides in by searching exposed packages and home modules
348+    found_module <- findImportedModule hsc_env mod_name Nothing
349+    case found_module of
350+        Found _ mod -> do
351+            -- Find the exports of the module
352+            (_, mb_avail_info) <- getModuleExports hsc_env mod
353+            case mb_avail_info of
354+                Just avail_info -> do
355+                    -- Try and find the required name in the exports
356+                    let decl_spec = ImpDeclSpec { is_mod = mod_name, is_as = mod_name, is_qual = False, is_dloc = noSrcSpan }
357+                        provenance = Imported [ImpSpec decl_spec ImpAll]
358+                        env = mkGlobalRdrEnv (gresFromAvails provenance avail_info)
359+                    case [name | gre <- lookupGRE_RdrName rdr_name env, let name = gre_name gre, rdrNameSpace rdr_name == occNameSpace (nameOccName name)] of
360+                        [name] -> return (Just name)
361+                        []     -> return Nothing
362+                        _      -> panic "lookupRdrNameInModule"
363+                Nothing -> throwCmdLineErrorS $ hsep [ptext (sLit "Could not determine the exports of the module"), ppr mod_name]
364+        err -> throwCmdLineErrorS $ cannotFindModule dflags mod_name err
365+  where
366+    dflags = hsc_dflags hsc_env
367+
368+
369+wrongTyThingError :: Name -> TyThing -> SDoc
370+wrongTyThingError name got_thing = hsep [ptext (sLit "The name"), ppr name, ptext (sLit "is not that of a value but rather a"), pprTyThingCategory got_thing]
371+
372+missingTyThingError :: Name -> SDoc
373+missingTyThingError name = hsep [ptext (sLit "The name"), ppr name, ptext (sLit "is not in the type environment: are you sure it exists?")]
374+
375+throwCmdLineErrorS :: SDoc -> IO a
376+throwCmdLineErrorS = throwCmdLineError . showSDoc
377+
378+throwCmdLineError :: String -> IO a
379+throwCmdLineError = throwGhcException . CmdLineError
380+#endif
381addfile ./compiler/main/GHCPlugins.hs
382hunk ./compiler/main/GHCPlugins.hs 1
383+{-# OPTIONS_GHC -fno-warn-duplicate-exports #-}
384+
385+-- | Re-exports all of the functions and types you are likely to need when
386+-- writing a plugin for GHC. Particularly interesting modules for plugin writers
387+-- include "Plugins", "CoreSyn" and "CoreMonad".
388+module GHCPlugins(
389+#ifdef GHCI
390+        -- This must be under #ifdef GHCI since it exports nothing when GHCI is disabled and hence generates a warning
391+        module Plugins,
392+#endif
393+        module CoreMonad,
394+        module RdrName, module OccName, module Name, module Var, module Id, module IdInfo,
395+        module CoreSyn, module Literal, module DataCon, module CoreUtils, module MkCore, module CoreFVs, module CoreSubst,
396+        module Rules, module Annotations,
397+        module DynFlags, module Packages,
398+        module Module, module Type, module TyCon, module Coercion, module TysWiredIn, module HscTypes, module BasicTypes,
399+        module VarSet, module VarEnv, module NameSet, module NameEnv, module UniqSet, module UniqFM, module FiniteMap,
400+        module Util, module Serialized, module SrcLoc, module Outputable, module UniqSupply, module Unique, module FastString, module FastTypes
401+    ) where
402+
403+-- Plugin stuff itself
404+#ifdef GHCI
405+-- As with the export
406+import Plugins
407+#endif
408+import CoreMonad
409+
410+-- Variable naming
411+import RdrName
412+import OccName  hiding  ( varName {- conflicts with Var.varName -} )
413+import Name     hiding  ( varName {- reexport from OccName, conflicts with Var.varName -} )
414+import Var
415+import Id       hiding  ( lazySetIdInfo, setIdExported, setIdNotExported {- all three conflict with Var -} )
416+import IdInfo
417+
418+-- Core
419+import CoreSyn
420+import Literal
421+import DataCon
422+import CoreUtils
423+import MkCore
424+import CoreFVs
425+import CoreSubst
426+
427+-- Core "extras"
428+import Rules
429+import Annotations
430+
431+-- Pipeline-related stuff
432+import DynFlags
433+import Packages
434+
435+-- Important GHC types
436+import Module
437+import Type     hiding ( substTy, extendTvSubst, extendTvSubstList, isInScope {- conflict with CoreSubst -} )
438+import TyCon
439+import Coercion
440+import TysWiredIn
441+import HscTypes
442+import BasicTypes hiding ( Version {- conflicts with Packages.Version -} )
443+
444+-- Collections and maps
445+import VarSet
446+import VarEnv
447+import NameSet
448+import NameEnv
449+import UniqSet
450+import UniqFM
451+-- Conflicts with UniqFM:
452+--import LazyUniqFM
453+import FiniteMap
454+
455+-- Common utilities
456+import Util
457+import Serialized
458+import SrcLoc
459+import Outputable
460+import UniqSupply
461+import Unique           ( Unique, Uniquable(..) )
462+import FastString
463+import FastTypes
464addfile ./compiler/main/LoadPlugins.lhs
465hunk ./compiler/main/LoadPlugins.lhs 1
466+%
467+% (c) The GRASP/AQUA Project, Glasgow University, 1993-2008
468+%
469+\begin{code}
470+
471+-- | Code relating purely to the administration of plugins, i.e. no code that would actually
472+-- be useful to plugins!
473+module LoadPlugins (
474+#ifdef GHCI
475+        loadPlugins
476+#endif
477+    ) where
478+
479+#ifdef GHCI
480+import DynamicLoading
481+
482+import OccName          ( mkVarOcc )
483+import RdrName          ( mkRdrQual )
484+
485+import DynFlags         ( DynFlags, pluginModNames )
486+import HscTypes         ( HscEnv(..) )
487+import Type             ( mkTyConTy )
488+import PrelNames        ( pluginTyConName )
489+import Module           ( ModuleName )
490+import Panic            ( GhcException(..), throwGhcException )
491+import FastString
492+import Outputable
493+
494+import Plugins
495+\end{code}
496+
497+\begin{code}
498+loadPlugins :: HscEnv -> IO [(ModuleName, Plugin)]
499+loadPlugins hsc_env = do
500+    let to_load = pluginModNames dflags
501+    plugins <- mapM (loadPlugin hsc_env) to_load
502+    return $ to_load `zip` plugins
503+  where dflags = hsc_dflags hsc_env
504+
505+loadPlugin :: HscEnv -> ModuleName -> IO Plugin
506+loadPlugin hsc_env mod_name = do
507+    mb_name <- lookupRdrNameInModule hsc_env mod_name plugin_rdr_name
508+    case mb_name of
509+      Nothing -> throwGhcException (CmdLineError $ showSDoc $ hsep [
510+                                         ptext (sLit "The module"), ppr mod_name
511+                                       , ptext (sLit "did not export the plugin name"), ppr plugin_rdr_name
512+                                       ])
513+      Just name -> do
514+        plugin_tycon <- forceLoadTyCon hsc_env pluginTyConName
515+        mb_plugin <- getValueSafely hsc_env name (mkTyConTy plugin_tycon)
516+        case mb_plugin of
517+          Nothing -> throwGhcException (CmdLineError $ showSDoc $ hsep [
518+                                             ptext (sLit "The value"), ppr name, ptext (sLit "did not have the type")
519+                                           , ppr pluginTyConName, ptext (sLit "as required")])
520+          Just plugin -> return plugin
521+  where plugin_rdr_name = mkRdrQual mod_name (mkVarOcc "plugin")
522+
523+#endif
524+\end{code}
525addfile ./compiler/main/Plugins.lhs
526hunk ./compiler/main/Plugins.lhs 1
527+%
528+% (c) The GRASP/AQUA Project, Glasgow University, 1993-2008
529+%
530+
531+\section[Plugins]{Plugins for GHC}
532+\begin{code}
533+
534+-- | Contains code and definitions that are used by both the compiler and the plugins themselves. All the
535+-- functions likely to be useful for plugins are exported from 'GHCPlugins'.
536+module Plugins (
537+#ifdef GHCI
538+        -- * Plugin data types
539+       Plugin(..), CommandLineOption, defaultPlugin,
540+       PluginPass(..),
541+#endif
542+  ) where
543+
544+#ifdef GHCI
545+import HscTypes
546+import CoreSyn          ( CoreBind )
547+import CoreMonad
548+\end{code}
549+
550+\subsection{Essential data type}
551+
552+\begin{code}
553+-- | The kinds of core pass a plugin can install
554+data PluginPass = BindsToBindsPluginPass ([CoreBind] -> CoreM [CoreBind]) -- ^ Simple pass just mutating the Core bindings
555+                | ModGutsToBindsPluginPass (ModGuts -> CoreM [CoreBind])  -- ^ Pass that has access to the information from a 'ModGuts'
556+                                                                          -- from which to generate it's bindings
557+                | ModGutsToModGutsPluginPass (ModGuts -> CoreM ModGuts)   -- ^ Pass that can change everything about the module being compiled.
558+                                                                          -- Do not change any field other than 'HscTypes.mg_binds' unless you
559+                                                                          -- know what you're doing! Plugins using this are unlikely to be stable
560+                                                                          -- between GHC versions
561+
562+-- | Command line options gathered from the -PModule.Name:stuff syntax are given to you as this type
563+type CommandLineOption = String
564+
565+-- | Core compiler plugin data type. Try to avoid constructing one of these
566+-- directly, and just modify some fields of 'defaultPlugin' instead: this
567+-- is to try and preserve source-code compatability when we add fields to this.
568+--
569+-- Nonetheless, this API is preliminary and highly likely to change in the future.
570+data Plugin = Plugin {
571+        installCoreToDos :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
572+                -- ^ Modify the Core pipeline that will be used for compilation. This is called as the Core pipeline is built for every module being compiled,
573+                -- and plugins get the opportunity to modify the pipeline in a nondeterministic order.
574+}
575+
576+-- | Default plugin: does nothing at all! For compatability reasons you should base all your
577+-- plugin definitions on this default value.
578+defaultPlugin :: Plugin
579+defaultPlugin = Plugin {
580+        installCoreToDos = const return
581+}
582+#endif
583+\end{code}
584addfile ./compiler/main/Plugins.lhs-boot
585hunk ./compiler/main/Plugins.lhs-boot 1
586+\begin{code}
587+module Plugins where
588+
589+data Plugin
590+data PluginPass
591+\end{code}
592hunk ./compiler/prelude/PrelNames.lhs 220
593        -- The Either type
594        , eitherTyConName, leftDataConName, rightDataConName
595 
596+        -- Plugins
597+        , pluginTyConName
598+                                           
599        -- dotnet interop
600        , objectTyConName, marshalObjectName, unmarshalObjectName
601        , marshalStringName, unmarshalStringName, checkDotnetResName
602hunk ./compiler/prelude/PrelNames.lhs 254
603     gHC_ST, gHC_ARR, gHC_STABLE, gHC_ADDR, gHC_PTR, gHC_ERR, gHC_REAL,
604     gHC_FLOAT, gHC_TOP_HANDLER, sYSTEM_IO, dYNAMIC, tYPEABLE, gENERICS,
605     dOTNET, rEAD_PREC, lEX, gHC_INT, gHC_WORD, mONAD, mONAD_FIX, aRROW, cONTROL_APPLICATIVE,
606-    gHC_DESUGAR, rANDOM, gHC_EXTS, cONTROL_EXCEPTION_BASE :: Module
607+    gHC_DESUGAR, rANDOM, gHC_EXTS, cONTROL_EXCEPTION_BASE, pLUGINS :: Module
608 
609 gHC_PRIM       = mkPrimModule (fsLit "GHC.Prim")   -- Primitive types and values
610 gHC_TYPES       = mkPrimModule (fsLit "GHC.Types")
611hunk ./compiler/prelude/PrelNames.lhs 309
612 rANDOM         = mkBaseModule (fsLit "System.Random")
613 gHC_EXTS       = mkBaseModule (fsLit "GHC.Exts")
614 cONTROL_EXCEPTION_BASE = mkBaseModule (fsLit "Control.Exception.Base")
615+pLUGINS         = mkThisGhcModule (fsLit "Plugins")
616 
617 mAIN, rOOT_MAIN :: Module
618 mAIN           = mkMainModule_ mAIN_NAME
619hunk ./compiler/prelude/PrelNames.lhs 338
620 mkBaseModule_ :: ModuleName -> Module
621 mkBaseModule_ m = mkModule basePackageId m
622 
623+mkThisGhcModule :: FastString -> Module
624+mkThisGhcModule m = mkModule thisGhcPackageId (mkModuleNameFS m)
625+
626+mkThisGhcModule_ :: ModuleName -> Module
627+mkThisGhcModule_ m = mkModule thisGhcPackageId m
628+
629 mkMainModule :: FastString -> Module
630 mkMainModule m = mkModule mainPackageId (mkModuleNameFS m)
631 
632hunk ./compiler/prelude/PrelNames.lhs 848
633 marshalStringName   = varQual  dOTNET (fsLit "marshalString") marshalStringIdKey
634 unmarshalStringName = varQual  dOTNET (fsLit "unmarshalString") unmarshalStringIdKey
635 checkDotnetResName  = varQual  dOTNET (fsLit "checkResult")     checkDotnetResNameIdKey
636+
637+-- plugins
638+pluginTyConName :: Name
639+pluginTyConName = tcQual pLUGINS (fsLit "Plugin") pluginTyConKey
640+
641+
642 \end{code}
643 
644 %************************************************************************
645hunk ./compiler/prelude/PrelNames.lhs 1082
646 stringTyConKey :: Unique
647 stringTyConKey                         = mkPreludeTyConUnique 134
648 
649+pluginTyConKey :: Unique
650+pluginTyConKey                          = mkPreludeTyConUnique 135
651+
652 ---------------- Template Haskell -------------------
653 --     USES TyConUniques 100-129
654 -----------------------------------------------------
655hunk ./compiler/simplCore/CoreMonad.lhs 16
656     FloatOutSwitches(..),
657     getCoreToDo, dumpSimplPhase,
658 
659+    defaultGentleSimplToDo,
660+   
661     -- * Counting
662     SimplCount, doSimplTick, doFreeSimplTick, simplCountN,
663     pprSimplCount, plusSimplCount, zeroSimplCount, isZeroSimplCount, Tick(..),
664hunk ./compiler/simplCore/CoreMonad.lhs 99
665 #ifdef GHCI
666 import {-# SOURCE #-} TcSplice ( lookupThName_maybe )
667 import qualified Language.Haskell.TH as TH
668+
669+import {-# SOURCE #-} Plugins
670 #endif
671 \end{code}
672 
673hunk ./compiler/simplCore/CoreMonad.lhs 205
674 %************************************************************************
675 
676 \begin{code}
677+
678 data CoreToDo           -- These are diff core-to-core passes,
679                         -- which may be invoked in any order,
680                         -- as many times as you like.
681hunk ./compiler/simplCore/CoreMonad.lhs 213
682   = CoreDoSimplify      -- The core-to-core simplifier.
683         Int                    -- Max iterations
684         SimplifierMode
685-
686+#ifdef GHCI
687+  | CoreDoPluginPass String PluginPass
688+#endif
689   | CoreDoFloatInwards
690   | CoreDoFloatOutwards FloatOutSwitches
691   | CoreLiberateCase
692hunk ./compiler/simplCore/CoreMonad.lhs 241
693 
694 coreDumpFlag :: CoreToDo -> Maybe DynFlag
695 coreDumpFlag (CoreDoSimplify {})      = Just Opt_D_dump_simpl_phases
696+#ifdef GHCI
697+coreDumpFlag (CoreDoPluginPass {})    = Just Opt_D_dump_core_pipeline
698+#endif
699 coreDumpFlag CoreDoFloatInwards       = Just Opt_D_verbose_core2core
700 coreDumpFlag (CoreDoFloatOutwards {}) = Just Opt_D_verbose_core2core
701 coreDumpFlag CoreLiberateCase         = Just Opt_D_verbose_core2core
702hunk ./compiler/simplCore/CoreMonad.lhs 268
703   ppr (CoreDoSimplify n md)  = ptext (sLit "Simplifier")
704                                <+> ppr md
705                                  <+> ptext (sLit "max-iterations=") <> int n
706+#ifdef GHCI 
707+  ppr (CoreDoPluginPass desc _) = ptext (sLit "Core plugin: ") <+> ptext (sLit desc)
708+#endif
709   ppr CoreDoFloatInwards       = ptext (sLit "Float inwards")
710   ppr (CoreDoFloatOutwards f)  = ptext (sLit "Float out") <> parens (ppr f)
711   ppr CoreLiberateCase         = ptext (sLit "Liberate case")
712hunk ./compiler/simplCore/CoreMonad.lhs 531
713         simpl_phase 0 ["final"] max_iter
714      ]
715 
716+-- | A reasonably gentle simplification pass for doing "obvious" simplifications
717+defaultGentleSimplToDo :: CoreToDo
718+defaultGentleSimplToDo = CoreDoSimplify 4 -- 4 is the default maxSimpleIterations
719+                       (SimplMode { sm_phase = InitialPhase
720+                                  , sm_names = ["Gentle"]
721+                                  , sm_rules = True     -- Note [RULEs enabled in SimplGently]
722+                                  , sm_inline = False
723+                                  , sm_eta_expand = False
724+                                  , sm_case_case = False
725+                                  })
726+
727 -- The core-to-core pass ordering is derived from the DynFlags:
728 runWhen :: Bool -> CoreToDo -> CoreToDo
729 runWhen True  do_this = do_this
730hunk ./compiler/simplCore/CoreMonad.lhs 551
731 runMaybe (Just x) f = f x
732 runMaybe Nothing  _ = CoreDoNothing
733 
734+
735 dumpSimplPhase :: DynFlags -> SimplifierMode -> Bool
736 dumpSimplPhase dflags mode
737    | Just spec_string <- shouldDumpSimplPhase dflags
738hunk ./compiler/simplCore/SimplCore.lhs 11
739 
740 #include "HsVersions.h"
741 
742-import DynFlags                ( DynFlags, DynFlag(..), dopt )
743+import DynFlags                ( DynFlags, DynFlag(..), dopt)
744+#ifdef GHCI
745+import DynFlags         ( pluginModNameOpts )
746+#endif
747 import CoreSyn
748 import CoreSubst
749 import HscTypes
750hunk ./compiler/simplCore/SimplCore.lhs 51
751 import UniqSupply      ( UniqSupply, mkSplitUniqSupply, splitUniqSupply )
752 import Outputable
753 import Control.Monad
754+
755+#ifdef GHCI
756+import Plugins
757+import LoadPlugins      ( loadPlugins )
758+#endif
759+
760 \end{code}
761 
762 %************************************************************************
763hunk ./compiler/simplCore/SimplCore.lhs 69
764 core2core :: HscEnv -> ModGuts -> IO ModGuts
765 core2core hsc_env guts
766   = do { us <- mkSplitUniqSupply 's'
767-       ; (guts2, stats) <- runCoreM hsc_env hpt_rule_base us mod $
768-                           doCorePasses (getCoreToDo dflags) guts
769+       -- make sure all plugins are loaded
770+#ifdef GHCI
771+      ; named_plugins <- loadPlugins hsc_env
772+#endif
773+       ; (guts2, stats) <- runCoreM hsc_env hpt_rule_base us mod
774+         (do { let builtin_passes = getCoreToDo dflags
775+#ifdef GHCI
776+             ; let queryPlugin todos (mod_nm,plug) = installCoreToDos plug options todos
777+                     where options = [ option | (opt_mod_nm, option) <- pluginModNameOpts dflags
778+                                              , opt_mod_nm == mod_nm ]
779+             ; all_passes <- foldM queryPlugin builtin_passes named_plugins
780+#else
781+             ; let all_passes = builtin_passes
782+#endif
783+             ; doCorePasses all_passes guts })
784 
785hunk ./compiler/simplCore/SimplCore.lhs 85
786+{--                           
787+       ; Err.dumpIfSet_dyn dflags Opt_D_dump_core_pipeline
788+             "Plugin information" "" -- TODO FIXME: dump plugin info
789+--}
790        ; Err.dumpIfSet_dyn dflags Opt_D_dump_simpl_stats
791              "Grand total simplifier statistics"
792              (pprSimplCount stats)
793hunk ./compiler/simplCore/SimplCore.lhs 160
794 doCorePass (CoreDoRuleCheck phase pat)  = ruleCheck phase pat
795 doCorePass CoreDoNothing                = return
796 doCorePass (CoreDoPasses passes)        = doCorePasses passes
797+#ifdef GHCI
798+doCorePass (CoreDoPluginPass _ pass) = {-# SCC "Plugin" #-}
799+                                          doPluginPass pass
800+   where doPluginPass (BindsToBindsPluginPass p)     = doPassM p
801+         doPluginPass (ModGutsToBindsPluginPass p)   = doPassMG p
802+         doPluginPass (ModGutsToModGutsPluginPass p) = p
803+#endif
804 doCorePass pass = pprPanic "doCorePass" (ppr pass)
805hunk ./compiler/simplCore/SimplCore.lhs 168
806+
807 \end{code}
808 
809 %************************************************************************
810hunk ./compiler/simplCore/SimplCore.lhs 215
811     binds' <- bind_f (mg_binds guts)
812     return (guts { mg_binds = binds' })
813 
814+#ifdef GHCI
815+-- Only used by ModGutsToBindsPluginPass - it seems it was removed from when
816+-- max originally wrote this patch. Do we still need/want this?
817+doPassMG :: Monad m => (ModGuts -> m [CoreBind]) -> ModGuts -> m ModGuts
818+doPassMG bind_f guts = do
819+  binds' <- bind_f guts
820+  return (guts { mg_binds = binds' })
821+#endif
822+
823 doPass :: ([CoreBind] -> [CoreBind]) -> ModGuts -> CoreM ModGuts
824 doPass bind_f guts = return $ guts { mg_binds = bind_f (mg_binds guts) }
825 
826}
827
828Context:
829
830[ForceSpecConstr now forces specialisation even for arguments which aren't scrutinised
831Roman Leshchinskiy <rl@cse.unsw.edu.au>**20101118212839
832 Ignore-this: db45721d29a694e53746f8b76513efa4
833]
834[Move the superclass generation to the canonicaliser
835simonpj@microsoft.com**20101118120533
836 Ignore-this: 5e0e525402a240b709f2b8104c1682b2
837 
838 Doing superclass generation in the canonicaliser (rather than
839 TcInteract) uses less code, and is generally more efficient.
840 
841 See Note [Adding superclasses] in TcCanonical.
842 
843 Fixes Trac #4497.
844]
845[Fix the generation of in-scope variables for IfaceLint check
846simonpj@microsoft.com**20101118090057
847 Ignore-this: bbcdba61ddf89d07fe69ca99c2017e3f
848]
849[Comments only
850simonpj@microsoft.com**20101118090034
851 Ignore-this: fa2936d35a0f7be4e4535ea9e2b7bf7b
852]
853[Omit bogus test for -XDeriveFunctor
854simonpj@microsoft.com**20101118090028
855 Ignore-this: a534243011809ebbb788b910961601c5
856 
857 It was duplicated in the case of 'deriving( Functor )'
858 and wrong for 'deriving( Foldable )'
859]
860[Improve error message on advice from a user
861simonpj@microsoft.com**20101118085306
862 Ignore-this: bd4f3858ff24e602e985288f27d536f3
863 
864 See Trac #4499
865]
866[TAG 2010-11-18
867Ian Lynagh <igloo@earth.li>**20101118011554
868 Ignore-this: ccadbe7fadd1148d2ee3caa8c8821ec5
869]
870Patch bundle hash:
8718e29c13db1f759715cdf1233fd2d8f0f5c19b322