packages feed

ghc-lib 9.6.2.20230523 → 9.6.2.20231121

raw patch · 23 files changed

+6/−5510 lines, 23 filesdep ~containersdep ~deepseqdep ~ghc-lib-parserPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: containers, deepseq, ghc-lib-parser

API changes (from Hackage documentation)

- GHC.Cmm.Reducibility: Irreducible :: Reducibility
- GHC.Cmm.Reducibility: Reducible :: Reducibility
- GHC.Cmm.Reducibility: asReducible :: GraphWithDominators CmmNode -> UniqSM (GraphWithDominators CmmNode)
- GHC.Cmm.Reducibility: data Reducibility
- GHC.Cmm.Reducibility: instance GHC.Base.Semigroup GHC.Cmm.Reducibility.CmmSuper
- GHC.Cmm.Reducibility: instance GHC.Classes.Eq GHC.Cmm.Reducibility.Reducibility
- GHC.Cmm.Reducibility: instance GHC.Data.Graph.Collapse.PureSupernode GHC.Cmm.Reducibility.CmmSuper
- GHC.Cmm.Reducibility: instance GHC.Data.Graph.Collapse.Supernode GHC.Cmm.Reducibility.CmmSuper GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Cmm.Reducibility: instance GHC.Show.Show GHC.Cmm.Reducibility.Reducibility
- GHC.Cmm.Reducibility: reducibility :: NonLocal node => GraphWithDominators node -> Reducibility
- GHC.CmmToAsm.Reg.Graph.Base: ClassF64 :: RegClass
- GHC.CmmToAsm.Reg.Graph.Base: ClassG16 :: RegClass
- GHC.CmmToAsm.Reg.Graph.Base: ClassG32 :: RegClass
- GHC.CmmToAsm.Reg.Graph.Base: ClassG8 :: RegClass
- GHC.CmmToAsm.Reg.Graph.Base: Reg :: RegClass -> Int -> Reg
- GHC.CmmToAsm.Reg.Graph.Base: RegSub :: RegSub -> Reg -> Reg
- GHC.CmmToAsm.Reg.Graph.Base: SubL16 :: RegSub
- GHC.CmmToAsm.Reg.Graph.Base: SubL8 :: RegSub
- GHC.CmmToAsm.Reg.Graph.Base: SubL8H :: RegSub
- GHC.CmmToAsm.Reg.Graph.Base: bound :: (RegClass -> UniqSet Reg) -> (Reg -> UniqSet Reg) -> RegClass -> [RegClass] -> Int
- GHC.CmmToAsm.Reg.Graph.Base: data Reg
- GHC.CmmToAsm.Reg.Graph.Base: data RegClass
- GHC.CmmToAsm.Reg.Graph.Base: data RegSub
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Classes.Eq GHC.CmmToAsm.Reg.Graph.Base.Reg
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Classes.Eq GHC.CmmToAsm.Reg.Graph.Base.RegClass
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Classes.Eq GHC.CmmToAsm.Reg.Graph.Base.RegSub
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Classes.Ord GHC.CmmToAsm.Reg.Graph.Base.RegSub
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Enum.Enum GHC.CmmToAsm.Reg.Graph.Base.RegClass
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Enum.Enum GHC.CmmToAsm.Reg.Graph.Base.RegSub
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Show.Show GHC.CmmToAsm.Reg.Graph.Base.Reg
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Show.Show GHC.CmmToAsm.Reg.Graph.Base.RegClass
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Show.Show GHC.CmmToAsm.Reg.Graph.Base.RegSub
- GHC.CmmToAsm.Reg.Graph.Base: instance GHC.Types.Unique.Uniquable GHC.CmmToAsm.Reg.Graph.Base.Reg
- GHC.CmmToAsm.Reg.Graph.Base: squeese :: (RegClass -> UniqSet Reg) -> (Reg -> UniqSet Reg) -> RegClass -> [(Int, RegClass)] -> Int
- GHC.CmmToAsm.Reg.Graph.Base: worst :: (RegClass -> UniqSet Reg) -> (Reg -> UniqSet Reg) -> Int -> RegClass -> RegClass -> Int
- GHC.CmmToAsm.Reg.Graph.Coalesce: regCoalesce :: Instruction instr => [LiveCmmDecl statics instr] -> UniqSM [LiveCmmDecl statics instr]
- GHC.CmmToAsm.Reg.Graph.Coalesce: slurpJoinMovs :: Instruction instr => LiveCmmDecl statics instr -> Bag (Reg, Reg)
- GHC.CmmToAsm.Reg.Graph.X86: classOfReg :: Reg -> RegClass
- GHC.CmmToAsm.Reg.Graph.X86: regAlias :: Reg -> UniqSet Reg
- GHC.CmmToAsm.Reg.Graph.X86: regName :: Reg -> Maybe String
- GHC.CmmToAsm.Reg.Graph.X86: regsOfClass :: RegClass -> UniqSet Reg
- GHC.CmmToAsm.Reg.Graph.X86: squeese :: RegClass -> [(Int, RegClass)] -> Int
- GHC.CmmToAsm.Reg.Graph.X86: worst :: Int -> RegClass -> RegClass -> Int
- GHC.Data.Graph.Collapse: NullCollapseViz :: UniqSM a -> NullCollapseViz a
- GHC.Data.Graph.Collapse: [unNCV] :: NullCollapseViz a -> UniqSM a
- GHC.Data.Graph.Collapse: class (Monad m) => MonadUniqSM m
- GHC.Data.Graph.Collapse: class (Semigroup node) => PureSupernode node
- GHC.Data.Graph.Collapse: class (MonadUnique m, PureSupernode node) => Supernode node m
- GHC.Data.Graph.Collapse: class (MonadUniqSM m, Graph gr, Supernode s m) => VizCollapseMonad m gr s
- GHC.Data.Graph.Collapse: collapseInductiveGraph :: (DynGraph gr, Supernode s m, VizCollapseMonad m gr s) => gr s () -> m (gr s ())
- GHC.Data.Graph.Collapse: consumeByInGraph :: VizCollapseMonad m gr s => Node -> Node -> gr s () -> m ()
- GHC.Data.Graph.Collapse: finalGraph :: VizCollapseMonad m gr s => gr s () -> m ()
- GHC.Data.Graph.Collapse: freshen :: Supernode node m => node -> m node
- GHC.Data.Graph.Collapse: instance (GHC.Data.Graph.Inductive.Graph.Graph gr, GHC.Data.Graph.Collapse.Supernode s GHC.Data.Graph.Collapse.NullCollapseViz) => GHC.Data.Graph.Collapse.VizCollapseMonad GHC.Data.Graph.Collapse.NullCollapseViz gr s
- GHC.Data.Graph.Collapse: instance GHC.Base.Applicative GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Data.Graph.Collapse: instance GHC.Base.Functor GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Data.Graph.Collapse: instance GHC.Base.Monad GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Data.Graph.Collapse: instance GHC.Data.Graph.Collapse.MonadUniqSM GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Data.Graph.Collapse: instance GHC.Types.Unique.Supply.MonadUnique GHC.Data.Graph.Collapse.NullCollapseViz
- GHC.Data.Graph.Collapse: liftUniqSM :: MonadUniqSM m => UniqSM a -> m a
- GHC.Data.Graph.Collapse: mapLabels :: PureSupernode node => (Label -> Label) -> node -> node
- GHC.Data.Graph.Collapse: newtype NullCollapseViz a
- GHC.Data.Graph.Collapse: runNullCollapse :: NullCollapseViz a -> UniqSM a
- GHC.Data.Graph.Collapse: splitGraphAt :: VizCollapseMonad m gr s => gr s () -> LNode s -> m ()
- GHC.Data.Graph.Collapse: superLabel :: PureSupernode node => node -> Label
- GHC.Data.Graph.Inductive.Graph: (&) :: DynGraph gr => Context a b -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: LP :: [LNode a] -> LPath a
- GHC.Data.Graph.Inductive.Graph: OrdGr :: gr a b -> OrdGr gr a b
- GHC.Data.Graph.Inductive.Graph: [unLPath] :: LPath a -> [LNode a]
- GHC.Data.Graph.Inductive.Graph: [unOrdGr] :: OrdGr gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: buildGr :: DynGraph gr => [Context a b] -> gr a b
- GHC.Data.Graph.Inductive.Graph: class (Graph gr) => DynGraph gr
- GHC.Data.Graph.Inductive.Graph: class Graph gr
- GHC.Data.Graph.Inductive.Graph: context :: Graph gr => gr a b -> Node -> Context a b
- GHC.Data.Graph.Inductive.Graph: deg :: Graph gr => gr a b -> Node -> Int
- GHC.Data.Graph.Inductive.Graph: deg' :: Context a b -> Int
- GHC.Data.Graph.Inductive.Graph: delAllLEdge :: (DynGraph gr, Eq b) => LEdge b -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: delEdge :: DynGraph gr => Edge -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: delEdges :: DynGraph gr => [Edge] -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: delLEdge :: (DynGraph gr, Eq b) => LEdge b -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: delNode :: Graph gr => Node -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: delNodes :: Graph gr => [Node] -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: edgeLabel :: LEdge b -> b
- GHC.Data.Graph.Inductive.Graph: edges :: Graph gr => gr a b -> [Edge]
- GHC.Data.Graph.Inductive.Graph: emap :: DynGraph gr => (b -> c) -> gr a b -> gr a c
- GHC.Data.Graph.Inductive.Graph: empty :: Graph gr => gr a b
- GHC.Data.Graph.Inductive.Graph: equal :: (Eq a, Eq b, Graph gr) => gr a b -> gr a b -> Bool
- GHC.Data.Graph.Inductive.Graph: gelem :: Graph gr => Node -> gr a b -> Bool
- GHC.Data.Graph.Inductive.Graph: gfiltermap :: DynGraph gr => (Context a b -> MContext c d) -> gr a b -> gr c d
- GHC.Data.Graph.Inductive.Graph: gmap :: DynGraph gr => (Context a b -> Context c d) -> gr a b -> gr c d
- GHC.Data.Graph.Inductive.Graph: hasEdge :: Graph gr => gr a b -> Edge -> Bool
- GHC.Data.Graph.Inductive.Graph: hasLEdge :: (Graph gr, Eq b) => gr a b -> LEdge b -> Bool
- GHC.Data.Graph.Inductive.Graph: hasNeighbor :: Graph gr => gr a b -> Node -> Node -> Bool
- GHC.Data.Graph.Inductive.Graph: hasNeighborAdj :: (Graph gr, Eq b) => gr a b -> Node -> (b, Node) -> Bool
- GHC.Data.Graph.Inductive.Graph: indeg :: Graph gr => gr a b -> Node -> Int
- GHC.Data.Graph.Inductive.Graph: indeg' :: Context a b -> Int
- GHC.Data.Graph.Inductive.Graph: inn :: Graph gr => gr a b -> Node -> [LEdge b]
- GHC.Data.Graph.Inductive.Graph: inn' :: Context a b -> [LEdge b]
- GHC.Data.Graph.Inductive.Graph: insEdge :: DynGraph gr => LEdge b -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: insEdges :: DynGraph gr => [LEdge b] -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: insNode :: DynGraph gr => LNode a -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: insNodes :: DynGraph gr => [LNode a] -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: instance (GHC.Data.Graph.Inductive.Graph.Graph gr, GHC.Classes.Ord a, GHC.Classes.Ord b) => GHC.Classes.Eq (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Data.Graph.Inductive.Graph: instance (GHC.Data.Graph.Inductive.Graph.Graph gr, GHC.Classes.Ord a, GHC.Classes.Ord b) => GHC.Classes.Ord (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Classes.Eq a => GHC.Classes.Eq (GHC.Data.Graph.Inductive.Graph.LPath a)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Classes.Eq b => GHC.Classes.Eq (GHC.Data.Graph.Inductive.Graph.GroupEdges b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Classes.Ord a => GHC.Classes.Ord (GHC.Data.Graph.Inductive.Graph.LPath a)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Read.Read (gr a b) => GHC.Read.Read (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Read.Read b => GHC.Read.Read (GHC.Data.Graph.Inductive.Graph.GroupEdges b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Show.Show (gr a b) => GHC.Show.Show (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Show.Show a => GHC.Show.Show (GHC.Data.Graph.Inductive.Graph.LPath a)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Show.Show b => GHC.Show.Show (GHC.Data.Graph.Inductive.Graph.GroupEdges b)
- GHC.Data.Graph.Inductive.Graph: isEmpty :: Graph gr => gr a b -> Bool
- GHC.Data.Graph.Inductive.Graph: lab :: Graph gr => gr a b -> Node -> Maybe a
- GHC.Data.Graph.Inductive.Graph: lab' :: Context a b -> a
- GHC.Data.Graph.Inductive.Graph: labEdges :: Graph gr => gr a b -> [LEdge b]
- GHC.Data.Graph.Inductive.Graph: labNode' :: Context a b -> LNode a
- GHC.Data.Graph.Inductive.Graph: labNodes :: Graph gr => gr a b -> [LNode a]
- GHC.Data.Graph.Inductive.Graph: labfilter :: DynGraph gr => (a -> Bool) -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: labnfilter :: Graph gr => (LNode a -> Bool) -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: lneighbors :: Graph gr => gr a b -> Node -> Adj b
- GHC.Data.Graph.Inductive.Graph: lneighbors' :: Context a b -> Adj b
- GHC.Data.Graph.Inductive.Graph: lpre :: Graph gr => gr a b -> Node -> [(Node, b)]
- GHC.Data.Graph.Inductive.Graph: lpre' :: Context a b -> [(Node, b)]
- GHC.Data.Graph.Inductive.Graph: lsuc :: Graph gr => gr a b -> Node -> [(Node, b)]
- GHC.Data.Graph.Inductive.Graph: lsuc' :: Context a b -> [(Node, b)]
- GHC.Data.Graph.Inductive.Graph: match :: Graph gr => Node -> gr a b -> Decomp gr a b
- GHC.Data.Graph.Inductive.Graph: matchAny :: Graph gr => gr a b -> GDecomp gr a b
- GHC.Data.Graph.Inductive.Graph: mkGraph :: Graph gr => [LNode a] -> [LEdge b] -> gr a b
- GHC.Data.Graph.Inductive.Graph: mkUGraph :: Graph gr => [Node] -> [Edge] -> gr () ()
- GHC.Data.Graph.Inductive.Graph: neighbors :: Graph gr => gr a b -> Node -> [Node]
- GHC.Data.Graph.Inductive.Graph: neighbors' :: Context a b -> [Node]
- GHC.Data.Graph.Inductive.Graph: nemap :: DynGraph gr => (a -> c) -> (b -> d) -> gr a b -> gr c d
- GHC.Data.Graph.Inductive.Graph: newNodes :: Graph gr => Int -> gr a b -> [Node]
- GHC.Data.Graph.Inductive.Graph: newtype LPath a
- GHC.Data.Graph.Inductive.Graph: newtype OrdGr gr a b
- GHC.Data.Graph.Inductive.Graph: nfilter :: DynGraph gr => (Node -> Bool) -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: nmap :: DynGraph gr => (a -> c) -> gr a b -> gr c b
- GHC.Data.Graph.Inductive.Graph: noNodes :: Graph gr => gr a b -> Int
- GHC.Data.Graph.Inductive.Graph: node' :: Context a b -> Node
- GHC.Data.Graph.Inductive.Graph: nodeRange :: Graph gr => gr a b -> (Node, Node)
- GHC.Data.Graph.Inductive.Graph: nodes :: Graph gr => gr a b -> [Node]
- GHC.Data.Graph.Inductive.Graph: order :: Graph gr => gr a b -> Int
- GHC.Data.Graph.Inductive.Graph: out :: Graph gr => gr a b -> Node -> [LEdge b]
- GHC.Data.Graph.Inductive.Graph: out' :: Context a b -> [LEdge b]
- GHC.Data.Graph.Inductive.Graph: outdeg :: Graph gr => gr a b -> Node -> Int
- GHC.Data.Graph.Inductive.Graph: outdeg' :: Context a b -> Int
- GHC.Data.Graph.Inductive.Graph: pre :: Graph gr => gr a b -> Node -> [Node]
- GHC.Data.Graph.Inductive.Graph: pre' :: Context a b -> [Node]
- GHC.Data.Graph.Inductive.Graph: prettify :: (DynGraph gr, Show a, Show b) => gr a b -> String
- GHC.Data.Graph.Inductive.Graph: prettyPrint :: (DynGraph gr, Show a, Show b) => gr a b -> IO ()
- GHC.Data.Graph.Inductive.Graph: size :: Graph gr => gr a b -> Int
- GHC.Data.Graph.Inductive.Graph: subgraph :: DynGraph gr => [Node] -> gr a b -> gr a b
- GHC.Data.Graph.Inductive.Graph: suc :: Graph gr => gr a b -> Node -> [Node]
- GHC.Data.Graph.Inductive.Graph: suc' :: Context a b -> [Node]
- GHC.Data.Graph.Inductive.Graph: toEdge :: LEdge b -> Edge
- GHC.Data.Graph.Inductive.Graph: toLEdge :: Edge -> b -> LEdge b
- GHC.Data.Graph.Inductive.Graph: type Adj b = [(b, Node)]
- GHC.Data.Graph.Inductive.Graph: type Context a b = (Adj b, Node, a, Adj b)
- GHC.Data.Graph.Inductive.Graph: type Decomp g a b = (MContext a b, g a b)
- GHC.Data.Graph.Inductive.Graph: type Edge = (Node, Node)
- GHC.Data.Graph.Inductive.Graph: type GDecomp g a b = (Context a b, g a b)
- GHC.Data.Graph.Inductive.Graph: type LEdge b = (Node, Node, b)
- GHC.Data.Graph.Inductive.Graph: type LNode a = (Node, a)
- GHC.Data.Graph.Inductive.Graph: type MContext a b = Maybe (Context a b)
- GHC.Data.Graph.Inductive.Graph: type Node = Int
- GHC.Data.Graph.Inductive.Graph: type Path = [Node]
- GHC.Data.Graph.Inductive.Graph: type UContext = ([Node], Node, [Node])
- GHC.Data.Graph.Inductive.Graph: type UDecomp g = (Maybe UContext, g)
- GHC.Data.Graph.Inductive.Graph: type UEdge = LEdge ()
- GHC.Data.Graph.Inductive.Graph: type UNode = LNode ()
- GHC.Data.Graph.Inductive.Graph: type UPath = [UNode]
- GHC.Data.Graph.Inductive.Graph: ufold :: Graph gr => (Context a b -> c -> c) -> c -> gr a b -> c
- GHC.Data.Graph.Inductive.PatriciaTree: data Gr a b
- GHC.Data.Graph.Inductive.PatriciaTree: instance (GHC.Classes.Eq a, GHC.Classes.Ord b) => GHC.Classes.Eq (GHC.Data.Graph.Inductive.PatriciaTree.Gr a b)
- GHC.Data.Graph.Inductive.PatriciaTree: instance (GHC.Read.Read a, GHC.Read.Read b) => GHC.Read.Read (GHC.Data.Graph.Inductive.PatriciaTree.Gr a b)
- GHC.Data.Graph.Inductive.PatriciaTree: instance (GHC.Show.Show a, GHC.Show.Show b) => GHC.Show.Show (GHC.Data.Graph.Inductive.PatriciaTree.Gr a b)
- GHC.Data.Graph.Inductive.PatriciaTree: instance Data.Bifunctor.Bifunctor GHC.Data.Graph.Inductive.PatriciaTree.Gr
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Base.Functor (GHC.Data.Graph.Inductive.PatriciaTree.Gr a)
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Classes.Eq a => GHC.Classes.Eq (GHC.Data.Graph.Inductive.PatriciaTree.FromListCounting a)
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Data.Graph.Inductive.Graph.DynGraph GHC.Data.Graph.Inductive.PatriciaTree.Gr
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Data.Graph.Inductive.Graph.Graph GHC.Data.Graph.Inductive.PatriciaTree.Gr
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Generics.Generic (GHC.Data.Graph.Inductive.PatriciaTree.Gr a b)
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Read.Read a => GHC.Read.Read (GHC.Data.Graph.Inductive.PatriciaTree.FromListCounting a)
- GHC.Data.Graph.Inductive.PatriciaTree: instance GHC.Show.Show a => GHC.Show.Show (GHC.Data.Graph.Inductive.PatriciaTree.FromListCounting a)
- GHC.Data.Graph.Inductive.PatriciaTree: type UGr = Gr () ()
- GHC.Driver.Backpack: doBackpack :: [FilePath] -> Ghc ()
- GHC.Driver.Backpack: instance GHC.Classes.Eq GHC.Driver.Backpack.SessionType
- GHC.Driver.Backpack: instance GHC.Driver.Monad.GhcMonad GHC.Driver.Backpack.BkpM
- GHC.Driver.Backpack: instance GHC.Driver.Session.HasDynFlags GHC.Driver.Backpack.BkpM
- GHC.Driver.Backpack: instance GHC.Utils.Logger.HasLogger GHC.Driver.Backpack.BkpM
- GHC.Driver.MakeFile: doMkDependHS :: GhcMonad m => [FilePath] -> m ()
- GHC.HandleEncoding: configureHandleEncoding :: IO ()
- GHC.Runtime.Debugger: pprTypeAndContents :: GhcMonad m => Id -> m SDoc
- GHC.Runtime.Debugger: pprintClosureCommand :: GhcMonad m => Bool -> Bool -> String -> m ()
- GHC.Runtime.Debugger: showTerm :: GhcMonad m => Term -> m SDoc
- GHC.Tc.Plugin: Found :: ModLocation -> Module -> FindResult
- GHC.Tc.Plugin: FoundMultiple :: [(Module, ModuleOrigin)] -> FindResult
- GHC.Tc.Plugin: NoPackage :: Unit -> FindResult
- GHC.Tc.Plugin: NotFound :: [FilePath] -> Maybe Unit -> [Unit] -> [Unit] -> [(Unit, UnusableUnitReason)] -> [ModuleSuggestion] -> FindResult
- GHC.Tc.Plugin: [fr_mods_hidden] :: FindResult -> [Unit]
- GHC.Tc.Plugin: [fr_paths] :: FindResult -> [FilePath]
- GHC.Tc.Plugin: [fr_pkg] :: FindResult -> Maybe Unit
- GHC.Tc.Plugin: [fr_pkgs_hidden] :: FindResult -> [Unit]
- GHC.Tc.Plugin: [fr_suggestions] :: FindResult -> [ModuleSuggestion]
- GHC.Tc.Plugin: [fr_unusables] :: FindResult -> [(Unit, UnusableUnitReason)]
- GHC.Tc.Plugin: data FindResult
- GHC.Tc.Plugin: data TcPluginM a
- GHC.Tc.Plugin: findImportedModule :: ModuleName -> PkgQual -> TcPluginM FindResult
- GHC.Tc.Plugin: getEnvs :: TcPluginM (TcGblEnv, TcLclEnv)
- GHC.Tc.Plugin: getFamInstEnvs :: TcPluginM (FamInstEnv, FamInstEnv)
- GHC.Tc.Plugin: getInstEnvs :: TcPluginM InstEnvs
- GHC.Tc.Plugin: getTargetPlatform :: TcPluginM Platform
- GHC.Tc.Plugin: getTopEnv :: TcPluginM HscEnv
- GHC.Tc.Plugin: isTouchableTcPluginM :: TcTyVar -> TcPluginM Bool
- GHC.Tc.Plugin: lookupOrig :: Module -> OccName -> TcPluginM Name
- GHC.Tc.Plugin: matchFam :: TyCon -> [Type] -> TcPluginM (Maybe Reduction)
- GHC.Tc.Plugin: newCoercionHole :: PredType -> TcPluginM CoercionHole
- GHC.Tc.Plugin: newEvVar :: PredType -> TcPluginM EvVar
- GHC.Tc.Plugin: newFlexiTyVar :: Kind -> TcPluginM TcTyVar
- GHC.Tc.Plugin: newGiven :: EvBindsVar -> CtLoc -> PredType -> EvExpr -> TcPluginM CtEvidence
- GHC.Tc.Plugin: newUnique :: TcPluginM Unique
- GHC.Tc.Plugin: newWanted :: CtLoc -> PredType -> TcPluginM CtEvidence
- GHC.Tc.Plugin: setEvBind :: EvBindsVar -> EvBind -> TcPluginM ()
- GHC.Tc.Plugin: tcLookup :: Name -> TcPluginM TcTyThing
- GHC.Tc.Plugin: tcLookupClass :: Name -> TcPluginM Class
- GHC.Tc.Plugin: tcLookupDataCon :: Name -> TcPluginM DataCon
- GHC.Tc.Plugin: tcLookupGlobal :: Name -> TcPluginM TyThing
- GHC.Tc.Plugin: tcLookupId :: Name -> TcPluginM Id
- GHC.Tc.Plugin: tcLookupTyCon :: Name -> TcPluginM TyCon
- GHC.Tc.Plugin: tcPluginIO :: IO a -> TcPluginM a
- GHC.Tc.Plugin: tcPluginTrace :: String -> SDoc -> TcPluginM ()
- GHC.Tc.Plugin: unsafeTcPluginTcM :: TcM a -> TcPluginM a
- GHC.Tc.Plugin: zonkCt :: Ct -> TcPluginM Ct
- GHC.Tc.Plugin: zonkTcType :: TcType -> TcPluginM TcType
- GHCi.CreateBCO: createBCOs :: [ResolvedBCO] -> IO [HValueRef]
- GHCi.InfoTable: mkConInfoTable :: Bool -> Int -> Int -> Int -> Int -> ByteString -> IO (Ptr StgInfoTable)
- GHCi.ObjLink: DontRetainCAFs :: ShouldRetainCAFs
- GHCi.ObjLink: RetainCAFs :: ShouldRetainCAFs
- GHCi.ObjLink: addLibrarySearchPath :: String -> IO (Ptr ())
- GHCi.ObjLink: data ShouldRetainCAFs
- GHCi.ObjLink: findSystemLibrary :: String -> IO (Maybe String)
- GHCi.ObjLink: initObjLinker :: ShouldRetainCAFs -> IO ()
- GHCi.ObjLink: loadArchive :: String -> IO ()
- GHCi.ObjLink: loadDLL :: String -> IO (Maybe String)
- GHCi.ObjLink: loadObj :: String -> IO ()
- GHCi.ObjLink: lookupClosure :: String -> IO (Maybe HValueRef)
- GHCi.ObjLink: lookupSymbol :: String -> IO (Maybe (Ptr a))
- GHCi.ObjLink: purgeObj :: String -> IO ()
- GHCi.ObjLink: removeLibrarySearchPath :: Ptr () -> IO Bool
- GHCi.ObjLink: resolveObjs :: IO Bool
- GHCi.ObjLink: unloadObj :: String -> IO ()
- GHCi.Run: redirectInterrupts :: ThreadId -> IO a -> IO a
- GHCi.Run: run :: Message a -> IO a
- GHCi.Signals: installSignalHandlers :: IO ()
- GHCi.StaticPtrTable: sptAddEntry :: Fingerprint -> HValue -> IO ()
- GHCi.TH: GHCiQException :: QState -> String -> GHCiQException
- GHCi.TH: data GHCiQException
- GHCi.TH: instance Control.Monad.Fail.MonadFail GHCi.TH.GHCiQ
- GHCi.TH: instance Control.Monad.IO.Class.MonadIO GHCi.TH.GHCiQ
- GHCi.TH: instance GHC.Base.Applicative GHCi.TH.GHCiQ
- GHCi.TH: instance GHC.Base.Functor GHCi.TH.GHCiQ
- GHCi.TH: instance GHC.Base.Monad GHCi.TH.GHCiQ
- GHCi.TH: instance GHC.Exception.Type.Exception GHCi.TH.GHCiQException
- GHCi.TH: instance GHC.Show.Show GHCi.TH.GHCiQException
- GHCi.TH: instance Language.Haskell.TH.Syntax.Quasi GHCi.TH.GHCiQ
- GHCi.TH: runModFinalizerRefs :: Pipe -> RemoteRef (IORef QState) -> [RemoteRef (Q ())] -> IO ()
- GHCi.TH: runTH :: Pipe -> RemoteRef (IORef QState) -> HValueRef -> THResultType -> Maybe Loc -> IO ByteString
- GHCi.TH: startTH :: IO (RemoteRef (IORef QState))
- Language.Haskell.TH.CodeDo: (>>) :: Monad m => m a -> Code m b -> Code m b
- Language.Haskell.TH.CodeDo: (>>=) :: Monad m => m a -> (a -> Code m b) -> Code m b
- Language.Haskell.TH.Quote: QuasiQuoter :: (String -> Q Exp) -> (String -> Q Pat) -> (String -> Q Type) -> (String -> Q [Dec]) -> QuasiQuoter
- Language.Haskell.TH.Quote: [quoteDec] :: QuasiQuoter -> String -> Q [Dec]
- Language.Haskell.TH.Quote: [quoteExp] :: QuasiQuoter -> String -> Q Exp
- Language.Haskell.TH.Quote: [quotePat] :: QuasiQuoter -> String -> Q Pat
- Language.Haskell.TH.Quote: [quoteType] :: QuasiQuoter -> String -> Q Type
- Language.Haskell.TH.Quote: data QuasiQuoter
- Language.Haskell.TH.Quote: dataToExpQ :: (Quote m, Data a) => (forall b. Data b => b -> Maybe (m Exp)) -> a -> m Exp
- Language.Haskell.TH.Quote: dataToPatQ :: (Quote m, Data a) => (forall b. Data b => b -> Maybe (m Pat)) -> a -> m Pat
- Language.Haskell.TH.Quote: dataToQa :: (Quote m, Data a) => (Name -> k) -> (Lit -> m q) -> (k -> [m q] -> m q) -> (forall b. Data b => b -> Maybe (m q)) -> a -> m q
- Language.Haskell.TH.Quote: quoteFile :: QuasiQuoter -> QuasiQuoter

Files

− compiler/GHC/Cmm/Reducibility.hs
@@ -1,224 +0,0 @@-{-# LANGUAGE GADTs #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE MultiParamTypeClasses #-}--{-|-Module      : GHC.Cmm.Reducibility-Description : Tell if a `CmmGraph` is reducible, or make it so--Test a Cmm control-flow graph for reducibility.  And provide a-function that, when given an arbitrary control-flow graph, returns an-equivalent, reducible control-flow graph.  The equivalent graph is-obtained by "splitting" (copying) nodes of the original graph.-The resulting equivalent graph has the same dynamic behavior as the-original, but it is larger.--Documentation uses the language of control-flow analysis, in which a-basic block is called a "node."  These "nodes" are `CmmBlock`s or-equivalent; they have nothing to do with a `CmmNode`.--For more on reducibility and related analyses and algorithms, see-Note [Reducibility resources]--}--module GHC.Cmm.Reducibility-  ( Reducibility(..)-  , reducibility--  , asReducible-  )-where--import GHC.Prelude hiding (splitAt, succ)--import Control.Monad-import Data.List (nub)-import Data.Maybe-import Data.Semigroup-import qualified Data.Sequence as Seq--import GHC.Cmm-import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow-import GHC.Cmm.Dataflow.Collections-import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dominators-import GHC.Cmm.Dataflow.Graph hiding (addBlock)-import GHC.Cmm.Dataflow.Label-import GHC.Data.Graph.Collapse-import GHC.Data.Graph.Inductive.Graph-import GHC.Data.Graph.Inductive.PatriciaTree-import GHC.Types.Unique.Supply-import GHC.Utils.Panic---- | Represents the result of a reducibility analysis.-data Reducibility = Reducible | Irreducible-  deriving (Eq, Show)---- | Given a graph, say whether the graph is reducible.  The graph must--- be bundled with a dominator analysis and a reverse postorder--- numbering, as these results are needed to perform the test.--reducibility :: NonLocal node-             => GraphWithDominators node-             -> Reducibility-reducibility gwd =-    if all goodBlock blockmap then Reducible else Irreducible-  where goodBlock b = all (goodEdge (entryLabel b)) (successors b)-        goodEdge from to = rpnum to > rpnum from || to `dominates` from-        rpnum = gwdRPNumber gwd-        blockmap = graphMap $ gwd_graph gwd-        dominators = gwdDominatorsOf gwd-        dominates lbl blockname =-            lbl == blockname || dominatorsMember lbl (dominators blockname)---- | Given a graph, return an equivalent reducible graph, by--- "splitting" (copying) nodes if necessary.  The input--- graph must be bundled with a dominator analysis and a reverse--- postorder numbering.  The computation is monadic because when a--- node is split, the new copy needs a fresh label.------ Use this function whenever a downstream algorithm needs a reducible--- control-flow graph.--asReducible :: GraphWithDominators CmmNode-            -> UniqSM (GraphWithDominators CmmNode)-asReducible gwd = case reducibility gwd of-                    Reducible -> return gwd-                    Irreducible -> assertReducible <$> nodeSplit gwd--assertReducible :: GraphWithDominators CmmNode -> GraphWithDominators CmmNode-assertReducible gwd = case reducibility gwd of-                        Reducible -> gwd-                        Irreducible -> panic "result not reducible"---------------------------------------------------------------------- | Split one or more nodes of the given graph, which must be--- irreducible.--nodeSplit :: GraphWithDominators CmmNode-          -> UniqSM (GraphWithDominators CmmNode)-nodeSplit gwd =-    graphWithDominators <$> inflate (g_entry g) <$> runNullCollapse collapsed-  where g = gwd_graph gwd-        collapsed :: NullCollapseViz (Gr CmmSuper ())-        collapsed = collapseInductiveGraph (cgraphOfCmm g)--type CGraph = Gr CmmSuper ()---- | Turn a collapsed supernode back into a control-flow graph-inflate :: Label -> CGraph -> CmmGraph-inflate entry cg = CmmGraph entry graph-  where graph = GMany NothingO body NothingO-        body :: LabelMap CmmBlock-        body = foldl (\map block -> mapInsert (entryLabel block) block map) mapEmpty $-               blocks super-        super = case labNodes cg of-                  [(_, s)] -> s-                  _ -> panic "graph given to `inflate` is not singleton"----- | Convert a `CmmGraph` into an inductive graph.--- (The function coalesces duplicate edges into a single edge.)-cgraphOfCmm :: CmmGraph -> CGraph-cgraphOfCmm g = foldl' addSuccEdges (mkGraph cnodes []) blocks-   where blocks = zip [0..] $ revPostorderFrom (graphMap g) (g_entry g)-         cnodes = [(k, super block) | (k, block) <- blocks]-          where super block = Nodes (entryLabel block) (Seq.singleton block)-         labelNumber = \lbl -> fromJust $ mapLookup lbl numbers-             where numbers :: LabelMap Int-                   numbers = mapFromList $ map swap blocks-                   swap (k, block) = (entryLabel block, k)-         addSuccEdges :: CGraph -> (Node, CmmBlock) -> CGraph-         addSuccEdges graph (k, block) =-             insEdges [(k, labelNumber lbl, ()) | lbl <- nub $ successors block] graph-{--Note [Reducibility resources]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--*Flow Analysis of Computer Programs.* Matthew S. Hecht North Holland, 1977.-Available to borrow from archive.org.--Matthew S. Hecht and Jeffrey D. Ullman (1972).-Flow Graph Reducibility. SIAM J. Comput., 1(2), 188–202.-https://doi.org/10.1137/0201014--Johan Janssen and Henk Corporaal. 1997. Making graphs reducible with-controlled node splitting. ACM TOPLAS 19, 6 (Nov. 1997),-1031–1052. DOI:https://doi.org/10.1145/267959.269971--Sebastian Unger and Frank Mueller. 2002. Handling irreducible loops:-optimized node splitting versus DJ-graphs. ACM TOPLAS 24, 4 (July-2002), 299–333. https://doi.org/10.1145/567097.567098.  (This one-contains the most detailed account of how the Hecht/Ullman algorithm-is used to modify an actual control-flow graph.  But still not much detail.)--https://rgrig.blogspot.com/2009/10/dtfloatleftclearleft-summary-of-some.html- (Nice summary of useful facts)---}----type Seq = Seq.Seq---- | A "supernode" contains a single-entry, multiple-exit, reducible subgraph.--- The entry point is the given label, and the block with that label--- dominates all the other blocks in the supernode.  When an entire--- graph is collapsed into a single supernode, the graph is reducible.--- More detail can be found in "GHC.Data.Graph.Collapse".--data CmmSuper-    = Nodes { label :: Label-            , blocks :: Seq CmmBlock-            }--instance Semigroup CmmSuper where-  s <> s' = Nodes (label s) (blocks s <> blocks s')--instance PureSupernode CmmSuper where-  superLabel = label-  mapLabels = changeLabels--instance Supernode CmmSuper NullCollapseViz where-  freshen s = liftUniqSM $ relabel s----- | Return all labels defined within a supernode.-definedLabels :: CmmSuper -> Seq Label-definedLabels = fmap entryLabel . blocks------ | Map the given function over every use and definition of a label--- in the given supernode.-changeLabels :: (Label -> Label) -> (CmmSuper -> CmmSuper)-changeLabels f (Nodes l blocks) = Nodes (f l) (fmap (changeBlockLabels f) blocks)---- | Map the given function over every use and definition of a label--- in the given block.-changeBlockLabels :: (Label -> Label) -> CmmBlock -> CmmBlock-changeBlockLabels f block = blockJoin entry' middle exit'-  where (entry, middle, exit) = blockSplit block-        entry' = let CmmEntry l scope = entry-                 in  CmmEntry (f l) scope-        exit' = case exit of-                  -- unclear why mapSuccessors doesn't touch these-                  CmmCall { cml_cont = Just l } -> exit { cml_cont = Just (f l) }-                  CmmForeignCall { succ = l } -> exit { succ = f l }-                  _ -> mapSuccessors f exit----- | Within the given supernode, replace every defined label (and all--- of its uses) with a fresh label.--relabel :: CmmSuper -> UniqSM CmmSuper-relabel node = do-     finite_map <- foldM addPair mapEmpty $ definedLabels node-     return $ changeLabels (labelChanger finite_map) node-  where addPair :: LabelMap Label -> Label -> UniqSM (LabelMap Label)-        addPair map old = do new <- newBlockId-                             return $ mapInsert old new map-        labelChanger :: LabelMap Label -> (Label -> Label)-        labelChanger mapping = \lbl -> mapFindWithDefault lbl lbl mapping
− compiler/GHC/CmmToAsm/Reg/Graph/Base.hs
@@ -1,164 +0,0 @@---- | Utils for calculating general worst, bound, squeese and free, functions.------   as per: "A Generalized Algorithm for Graph-Coloring Register Allocation"---           Michael Smith, Normal Ramsey, Glenn Holloway.---           PLDI 2004------   These general versions are not used in GHC proper because they are too slow.---   Instead, hand written optimised versions are provided for each architecture---   in MachRegs*.hs------   This code is here because we can test the architecture specific code against---   it.----module GHC.CmmToAsm.Reg.Graph.Base (-        RegClass(..),-        Reg(..),-        RegSub(..),--        worst,-        bound,-        squeese-) where--import GHC.Prelude--import GHC.Types.Unique.Set-import GHC.Types.Unique.FM-import GHC.Types.Unique-import GHC.Builtin.Uniques-import GHC.Utils.Monad (concatMapM)----- Some basic register classes.---      These aren't necessarily in 1-to-1 correspondence with the allocatable---      RegClasses in MachRegs.hs-data RegClass-        -- general purpose regs-        = ClassG32      -- 32 bit GPRs-        | ClassG16      -- 16 bit GPRs-        | ClassG8       -- 8  bit GPRs--        -- floating point regs-        | ClassF64      -- 64 bit FPRs-        deriving (Show, Eq, Enum)----- | A register of some class-data Reg-        -- a register of some class-        = Reg RegClass Int--        -- a sub-component of one of the other regs-        | RegSub RegSub Reg-        deriving (Show, Eq)----- | so we can put regs in UniqSets-instance Uniquable Reg where-        getUnique (Reg c i)-         = mkRegSingleUnique-         $ fromEnum c * 1000 + i--        getUnique (RegSub s (Reg c i))-         = mkRegSubUnique-         $ fromEnum s * 10000 + fromEnum c * 1000 + i--        getUnique (RegSub _ (RegSub _ _))-          = error "RegArchBase.getUnique: can't have a sub-reg of a sub-reg."----- | A subcomponent of another register-data RegSub-        = SubL16        -- lowest 16 bits-        | SubL8         -- lowest  8 bits-        | SubL8H        -- second lowest 8 bits-        deriving (Show, Enum, Ord, Eq)----- | Worst case displacement------      a node N of classN has some number of neighbors,---      all of which are from classC.------      (worst neighbors classN classC) is the maximum number of potential---      colors for N that can be lost by coloring its neighbors.------ This should be hand coded/cached for each particular architecture,---      because the compute time is very long..-worst   :: (RegClass    -> UniqSet Reg)-        -> (Reg         -> UniqSet Reg)-        -> Int -> RegClass -> RegClass -> Int--worst regsOfClass regAlias neighbors classN classC- = let  regAliasS regs  = unionManyUniqSets-                        $ map regAlias-                        $ nonDetEltsUniqSet regs-                        -- This is non-deterministic but we do not-                        -- currently support deterministic code-generation.-                        -- See Note [Unique Determinism and code generation]--        -- all the regs in classes N, C-        regsN           = regsOfClass classN-        regsC           = regsOfClass classC--        -- all the possible subsets of c which have size < m-        regsS           = filter (\s -> not (isEmptyUniqSet s)-                                     && sizeUniqSet s <= neighbors)-                        $ powersetLS regsC--        -- for each of the subsets of C, the regs which conflict-        -- with possibilities for N-        regsS_conflict-                = map (\s -> intersectUniqSets regsN (regAliasS s)) regsS--  in    maximum $ map sizeUniqSet $ regsS_conflict----- | For a node N of classN and neighbors of classesC---      (bound classN classesC) is the maximum number of potential---      colors for N that can be lost by coloring its neighbors.-bound   :: (RegClass    -> UniqSet Reg)-        -> (Reg         -> UniqSet Reg)-        -> RegClass -> [RegClass] -> Int--bound regsOfClass regAlias classN classesC- = let  regAliasS regs  = unionManyUniqSets-                        $ map regAlias-                        $ nonDetEltsUFM regs-                        -- See Note [Unique Determinism and code generation]--        regsC_aliases-                = unionManyUniqSets-                $ map (regAliasS . getUniqSet . regsOfClass) classesC--        overlap = intersectUniqSets (regsOfClass classN) regsC_aliases--   in   sizeUniqSet overlap----- | The total squeese on a particular node with a list of neighbors.------   A version of this should be constructed for each particular architecture,---   possibly including uses of bound, so that aliased registers don't get---   counted twice, as per the paper.-squeese :: (RegClass    -> UniqSet Reg)-        -> (Reg         -> UniqSet Reg)-        -> RegClass -> [(Int, RegClass)] -> Int--squeese regsOfClass regAlias classN countCs-        = sum-        $ map (\(i, classC) -> worst regsOfClass regAlias i classN classC)-        $ countCs----- | powerset (for lists)-powersetL :: [a] -> [[a]]-powersetL       = concatMapM (\x -> [[],[x]])----- | powersetLS (list of sets)-powersetLS :: Uniquable a => UniqSet a -> [UniqSet a]-powersetLS s    = map mkUniqSet $ powersetL $ nonDetEltsUniqSet s-  -- See Note [Unique Determinism and code generation]
− compiler/GHC/CmmToAsm/Reg/Graph/Coalesce.hs
@@ -1,99 +0,0 @@--- | Register coalescing.-module GHC.CmmToAsm.Reg.Graph.Coalesce (-        regCoalesce,-        slurpJoinMovs-) where-import GHC.Prelude--import GHC.CmmToAsm.Reg.Liveness-import GHC.CmmToAsm.Instr-import GHC.Platform.Reg--import GHC.Cmm-import GHC.Data.Bag-import GHC.Data.Graph.Directed-import GHC.Types.Unique.FM-import GHC.Types.Unique.Set-import GHC.Types.Unique.Supply----- | Do register coalescing on this top level thing------   For Reg -> Reg moves, if the first reg dies at the same time the---   second reg is born then the mov only serves to join live ranges.---   The two regs can be renamed to be the same and the move instruction---   safely erased.-regCoalesce-        :: Instruction instr-        => [LiveCmmDecl statics instr]-        -> UniqSM [LiveCmmDecl statics instr]--regCoalesce code- = do-        let joins       = foldl' unionBags emptyBag-                        $ map slurpJoinMovs code--        let alloc       = foldl' buildAlloc emptyUFM-                        $ bagToList joins--        let patched     = map (patchEraseLive (sinkReg alloc)) code--        return patched----- | Add a v1 = v2 register renaming to the map.---   The register with the lowest lexical name is set as the---   canonical version.-buildAlloc :: UniqFM Reg Reg -> (Reg, Reg) -> UniqFM Reg Reg-buildAlloc fm (r1, r2)- = let  rmin    = min r1 r2-        rmax    = max r1 r2-   in   addToUFM fm rmax rmin----- | Determine the canonical name for a register by following---   v1 = v2 renamings in this map.-sinkReg :: UniqFM Reg Reg -> Reg -> Reg-sinkReg fm r- = case lookupUFM fm r of-        Nothing -> r-        Just r' -> sinkReg fm r'----- | Slurp out mov instructions that only serve to join live ranges.------   During a mov, if the source reg dies and the destination reg is---   born then we can rename the two regs to the same thing and---   eliminate the move.-slurpJoinMovs-        :: Instruction instr-        => LiveCmmDecl statics instr-        -> Bag (Reg, Reg)--slurpJoinMovs live-        = slurpCmm emptyBag live- where-        slurpCmm   rs  CmmData{}-         = rs--        slurpCmm   rs (CmmProc _ _ _ sccs)-         = foldl' slurpBlock rs (flattenSCCs sccs)--        slurpBlock rs (BasicBlock _ instrs)-         = foldl' slurpLI    rs instrs--        slurpLI    rs (LiveInstr _      Nothing)    = rs-        slurpLI    rs (LiveInstr instr (Just live))-                | Just (r1, r2) <- takeRegRegMoveInstr instr-                , elementOfUniqSet r1 $ liveDieRead live-                , elementOfUniqSet r2 $ liveBorn live--                -- only coalesce movs between two virtuals for now,-                -- else we end up with allocatable regs in the live-                -- regs list..-                , isVirtualReg r1 && isVirtualReg r2-                = consBag (r1, r2) rs--                | otherwise-                = rs-
− compiler/GHC/CmmToAsm/Reg/Graph/X86.hs
@@ -1,161 +0,0 @@---- | A description of the register set of the X86.------   This isn't used directly in GHC proper.------   See RegArchBase.hs for the reference.---   See MachRegs.hs for the actual trivColorable function used in GHC.----module GHC.CmmToAsm.Reg.Graph.X86 (-        classOfReg,-        regsOfClass,-        regName,-        regAlias,-        worst,-        squeese,-) where--import GHC.Prelude--import GHC.CmmToAsm.Reg.Graph.Base  (Reg(..), RegSub(..), RegClass(..))-import GHC.Types.Unique.Set--import qualified Data.Array as A----- | Determine the class of a register-classOfReg :: Reg -> RegClass-classOfReg reg- = case reg of-        Reg c _         -> c--        RegSub SubL16 _ -> ClassG16-        RegSub SubL8  _ -> ClassG8-        RegSub SubL8H _ -> ClassG8----- | Determine all the regs that make up a certain class.-regsOfClass :: RegClass -> UniqSet Reg-regsOfClass c- = case c of-        ClassG32-         -> mkUniqSet   [ Reg ClassG32  i-                        | i <- [0..7] ]--        ClassG16-         -> mkUniqSet   [ RegSub SubL16 (Reg ClassG32 i)-                        | i <- [0..7] ]--        ClassG8-         -> unionUniqSets-                (mkUniqSet [ RegSub SubL8  (Reg ClassG32 i) | i <- [0..3] ])-                (mkUniqSet [ RegSub SubL8H (Reg ClassG32 i) | i <- [0..3] ])--        ClassF64-         -> mkUniqSet   [ Reg ClassF64  i-                        | i <- [0..5] ]----- | Determine the common name of a reg---      returns Nothing if this reg is not part of the machine.-regName :: Reg -> Maybe String-regName reg- = case reg of-        Reg ClassG32 i-         | i <= 7 ->-           let names = A.listArray (0,8)-                       [ "eax", "ebx", "ecx", "edx"-                       , "ebp", "esi", "edi", "esp" ]-           in Just $ names A.! i--        RegSub SubL16 (Reg ClassG32 i)-         | i <= 7 ->-           let names = A.listArray (0,8)-                       [ "ax", "bx", "cx", "dx"-                       , "bp", "si", "di", "sp"]-           in Just $ names A.! i--        RegSub SubL8  (Reg ClassG32 i)-         | i <= 3 ->-           let names = A.listArray (0,4) [ "al", "bl", "cl", "dl"]-           in Just $ names A.! i--        RegSub SubL8H (Reg ClassG32 i)-         | i <= 3 ->-           let names = A.listArray (0,4) [ "ah", "bh", "ch", "dh"]-           in Just $ names A.! i--        _         -> Nothing----- | Which regs alias what other regs.-regAlias :: Reg -> UniqSet Reg-regAlias reg- = case reg of--        -- 32 bit regs alias all of the subregs-        Reg ClassG32 i--         -- for eax, ebx, ecx, eds-         |  i <= 3-         -> mkUniqSet-         $ [ Reg ClassG32 i,   RegSub SubL16 reg-           , RegSub SubL8 reg, RegSub SubL8H reg ]--         -- for esi, edi, esp, ebp-         | 4 <= i && i <= 7-         -> mkUniqSet-         $ [ Reg ClassG32 i,   RegSub SubL16 reg ]--        -- 16 bit subregs alias the whole reg-        RegSub SubL16 r@(Reg ClassG32 _)-         ->     regAlias r--        -- 8 bit subregs alias the 32 and 16, but not the other 8 bit subreg-        RegSub SubL8  r@(Reg ClassG32 _)-         -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8 r ]--        RegSub SubL8H r@(Reg ClassG32 _)-         -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8H r ]--        -- fp-        Reg ClassF64 _-         -> unitUniqSet reg--        _ -> error "regAlias: invalid register"----- | Optimised versions of RegColorBase.{worst, squeese} specific to x86-worst :: Int -> RegClass -> RegClass -> Int-worst n classN classC- = case classN of-        ClassG32-         -> case classC of-                ClassG32        -> min n 8-                ClassG16        -> min n 8-                ClassG8         -> min n 4-                ClassF64        -> 0--        ClassG16-         -> case classC of-                ClassG32        -> min n 8-                ClassG16        -> min n 8-                ClassG8         -> min n 4-                ClassF64        -> 0--        ClassG8-         -> case classC of-                ClassG32        -> min (n*2) 8-                ClassG16        -> min (n*2) 8-                ClassG8         -> min n 8-                ClassF64        -> 0--        ClassF64-         -> case classC of-                ClassF64        -> min n 6-                _               -> 0--squeese :: RegClass -> [(Int, RegClass)] -> Int-squeese classN countCs-        = sum (map (\(i, classC) -> worst i classN classC) countCs)-
− compiler/GHC/Data/Graph/Collapse.hs
@@ -1,264 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module GHC.Data.Graph.Collapse-  ( PureSupernode(..)-  , Supernode(..)-  , collapseInductiveGraph-  , VizCollapseMonad(..)-  , NullCollapseViz(..)-  , runNullCollapse-  , MonadUniqSM(..)-  )-where--import GHC.Prelude--import Control.Exception-import Control.Monad-import Data.List (delete, union, insert, intersect)-import Data.Semigroup--import GHC.Cmm.Dataflow.Label-import GHC.Data.Graph.Inductive.Graph-import GHC.Types.Unique.Supply-import GHC.Utils.Panic---{-|-Module      : GHC.Data.Graph.Collapse-Description : Implement the "collapsing" algorithm Hecht and Ullman--A control-flow graph is reducible if and only if it is collapsible-according to the definition of Hecht and Ullman (1972).   This module-implements the collapsing algorithm of Hecht and Ullman, and if it-encounters a graph that is not collapsible, it splits nodes until the-graph is fully collapsed.  It then reports what nodes (if any) had to-be split in order to collapse the graph.  The information is used-upstream to node-split Cmm graphs.--The module uses the inductive graph representation cloned from the-Functional Graph Library (Hackage package `fgl`, modules-`GHC.Data.Graph.Inductive.*`.)---}---- Full reference to paper: Matthew S. Hecht and Jeffrey D. Ullman--- (1972).  Flow Graph Reducibility. SIAM J. Comput., 1(2), 188–202.--- https://doi.org/10.1137/0201014--------------------- Graph-splitting monad --------------------------- | If you want to visualize the graph-collapsing algorithm, create--- an instance of monad `VizCollapseMonad`.  Each step in the--- algorithm is announced to the monad as a side effect.  If you don't--- care about visualization, you would use the `NullCollapseViz`--- monad, in which these operations are no-ops.--class (Monad m) => MonadUniqSM m where-  liftUniqSM :: UniqSM a -> m a--class (MonadUniqSM m, Graph gr, Supernode s m) => VizCollapseMonad m gr s where-  consumeByInGraph :: Node -> Node -> gr s () -> m ()-  splitGraphAt :: gr s () -> LNode s -> m ()-  finalGraph :: gr s () -> m ()------ | The identity monad as a `VizCollapseMonad`.  Use this monad when--- you want efficiency in graph collapse.-newtype NullCollapseViz a = NullCollapseViz { unNCV :: UniqSM a }-  deriving (Functor, Applicative, Monad, MonadUnique)--instance MonadUniqSM NullCollapseViz where-  liftUniqSM = NullCollapseViz--instance (Graph gr, Supernode s NullCollapseViz) =>-    VizCollapseMonad NullCollapseViz gr s where-  consumeByInGraph _ _ _ = return ()-  splitGraphAt _ _ = return ()-  finalGraph _ = return ()--runNullCollapse :: NullCollapseViz a -> UniqSM a-runNullCollapse = unNCV--------------------- Utility functions on graphs ---------------------------- | Tell if a `Node` has a single predecessor.-singlePred :: Graph gr => gr a b -> Node -> Bool-singlePred gr n-    | ([_], _, _, _) <- context gr n = True-    | otherwise = False---- | Use this function to extract information about a `Node` that you--- know is in a `Graph`.  It's like `match` from `Graph`, but it must--- succeed.-forceMatch :: (Graph gr)-           => Node -> gr s b -> (Context s b, gr s b)-forceMatch node g = case match node g of (Just c, g') -> (c, g')-                                         _ -> panicDump node g- where panicDump :: Graph gr => Node -> gr s b -> any-       panicDump k _g =-         panic $ "GHC.Data.Graph.Collapse failed to match node " ++ show k---- | Rewrite the label of a given node.-updateNode :: DynGraph gr => (s -> s) -> Node -> gr s b -> gr s b-updateNode relabel node g = (preds, n, relabel this, succs) & g'-    where ((preds, n, this, succs), g') = forceMatch node g----- | Test if a graph has but a single node.-singletonGraph :: Graph gr => gr a b -> Bool-singletonGraph g = case labNodes g of [_] -> True-                                      _ -> False-------------------  Supernodes ---------------------------------------- | A "supernode" stands for a collection of one or more nodes (basic--- blocks) that have been coalesced by the Hecht-Ullman algorithm.--- A collection in a supernode constitutes a /reducible/ subgraph of a--- control-flow graph.  (When an entire control-flow graph is collapsed--- to a single supernode, the flow graph is reducible.)------ The idea of node splitting is to collapse a control-flow graph down--- to a single supernode, then materialize (``inflate'') the reducible--- equivalent graph from that supernode.  The `Supernode` class--- defines only the methods needed to collapse; rematerialization is--- the responsiblity of the client.------ During the Hecht-Ullman algorithm, every supernode has a unique--- entry point, which is given by `superLabel`.  But this invariant is--- not guaranteed by the class methods and is not a law of the class.--- The `mapLabels` function rewrites all labels that appear in a--- supernode (both definitions and uses).  The `freshen` function--- replaces every appearance of a /defined/ label with a fresh label.--- (Appearances include both definitions and uses.)------ Laws:--- @---    superLabel (n <> n') == superLabel n---    blocks (n <> n') == blocks n `union` blocks n'---    mapLabels f (n <> n') = mapLabels f n <> mapLabels f n'---    mapLabels id == id---    mapLabels (f . g) == mapLabels f . mapLabels g--- @------ (We expect `freshen` to distribute over `<>`, but because of--- the fresh names involved, formulating a precise law is a bit--- challenging.)--class (Semigroup node) => PureSupernode node where-  superLabel :: node -> Label-  mapLabels :: (Label -> Label) -> (node -> node)--class (MonadUnique m, PureSupernode node) => Supernode node m where-  freshen :: node -> m node--  -- ghost method-  -- blocks :: node -> Set Block-------------------- Functions specific to the algorithm --------------------------- | Merge two nodes, return new graph plus list of nodes that newly have a single--- predecessor.  This function implements transformation $T_2$ from--- the Hecht and Ullman paper (merge the node into its unique--- predecessor).  It then also removes self-edges (transformation $T_1$ from--- the Hecht and Ullman paper).  There is no need for a separate--- implementation of $T_1$.------ `consumeBy v u g` returns the graph that results when node v is--- consumed by node u in graph g.  Both v and u are replaced with a new node u'--- with these properties:------    LABELS(u') = LABELS(u) `union` LABELS(v)---    SUCC(u') = SUCC(u) `union` SUCC(v) - { u }---    every node that previously points to u now points to u'------ It also returns a list of nodes in the result graph that--- are *newly* single-predecessor nodes.--consumeBy :: (DynGraph gr, PureSupernode s)-          => Node -> Node -> gr s () -> (gr s (), [Node])-consumeBy toNode fromNode g =-    assert (toPreds == [((), fromNode)]) $-    (newGraph, newCandidates)-  where ((toPreds,   _, to,   toSuccs),   g')  = forceMatch toNode   g-        ((fromPreds, _, from, fromSuccs), g'') = forceMatch fromNode g'-        context = ( fromPreds -- by construction, can't have `toNode`-                  , fromNode-                  , from <> to-                  , delete ((), fromNode) toSuccs `union` fromSuccs-                  )-        newGraph = context & g''-        newCandidates = filter (singlePred newGraph) changedNodes-        changedNodes = fromNode `insert` map snd (toSuccs `intersect` fromSuccs)---- | Split a given node.  The node is replaced with a collection of replicas,--- one for each predecessor.  After the split, every predecessor--- points to a unique replica.-split :: forall gr s b m . (DynGraph gr, Supernode s m)-      => Node -> gr s b -> m (gr s b)-split node g = assert (isMultiple preds) $ foldM addReplica g' newNodes-  where ((preds, _, this, succs), g') = forceMatch node g-        newNodes :: [((b, Node), Node)]-        newNodes = zip preds [maxNode+1..]-        (_, maxNode) = nodeRange g-        thisLabel = superLabel this-        addReplica :: gr s b -> ((b, Node), Node) -> m (gr s b)-        addReplica g ((b, pred), newNode) = do-            newSuper <- freshen this-            return $ add newSuper-          where add newSuper =-                  updateNode (thisLabel `replacedWith` superLabel newSuper) pred $-                  ([(b, pred)], newNode, newSuper, succs) & g--replacedWith :: PureSupernode s => Label -> Label -> s -> s-replacedWith old new = mapLabels (\l -> if l == old then new else l)----- | Does a list have more than one element? (in constant time).-isMultiple :: [a] -> Bool-isMultiple [] = False-isMultiple [_] = False-isMultiple (_:_:_) = True---- | Find a candidate for splitting by finding a node that has multiple predecessors.--anySplittable :: forall gr a b . Graph gr => gr a b -> LNode a-anySplittable g = case splittable of-                    n : _ -> n-                    [] -> panic "anySplittable found no splittable nodes"-  where splittable = filter (isMultiple . pre g . fst) $ labNodes g-        splittable :: [LNode a]--------------------- The collapsing algorithm --------------------------- | Using the algorithm of Hecht and Ullman (1972), collapse a graph--- into a single node, splitting nodes as needed.  Record--- visualization events in monad `m`.-collapseInductiveGraph :: (DynGraph gr, Supernode s m, VizCollapseMonad m gr s)-                       => gr s () -> m (gr s ())-collapseInductiveGraph g = drain g worklist-  where worklist :: [[Node]] -- nodes with exactly one predecessor-        worklist = [filter (singlePred g) $ nodes g]--        drain g [] = if singletonGraph g then finalGraph g >> return g-                     else let (n, super) = anySplittable g-                          in  do splitGraphAt g (n, super)-                                 collapseInductiveGraph =<< split n g-        drain g ([]:nss) = drain g nss-        drain g ((n:ns):nss) = let (g', ns') = consumeBy n (theUniquePred n) g-                               in  do consumeByInGraph n (theUniquePred n) g-                                      drain g' (ns':ns:nss)-         where theUniquePred n-                 | ([(_, p)], _, _, _) <- context g n = p-                 | otherwise =-                     panic "node claimed to have a unique predecessor; it doesn't"
− compiler/GHC/Data/Graph/Inductive/Graph.hs
@@ -1,643 +0,0 @@--- (c) 1999-2005 by Martin Erwig (see copyright at bottom)--- | Static and Dynamic Inductive Graphs------ Code is from Hackage `fgl` package version 5.7.0.3----module GHC.Data.Graph.Inductive.Graph (-    -- * General Type Defintions-    -- ** Node and Edge Types-    Node,LNode,UNode,-    Edge,LEdge,UEdge,-    -- ** Types Supporting Inductive Graph View-    Adj,Context,MContext,Decomp,GDecomp,UContext,UDecomp,-    Path,LPath(..),UPath,-    -- * Graph Type Classes-    -- | We define two graph classes:-    ---    --   Graph: static, decomposable graphs.-    --    Static means that a graph itself cannot be changed-    ---    --   DynGraph: dynamic, extensible graphs.-    --             Dynamic graphs inherit all operations from static graphs-    --             but also offer operations to extend and change graphs.-    ---    -- Each class contains in addition to its essential operations those-    -- derived operations that might be overwritten by a more efficient-    -- implementation in an instance definition.-    ---    -- Note that labNodes is essentially needed because the default definition-    -- for matchAny is based on it: we need some node from the graph to define-    -- matchAny in terms of match. Alternatively, we could have made matchAny-    -- essential and have labNodes defined in terms of ufold and matchAny.-    -- However, in general, labNodes seems to be (at least) as easy to define-    -- as matchAny. We have chosen labNodes instead of the function nodes since-    -- nodes can be easily derived from labNodes, but not vice versa.-    Graph(..),-    DynGraph(..),-    -- * Operations-    order,-    size,-    -- ** Graph Folds and Maps-    ufold,gmap,nmap,emap,nemap,-    -- ** Graph Projection-    nodes,edges,toEdge,edgeLabel,toLEdge,newNodes,gelem,-    -- ** Graph Construction and Destruction-    insNode,insEdge,delNode,delEdge,delLEdge,delAllLEdge,-    insNodes,insEdges,delNodes,delEdges,-    buildGr,mkUGraph,-    -- ** Subgraphs-    gfiltermap,nfilter,labnfilter,labfilter,subgraph,-    -- ** Graph Inspection-    context,lab,neighbors,lneighbors,-    suc,pre,lsuc,lpre,-    out,inn,outdeg,indeg,deg,-    hasEdge,hasNeighbor,hasLEdge,hasNeighborAdj,-    equal,-    -- ** Context Inspection-    node',lab',labNode',neighbors',lneighbors',-    suc',pre',lpre',lsuc',-    out',inn',outdeg',indeg',deg',-    -- * Pretty-printing-    prettify,-    prettyPrint,-    -- * Ordering of Graphs-    OrdGr(..)-) where--import GHC.Prelude--import           Control.Arrow (first)-import           Data.Function (on)-import qualified Data.IntSet   as IntSet-import           Data.List     (delete, groupBy, sort, sortBy, (\\))-import           Data.Maybe    (fromMaybe, isJust)--import GHC.Utils.Panic---- | Unlabeled node-type  Node   = Int--- | Labeled node-type LNode a = (Node,a)--- | Quasi-unlabeled node-type UNode   = LNode ()---- | Unlabeled edge-type  Edge   = (Node,Node)--- | Labeled edge-type LEdge b = (Node,Node,b)--- | Quasi-unlabeled edge-type UEdge   = LEdge ()---- | Unlabeled path-type Path    = [Node]--- | Labeled path-newtype LPath a = LP { unLPath :: [LNode a] }--instance (Show a) => Show (LPath a) where-  show (LP xs) = show xs--instance (Eq a) => Eq (LPath a) where-  (LP [])        == (LP [])        = True-  (LP ((_,x):_)) == (LP ((_,y):_)) = x==y-  (LP _)         == (LP _)         = False--instance (Ord a) => Ord (LPath a) where-  compare (LP [])        (LP [])        = EQ-  compare (LP ((_,x):_)) (LP ((_,y):_)) = compare x y-  compare _ _ = panic "LPath: cannot compare two empty paths"---- | Quasi-unlabeled path-type UPath   = [UNode]---- | Labeled links to or from a 'Node'.-type Adj b        = [(b,Node)]--- | Links to the 'Node', the 'Node' itself, a label, links from the 'Node'.------   In other words, this captures all information regarding the---   specified 'Node' within a graph.-type Context a b  = (Adj b,Node,a,Adj b) -- Context a b "=" Context' a b "+" Node-type MContext a b = Maybe (Context a b)--- | 'Graph' decomposition - the context removed from a 'Graph', and the rest--- of the 'Graph'.-type Decomp g a b = (MContext a b,g a b)--- | The same as 'Decomp', only more sure of itself.-type GDecomp g a b  = (Context a b,g a b)---- | Unlabeled context.-type UContext     = ([Node],Node,[Node])--- | Unlabeled decomposition.-type UDecomp g    = (Maybe UContext,g)---- | Minimum implementation: 'empty', 'isEmpty', 'match', 'mkGraph', 'labNodes'-class Graph gr where-  {-# MINIMAL empty, isEmpty, match, mkGraph, labNodes #-}--  -- | An empty 'Graph'.-  empty     :: gr a b--  -- | True if the given 'Graph' is empty.-  isEmpty   :: gr a b -> Bool--  -- | Decompose a 'Graph' into the 'MContext' found for the given node and the-  -- remaining 'Graph'.-  match     :: Node -> gr a b -> Decomp gr a b--  -- | Create a 'Graph' from the list of 'LNode's and 'LEdge's.-  ---  --   For graphs that are also instances of 'DynGraph', @mkGraph ns-  --   es@ should be equivalent to @('insEdges' es . 'insNodes' ns)-  --   'empty'@.-  mkGraph   :: [LNode a] -> [LEdge b] -> gr a b--  -- | A list of all 'LNode's in the 'Graph'.-  labNodes  :: gr a b -> [LNode a]--  -- | Decompose a graph into the 'Context' for an arbitrarily-chosen 'Node'-  -- and the remaining 'Graph'.-  matchAny  :: gr a b -> GDecomp gr a b-  matchAny g = case labNodes g of-                 []      -> panic "Match Exception, Empty Graph"-                 (v,_):_ | (Just c,g') <- match v g -> (c,g')-                 _       -> panic "This can't happen: failed to match node in graph"---  -- | The number of 'Node's in a 'Graph'.-  noNodes   :: gr a b -> Int-  noNodes = length . labNodes--  -- | The minimum and maximum 'Node' in a 'Graph'.-  nodeRange :: gr a b -> (Node,Node)-  nodeRange g-    | isEmpty g = panic "nodeRange of empty graph"-    | otherwise = (minimum vs, maximum vs)-    where-      vs = nodes g--  -- | A list of all 'LEdge's in the 'Graph'.-  labEdges  :: gr a b -> [LEdge b]-  labEdges = ufold (\(_,v,_,s)->(map (\(l,w)->(v,w,l)) s ++)) []--class (Graph gr) => DynGraph gr where-  -- | Merge the 'Context' into the 'DynGraph'.-  ---  --   Context adjacencies should only refer to either a Node already-  --   in a graph or the node in the Context itself (for loops).-  ---  --   Behaviour is undefined if the specified 'Node' already exists-  --   in the graph.-  (&) :: Context a b -> gr a b -> gr a b----- | The number of nodes in the graph.  An alias for 'noNodes'.-order :: (Graph gr) => gr a b -> Int-order = noNodes---- | The number of edges in the graph.------   Note that this counts every edge found, so if you are---   representing an unordered graph by having each edge mirrored this---   will be incorrect.------   If you created an unordered graph by either mirroring every edge---   (including loops!) or using the @undir@ function in---   "Data.Graph.Inductive.Basic" then you can safely halve the value---   returned by this.-size :: (Graph gr) => gr a b -> Int-size = length . labEdges---- | Fold a function over the graph by recursively calling 'match'.-ufold :: (Graph gr) => (Context a b -> c -> c) -> c -> gr a b -> c-ufold f u g-  | isEmpty g = u-  | otherwise = f c (ufold f u g')-  where-    (c,g') = matchAny g---- | Map a function over the graph by recursively calling 'match'.-gmap :: (DynGraph gr) => (Context a b -> Context c d) -> gr a b -> gr c d-gmap f = ufold (\c->(f c&)) empty-{-# NOINLINE [0] gmap #-}---- | Map a function over the 'Node' labels in a graph.-nmap :: (DynGraph gr) => (a -> c) -> gr a b -> gr c b-nmap f = gmap (\(p,v,l,s)->(p,v,f l,s))-{-# NOINLINE [0] nmap #-}---- | Map a function over the 'Edge' labels in a graph.-emap :: (DynGraph gr) => (b -> c) -> gr a b -> gr a c-emap f = gmap (\(p,v,l,s)->(map1 f p,v,l,map1 f s))-  where-    map1 g = map (first g)-{-# NOINLINE [0] emap #-}---- | Map functions over both the 'Node' and 'Edge' labels in a graph.-nemap :: (DynGraph gr) => (a -> c) -> (b -> d) -> gr a b -> gr c d-nemap fn fe = gmap (\(p,v,l,s) -> (fe' p,v,fn l,fe' s))-  where-    fe' = map (first fe)-{-# NOINLINE [0] nemap #-}---- | List all 'Node's in the 'Graph'.-nodes :: (Graph gr) => gr a b -> [Node]-nodes = map fst . labNodes---- | List all 'Edge's in the 'Graph'.-edges :: (Graph gr) => gr a b -> [Edge]-edges = map toEdge . labEdges---- | Drop the label component of an edge.-toEdge :: LEdge b -> Edge-toEdge (v,w,_) = (v,w)---- | Add a label to an edge.-toLEdge :: Edge -> b -> LEdge b-toLEdge (v,w) l = (v,w,l)---- | The label in an edge.-edgeLabel :: LEdge b -> b-edgeLabel (_,_,l) = l---- | List N available 'Node's, i.e. 'Node's that are not used in the 'Graph'.-newNodes :: (Graph gr) => Int -> gr a b -> [Node]-newNodes i g-  | isEmpty g = [0..i-1]-  | otherwise = [n+1..n+i]-  where-    (_,n) = nodeRange g---- | 'True' if the 'Node' is present in the 'Graph'.-gelem :: (Graph gr) => Node -> gr a b -> Bool-gelem v = isJust . fst . match v---- | Insert a 'LNode' into the 'Graph'.-insNode :: (DynGraph gr) => LNode a -> gr a b -> gr a b-insNode (v,l) = (([],v,l,[])&)-{-# NOINLINE [0] insNode #-}---- | Insert a 'LEdge' into the 'Graph'.-insEdge :: (DynGraph gr) => LEdge b -> gr a b -> gr a b-insEdge (v,w,l) g = (pr,v,la,(l,w):su) & g'-  where-    (mcxt,g') = match v g-    (pr,_,la,su) = fromMaybe-                     (panic ("insEdge: cannot add edge from non-existent vertex " ++ show v))-                     mcxt-{-# NOINLINE [0] insEdge #-}---- | Remove a 'Node' from the 'Graph'.-delNode :: (Graph gr) => Node -> gr a b -> gr a b-delNode v = delNodes [v]---- | Remove an 'Edge' from the 'Graph'.------   NOTE: in the case of multiple edges, this will delete /all/ such---   edges from the graph as there is no way to distinguish between---   them.  If you need to delete only a single such edge, please use---   'delLEdge'.-delEdge :: (DynGraph gr) => Edge -> gr a b -> gr a b-delEdge (v,w) g = case match v g of-                    (Nothing,_)          -> g-                    (Just (p,v',l,s),g') -> (p,v',l,filter ((/=w).snd) s) & g'---- | Remove an 'LEdge' from the 'Graph'.------   NOTE: in the case of multiple edges with the same label, this---   will only delete the /first/ such edge.  To delete all such---   edges, please use 'delAllLedge'.-delLEdge :: (DynGraph gr, Eq b) => LEdge b -> gr a b -> gr a b-delLEdge = delLEdgeBy delete---- | Remove all edges equal to the one specified.-delAllLEdge :: (DynGraph gr, Eq b) => LEdge b -> gr a b -> gr a b-delAllLEdge = delLEdgeBy (filter . (/=))--delLEdgeBy :: (DynGraph gr) => ((b,Node) -> Adj b -> Adj b)-              -> LEdge b -> gr a b -> gr a b-delLEdgeBy f (v,w,b) g = case match v g of-                           (Nothing,_)          -> g-                           (Just (p,v',l,s),g') -> (p,v',l,f (b,w) s) & g'---- | Insert multiple 'LNode's into the 'Graph'.-insNodes   :: (DynGraph gr) => [LNode a] -> gr a b -> gr a b-insNodes vs g = foldl' (flip insNode) g vs-{-# INLINABLE insNodes #-}---- | Insert multiple 'LEdge's into the 'Graph'.-insEdges :: (DynGraph gr) => [LEdge b] -> gr a b -> gr a b-insEdges es g = foldl' (flip insEdge) g es-{-# INLINABLE insEdges #-}---- | Remove multiple 'Node's from the 'Graph'.-delNodes :: (Graph gr) => [Node] -> gr a b -> gr a b-delNodes vs g = foldl' (snd .: flip match) g vs---- | Remove multiple 'Edge's from the 'Graph'.-delEdges :: (DynGraph gr) => [Edge] -> gr a b -> gr a b-delEdges es g = foldl' (flip delEdge) g es---- | Build a 'Graph' from a list of 'Context's.------   The list should be in the order such that earlier 'Context's---   depend upon later ones (i.e. as produced by @'ufold' (:) []@).-buildGr :: (DynGraph gr) => [Context a b] -> gr a b-buildGr = foldr (&) empty---- | Build a quasi-unlabeled 'Graph'.-mkUGraph :: (Graph gr) => [Node] -> [Edge] -> gr () ()-mkUGraph vs es = mkGraph (labUNodes vs) (labUEdges es)-   where-     labUEdges = map (`toLEdge` ())-     labUNodes = map (flip (,) ())---- | Build a graph out of the contexts for which the predicate is--- satisfied by recursively calling 'match'.-gfiltermap :: DynGraph gr => (Context a b -> MContext c d) -> gr a b -> gr c d-gfiltermap f = ufold (maybe id (&) . f) empty---- | Returns the subgraph only containing the labelled nodes which--- satisfy the given predicate.-labnfilter :: Graph gr => (LNode a -> Bool) -> gr a b -> gr a b-labnfilter p gr = delNodes (map fst . filter (not . p) $ labNodes gr) gr---- | Returns the subgraph only containing the nodes which satisfy the--- given predicate.-nfilter :: DynGraph gr => (Node -> Bool) -> gr a b -> gr a b-nfilter f = labnfilter (f . fst)---- | Returns the subgraph only containing the nodes whose labels--- satisfy the given predicate.-labfilter :: DynGraph gr => (a -> Bool) -> gr a b -> gr a b-labfilter f = labnfilter (f . snd)---- | Returns the subgraph induced by the supplied nodes.-subgraph :: DynGraph gr => [Node] -> gr a b -> gr a b-subgraph vs = let vs' = IntSet.fromList vs-              in nfilter (`IntSet.member` vs')---- | Find the context for the given 'Node'.  Causes an error if the 'Node' is--- not present in the 'Graph'.-context :: (Graph gr) => gr a b -> Node -> Context a b-context g v = fromMaybe (panic ("Match Exception, Node: "++show v))-                        (fst (match v g))---- | Find the label for a 'Node'.-lab :: (Graph gr) => gr a b -> Node -> Maybe a-lab g v = fmap lab' . fst $ match v g---- | Find the neighbors for a 'Node'.-neighbors :: (Graph gr) => gr a b -> Node -> [Node]-neighbors = map snd .: lneighbors---- | Find the labelled links coming into or going from a 'Context'.-lneighbors :: (Graph gr) => gr a b -> Node -> Adj b-lneighbors = maybe [] lneighbors' .: mcontext---- | Find all 'Node's that have a link from the given 'Node'.-suc :: (Graph gr) => gr a b -> Node -> [Node]-suc = map snd .: context4l---- | Find all 'Node's that link to to the given 'Node'.-pre :: (Graph gr) => gr a b -> Node -> [Node]-pre = map snd .: context1l---- | Find all 'Node's that are linked from the given 'Node' and the label of--- each link.-lsuc :: (Graph gr) => gr a b -> Node -> [(Node,b)]-lsuc = map flip2 .: context4l---- | Find all 'Node's that link to the given 'Node' and the label of each link.-lpre :: (Graph gr) => gr a b -> Node -> [(Node,b)]-lpre = map flip2 .: context1l---- | Find all outward-bound 'LEdge's for the given 'Node'.-out :: (Graph gr) => gr a b -> Node -> [LEdge b]-out g v = map (\(l,w)->(v,w,l)) (context4l g v)---- | Find all inward-bound 'LEdge's for the given 'Node'.-inn :: (Graph gr) => gr a b -> Node -> [LEdge b]-inn g v = map (\(l,w)->(w,v,l)) (context1l g v)---- | The outward-bound degree of the 'Node'.-outdeg :: (Graph gr) => gr a b -> Node -> Int-outdeg = length .: context4l---- | The inward-bound degree of the 'Node'.-indeg :: (Graph gr) => gr a b -> Node -> Int-indeg  = length .: context1l---- | The degree of the 'Node'.-deg :: (Graph gr) => gr a b -> Node -> Int-deg = deg' .: context---- | The 'Node' in a 'Context'.-node' :: Context a b -> Node-node' (_,v,_,_) = v---- | The label in a 'Context'.-lab' :: Context a b -> a-lab' (_,_,l,_) = l---- | The 'LNode' from a 'Context'.-labNode' :: Context a b -> LNode a-labNode' (_,v,l,_) = (v,l)---- | All 'Node's linked to or from in a 'Context'.-neighbors' :: Context a b -> [Node]-neighbors' (p,_,_,s) = map snd p++map snd s---- | All labelled links coming into or going from a 'Context'.-lneighbors' :: Context a b -> Adj b-lneighbors' (p,_,_,s) = p ++ s---- | All 'Node's linked to in a 'Context'.-suc' :: Context a b -> [Node]-suc' = map snd . context4l'---- | All 'Node's linked from in a 'Context'.-pre' :: Context a b -> [Node]-pre' = map snd . context1l'---- | All 'Node's linked from in a 'Context', and the label of the links.-lsuc' :: Context a b -> [(Node,b)]-lsuc' = map flip2 . context4l'---- | All 'Node's linked from in a 'Context', and the label of the links.-lpre' :: Context a b -> [(Node,b)]-lpre' = map flip2 . context1l'---- | All outward-directed 'LEdge's in a 'Context'.-out' :: Context a b -> [LEdge b]-out' c@(_,v,_,_) = map (\(l,w)->(v,w,l)) (context4l' c)---- | All inward-directed 'LEdge's in a 'Context'.-inn' :: Context a b -> [LEdge b]-inn' c@(_,v,_,_) = map (\(l,w)->(w,v,l)) (context1l' c)---- | The outward degree of a 'Context'.-outdeg' :: Context a b -> Int-outdeg' = length . context4l'---- | The inward degree of a 'Context'.-indeg' :: Context a b -> Int-indeg' = length . context1l'---- | The degree of a 'Context'.-deg' :: Context a b -> Int-deg' (p,_,_,s) = length p+length s---- | Checks if there is a directed edge between two nodes.-hasEdge :: Graph gr => gr a b -> Edge -> Bool-hasEdge gr (v,w) = w `elem` suc gr v---- | Checks if there is an undirected edge between two nodes.-hasNeighbor :: Graph gr => gr a b -> Node -> Node -> Bool-hasNeighbor gr v w = w `elem` neighbors gr v---- | Checks if there is a labelled edge between two nodes.-hasLEdge :: (Graph gr, Eq b) => gr a b -> LEdge b -> Bool-hasLEdge gr (v,w,l) = (w,l) `elem` lsuc gr v---- | Checks if there is an undirected labelled edge between two nodes.-hasNeighborAdj :: (Graph gr, Eq b) => gr a b -> Node -> (b,Node) -> Bool-hasNeighborAdj gr v a = a `elem` lneighbors gr v--------------------------------------------------------------------------- GRAPH EQUALITY-------------------------------------------------------------------------slabNodes :: (Graph gr) => gr a b -> [LNode a]-slabNodes = sortBy (compare `on` fst) . labNodes--glabEdges :: (Graph gr) => gr a b -> [GroupEdges b]-glabEdges = map (GEs . groupLabels)-            . groupBy ((==) `on` toEdge)-            . sortBy (compare `on` toEdge)-            . labEdges-  where-    groupLabels les = toLEdge (toEdge (head les)) (map edgeLabel les)--equal :: (Eq a,Eq b,Graph gr) => gr a b -> gr a b -> Bool-equal g g' = slabNodes g == slabNodes g' && glabEdges g == glabEdges g'--- This assumes that nodes aren't repeated (which shouldn't happen for--- sane graph instances).  If node IDs are repeated, then the usage of--- slabNodes cannot guarantee stable ordering.---- Newtype wrapper just to test for equality of multiple edges.  This--- is needed because without an Ord constraint on `b' it is not--- possible to guarantee a stable ordering on edge labels.-newtype GroupEdges b = GEs (LEdge [b])-  deriving (Show, Read)--instance (Eq b) => Eq (GroupEdges b) where-  (GEs (v1,w1,bs1)) == (GEs (v2,w2,bs2)) = v1 == v2-                                           && w1 == w2-                                           && eqLists bs1 bs2--eqLists :: (Eq a) => [a] -> [a] -> Bool-eqLists xs ys = null (xs \\ ys) && null (ys \\ xs)--- OK to use \\ here as we want each value in xs to cancel a *single*--- value in ys.--------------------------------------------------------------------------- UTILITIES--------------------------------------------------------------------------- auxiliary functions used in the implementation of the--- derived class members----(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d--- f .: g = \x y->f (g x y)--- f .: g = (f .) . g--- (.:) f = ((f .) .)--- (.:) = (.) (.) (.)-(.:) = (.) . (.)--flip2 :: (a,b) -> (b,a)-flip2 (x,y) = (y,x)---- projecting on context elements----context1l :: (Graph gr) => gr a b -> Node -> Adj b-context1l = maybe [] context1l' .: mcontext--context4l :: (Graph gr) => gr a b -> Node -> Adj b-context4l = maybe [] context4l' .: mcontext--mcontext :: (Graph gr) => gr a b -> Node -> MContext a b-mcontext = fst .: flip match--context1l' :: Context a b -> Adj b-context1l' (p,v,_,s) = p++filter ((==v).snd) s--context4l' :: Context a b -> Adj b-context4l' (p,v,_,s) = s++filter ((==v).snd) p--------------------------------------------------------------------------- PRETTY PRINTING--------------------------------------------------------------------------- | Pretty-print the graph.  Note that this loses a lot of---   information, such as edge inverses, etc.-prettify :: (DynGraph gr, Show a, Show b) => gr a b -> String-prettify g = foldr (showsContext . context g) id (nodes g) ""-  where-    showsContext (_,n,l,s) sg = shows n . (':':) . shows l-                                . showString "->" . shows s-                                . ('\n':) . sg---- | Pretty-print the graph to stdout.-prettyPrint :: (DynGraph gr, Show a, Show b) => gr a b -> IO ()-prettyPrint = putStr . prettify--------------------------------------------------------------------------- Ordered Graph--------------------------------------------------------------------------- | OrdGr comes equipped with an Ord instance, so that graphs can be---   used as e.g. Map keys.-newtype OrdGr gr a b = OrdGr { unOrdGr :: gr a b }-  deriving (Read,Show)--instance (Graph gr, Ord a, Ord b) => Eq (OrdGr gr a b) where-  g1 == g2 = compare g1 g2 == EQ--instance (Graph gr, Ord a, Ord b) => Ord (OrdGr gr a b) where-  compare (OrdGr g1) (OrdGr g2) =-    (compare `on` sort . labNodes) g1 g2-    `mappend` (compare `on` sort . labEdges) g1 g2---{-------------------------------------------------------------------Copyright (c) 1999-2008, Martin Erwig-              2010, Ivan Lazar Miljenovic-              2022, Norman Ramsey-All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--1. Redistributions of source code must retain the above copyright notice,-   this list of conditions and the following disclaimer.--2. Redistributions in binary form must reproduce the above copyright-   notice, this list of conditions and the following disclaimer in the-   documentation and/or other materials provided with the distribution.--3. Neither the name of the author nor the names of its contributors may be-   used to endorse or promote products derived from this software without-   specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.------------------------------------------------------------------}
− compiler/GHC/Data/Graph/Inductive/PatriciaTree.hs
@@ -1,346 +0,0 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}-{-# LANGUAGE DeriveGeneric #-}---- |An efficient implementation of 'Data.Graph.Inductive.Graph.Graph'--- using big-endian patricia tree (i.e. "Data.IntMap").------ This module provides the following specialised functions to gain--- more performance, using GHC's RULES pragma:------ * 'Data.Graph.Inductive.Graph.insNode'------ * 'Data.Graph.Inductive.Graph.insEdge'------ * 'Data.Graph.Inductive.Graph.gmap'------ * 'Data.Graph.Inductive.Graph.nmap'------ * 'Data.Graph.Inductive.Graph.emap'------ Code is from Hackage `fgl` package version 5.7.0.3---module GHC.Data.Graph.Inductive.PatriciaTree-    ( Gr-    , UGr-    )-    where--import GHC.Prelude--import GHC.Data.Graph.Inductive.Graph--import           Data.IntMap         (IntMap)-import qualified Data.IntMap         as IM-import           Data.List           (sort)-import           Data.Maybe          (fromMaybe)-import           Data.Tuple          (swap)--import qualified Data.IntMap.Strict as IMS--import GHC.Generics (Generic)--import Data.Bifunctor--------------------------------------------------------------------------- GRAPH REPRESENTATION-------------------------------------------------------------------------newtype Gr a b = Gr (GraphRep a b)-  deriving (Generic)--type GraphRep a b = IntMap (Context' a b)-type Context' a b = (IntMap [b], a, IntMap [b])--type UGr = Gr () ()--------------------------------------------------------------------------- CLASS INSTANCES-------------------------------------------------------------------------instance (Eq a, Ord b) => Eq (Gr a b) where-  (Gr g1) == (Gr g2) = fmap sortAdj g1 == fmap sortAdj g2-    where-      sortAdj (p,n,s) = (fmap sort p,n,fmap sort s)--instance (Show a, Show b) => Show (Gr a b) where-  showsPrec d g = showParen (d > 10) $-                    showString "mkGraph "-                    . shows (labNodes g)-                    . showString " "-                    . shows (labEdges g)--instance (Read a, Read b) => Read (Gr a b) where-  readsPrec p = readParen (p > 10) $ \ r -> do-    ("mkGraph", s) <- lex r-    (ns,t) <- reads s-    (es,u) <- reads t-    return (mkGraph ns es, u)--instance Graph Gr where-    empty           = Gr IM.empty--    isEmpty (Gr g)  = IM.null g--    match           = matchGr--    mkGraph vs es   = insEdges es-                      . Gr-                      . IM.fromList-                      . map (second (\l -> (IM.empty,l,IM.empty)))-                      $ vs--    labNodes (Gr g) = [ (node, label)-                            | (node, (_, label, _)) <- IM.toList g ]--    noNodes   (Gr g) = IM.size g--    nodeRange (Gr g) = fromMaybe (error "nodeRange of empty graph")-                       $ liftA2 (,) (ix (IM.minViewWithKey g))-                                    (ix (IM.maxViewWithKey g))-      where-        ix = fmap (fst . fst)--    labEdges (Gr g) = do (node, (_, _, s)) <- IM.toList g-                         (next, labels)    <- IM.toList s-                         label             <- labels-                         return (node, next, label)--instance DynGraph Gr where-    (p, v, l, s) & (Gr g)-        = let !g1 = IM.insert v (preds, l, succs) g-              !(np, preds) = fromAdjCounting p-              !(ns, succs) = fromAdjCounting s-              !g2 = addSucc g1 v np preds-              !g3 = addPred g2 v ns succs-          in Gr g3---instance Functor (Gr a) where-  fmap = fastEMap--instance Bifunctor Gr where-  bimap = fastNEMap--  first = fastNMap--  second = fastEMap---matchGr :: Node -> Gr a b -> Decomp Gr a b-matchGr node (Gr g)-    = case IM.lookup node g of-        Nothing-            -> (Nothing, Gr g)--        Just (p, label, s)-            -> let !g1 = IM.delete node g-                   !p' = IM.delete node p-                   !s' = IM.delete node s-                   !g2 = clearPred g1 node s'-                   !g3 = clearSucc g2 node p'-               in (Just (toAdj p', node, label, toAdj s), Gr g3)--------------------------------------------------------------------------- OVERRIDING FUNCTIONS-------------------------------------------------------------------------{---{- RULES-      "insNode/Data.Graph.Inductive.PatriciaTree"  insNode = fastInsNode-  -}-fastInsNode :: LNode a -> Gr a b -> Gr a b-fastInsNode (v, l) (Gr g) = g' `seq` Gr g'-  where-    g' = IM.insert v (IM.empty, l, IM.empty) g---}-{-# RULES-      "insEdge/GHC.Data.Graph.Inductive.PatriciaTree"  insEdge = fastInsEdge-  #-}-fastInsEdge :: LEdge b -> Gr a b -> Gr a b-fastInsEdge (v, w, l) (Gr g) = g2 `seq` Gr g2-  where-    g1 = IM.adjust addS' v g-    g2 = IM.adjust addP' w g1--    addS' (ps, l', ss) = (ps, l', IM.insertWith addLists w [l] ss)-    addP' (ps, l', ss) = (IM.insertWith addLists v [l] ps, l', ss)--{---{- RULES-      "gmap/Data.Graph.Inductive.PatriciaTree"  gmap = fastGMap-  -}-fastGMap :: forall a b c d. (Context a b -> Context c d) -> Gr a b -> Gr c d-fastGMap f (Gr g) = Gr (IM.mapWithKey f' g)-  where-    f' :: Node -> Context' a b -> Context' c d-    f' = ((fromContext . f) .) . toContext--{- RULES-      "nmap/Data.Graph.Inductive.PatriciaTree"  nmap = fastNMap-  -}--}-fastNMap :: forall a b c. (a -> c) -> Gr a b -> Gr c b-fastNMap f (Gr g) = Gr (IM.map f' g)-  where-    f' :: Context' a b -> Context' c b-    f' (ps, a, ss) = (ps, f a, ss)-{---{- RULES-      "emap/GHC.Data.Graph.Inductive.PatriciaTree"  emap = fastEMap-   -}--}-fastEMap :: forall a b c. (b -> c) -> Gr a b -> Gr a c-fastEMap f (Gr g) = Gr (IM.map f' g)-  where-    f' :: Context' a b -> Context' a c-    f' (ps, a, ss) = (IM.map (map f) ps, a, IM.map (map f) ss)--{-  RULES-      "nemap/GHC.Data.Graph.Inductive.PatriciaTree"  nemap = fastNEMap-   -}--fastNEMap :: forall a b c d. (a -> c) -> (b -> d) -> Gr a b -> Gr c d-fastNEMap fn fe (Gr g) = Gr (IM.map f g)-  where-    f :: Context' a b -> Context' c d-    f (ps, a, ss) = (IM.map (map fe) ps, fn a, IM.map (map fe) ss)----------------------------------------------------------------------------- UTILITIES-------------------------------------------------------------------------toAdj :: IntMap [b] -> Adj b-toAdj = concatMap expand . IM.toList-  where-    expand (n,ls) = map (flip (,) n) ls----fromAdj :: Adj b -> IntMap [b]---fromAdj = IM.fromListWith addLists . map (second (:[]) . swap)--data FromListCounting a = FromListCounting !Int !(IntMap a)-  deriving (Eq, Show, Read)--getFromListCounting :: FromListCounting a -> (Int, IntMap a)-getFromListCounting (FromListCounting i m) = (i, m)-{-# INLINE getFromListCounting #-}--fromListWithKeyCounting :: (Int -> a -> a -> a) -> [(Int, a)] -> (Int, IntMap a)-fromListWithKeyCounting f = getFromListCounting . foldl' ins (FromListCounting 0 IM.empty)-  where-    ins (FromListCounting i t) (k,x) = FromListCounting (i + 1) (IM.insertWithKey f k x t)-{-# INLINE fromListWithKeyCounting #-}--fromListWithCounting :: (a -> a -> a) -> [(Int, a)] -> (Int, IntMap a)-fromListWithCounting f = fromListWithKeyCounting (\_ x y -> f x y)-{-# INLINE fromListWithCounting #-}--fromAdjCounting :: Adj b -> (Int, IntMap [b])-fromAdjCounting = fromListWithCounting addLists . map (second (:[]) . swap)---- We use differenceWith to modify a graph more than bulkThreshold times,--- and repeated insertWith otherwise.-bulkThreshold :: Int-bulkThreshold = 5----toContext :: Node -> Context' a b -> Context a b---toContext v (ps, a, ss) = (toAdj ps, v, a, toAdj ss)----fromContext :: Context a b -> Context' a b---fromContext (ps, _, a, ss) = (fromAdj ps, a, fromAdj ss)---- A version of @++@ where order isn't important, so @xs ++ [x]@--- becomes @x:xs@.  Used when we have to have a function of type @[a]--- -> [a] -> [a]@ but one of the lists is just going to be a single--- element (and it isn't possible to tell which).-addLists :: [a] -> [a] -> [a]-addLists [a] as  = a : as-addLists as  [a] = a : as-addLists xs  ys  = xs ++ ys--addSucc :: forall a b . GraphRep a b -> Node -> Int -> IM.IntMap [b] -> GraphRep a b-addSucc g0 v numAdd xs-  | numAdd < bulkThreshold = foldlWithKey' go g0 xs-  where-    go :: GraphRep a b -> Node -> [b] -> GraphRep a b-    go g p l = IMS.adjust f p g-      where f (ps, l', ss) = let !ss' = IM.insertWith addLists v l ss-                             in (ps, l', ss')-addSucc g v _ xs = IMS.differenceWith go g xs-  where-    go :: Context' a b -> [b] -> Maybe (Context' a b)-    go (ps, l', ss) l = let !ss' = IM.insertWith addLists v l ss-                        in Just (ps, l', ss')--foldlWithKey' :: (a -> IM.Key -> b -> a) -> a -> IntMap b -> a-foldlWithKey' =-  IM.foldlWithKey'--addPred :: forall a b . GraphRep a b -> Node -> Int -> IM.IntMap [b] -> GraphRep a b-addPred g0 v numAdd xs-  | numAdd < bulkThreshold = foldlWithKey' go g0 xs-  where-    go :: GraphRep a b -> Node -> [b] -> GraphRep a b-    go g p l = IMS.adjust f p g-      where f (ps, l', ss) = let !ps' = IM.insertWith addLists v l ps-                             in (ps', l', ss)-addPred g v _ xs = IMS.differenceWith go g xs-  where-    go :: Context' a b -> [b] -> Maybe (Context' a b)-    go (ps, l', ss) l = let !ps' = IM.insertWith addLists v l ps-                        in Just (ps', l', ss)--clearSucc :: forall a b x . GraphRep a b -> Node -> IM.IntMap x -> GraphRep a b-clearSucc g v = IMS.differenceWith go g-  where-    go :: Context' a b -> x -> Maybe (Context' a b)-    go (ps, l, ss) _ = let !ss' = IM.delete v ss-                       in Just (ps, l, ss')--clearPred :: forall a b x . GraphRep a b -> Node -> IM.IntMap x -> GraphRep a b-clearPred g v = IMS.differenceWith go g-  where-    go :: Context' a b -> x -> Maybe (Context' a b)-    go (ps, l, ss) _ = let !ps' = IM.delete v ps-                       in Just (ps', l, ss)--{-------------------------------------------------------------------Copyright (c) 1999-2008, Martin Erwig-              2010, Ivan Lazar Miljenovic-              2022, Norman Ramsey-All rights reserved.--Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--1. Redistributions of source code must retain the above copyright notice,-   this list of conditions and the following disclaimer.--2. Redistributions in binary form must reproduce the above copyright-   notice, this list of conditions and the following disclaimer in the-   documentation and/or other materials provided with the distribution.--3. Neither the name of the author nor the names of its contributors may be-   used to endorse or promote products derived from this software without-   specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-POSSIBILITY OF SUCH DAMAGE.------------------------------------------------------------------}
− compiler/GHC/Driver/Backpack.hs
@@ -1,944 +0,0 @@--{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TypeFamilies #-}----- | This is the driver for the 'ghc --backpack' mode, which--- is a reimplementation of the "package manager" bits of--- Backpack directly in GHC.  The basic method of operation--- is to compile packages and then directly insert them into--- GHC's in memory database.------ The compilation products of this mode aren't really suitable--- for Cabal, because GHC makes up component IDs for the things--- it builds and doesn't serialize out the database contents.--- But it's still handy for constructing tests.--module GHC.Driver.Backpack (doBackpack) where--import GHC.Prelude--import GHC.Driver.Backend--- In a separate module because it hooks into the parser.-import GHC.Driver.Backpack.Syntax-import GHC.Driver.Config.Finder (initFinderOpts)-import GHC.Driver.Config.Parser (initParserOpts)-import GHC.Driver.Config.Diagnostic-import GHC.Driver.Monad-import GHC.Driver.Session-import GHC.Driver.Ppr-import GHC.Driver.Main-import GHC.Driver.Make-import GHC.Driver.Env-import GHC.Driver.Errors-import GHC.Driver.Errors.Types--import GHC.Parser-import GHC.Parser.Header-import GHC.Parser.Lexer-import GHC.Parser.Annotation--import GHC.Rename.Names--import GHC hiding (Failed, Succeeded)-import GHC.Tc.Utils.Monad-import GHC.Iface.Recomp-import GHC.Builtin.Names--import GHC.Types.SrcLoc-import GHC.Types.SourceError-import GHC.Types.SourceFile-import GHC.Types.Unique.FM-import GHC.Types.Unique.DFM-import GHC.Types.Unique.DSet--import GHC.Utils.Outputable-import GHC.Utils.Fingerprint-import GHC.Utils.Misc-import GHC.Utils.Panic-import GHC.Utils.Error-import GHC.Utils.Logger--import GHC.Unit-import GHC.Unit.Env-import GHC.Unit.External-import GHC.Unit.Finder-import GHC.Unit.Module.Graph-import GHC.Unit.Module.ModSummary-import GHC.Unit.Home.ModInfo--import GHC.Linker.Types--import qualified GHC.LanguageExtensions as LangExt--import GHC.Data.Maybe-import GHC.Data.StringBuffer-import GHC.Data.FastString-import qualified GHC.Data.EnumSet as EnumSet-import qualified GHC.Data.ShortText as ST--import Data.List ( partition )-import System.Exit-import Control.Monad-import System.FilePath-import Data.Version---- for the unification-import Data.IORef-import Data.Map (Map)-import qualified Data.Map as Map-import qualified Data.Set as Set---- | Entry point to compile a Backpack file.-doBackpack :: [FilePath] -> Ghc ()-doBackpack [src_filename] = do-    -- Apply options from file to dflags-    dflags0 <- getDynFlags-    let dflags1 = dflags0-    let parser_opts1 = initParserOpts dflags1-    (p_warns, src_opts) <- liftIO $ getOptionsFromFile parser_opts1 src_filename-    (dflags, unhandled_flags, warns) <- liftIO $ parseDynamicFilePragma dflags1 src_opts-    modifySession (hscSetFlags dflags)-    logger <- getLogger -- Get the logger after having set the session flags,-                        -- so that logger options are correctly set.-                        -- Not doing so caused #20396.-    -- Cribbed from: preprocessFile / GHC.Driver.Pipeline-    liftIO $ checkProcessArgsResult unhandled_flags-    let print_config = initPrintConfig dflags-    liftIO $ printOrThrowDiagnostics logger print_config (initDiagOpts dflags) (GhcPsMessage <$> p_warns)-    liftIO $ handleFlagWarnings logger print_config (initDiagOpts dflags) warns-    -- TODO: Preprocessing not implemented--    buf <- liftIO $ hGetStringBuffer src_filename-    let loc = mkRealSrcLoc (mkFastString src_filename) 1 1 -- TODO: not great-    case unP parseBackpack (initParserState (initParserOpts dflags) buf loc) of-        PFailed pst -> throwErrors (GhcPsMessage <$> getPsErrorMessages pst)-        POk _ pkgname_bkp -> do-            -- OK, so we have an LHsUnit PackageName, but we want an-            -- LHsUnit HsComponentId.  So let's rename it.-            hsc_env <- getSession-            let bkp = renameHsUnits (hsc_units hsc_env) (bkpPackageNameMap pkgname_bkp) pkgname_bkp-            initBkpM src_filename bkp $-                forM_ (zip [1..] bkp) $ \(i, lunit) -> do-                    let comp_name = unLoc (hsunitName (unLoc lunit))-                    msgTopPackage (i,length bkp) comp_name-                    innerBkpM $ do-                        let (cid, insts) = computeUnitId lunit-                        if null insts-                            then if cid == UnitId (fsLit "main")-                                    then compileExe lunit-                                    else compileUnit cid []-                            else typecheckUnit cid insts-doBackpack _ =-    throwGhcException (CmdLineError "--backpack can only process a single file")--computeUnitId :: LHsUnit HsComponentId -> (UnitId, [(ModuleName, Module)])-computeUnitId (L _ unit) = (cid, [ (r, mkHoleModule r) | r <- reqs ])-  where-    cid = hsComponentId (unLoc (hsunitName unit))-    reqs = uniqDSetToList (unionManyUniqDSets (map (get_reqs . unLoc) (hsunitBody unit)))-    get_reqs (DeclD HsigFile (L _ modname) _) = unitUniqDSet modname-    get_reqs (DeclD HsSrcFile _ _) = emptyUniqDSet-    get_reqs (DeclD HsBootFile _ _) = emptyUniqDSet-    get_reqs (IncludeD (IncludeDecl (L _ hsuid) _ _)) =-        unitFreeModuleHoles (convertHsComponentId hsuid)---- | Tiny enum for all types of Backpack operations we may do.-data SessionType-    -- | A compilation operation which will result in a-    -- runnable executable being produced.-    = ExeSession-    -- | A type-checking operation which produces only-    -- interface files, no object files.-    | TcSession-    -- | A compilation operation which produces both-    -- interface files and object files.-    | CompSession-    deriving (Eq)---- | Create a temporary Session to do some sort of type checking or--- compilation.-withBkpSession :: UnitId-               -> [(ModuleName, Module)]-               -> [(Unit, ModRenaming)]-               -> SessionType   -- what kind of session are we doing-               -> BkpM a        -- actual action to run-               -> BkpM a-withBkpSession cid insts deps session_type do_this = do-    dflags <- getDynFlags-    let cid_fs = unitFS cid-        is_primary = False-        uid_str = unpackFS (mkInstantiatedUnitHash cid insts)-        cid_str = unpackFS cid_fs-        -- There are multiple units in a single Backpack file, so we-        -- need to separate out the results in those cases.  Right now,-        -- we follow this hierarchy:-        --      $outputdir/$compid          --> typecheck results-        --      $outputdir/$compid/$unitid  --> compile results-        key_base p | Just f <- p dflags = f-                   | otherwise          = "."-        sub_comp p | is_primary = p-                   | otherwise = p </> cid_str-        outdir p | CompSession <- session_type-                 -- Special case when package is definite-                 , not (null insts) = sub_comp (key_base p) </> uid_str-                 | otherwise = sub_comp (key_base p)--        mk_temp_env hsc_env =-          hscUpdateFlags (\dflags -> mk_temp_dflags (hsc_units hsc_env) dflags) hsc_env-        mk_temp_dflags unit_state dflags = dflags-            { backend = case session_type of-                            TcSession -> noBackend-                            _         -> backend dflags-            , ghcLink = case session_type of-                            TcSession -> NoLink-                            _         -> ghcLink dflags-            , homeUnitInstantiations_ = insts-                                     -- if we don't have any instantiation, don't-                                     -- fill `homeUnitInstanceOfId` as it makes no-                                     -- sense (we're not instantiating anything)-            , homeUnitInstanceOf_   = if null insts then Nothing else Just cid-            , homeUnitId_ = case session_type of-                TcSession -> newUnitId cid Nothing-                -- No hash passed if no instances-                _ | null insts -> newUnitId cid Nothing-                  | otherwise  -> newUnitId cid (Just (mkInstantiatedUnitHash cid insts))---            -- If we're type-checking an indefinite package, we want to-            -- turn on interface writing.  However, if the user also-            -- explicitly passed in `-fno-code`, we DON'T want to write-            -- interfaces unless the user also asked for `-fwrite-interface`.-            -- See Note [-fno-code mode]-            , generalFlags = case session_type of-                -- Make sure to write interfaces when we are type-checking-                -- indefinite packages.-                TcSession-                  | backendSupportsInterfaceWriting $ backend dflags-                  -> EnumSet.insert Opt_WriteInterface (generalFlags dflags)-                _ -> generalFlags dflags--            -- Setup all of the output directories according to our hierarchy-            , objectDir   = Just (outdir objectDir)-            , hiDir       = Just (outdir hiDir)-            , stubDir     = Just (outdir stubDir)-            -- Unset output-file for non exe builds-            , outputFile_ = case session_type of-                ExeSession -> outputFile_ dflags-                _          -> Nothing-            , dynOutputFile_ = case session_type of-                ExeSession -> dynOutputFile_ dflags-                _          -> Nothing-            -- Clear the import path so we don't accidentally grab anything-            , importPaths = []-            -- Synthesize the flags-            , packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->-              let uid = unwireUnit unit_state-                        $ improveUnit unit_state-                        $ renameHoleUnit unit_state (listToUFM insts) uid0-              in ExposePackage-                (showSDoc dflags-                    (text "-unit-id" <+> ppr uid <+> ppr rn))-                (UnitIdArg uid) rn) deps-            }-    withTempSession mk_temp_env $ do-      dflags <- getSessionDynFlags-      -- pprTrace "flags" (ppr insts <> ppr deps) $ return ()-      setSessionDynFlags dflags -- calls initUnits-      do_this--withBkpExeSession :: [(Unit, ModRenaming)] -> BkpM a -> BkpM a-withBkpExeSession deps do_this =-    withBkpSession (UnitId (fsLit "main")) [] deps ExeSession do_this--getSource :: UnitId -> BkpM (LHsUnit HsComponentId)-getSource cid = do-    bkp_env <- getBkpEnv-    case Map.lookup cid (bkp_table bkp_env) of-        Nothing -> pprPanic "missing needed dependency" (ppr cid)-        Just lunit -> return lunit--typecheckUnit :: UnitId -> [(ModuleName, Module)] -> BkpM ()-typecheckUnit cid insts = do-    lunit <- getSource cid-    buildUnit TcSession cid insts lunit--compileUnit :: UnitId -> [(ModuleName, Module)] -> BkpM ()-compileUnit cid insts = do-    -- Let everyone know we're building this unit-    msgUnitId (mkVirtUnit cid insts)-    lunit <- getSource cid-    buildUnit CompSession cid insts lunit---- | Compute the dependencies with instantiations of a syntactic--- HsUnit; e.g., wherever you see @dependency p[A=<A>]@ in a--- unit file, return the 'Unit' corresponding to @p[A=<A>]@.--- The @include_sigs@ parameter controls whether or not we also--- include @dependency signature@ declarations in this calculation.------ Invariant: this NEVER returns UnitId.-hsunitDeps :: Bool {- include sigs -} -> HsUnit HsComponentId -> [(Unit, ModRenaming)]-hsunitDeps include_sigs unit = concatMap get_dep (hsunitBody unit)-  where-    get_dep (L _ (IncludeD (IncludeDecl (L _ hsuid) mb_lrn is_sig)))-        | include_sigs || not is_sig = [(convertHsComponentId hsuid, go mb_lrn)]-        | otherwise = []-      where-        go Nothing = ModRenaming True []-        go (Just lrns) = ModRenaming False (map convRn lrns)-          where-            convRn (L _ (Renaming (L _ from) Nothing))         = (from, from)-            convRn (L _ (Renaming (L _ from) (Just (L _ to)))) = (from, to)-    get_dep _ = []--buildUnit :: SessionType -> UnitId -> [(ModuleName, Module)] -> LHsUnit HsComponentId -> BkpM ()-buildUnit session cid insts lunit = do-    -- NB: include signature dependencies ONLY when typechecking.-    -- If we're compiling, it's not necessary to recursively-    -- compile a signature since it isn't going to produce-    -- any object files.-    let deps_w_rns = hsunitDeps (session == TcSession) (unLoc lunit)-        raw_deps = map fst deps_w_rns-    hsc_env <- getSession-    -- The compilation dependencies are just the appropriately filled-    -- in unit IDs which must be compiled before we can compile.-    let hsubst = listToUFM insts-        deps0 = map (renameHoleUnit (hsc_units hsc_env) hsubst) raw_deps--    -- Build dependencies OR make sure they make sense. BUT NOTE,-    -- we can only check the ones that are fully filled; the rest-    -- we have to defer until we've typechecked our local signature.-    -- TODO: work this into GHC.Driver.Make!!-    forM_ (zip [1..] deps0) $ \(i, dep) ->-        case session of-            TcSession -> return ()-            _ -> compileInclude (length deps0) (i, dep)--    -- IMPROVE IT-    let deps = map (improveUnit (hsc_units hsc_env)) deps0--    mb_old_eps <- case session of-                    TcSession -> fmap Just getEpsGhc-                    _ -> return Nothing--    conf <- withBkpSession cid insts deps_w_rns session $ do--        dflags <- getDynFlags-        mod_graph <- hsunitModuleGraph False (unLoc lunit)--        msg <- mkBackpackMsg-        ok <- load' noIfaceCache LoadAllTargets (Just msg) mod_graph-        when (failed ok) (liftIO $ exitWith (ExitFailure 1))--        let hi_dir = expectJust (panic "hiDir Backpack") $ hiDir dflags-            export_mod ms = (ms_mod_name ms, ms_mod ms)-            -- Export everything!-            mods = [ export_mod ms | ms <- mgModSummaries mod_graph-                                   , ms_hsc_src ms == HsSrcFile ]--        -- Compile relevant only-        hsc_env <- getSession-        let home_mod_infos = eltsUDFM (hsc_HPT hsc_env)-            linkables = map (expectJust "bkp link" . homeModInfoObject)-                      . filter ((==HsSrcFile) . mi_hsc_src . hm_iface)-                      $ home_mod_infos-            getOfiles LM{ linkableUnlinked = us } = map nameOfObject (filter isObject us)-            obj_files = concatMap getOfiles linkables-            state     = hsc_units hsc_env--        let compat_fs = unitIdFS cid-            compat_pn = PackageName compat_fs-            unit_id   = homeUnitId (hsc_home_unit hsc_env)--        return GenericUnitInfo {-            -- Stub data-            unitAbiHash = "",-            unitPackageId = PackageId compat_fs,-            unitPackageName = compat_pn,-            unitPackageVersion = makeVersion [],-            unitId = unit_id,-            unitComponentName = Nothing,-            unitInstanceOf = cid,-            unitInstantiations = insts,-            -- Slight inefficiency here haha-            unitExposedModules = map (\(m,n) -> (m,Just n)) mods,-            unitHiddenModules = [], -- TODO: doc only-            unitDepends = case session of-                        -- Technically, we should state that we depend-                        -- on all the indefinite libraries we used to-                        -- typecheck this.  However, this field isn't-                        -- really used for anything, so we leave it-                        -- blank for now.-                        TcSession -> []-                        _ -> map (toUnitId . unwireUnit state)-                                $ deps ++ [ moduleUnit mod-                                          | (_, mod) <- insts-                                          , not (isHoleModule mod) ],-            unitAbiDepends = [],-            unitLinkerOptions = case session of-                                 TcSession -> []-                                 _ -> map ST.pack $ obj_files,-            unitImportDirs = [ ST.pack $ hi_dir ],-            unitIsExposed = False,-            unitIsIndefinite = case session of-                                 TcSession -> True-                                 _ -> False,-            -- nope-            unitLibraries = [],-            unitExtDepLibsSys = [],-            unitExtDepLibsGhc = [],-            unitLibraryDynDirs = [],-            unitLibraryDirs = [],-            unitExtDepFrameworks = [],-            unitExtDepFrameworkDirs = [],-            unitCcOptions = [],-            unitIncludes = [],-            unitIncludeDirs = [],-            unitHaddockInterfaces = [],-            unitHaddockHTMLs = [],-            unitIsTrusted = False-            }---    addUnit conf-    case mb_old_eps of-        Just old_eps -> updateEpsGhc_ (const old_eps)-        _ -> return ()--compileExe :: LHsUnit HsComponentId -> BkpM ()-compileExe lunit = do-    msgUnitId mainUnit-    let deps_w_rns = hsunitDeps False (unLoc lunit)-        deps = map fst deps_w_rns-        -- no renaming necessary-    forM_ (zip [1..] deps) $ \(i, dep) ->-        compileInclude (length deps) (i, dep)-    withBkpExeSession deps_w_rns $ do-        mod_graph <- hsunitModuleGraph True (unLoc lunit)-        msg <- mkBackpackMsg-        ok <- load' noIfaceCache LoadAllTargets (Just msg) mod_graph-        when (failed ok) (liftIO $ exitWith (ExitFailure 1))---- | Register a new virtual unit database containing a single unit-addUnit :: GhcMonad m => UnitInfo -> m ()-addUnit u = do-    hsc_env <- getSession-    logger <- getLogger-    let dflags0 = hsc_dflags hsc_env-    let old_unit_env = hsc_unit_env hsc_env-    newdbs <- case ue_unit_dbs old_unit_env of-        Nothing  -> panic "addUnit: called too early"-        Just dbs ->-         let newdb = UnitDatabase-               { unitDatabasePath  = "(in memory " ++ showSDoc dflags0 (ppr (unitId u)) ++ ")"-               , unitDatabaseUnits = [u]-               }-         in return (dbs ++ [newdb]) -- added at the end because ordering matters-    (dbs,unit_state,home_unit,mconstants) <- liftIO $ initUnits logger dflags0 (Just newdbs) (hsc_all_home_unit_ids hsc_env)--    -- update platform constants-    dflags <- liftIO $ updatePlatformConstants dflags0 mconstants--    let unit_env = ue_setUnits unit_state $ ue_setUnitDbs (Just dbs) $ UnitEnv-          { ue_platform  = targetPlatform dflags-          , ue_namever   = ghcNameVersion dflags-          , ue_current_unit = homeUnitId home_unit--          , ue_home_unit_graph =-                unitEnv_singleton-                    (homeUnitId home_unit)-                    (mkHomeUnitEnv dflags (ue_hpt old_unit_env) (Just home_unit))-          , ue_eps       = ue_eps old_unit_env-          }-    setSession $ hscSetFlags dflags $ hsc_env { hsc_unit_env = unit_env }--compileInclude :: Int -> (Int, Unit) -> BkpM ()-compileInclude n (i, uid) = do-    hsc_env <- getSession-    let pkgs = hsc_units hsc_env-    msgInclude (i, n) uid-    -- Check if we've compiled it already-    case uid of-      HoleUnit   -> return ()-      RealUnit _ -> return ()-      VirtUnit i -> case lookupUnit pkgs uid of-        Nothing -> innerBkpM $ compileUnit (instUnitInstanceOf i) (instUnitInsts i)-        Just _  -> return ()---- ------------------------------------------------------------------------------- Backpack monad---- | Backpack monad is a 'GhcMonad' which also maintains a little extra state--- beyond the 'Session', c.f. 'BkpEnv'.-type BkpM = IOEnv BkpEnv---- | Backpack environment.  NB: this has a 'Session' and not an 'HscEnv',--- because we are going to update the 'HscEnv' as we go.-data BkpEnv-    = BkpEnv {-        -- | The session-        bkp_session :: Session,-        -- | The filename of the bkp file we're compiling-        bkp_filename :: FilePath,-        -- | Table of source units which we know how to compile-        bkp_table :: Map UnitId (LHsUnit HsComponentId),-        -- | When a package we are compiling includes another package-        -- which has not been compiled, we bump the level and compile-        -- that.-        bkp_level :: Int-    }---- Blah, to get rid of the default instance for IOEnv--- TODO: just make a proper new monad for BkpM, rather than use IOEnv-instance {-# OVERLAPPING #-} HasDynFlags BkpM where-    getDynFlags = fmap hsc_dflags getSession-instance {-# OVERLAPPING #-} HasLogger BkpM where-    getLogger = fmap hsc_logger getSession---instance GhcMonad BkpM where-    getSession = do-        Session s <- fmap bkp_session getEnv-        readMutVar s-    setSession hsc_env = do-        Session s <- fmap bkp_session getEnv-        writeMutVar s hsc_env---- | Get the current 'BkpEnv'.-getBkpEnv :: BkpM BkpEnv-getBkpEnv = getEnv---- | Get the nesting level, when recursively compiling modules.-getBkpLevel :: BkpM Int-getBkpLevel = bkp_level `fmap` getBkpEnv---- | Run a 'BkpM' computation, with the nesting level bumped one.-innerBkpM :: BkpM a -> BkpM a-innerBkpM do_this =-    -- NB: withTempSession mutates, so we don't have to worry-    -- about bkp_session being stale.-    updEnv (\env -> env { bkp_level = bkp_level env + 1 }) do_this---- | Update the EPS from a 'GhcMonad'. TODO move to appropriate library spot.-updateEpsGhc_ :: GhcMonad m => (ExternalPackageState -> ExternalPackageState) -> m ()-updateEpsGhc_ f = do-    hsc_env <- getSession-    liftIO $ atomicModifyIORef' (euc_eps (ue_eps (hsc_unit_env hsc_env))) (\x -> (f x, ()))---- | Get the EPS from a 'GhcMonad'.-getEpsGhc :: GhcMonad m => m ExternalPackageState-getEpsGhc = do-    hsc_env <- getSession-    liftIO $ hscEPS hsc_env---- | Run 'BkpM' in 'Ghc'.-initBkpM :: FilePath -> [LHsUnit HsComponentId] -> BkpM a -> Ghc a-initBkpM file bkp m =-  reifyGhc $ \session -> do-    let env = BkpEnv {-        bkp_session = session,-        bkp_table = Map.fromList [(hsComponentId (unLoc (hsunitName (unLoc u))), u) | u <- bkp],-        bkp_filename = file,-        bkp_level = 0-      }-    runIOEnv env m---- ------------------------------------------------------------------------------- Messaging---- | Print a compilation progress message, but with indentation according--- to @level@ (for nested compilation).-backpackProgressMsg :: Int -> Logger -> SDoc -> IO ()-backpackProgressMsg level logger msg =-    compilationProgressMsg logger $ text (replicate (level * 2) ' ') -- TODO: use GHC.Utils.Ppr.RStr-                                    <> msg---- | Creates a 'Messager' for Backpack compilation; this is basically--- a carbon copy of 'batchMsg' but calling 'backpackProgressMsg', which--- handles indentation.-mkBackpackMsg :: BkpM Messager-mkBackpackMsg = do-    level <- getBkpLevel-    return $ \hsc_env mod_index recomp node ->-      let dflags = hsc_dflags hsc_env-          logger = hsc_logger hsc_env-          state = hsc_units hsc_env-          showMsg msg reason =-            backpackProgressMsg level logger $ pprWithUnitState state $-                showModuleIndex mod_index <>-                msg <> showModMsg dflags (recompileRequired recomp) node-                    <> reason-      in case node of-        InstantiationNode _ _ ->-          case recomp of-            UpToDate-              | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping  ") empty-              | otherwise -> return ()-            NeedsRecompile reason0 -> showMsg (text "Instantiating ") $ case reason0 of-              MustCompile -> empty-              RecompBecause reason -> text " [" <> pprWithUnitState state (ppr reason) <> text "]"-        ModuleNode _ _ ->-          case recomp of-            UpToDate-              | verbosity (hsc_dflags hsc_env) >= 2 -> showMsg (text "Skipping  ") empty-              | otherwise -> return ()-            NeedsRecompile reason0 -> showMsg (text "Compiling ") $ case reason0 of-              MustCompile -> empty-              RecompBecause reason -> text " [" <> pprWithUnitState state (ppr reason) <> text "]"-        LinkNode _ _ -> showMsg (text "Linking ")  empty---- | 'PprStyle' for Backpack messages; here we usually want the module to--- be qualified (so we can tell how it was instantiated.) But we try not--- to qualify packages so we can use simple names for them.-backpackStyle :: PprStyle-backpackStyle =-    mkUserStyle-        (QueryQualify neverQualifyNames-                      alwaysQualifyModules-                      neverQualifyPackages-                      alwaysPrintPromTick)-        AllTheWay---- | Message when we initially process a Backpack unit.-msgTopPackage :: (Int,Int) -> HsComponentId -> BkpM ()-msgTopPackage (i,n) (HsComponentId (PackageName fs_pn) _) = do-    logger <- getLogger-    level <- getBkpLevel-    liftIO . backpackProgressMsg level logger-        $ showModuleIndex (i, n) <> text "Processing " <> ftext fs_pn---- | Message when we instantiate a Backpack unit.-msgUnitId :: Unit -> BkpM ()-msgUnitId pk = do-    logger <- getLogger-    hsc_env <- getSession-    level <- getBkpLevel-    let state = hsc_units hsc_env-    liftIO . backpackProgressMsg level logger-        $ pprWithUnitState state-        $ text "Instantiating "-           <> withPprStyle backpackStyle (ppr pk)---- | Message when we include a Backpack unit.-msgInclude :: (Int,Int) -> Unit -> BkpM ()-msgInclude (i,n) uid = do-    logger <- getLogger-    hsc_env <- getSession-    level <- getBkpLevel-    let state = hsc_units hsc_env-    liftIO . backpackProgressMsg level logger-        $ pprWithUnitState state-        $ showModuleIndex (i, n) <> text "Including "-            <> withPprStyle backpackStyle (ppr uid)---- ------------------------------------------------------------------------------- Conversion from PackageName to HsComponentId--type PackageNameMap a = UniqFM PackageName a---- For now, something really simple, since we're not actually going--- to use this for anything-unitDefines :: LHsUnit PackageName -> (PackageName, HsComponentId)-unitDefines (L _ HsUnit{ hsunitName = L _ pn@(PackageName fs) })-    = (pn, HsComponentId pn (UnitId fs))--bkpPackageNameMap :: [LHsUnit PackageName] -> PackageNameMap HsComponentId-bkpPackageNameMap units = listToUFM (map unitDefines units)--renameHsUnits :: UnitState -> PackageNameMap HsComponentId -> [LHsUnit PackageName] -> [LHsUnit HsComponentId]-renameHsUnits pkgstate m units = map (fmap renameHsUnit) units-  where--    renamePackageName :: PackageName -> HsComponentId-    renamePackageName pn =-        case lookupUFM m pn of-            Nothing ->-                case lookupPackageName pkgstate pn of-                    Nothing -> error "no package name"-                    Just cid -> HsComponentId pn cid-            Just hscid -> hscid--    renameHsUnit :: HsUnit PackageName -> HsUnit HsComponentId-    renameHsUnit u =-        HsUnit {-            hsunitName = fmap renamePackageName (hsunitName u),-            hsunitBody = map (fmap renameHsUnitDecl) (hsunitBody u)-        }--    renameHsUnitDecl :: HsUnitDecl PackageName -> HsUnitDecl HsComponentId-    renameHsUnitDecl (DeclD a b c) = DeclD a b c-    renameHsUnitDecl (IncludeD idecl) =-        IncludeD IncludeDecl {-            idUnitId = fmap renameHsUnitId (idUnitId idecl),-            idModRenaming = idModRenaming idecl,-            idSignatureInclude = idSignatureInclude idecl-        }--    renameHsUnitId :: HsUnitId PackageName -> HsUnitId HsComponentId-    renameHsUnitId (HsUnitId ln subst)-        = HsUnitId (fmap renamePackageName ln) (map (fmap renameHsModuleSubst) subst)--    renameHsModuleSubst :: HsModuleSubst PackageName -> HsModuleSubst HsComponentId-    renameHsModuleSubst (lk, lm)-        = (lk, fmap renameHsModuleId lm)--    renameHsModuleId :: HsModuleId PackageName -> HsModuleId HsComponentId-    renameHsModuleId (HsModuleVar lm) = HsModuleVar lm-    renameHsModuleId (HsModuleId luid lm) = HsModuleId (fmap renameHsUnitId luid) lm--convertHsComponentId :: HsUnitId HsComponentId -> Unit-convertHsComponentId (HsUnitId (L _ hscid) subst)-    = mkVirtUnit (hsComponentId hscid) (map (convertHsModuleSubst . unLoc) subst)--convertHsModuleSubst :: HsModuleSubst HsComponentId -> (ModuleName, Module)-convertHsModuleSubst (L _ modname, L _ m) = (modname, convertHsModuleId m)--convertHsModuleId :: HsModuleId HsComponentId -> Module-convertHsModuleId (HsModuleVar (L _ modname)) = mkHoleModule modname-convertHsModuleId (HsModuleId (L _ hsuid) (L _ modname)) = mkModule (convertHsComponentId hsuid) modname----{--************************************************************************-*                                                                      *-                        Module graph construction-*                                                                      *-************************************************************************--}---- | This is our version of GHC.Driver.Make.downsweep, but with a few modifications:------  1. Every module is required to be mentioned, so we don't do any funny---     business with targets or recursively grabbing dependencies.  (We---     could support this in principle).---  2. We support inline modules, whose summary we have to synthesize ourself.------ We don't bother trying to support GHC.Driver.Make for now, it's more trouble--- than it's worth for inline modules.-hsunitModuleGraph :: Bool -> HsUnit HsComponentId -> BkpM ModuleGraph-hsunitModuleGraph do_link unit = do-    hsc_env <- getSession--    let decls = hsunitBody unit-        pn = hsPackageName (unLoc (hsunitName unit))-        home_unit = hsc_home_unit hsc_env--        sig_keys = flip map (homeUnitInstantiations home_unit) $ \(mod_name, _) -> NodeKey_Module (ModNodeKeyWithUid (GWIB mod_name NotBoot) (homeUnitId home_unit))-        keys = [NodeKey_Module (ModNodeKeyWithUid gwib (homeUnitId home_unit)) | (DeclD hsc_src lmodname _) <- map unLoc decls, let gwib = GWIB (unLoc lmodname) (hscSourceToIsBoot hsc_src) ]--    --  1. Create a HsSrcFile/HsigFile summary for every-    --  explicitly mentioned module/signature.-    let get_decl (L _ (DeclD hsc_src lmodname hsmod)) =-          Just <$> summariseDecl pn hsc_src lmodname hsmod (keys ++ sig_keys)-        get_decl _ = return Nothing-    nodes <- mapMaybeM get_decl decls--    --  2. For each hole which does not already have an hsig file,-    --  create an "empty" hsig file to induce compilation for the-    --  requirement.-    let hsig_set = Set.fromList-          [ ms_mod_name ms-          | ModuleNode _ ms <- nodes-          , ms_hsc_src ms == HsigFile-          ]-    req_nodes <- fmap catMaybes . forM (homeUnitInstantiations home_unit) $ \(mod_name, _) ->-        if Set.member mod_name hsig_set-            then return Nothing-            else fmap Just $ summariseRequirement pn mod_name--    let graph_nodes = nodes ++ req_nodes ++ (instantiationNodes (homeUnitId $ hsc_home_unit hsc_env) (hsc_units hsc_env))-        key_nodes = map mkNodeKey graph_nodes-        all_nodes = graph_nodes ++ [LinkNode key_nodes (homeUnitId $ hsc_home_unit hsc_env) | do_link]-    -- This error message is not very good but .bkp mode is just for testing so-    -- better to be direct rather than pretty.-    when-      (length key_nodes /= length (ordNub key_nodes))-      (pprPanic "Duplicate nodes keys in backpack file" (ppr key_nodes))--    -- 3. Return the kaboodle-    return $ mkModuleGraph $ all_nodes---summariseRequirement :: PackageName -> ModuleName -> BkpM ModuleGraphNode-summariseRequirement pn mod_name = do-    hsc_env <- getSession-    let dflags = hsc_dflags hsc_env-    let home_unit = hsc_home_unit hsc_env-    let fopts = initFinderOpts dflags--    let PackageName pn_fs = pn-    let location = mkHomeModLocation2 fopts mod_name-                    (unpackFS pn_fs </> moduleNameSlashes mod_name) "hsig"--    env <- getBkpEnv-    src_hash <- liftIO $ getFileHash (bkp_filename env)-    hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file location)-    hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)-    let loc = srcLocSpan (mkSrcLoc (mkFastString (bkp_filename env)) 1 1)--    let fc = hsc_FC hsc_env-    mod <- liftIO $ addHomeModuleToFinder fc home_unit mod_name location--    extra_sig_imports <- liftIO $ findExtraSigImports hsc_env HsigFile mod_name--    let ms = ModSummary {-        ms_mod = mod,-        ms_hsc_src = HsigFile,-        ms_location = location,-        ms_hs_hash = src_hash,-        ms_obj_date = Nothing,-        ms_dyn_obj_date = Nothing,-        ms_iface_date = hi_timestamp,-        ms_hie_date = hie_timestamp,-        ms_srcimps = [],-        ms_textual_imps = ((,) NoPkgQual . noLoc) <$> extra_sig_imports,-        ms_ghc_prim_import = False,-        ms_parsed_mod = Just (HsParsedModule {-                hpm_module = L loc (HsModule {-                        hsmodExt = XModulePs {-                            hsmodAnn = noAnn,-                            hsmodLayout = NoLayoutInfo,-                            hsmodDeprecMessage = Nothing,-                            hsmodHaddockModHeader = Nothing-                                             },-                        hsmodName = Just (L (noAnnSrcSpan loc) mod_name),-                        hsmodExports = Nothing,-                        hsmodImports = [],-                        hsmodDecls = []-                    }),-                hpm_src_files = []-            }),-        ms_hspp_file = "", -- none, it came inline-        ms_hspp_opts = dflags,-        ms_hspp_buf = Nothing-        }-    let nodes = [NodeKey_Module (ModNodeKeyWithUid (GWIB mn NotBoot) (homeUnitId home_unit)) | mn <- extra_sig_imports ]-    return (ModuleNode nodes ms)--summariseDecl :: PackageName-              -> HscSource-              -> Located ModuleName-              -> Located (HsModule GhcPs)-              -> [NodeKey]-              -> BkpM ModuleGraphNode-summariseDecl pn hsc_src (L _ modname) hsmod home_keys = hsModuleToModSummary home_keys pn hsc_src modname hsmod---- | Up until now, GHC has assumed a single compilation target per source file.--- Backpack files with inline modules break this model, since a single file--- may generate multiple output files.  How do we decide to name these files?--- Should there only be one output file? This function our current heuristic,--- which is we make a "fake" module and use that.-hsModuleToModSummary :: [NodeKey]-                     -> PackageName-                     -> HscSource-                     -> ModuleName-                     -> Located (HsModule GhcPs)-                     -> BkpM ModuleGraphNode-hsModuleToModSummary home_keys pn hsc_src modname-                     hsmod = do-    let imps = hsmodImports (unLoc hsmod)-        loc  = getLoc hsmod-    hsc_env <- getSession-    -- Sort of the same deal as in GHC.Driver.Pipeline's getLocation-    -- Use the PACKAGE NAME to find the location-    let PackageName unit_fs = pn-        dflags = hsc_dflags hsc_env-        fopts = initFinderOpts dflags-    -- Unfortunately, we have to define a "fake" location in-    -- order to appease the various code which uses the file-    -- name to figure out where to put, e.g. object files.-    -- To add insult to injury, we don't even actually use-    -- these filenames to figure out where the hi files go.-    -- A travesty!-    let location0 = mkHomeModLocation2 fopts modname-                             (unpackFS unit_fs </>-                              moduleNameSlashes modname)-                              (case hsc_src of-                                HsigFile -> "hsig"-                                HsBootFile -> "hs-boot"-                                HsSrcFile -> "hs")-    -- DANGEROUS: bootifying can POISON the module finder cache-    let location = case hsc_src of-                        HsBootFile -> addBootSuffixLocnOut location0-                        _ -> location0-    -- This duplicates a pile of logic in GHC.Driver.Make-    hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file location)-    hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)--    -- Also copied from 'getImports'-    let (src_idecls, ord_idecls) = partition ((== IsBoot) . ideclSource . unLoc) imps--             -- GHC.Prim doesn't exist physically, so don't go looking for it.-        (ordinary_imps, ghc_prim_import)-          = partition ((/= moduleName gHC_PRIM) . unLoc . ideclName . unLoc)-              ord_idecls--        implicit_prelude = xopt LangExt.ImplicitPrelude dflags-        implicit_imports = mkPrelImports modname loc-                                         implicit_prelude imps--        rn_pkg_qual = renameRawPkgQual (hsc_unit_env hsc_env) modname-        convImport (L _ i) = (rn_pkg_qual (ideclPkgQual i), reLoc $ ideclName i)--    extra_sig_imports <- liftIO $ findExtraSigImports hsc_env hsc_src modname--    let normal_imports = map convImport (implicit_imports ++ ordinary_imps)-    (implicit_sigs, inst_deps) <- liftIO $ implicitRequirementsShallow hsc_env normal_imports--    -- So that Finder can find it, even though it doesn't exist...-    this_mod <- liftIO $ do-      let home_unit = hsc_home_unit hsc_env-      let fc        = hsc_FC hsc_env-      addHomeModuleToFinder fc home_unit modname location-    let ms = ModSummary {-            ms_mod = this_mod,-            ms_hsc_src = hsc_src,-            ms_location = location,-            ms_hspp_file = (case hiDir dflags of-                            Nothing -> ""-                            Just d -> d) </> ".." </> moduleNameSlashes modname <.> "hi",-            ms_hspp_opts = dflags,-            ms_hspp_buf = Nothing,-            ms_srcimps = map convImport src_idecls,-            ms_ghc_prim_import = not (null ghc_prim_import),-            ms_textual_imps = normal_imports-                           -- We have to do something special here:-                           -- due to merging, requirements may end up with-                           -- extra imports-                           ++ ((,) NoPkgQual . noLoc <$> extra_sig_imports)-                           ++ ((,) NoPkgQual . noLoc <$> implicit_sigs),-            -- This is our hack to get the parse tree to the right spot-            ms_parsed_mod = Just (HsParsedModule {-                    hpm_module = hsmod,-                    hpm_src_files = [] -- TODO if we preprocessed it-                }),-            -- Source hash = fingerprint0, so the recompilation tests do not recompile-            -- too much. In future, if necessary then could get the hash by just hashing the-            -- relevant part of the .bkp file.-            ms_hs_hash = fingerprint0,-            ms_obj_date = Nothing, -- TODO do this, but problem: hi_timestamp is BOGUS-            ms_dyn_obj_date = Nothing, -- TODO do this, but problem: hi_timestamp is BOGUS-            ms_iface_date = hi_timestamp,-            ms_hie_date = hie_timestamp-          }--    -- Now, what are the dependencies.-    let inst_nodes = map NodeKey_Unit inst_deps-        mod_nodes  =-          -- hs-boot edge-          [k | k <- [NodeKey_Module (ModNodeKeyWithUid (GWIB (ms_mod_name ms) IsBoot)  (moduleUnitId this_mod))], NotBoot == isBootSummary ms,  k `elem` home_keys ] ++-          -- Normal edges-          [k | (_, mnwib) <- msDeps ms, let k = NodeKey_Module (ModNodeKeyWithUid (fmap unLoc mnwib) (moduleUnitId this_mod)), k `elem` home_keys]---    return (ModuleNode (mod_nodes ++ inst_nodes) ms)---- | Create a new, externally provided hashed unit id from--- a hash.-newUnitId :: UnitId -> Maybe FastString -> UnitId-newUnitId uid mhash = case mhash of-   Nothing   -> uid-   Just hash -> UnitId (concatFS [unitIdFS uid, fsLit "+", hash])
− compiler/GHC/Driver/MakeFile.hs
@@ -1,454 +0,0 @@-------------------------------------------------------------------------------------- Makefile Dependency Generation------ (c) The University of Glasgow 2005-----------------------------------------------------------------------------------module GHC.Driver.MakeFile-   ( doMkDependHS-   )-where--import GHC.Prelude--import qualified GHC-import GHC.Driver.Monad-import GHC.Driver.Session-import GHC.Driver.Ppr-import GHC.Utils.Misc-import GHC.Driver.Env-import GHC.Driver.Errors.Types-import qualified GHC.SysTools as SysTools-import GHC.Data.Graph.Directed ( SCC(..) )-import GHC.Utils.Outputable-import GHC.Utils.Panic-import GHC.Utils.Panic.Plain-import GHC.Types.Error (UnknownDiagnostic(..))-import GHC.Types.SourceError-import GHC.Types.SrcLoc-import GHC.Types.PkgQual-import Data.List (partition)-import GHC.Utils.TmpFs--import GHC.Iface.Load (cannotFindModule)--import GHC.Unit.Module-import GHC.Unit.Module.ModSummary-import GHC.Unit.Module.Graph-import GHC.Unit.Finder--import GHC.Utils.Exception-import GHC.Utils.Error-import GHC.Utils.Logger--import System.Directory-import System.FilePath-import System.IO-import System.IO.Error  ( isEOFError )-import Control.Monad    ( when, forM_ )-import Data.Maybe       ( isJust )-import Data.IORef-import qualified Data.Set as Set-------------------------------------------------------------------------              The main function-----------------------------------------------------------------------doMkDependHS :: GhcMonad m => [FilePath] -> m ()-doMkDependHS srcs = do-    logger <- getLogger--    -- Initialisation-    dflags0 <- GHC.getSessionDynFlags--    -- We kludge things a bit for dependency generation. Rather than-    -- generating dependencies for each way separately, we generate-    -- them once and then duplicate them for each way's osuf/hisuf.-    -- We therefore do the initial dependency generation with an empty-    -- way and .o/.hi extensions, regardless of any flags that might-    -- be specified.-    let dflags1 = dflags0-            { targetWays_ = Set.empty-            , hiSuf_      = "hi"-            , objectSuf_  = "o"-            }-    GHC.setSessionDynFlags dflags1--    -- If no suffix is provided, use the default -- the empty one-    let dflags = if null (depSuffixes dflags1)-                 then dflags1 { depSuffixes = [""] }-                 else dflags1--    tmpfs <- hsc_tmpfs <$> getSession-    files <- liftIO $ beginMkDependHS logger tmpfs dflags--    -- Do the downsweep to find all the modules-    targets <- mapM (\s -> GHC.guessTarget s Nothing Nothing) srcs-    GHC.setTargets targets-    let excl_mods = depExcludeMods dflags-    module_graph <- GHC.depanal excl_mods True {- Allow dup roots -}--    -- Sort into dependency order-    -- There should be no cycles-    let sorted = GHC.topSortModuleGraph False module_graph Nothing--    -- Print out the dependencies if wanted-    liftIO $ debugTraceMsg logger 2 (text "Module dependencies" $$ ppr sorted)--    -- Process them one by one, dumping results into makefile-    -- and complaining about cycles-    hsc_env <- getSession-    root <- liftIO getCurrentDirectory-    mapM_ (liftIO . processDeps dflags hsc_env excl_mods root (mkd_tmp_hdl files)) sorted--    -- If -ddump-mod-cycles, show cycles in the module graph-    liftIO $ dumpModCycles logger module_graph--    -- Tidy up-    liftIO $ endMkDependHS logger files--    -- Unconditional exiting is a bad idea.  If an error occurs we'll get an-    --exception; if that is not caught it's fine, but at least we have a-    --chance to find out exactly what went wrong.  Uncomment the following-    --line if you disagree.--    --`GHC.ghcCatch` \_ -> io $ exitWith (ExitFailure 1)-------------------------------------------------------------------------              beginMkDependHs---      Create a temporary file,---      find the Makefile,---      slurp through it, etc-----------------------------------------------------------------------data MkDepFiles-  = MkDep { mkd_make_file :: FilePath,          -- Name of the makefile-            mkd_make_hdl  :: Maybe Handle,      -- Handle for the open makefile-            mkd_tmp_file  :: FilePath,          -- Name of the temporary file-            mkd_tmp_hdl   :: Handle }           -- Handle of the open temporary file--beginMkDependHS :: Logger -> TmpFs -> DynFlags -> IO MkDepFiles-beginMkDependHS logger tmpfs dflags = do-        -- open a new temp file in which to stuff the dependency info-        -- as we go along.-  tmp_file <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "dep"-  tmp_hdl <- openFile tmp_file WriteMode--        -- open the makefile-  let makefile = depMakefile dflags-  exists <- doesFileExist makefile-  mb_make_hdl <--        if not exists-        then return Nothing-        else do-           makefile_hdl <- openFile makefile ReadMode--                -- slurp through until we get the magic start string,-                -- copying the contents into dep_makefile-           let slurp = do-                l <- hGetLine makefile_hdl-                if (l == depStartMarker)-                        then return ()-                        else do hPutStrLn tmp_hdl l; slurp--                -- slurp through until we get the magic end marker,-                -- throwing away the contents-           let chuck = do-                l <- hGetLine makefile_hdl-                if (l == depEndMarker)-                        then return ()-                        else chuck--           catchIO slurp-                (\e -> if isEOFError e then return () else ioError e)-           catchIO chuck-                (\e -> if isEOFError e then return () else ioError e)--           return (Just makefile_hdl)---        -- write the magic marker into the tmp file-  hPutStrLn tmp_hdl depStartMarker--  return (MkDep { mkd_make_file = makefile, mkd_make_hdl = mb_make_hdl,-                  mkd_tmp_file  = tmp_file, mkd_tmp_hdl  = tmp_hdl})--------------------------------------------------------------------------              processDeps-----------------------------------------------------------------------processDeps :: DynFlags-            -> HscEnv-            -> [ModuleName]-            -> FilePath-            -> Handle           -- Write dependencies to here-            -> SCC ModuleGraphNode-            -> IO ()--- Write suitable dependencies to handle--- Always:---                      this.o : this.hs------ If the dependency is on something other than a .hi file:---                      this.o this.p_o ... : dep--- otherwise---                      this.o ...   : dep.hi---                      this.p_o ... : dep.p_hi---                      ...--- (where .o is $osuf, and the other suffixes come from--- the cmdline -s options).------ For {-# SOURCE #-} imports the "hi" will be "hi-boot".--processDeps dflags _ _ _ _ (CyclicSCC nodes)-  =     -- There shouldn't be any cycles; report them-    throwGhcExceptionIO $ ProgramError $-      showSDoc dflags $ GHC.cyclicModuleErr nodes--processDeps dflags _ _ _ _ (AcyclicSCC (InstantiationNode _uid node))-  =     -- There shouldn't be any backpack instantiations; report them as well-    throwGhcExceptionIO $ ProgramError $-      showSDoc dflags $-        vcat [ text "Unexpected backpack instantiation in dependency graph while constructing Makefile:"-             , nest 2 $ ppr node ]-processDeps _dflags _ _ _ _ (AcyclicSCC (LinkNode {})) = return ()--processDeps dflags hsc_env excl_mods root hdl (AcyclicSCC (ModuleNode _ node))-  = do  { let extra_suffixes = depSuffixes dflags-              include_pkg_deps = depIncludePkgDeps dflags-              src_file  = msHsFilePath node-              obj_file  = msObjFilePath node-              obj_files = insertSuffixes obj_file extra_suffixes--              do_imp loc is_boot pkg_qual imp_mod-                = do { mb_hi <- findDependency hsc_env loc pkg_qual imp_mod-                                               is_boot include_pkg_deps-                     ; case mb_hi of {-                           Nothing      -> return () ;-                           Just hi_file -> do-                     { let hi_files = insertSuffixes hi_file extra_suffixes-                           write_dep (obj,hi) = writeDependency root hdl [obj] hi--                        -- Add one dependency for each suffix;-                        -- e.g.         A.o   : B.hi-                        --              A.x_o : B.x_hi-                     ; mapM_ write_dep (obj_files `zip` hi_files) }}}---                -- Emit std dependency of the object(s) on the source file-                -- Something like       A.o : A.hs-        ; writeDependency root hdl obj_files src_file--          -- add dependency between objects and their corresponding .hi-boot-          -- files if the module has a corresponding .hs-boot file (#14482)-        ; when (isBootSummary node == IsBoot) $ do-            let hi_boot = msHiFilePath node-            let obj     = removeBootSuffix (msObjFilePath node)-            forM_ extra_suffixes $ \suff -> do-               let way_obj     = insertSuffixes obj     [suff]-               let way_hi_boot = insertSuffixes hi_boot [suff]-               mapM_ (writeDependency root hdl way_obj) way_hi_boot--                -- Emit a dependency for each CPP import-        ; when (depIncludeCppDeps dflags) $ do-            -- CPP deps are discovered in the module parsing phase by parsing-            -- comment lines left by the preprocessor.-            -- Note that GHC.parseModule may throw an exception if the module-            -- fails to parse, which may not be desirable (see #16616).-          { session <- Session <$> newIORef hsc_env-          ; parsedMod <- reflectGhc (GHC.parseModule node) session-          ; mapM_ (writeDependency root hdl obj_files)-                  (GHC.pm_extra_src_files parsedMod)-          }--                -- Emit a dependency for each import--        ; let do_imps is_boot idecls = sequence_-                    [ do_imp loc is_boot mb_pkg mod-                    | (mb_pkg, L loc mod) <- idecls,-                      mod `notElem` excl_mods ]--        ; do_imps IsBoot (ms_srcimps node)-        ; do_imps NotBoot (ms_imps node)-        }---findDependency  :: HscEnv-                -> SrcSpan-                -> PkgQual              -- package qualifier, if any-                -> ModuleName           -- Imported module-                -> IsBootInterface      -- Source import-                -> Bool                 -- Record dependency on package modules-                -> IO (Maybe FilePath)  -- Interface file-findDependency hsc_env srcloc pkg imp is_boot include_pkg_deps = do-  -- Find the module; this will be fast because-  -- we've done it once during downsweep-  r <- findImportedModule hsc_env imp pkg-  case r of-    Found loc _-        -- Home package: just depend on the .hi or hi-boot file-        | isJust (ml_hs_file loc) || include_pkg_deps-        -> return (Just (addBootSuffix_maybe is_boot (ml_hi_file loc)))--        -- Not in this package: we don't need a dependency-        | otherwise-        -> return Nothing--    fail ->-        throwOneError $-          mkPlainErrorMsgEnvelope srcloc $-          GhcDriverMessage $ DriverUnknownMessage $-             UnknownDiagnostic $ mkPlainError noHints $-             cannotFindModule hsc_env imp fail--------------------------------writeDependency :: FilePath -> Handle -> [FilePath] -> FilePath -> IO ()--- (writeDependency r h [t1,t2] dep) writes to handle h the dependency---      t1 t2 : dep-writeDependency root hdl targets dep-  = do let -- We need to avoid making deps on-           --     c:/foo/...-           -- on cygwin as make gets confused by the :-           -- Making relative deps avoids some instances of this.-           dep' = makeRelative root dep-           forOutput = escapeSpaces . reslash Forwards . normalise-           output = unwords (map forOutput targets) ++ " : " ++ forOutput dep'-       hPutStrLn hdl output--------------------------------insertSuffixes-        :: FilePath     -- Original filename;   e.g. "foo.o"-        -> [String]     -- Suffix prefixes      e.g. ["x_", "y_"]-        -> [FilePath]   -- Zapped filenames     e.g. ["foo.x_o", "foo.y_o"]-        -- Note that the extra bit gets inserted *before* the old suffix-        -- We assume the old suffix contains no dots, so we know where to-        -- split it-insertSuffixes file_name extras-  = [ basename <.> (extra ++ suffix) | extra <- extras ]-  where-    (basename, suffix) = case splitExtension file_name of-                         -- Drop the "." from the extension-                         (b, s) -> (b, drop 1 s)--------------------------------------------------------------------------              endMkDependHs---      Complete the makefile, close the tmp file etc-----------------------------------------------------------------------endMkDependHS :: Logger -> MkDepFiles -> IO ()--endMkDependHS logger-   (MkDep { mkd_make_file = makefile, mkd_make_hdl =  makefile_hdl,-            mkd_tmp_file  = tmp_file, mkd_tmp_hdl  =  tmp_hdl })-  = do-  -- write the magic marker into the tmp file-  hPutStrLn tmp_hdl depEndMarker--  case makefile_hdl of-     Nothing  -> return ()-     Just hdl -> do-        -- slurp the rest of the original makefile and copy it into the output-        SysTools.copyHandle hdl tmp_hdl-        hClose hdl--  hClose tmp_hdl  -- make sure it's flushed--        -- Create a backup of the original makefile-  when (isJust makefile_hdl) $ do-    showPass logger ("Backing up " ++ makefile)-    SysTools.copyFile makefile (makefile++".bak")--        -- Copy the new makefile in place-  showPass logger "Installing new makefile"-  SysTools.copyFile tmp_file makefile-----------------------------------------------------------------------              Module cycles--------------------------------------------------------------------dumpModCycles :: Logger -> ModuleGraph -> IO ()-dumpModCycles logger module_graph-  | not (logHasDumpFlag logger Opt_D_dump_mod_cycles)-  = return ()--  | null cycles-  = putMsg logger (text "No module cycles")--  | otherwise-  = putMsg logger (hang (text "Module cycles found:") 2 pp_cycles)-  where-    topoSort = GHC.topSortModuleGraph True module_graph Nothing--    cycles :: [[ModuleGraphNode]]-    cycles =-      [ c | CyclicSCC c <- topoSort ]--    pp_cycles = vcat [ (text "---------- Cycle" <+> int n <+> text "----------")-                        $$ pprCycle c $$ blankLine-                     | (n,c) <- [1..] `zip` cycles ]--pprCycle :: [ModuleGraphNode] -> SDoc--- Print a cycle, but show only the imports within the cycle-pprCycle summaries = pp_group (CyclicSCC summaries)-  where-    cycle_mods :: [ModuleName]  -- The modules in this cycle-    cycle_mods = map (moduleName . ms_mod) [ms | ModuleNode _ ms <- summaries]--    pp_group :: SCC ModuleGraphNode -> SDoc-    pp_group (AcyclicSCC (ModuleNode _ ms)) = pp_ms ms-    pp_group (AcyclicSCC _) = empty-    pp_group (CyclicSCC mss)-        = assert (not (null boot_only)) $-                -- The boot-only list must be non-empty, else there would-                -- be an infinite chain of non-boot imports, and we've-                -- already checked for that in processModDeps-          pp_ms loop_breaker $$ vcat (map pp_group groups)-        where-          (boot_only, others) = partition is_boot_only mss-          is_boot_only (ModuleNode _ ms) = not (any in_group (map snd (ms_imps ms)))-          is_boot_only  _ = False-          in_group (L _ m) = m `elem` group_mods-          group_mods = map (moduleName . ms_mod) [ms | ModuleNode _ ms <- mss]--          loop_breaker = head ([ms | ModuleNode _ ms  <- boot_only])-          all_others   = tail boot_only ++ others-          groups =-            GHC.topSortModuleGraph True (mkModuleGraph all_others) Nothing--    pp_ms summary = text mod_str <> text (take (20 - length mod_str) (repeat ' '))-                       <+> (pp_imps empty (map snd (ms_imps summary)) $$-                            pp_imps (text "{-# SOURCE #-}") (map snd (ms_srcimps summary)))-        where-          mod_str = moduleNameString (moduleName (ms_mod summary))--    pp_imps :: SDoc -> [Located ModuleName] -> SDoc-    pp_imps _    [] = empty-    pp_imps what lms-        = case [m | L _ m <- lms, m `elem` cycle_mods] of-            [] -> empty-            ms -> what <+> text "imports" <+>-                                pprWithCommas ppr ms-------------------------------------------------------------------------              Flags-----------------------------------------------------------------------depStartMarker, depEndMarker :: String-depStartMarker = "# DO NOT DELETE: Beginning of Haskell dependencies"-depEndMarker   = "# DO NOT DELETE: End of Haskell dependencies"
− compiler/GHC/Linker.hs
@@ -1,36 +0,0 @@-module GHC.Linker-   (-   )-where--import GHC.Prelude ()-   -- We need this dummy dependency for the make build system. Otherwise it-   -- tries to load GHC.Types which may not be built yet.---- Note [Linkers and loaders]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~------ Linkers are used to produce linked objects (.so, executables); loaders are--- used to link in memory (e.g., in GHCi) with the already loaded libraries--- (ghc-lib, rts, etc.).------ Linking can usually be done with an external linker program ("ld"), but--- loading is more tricky:------    * Fully dynamic:---       when GHC is built as a set of dynamic libraries (ghc-lib, rts, etc.)---       and the modules to load are also compiled for dynamic linking, a---       solution is to fully rely on external tools:------       1) link a .so with the external linker---       2) load the .so with POSIX's "dlopen"------    * When GHC is built as a static program or when libraries we want to load---    aren't compiled for dynamic linking, GHC uses its own loader ("runtime---    linker"). The runtime linker is part of the rts (rts/Linker.c).------ Note that within GHC's codebase we often use the word "linker" to refer to--- the static object loader in the runtime system.------ Loading can be delegated to an external interpreter ("iserv") when--- -fexternal-interpreter is used.
− compiler/GHC/Runtime/Debugger.hs
@@ -1,271 +0,0 @@------------------------------------------------------------------------------------ GHCi Interactive debugging commands------ Pepe Iborra (supported by Google SoC) 2006------ ToDo: lots of violation of layering here.  This module should--- decide whether it is above the GHC API (import GHC and nothing--- else) or below it.-----------------------------------------------------------------------------------module GHC.Runtime.Debugger (pprintClosureCommand, showTerm, pprTypeAndContents) where--import GHC.Prelude--import GHC--import GHC.Driver.Session-import GHC.Driver.Ppr-import GHC.Driver.Monad-import GHC.Driver.Env--import GHC.Linker.Loader--import GHC.Runtime.Heap.Inspect-import GHC.Runtime.Interpreter-import GHC.Runtime.Context--import GHC.Iface.Syntax ( showToHeader )-import GHC.Iface.Env    ( newInteractiveBinder )-import GHC.Core.Type--import GHC.Utils.Outputable-import GHC.Utils.Error-import GHC.Utils.Monad-import GHC.Utils.Exception-import GHC.Utils.Logger--import GHC.Types.Id-import GHC.Types.Id.Make (ghcPrimIds)-import GHC.Types.Name-import GHC.Types.Var hiding ( varName )-import GHC.Types.Var.Set-import GHC.Types.Unique.Set-import GHC.Types.TyThing.Ppr-import GHC.Types.TyThing--import Control.Monad-import Control.Monad.Catch as MC-import Data.List ( (\\), partition )-import qualified Data.List.NonEmpty as NE-import Data.Maybe-import Data.IORef------------------------------------------ | The :print & friends commands---------------------------------------pprintClosureCommand :: GhcMonad m => Bool -> Bool -> String -> m ()-pprintClosureCommand bindThings force str = do-  tythings <- (catMaybes . concatMap NE.toList) `liftM`-                 mapM (\w -> GHC.parseName w >>=-                                mapM GHC.lookupName)-                      (words str)--  -- Sort out good and bad tythings for :print and friends-  let (pprintables, unpprintables) = partition can_pprint tythings--  -- Obtain the terms and the recovered type information-  let ids = [id | AnId id <- pprintables]-  (subst, terms) <- mapAccumLM go emptySubst ids--  -- Apply the substitutions obtained after recovering the types-  modifySession $ \hsc_env ->-    hsc_env{hsc_IC = substInteractiveContext (hsc_IC hsc_env) subst}--  -- Finally, print the Results-  docterms <- mapM showTerm terms-  let sdocTerms = zipWith (\id docterm -> ppr id <+> char '=' <+> docterm)-                          ids-                          docterms-  printSDocs $ (no_pprint <$> unpprintables) ++ sdocTerms- where-   -- Check whether a TyThing can be processed by :print and friends.-   -- Take only Ids, exclude pseudoops, they don't have any HValues.-   can_pprint :: TyThing -> Bool                              -- #19394-   can_pprint (AnId x)-       | x `notElem` ghcPrimIds = True-       | otherwise              = False-   can_pprint _                 = False--   -- Create a short message for a TyThing, that cannot processed by :print-   no_pprint :: TyThing -> SDoc-   no_pprint tything = ppr tything <+>-          text "is not eligible for the :print, :sprint or :force commands."--   -- Helper to print out the results of :print and friends-   printSDocs :: GhcMonad m => [SDoc] -> m ()-   printSDocs sdocs = do-      logger <- getLogger-      name_ppr_ctx <- GHC.getNamePprCtx-      liftIO $ printOutputForUser logger name_ppr_ctx $ vcat sdocs--   -- Do the obtainTerm--bindSuspensions-computeSubstitution dance-   go :: GhcMonad m => Subst -> Id -> m (Subst, Term)-   go subst id = do-       let id' = updateIdTypeAndMult (substTy subst) id-           id_ty' = idType id'-       term_    <- GHC.obtainTermFromId maxBound force id'-       term     <- tidyTermTyVars term_-       term'    <- if bindThings-                     then bindSuspensions term-                     else return term-     -- Before leaving, we compare the type obtained to see if it's more specific-     --  Then, we extract a substitution,-     --  mapping the old tyvars to the reconstructed types.-       let reconstructed_type = termType term-       hsc_env <- getSession-       case (improveRTTIType hsc_env id_ty' reconstructed_type) of-         Nothing     -> return (subst, term')-         Just subst' -> do { logger <- getLogger-                           ; liftIO $-                               putDumpFileMaybe logger Opt_D_dump_rtti "RTTI"-                                 FormatText-                                 (fsep $ [text "RTTI Improvement for", ppr id,-                                  text "old substitution:" , ppr subst,-                                  text "new substitution:" , ppr subst'])-                           ; return (subst `unionSubst` subst', term')}--   tidyTermTyVars :: GhcMonad m => Term -> m Term-   tidyTermTyVars t =-     withSession $ \hsc_env -> do-     let env_tvs      = tyThingsTyCoVars $ ic_tythings $ hsc_IC hsc_env-         my_tvs       = termTyCoVars t-         tvs          = env_tvs `minusVarSet` my_tvs-         tyvarOccName = nameOccName . tyVarName-         tidyEnv      = (initTidyOccEnv (map tyvarOccName (nonDetEltsUniqSet tvs))-           -- It's OK to use nonDetEltsUniqSet here because initTidyOccEnv-           -- forgets the ordering immediately by creating an env-                        , getUniqSet $ env_tvs `intersectVarSet` my_tvs)-     return $ mapTermType (snd . tidyOpenType tidyEnv) t---- | Give names, and bind in the interactive environment, to all the suspensions---   included (inductively) in a term-bindSuspensions :: GhcMonad m => Term -> m Term-bindSuspensions t = do-      hsc_env <- getSession-      inScope <- GHC.getBindings-      let ictxt        = hsc_IC hsc_env-          prefix       = "_t"-          alreadyUsedNames = map (occNameString . nameOccName . getName) inScope-          availNames   = map ((prefix++) . show) [(1::Int)..] \\ alreadyUsedNames-      availNames_var  <- liftIO $ newIORef availNames-      (t', stuff)     <- liftIO $ foldTerm (nameSuspensionsAndGetInfos hsc_env availNames_var) t-      let (names, tys, fhvs) = unzip3 stuff-      let ids = [ mkVanillaGlobal name ty-                | (name,ty) <- zip names tys]-          new_ic = extendInteractiveContextWithIds ictxt ids-          interp = hscInterp hsc_env-      liftIO $ extendLoadedEnv interp (zip names fhvs)-      setSession hsc_env {hsc_IC = new_ic }-      return t'-     where----    Processing suspensions. Give names and collect info-        nameSuspensionsAndGetInfos :: HscEnv -> IORef [String]-                                   -> TermFold (IO (Term, [(Name,Type,ForeignHValue)]))-        nameSuspensionsAndGetInfos hsc_env freeNames = TermFold-                      {-                        fSuspension = doSuspension hsc_env freeNames-                      , fTerm = \ty dc v tt -> do-                                    tt' <- sequence tt-                                    let (terms,names) = unzip tt'-                                    return (Term ty dc v terms, concat names)-                      , fPrim    = \ty n ->return (Prim ty n,[])-                      , fNewtypeWrap  =-                                \ty dc t -> do-                                    (term, names) <- t-                                    return (NewtypeWrap ty dc term, names)-                      , fRefWrap = \ty t -> do-                                    (term, names) <- t-                                    return (RefWrap ty term, names)-                      }-        doSuspension hsc_env freeNames ct ty hval _name = do-          name <- atomicModifyIORef' freeNames (\x->(tail x, head x))-          n <- newGrimName hsc_env name-          return (Suspension ct ty hval (Just n), [(n,ty,hval)])-----  A custom Term printer to enable the use of Show instances-showTerm :: GhcMonad m => Term -> m SDoc-showTerm term = do-    dflags       <- GHC.getSessionDynFlags-    if gopt Opt_PrintEvldWithShow dflags-       then cPprTerm (liftM2 (++) (\_y->[cPprShowable]) cPprTermBase) term-       else cPprTerm cPprTermBase term- where-  cPprShowable prec t@Term{ty=ty, val=fhv} =-    if not (isFullyEvaluatedTerm t)-     then return Nothing-     else do-        let set_session = do-                hsc_env <- getSession-                (new_env, bname) <- bindToFreshName hsc_env ty "showme"-                setSession new_env--                -- this disables logging of errors-                let noop_log _ _ _ _ = return ()-                pushLogHookM (const noop_log)--                return (hsc_env, bname)--            reset_session (old_env,_) = setSession old_env--        MC.bracket set_session reset_session $ \(_,bname) -> do-           hsc_env <- getSession-           dflags  <- GHC.getSessionDynFlags-           let expr = "Prelude.return (Prelude.show " ++-                         showPpr dflags bname ++-                      ") :: Prelude.IO Prelude.String"-               interp = hscInterp hsc_env-           txt_ <- withExtendedLoadedEnv interp-                                       [(bname, fhv)]-                                       (GHC.compileExprRemote expr)-           let myprec = 10 -- application precedence. TODO Infix constructors-           txt <- liftIO $ evalString interp txt_-           if not (null txt) then-             return $ Just $ cparen (prec >= myprec && needsParens txt)-                                    (text txt)-            else return Nothing--  cPprShowable prec NewtypeWrap{ty=new_ty,wrapped_term=t} =-      cPprShowable prec t{ty=new_ty}-  cPprShowable _ _ = return Nothing--  needsParens ('"':_) = False   -- some simple heuristics to see whether parens-                                -- are redundant in an arbitrary Show output-  needsParens ('(':_) = False-  needsParens txt = ' ' `elem` txt---  bindToFreshName hsc_env ty userName = do-    name <- newGrimName hsc_env userName-    let id       = mkVanillaGlobal name ty-        new_ic   = extendInteractiveContextWithIds (hsc_IC hsc_env) [id]-    return (hsc_env {hsc_IC = new_ic }, name)----    Create new uniques and give them sequentially numbered names-newGrimName :: MonadIO m => HscEnv -> String -> m Name-newGrimName hsc_env userName-  = liftIO (newInteractiveBinder hsc_env occ noSrcSpan)-  where-    occ = mkOccName varName userName--pprTypeAndContents :: GhcMonad m => Id -> m SDoc-pprTypeAndContents id = do-  dflags  <- GHC.getSessionDynFlags-  let pcontents = gopt Opt_PrintBindContents dflags-      pprdId    = (pprTyThing showToHeader . AnId) id-  if pcontents-    then do-      let depthBound = 100-      -- If the value is an exception, make sure we catch it and-      -- show the exception, rather than propagating the exception out.-      e_term <- MC.try $ GHC.obtainTermFromId depthBound False id-      docs_term <- case e_term of-                      Right term -> showTerm term-                      Left  exn  -> return (text "*** Exception:" <+>-                                            text (show (exn :: SomeException)))-      return $ pprdId <+> equals <+> docs_term-    else return pprdId
− compiler/GHC/Tc/Plugin.hs
@@ -1,194 +0,0 @@---- | This module provides an interface for typechecker plugins to--- access select functions of the 'TcM', principally those to do with--- reading parts of the state.-module GHC.Tc.Plugin (-        -- * Basic TcPluginM functionality-        TcPluginM,-        tcPluginIO,-        tcPluginTrace,-        unsafeTcPluginTcM,--        -- * Finding Modules and Names-        Finder.FindResult(..),-        findImportedModule,-        lookupOrig,--        -- * Looking up Names in the typechecking environment-        tcLookupGlobal,-        tcLookupTyCon,-        tcLookupDataCon,-        tcLookupClass,-        tcLookup,-        tcLookupId,--        -- * Getting the TcM state-        getTopEnv,-        getTargetPlatform,-        getEnvs,-        getInstEnvs,-        getFamInstEnvs,-        matchFam,--        -- * Type variables-        newUnique,-        newFlexiTyVar,-        isTouchableTcPluginM,--        -- * Zonking-        zonkTcType,-        zonkCt,--        -- * Creating constraints-        newWanted,-        newGiven,-        newCoercionHole,--        -- * Manipulating evidence bindings-        newEvVar,-        setEvBind,-    ) where--import GHC.Prelude--import GHC.Platform (Platform)--import qualified GHC.Tc.Utils.Monad     as TcM-import qualified GHC.Tc.Solver.Monad    as TcS-import qualified GHC.Tc.Utils.Env       as TcM-import qualified GHC.Tc.Utils.TcMType   as TcM-import qualified GHC.Tc.Instance.Family as TcM-import qualified GHC.Iface.Env          as IfaceEnv-import qualified GHC.Unit.Finder        as Finder--import GHC.Core.FamInstEnv     ( FamInstEnv )-import GHC.Tc.Utils.Monad      ( TcGblEnv, TcLclEnv, TcPluginM-                               , unsafeTcPluginTcM-                               , liftIO, traceTc )-import GHC.Tc.Types.Constraint ( Ct, CtLoc, CtEvidence(..) )-import GHC.Tc.Utils.TcMType    ( TcTyVar, TcType )-import GHC.Tc.Utils.Env        ( TcTyThing )-import GHC.Tc.Types.Evidence   ( CoercionHole, EvTerm(..)-                               , EvExpr, EvBindsVar, EvBind, mkGivenEvBind )-import GHC.Types.Var           ( EvVar )--import GHC.Unit.Module    ( ModuleName, Module )-import GHC.Types.Name     ( OccName, Name )-import GHC.Types.TyThing  ( TyThing )-import GHC.Core.Reduction ( Reduction )-import GHC.Core.TyCon     ( TyCon )-import GHC.Core.DataCon   ( DataCon )-import GHC.Core.Class     ( Class )-import GHC.Driver.Env       ( HscEnv(..) )-import GHC.Utils.Outputable ( SDoc )-import GHC.Core.Type        ( Kind, Type, PredType )-import GHC.Types.Id         ( Id )-import GHC.Core.InstEnv     ( InstEnvs )-import GHC.Types.Unique     ( Unique )-import GHC.Types.PkgQual    ( PkgQual )----- | Perform some IO, typically to interact with an external tool.-tcPluginIO :: IO a -> TcPluginM a-tcPluginIO a = unsafeTcPluginTcM (liftIO a)---- | Output useful for debugging the compiler.-tcPluginTrace :: String -> SDoc -> TcPluginM ()-tcPluginTrace a b = unsafeTcPluginTcM (traceTc a b)---findImportedModule :: ModuleName -> PkgQual -> TcPluginM Finder.FindResult-findImportedModule mod_name mb_pkg = do-    hsc_env <- getTopEnv-    tcPluginIO $ Finder.findImportedModule hsc_env mod_name mb_pkg--lookupOrig :: Module -> OccName -> TcPluginM Name-lookupOrig mod = unsafeTcPluginTcM . IfaceEnv.lookupOrig mod---tcLookupGlobal :: Name -> TcPluginM TyThing-tcLookupGlobal = unsafeTcPluginTcM . TcM.tcLookupGlobal--tcLookupTyCon :: Name -> TcPluginM TyCon-tcLookupTyCon = unsafeTcPluginTcM . TcM.tcLookupTyCon--tcLookupDataCon :: Name -> TcPluginM DataCon-tcLookupDataCon = unsafeTcPluginTcM . TcM.tcLookupDataCon--tcLookupClass :: Name -> TcPluginM Class-tcLookupClass = unsafeTcPluginTcM . TcM.tcLookupClass--tcLookup :: Name -> TcPluginM TcTyThing-tcLookup = unsafeTcPluginTcM . TcM.tcLookup--tcLookupId :: Name -> TcPluginM Id-tcLookupId = unsafeTcPluginTcM . TcM.tcLookupId---getTopEnv :: TcPluginM HscEnv-getTopEnv = unsafeTcPluginTcM TcM.getTopEnv--getTargetPlatform :: TcPluginM Platform-getTargetPlatform = unsafeTcPluginTcM TcM.getPlatform---getEnvs :: TcPluginM (TcGblEnv, TcLclEnv)-getEnvs = unsafeTcPluginTcM TcM.getEnvs--getInstEnvs :: TcPluginM InstEnvs-getInstEnvs = unsafeTcPluginTcM TcM.tcGetInstEnvs--getFamInstEnvs :: TcPluginM (FamInstEnv, FamInstEnv)-getFamInstEnvs = unsafeTcPluginTcM TcM.tcGetFamInstEnvs--matchFam :: TyCon -> [Type]-         -> TcPluginM (Maybe Reduction)-matchFam tycon args = unsafeTcPluginTcM $ TcS.matchFamTcM tycon args--newUnique :: TcPluginM Unique-newUnique = unsafeTcPluginTcM TcM.newUnique--newFlexiTyVar :: Kind -> TcPluginM TcTyVar-newFlexiTyVar = unsafeTcPluginTcM . TcM.newFlexiTyVar--isTouchableTcPluginM :: TcTyVar -> TcPluginM Bool-isTouchableTcPluginM = unsafeTcPluginTcM . TcM.isTouchableTcM---- Confused by zonking? See Note [What is zonking?] in GHC.Tc.Utils.TcMType.-zonkTcType :: TcType -> TcPluginM TcType-zonkTcType = unsafeTcPluginTcM . TcM.zonkTcType--zonkCt :: Ct -> TcPluginM Ct-zonkCt = unsafeTcPluginTcM . TcM.zonkCt---- | Create a new Wanted constraint with the given 'CtLoc'.-newWanted :: CtLoc -> PredType -> TcPluginM CtEvidence-newWanted loc pty-  = unsafeTcPluginTcM (TcM.newWantedWithLoc loc pty)---- | Create a new given constraint, with the supplied evidence.------ This should only be invoked within 'tcPluginSolve'.-newGiven :: EvBindsVar -> CtLoc -> PredType -> EvExpr -> TcPluginM CtEvidence-newGiven tc_evbinds loc pty evtm = do-   new_ev <- newEvVar pty-   setEvBind tc_evbinds $ mkGivenEvBind new_ev (EvExpr evtm)-   return CtGiven { ctev_pred = pty, ctev_evar = new_ev, ctev_loc = loc }---- | Create a fresh evidence variable.------ This should only be invoked within 'tcPluginSolve'.-newEvVar :: PredType -> TcPluginM EvVar-newEvVar = unsafeTcPluginTcM . TcM.newEvVar---- | Create a fresh coercion hole.--- This should only be invoked within 'tcPluginSolve'.-newCoercionHole :: PredType -> TcPluginM CoercionHole-newCoercionHole = unsafeTcPluginTcM . TcM.newCoercionHole---- | Bind an evidence variable.------ This should only be invoked within 'tcPluginSolve'.-setEvBind :: EvBindsVar -> EvBind -> TcPluginM ()-setEvBind tc_evbinds ev_bind = do-    unsafeTcPluginTcM $ TcM.addTcEvBind tc_evbinds ev_bind
ghc-lib.cabal view
@@ -1,8 +1,8 @@-cabal-version: 2.0+cabal-version: 3.0 build-type: Simple name: ghc-lib-version: 9.6.2.20230523-license: BSD3+version: 9.6.2.20231121+license: BSD-3-Clause license-file: LICENSE category: Development author: The GHC Team and Digital Asset@@ -74,23 +74,23 @@     build-depends:         base >= 4.16.1 && < 4.19,         ghc-prim > 0.2 && < 0.11,+        containers >= 0.6.2.1 && < 0.7,         bytestring >= 0.11.3 && < 0.12,         time >= 1.4 && < 1.13,         exceptions == 0.10.*,         parsec,-        containers >= 0.5 && < 0.7,         binary == 0.8.*,         filepath >= 1 && < 1.5,         directory >= 1 && < 1.4,         array >= 0.1 && < 0.6,-        deepseq >= 1.4 && < 1.5,+        deepseq >= 1.4 && < 1.6,         pretty == 1.1.*,         transformers >= 0.5 && < 0.7,         process >= 1 && < 1.7,         stm,         rts,         hpc == 0.6.*,-        ghc-lib-parser == 9.6.2.20230523+        ghc-lib-parser == 9.6.2.20231121     build-tool-depends: alex:alex >= 3.1, happy:happy >= 1.19.4     other-extensions:         BangPatterns@@ -135,9 +135,6 @@     hs-source-dirs:         ghc-lib/stage0/libraries/ghc-boot/build         ghc-lib/stage0/compiler/build-        libraries/template-haskell-        libraries/ghc-boot-        libraries/ghci         compiler     autogen-modules:         Paths_ghc_lib@@ -543,7 +540,6 @@         GHC.Cmm.Parser.Monad         GHC.Cmm.Pipeline         GHC.Cmm.ProcPoint-        GHC.Cmm.Reducibility         GHC.Cmm.Sink         GHC.Cmm.Switch.Implement         GHC.Cmm.ThreadSanitizer@@ -577,14 +573,11 @@         GHC.CmmToAsm.PPC.Regs         GHC.CmmToAsm.Ppr         GHC.CmmToAsm.Reg.Graph-        GHC.CmmToAsm.Reg.Graph.Base-        GHC.CmmToAsm.Reg.Graph.Coalesce         GHC.CmmToAsm.Reg.Graph.Spill         GHC.CmmToAsm.Reg.Graph.SpillClean         GHC.CmmToAsm.Reg.Graph.SpillCost         GHC.CmmToAsm.Reg.Graph.Stats         GHC.CmmToAsm.Reg.Graph.TrivColorable-        GHC.CmmToAsm.Reg.Graph.X86         GHC.CmmToAsm.Reg.Linear         GHC.CmmToAsm.Reg.Linear.AArch64         GHC.CmmToAsm.Reg.Linear.Base@@ -642,14 +635,10 @@         GHC.CoreToStg.Prep         GHC.Data.Bitmap         GHC.Data.Graph.Base-        GHC.Data.Graph.Collapse         GHC.Data.Graph.Color-        GHC.Data.Graph.Inductive.Graph-        GHC.Data.Graph.Inductive.PatriciaTree         GHC.Data.Graph.Ops         GHC.Data.Graph.Ppr         GHC.Data.UnionFind-        GHC.Driver.Backpack         GHC.Driver.CodeOutput         GHC.Driver.Config.Cmm         GHC.Driver.Config.Cmm.Parser@@ -678,11 +667,9 @@         GHC.Driver.GenerateCgIPEStub         GHC.Driver.Main         GHC.Driver.Make-        GHC.Driver.MakeFile         GHC.Driver.Pipeline         GHC.Driver.Pipeline.Execute         GHC.Driver.Pipeline.LogQueue-        GHC.HandleEncoding         GHC.Hs.Stats         GHC.Hs.Syn.Type         GHC.HsToCore@@ -734,7 +721,6 @@         GHC.JS.Ppr         GHC.JS.Syntax         GHC.JS.Transform-        GHC.Linker         GHC.Linker.Config         GHC.Linker.Dynamic         GHC.Linker.ExtraObj@@ -763,7 +749,6 @@         GHC.Rename.Splice         GHC.Rename.Unbound         GHC.Rename.Utils-        GHC.Runtime.Debugger         GHC.Runtime.Eval         GHC.Runtime.Heap.Inspect         GHC.Runtime.Loader@@ -875,7 +860,6 @@         GHC.Tc.Instance.FunDeps         GHC.Tc.Instance.Typeable         GHC.Tc.Module-        GHC.Tc.Plugin         GHC.Tc.Solver         GHC.Tc.Solver.Canonical         GHC.Tc.Solver.Interact@@ -905,12 +889,3 @@         GHC.Utils.Asm         GHC.Wasm.ControlFlow         GHC.Wasm.ControlFlow.FromCmm-        GHCi.CreateBCO-        GHCi.InfoTable-        GHCi.ObjLink-        GHCi.Run-        GHCi.Signals-        GHCi.StaticPtrTable-        GHCi.TH-        Language.Haskell.TH.CodeDo-        Language.Haskell.TH.Quote
− libraries/ghc-boot/GHC/HandleEncoding.hs
@@ -1,32 +0,0 @@--- | See GHC #10762 and #15021.-module GHC.HandleEncoding (configureHandleEncoding) where--import Prelude -- See note [Why do we import Prelude here?]-import GHC.IO.Encoding (textEncodingName)-import System.Environment-import System.IO---- | Handle GHC-specific character encoding flags, allowing us to control how--- GHC produces output regardless of OS.-configureHandleEncoding :: IO ()-configureHandleEncoding = do-   mb_val <- lookupEnv "GHC_CHARENC"-   case mb_val of-    Just "UTF-8" -> do-     hSetEncoding stdout utf8-     hSetEncoding stderr utf8-    _ -> do-     -- Avoid GHC erroring out when trying to display unhandled characters-     hSetTranslit stdout-     hSetTranslit stderr---- | Change the character encoding of the given Handle to transliterate--- on unsupported characters instead of throwing an exception-hSetTranslit :: Handle -> IO ()-hSetTranslit h = do-    menc <- hGetEncoding h-    case fmap textEncodingName menc of-        Just name | '/' `notElem` name -> do-            enc' <- mkTextEncoding $ name ++ "//TRANSLIT"-            hSetEncoding h enc'-        _ -> return ()
− libraries/ghci/GHCi/CreateBCO.hs
@@ -1,211 +0,0 @@-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE UnboxedTuples #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE CPP #-}-------  (c) The University of Glasgow 2002-2006------- | Create real byte-code objects from 'ResolvedBCO's.-module GHCi.CreateBCO (createBCOs) where--import Prelude -- See note [Why do we import Prelude here?]-import GHCi.ResolvedBCO-import GHCi.RemoteTypes-import GHCi.BreakArray-import GHC.Data.SizedSeq--import System.IO (fixIO)-import Control.Monad-import Data.Array.Base-import Foreign hiding (newArray)-import Unsafe.Coerce (unsafeCoerce)-import GHC.Arr          ( Array(..) )-import GHC.Exts-import GHC.IO-import Control.Exception ( ErrorCall(..) )--createBCOs :: [ResolvedBCO] -> IO [HValueRef]-createBCOs bcos = do-  let n_bcos = length bcos-  hvals <- fixIO $ \hvs -> do-     let arr = listArray (0, n_bcos-1) hvs-     mapM (createBCO arr) bcos-  mapM mkRemoteRef hvals--createBCO :: Array Int HValue -> ResolvedBCO -> IO HValue-createBCO _   ResolvedBCO{..} | resolvedBCOIsLE /= isLittleEndian-  = throwIO (ErrorCall $-        unlines [ "The endianness of the ResolvedBCO does not match"-                , "the systems endianness. Using ghc and iserv in a"-                , "mixed endianness setup is not supported!"-                ])-createBCO arr bco-   = -#if MIN_VERSION_ghc_prim(0, 7, 0)-     do linked_bco <- linkBCO' arr bco-#else-     do BCO bco# <- linkBCO' arr bco-#endif--        -- Note [Updatable CAF BCOs]-        -- ~~~~~~~~~~~~~~~~~~~~~~~~~-        -- Why do we need mkApUpd0 here?  Otherwise top-level-        -- interpreted CAFs don't get updated after evaluation.  A-        -- top-level BCO will evaluate itself and return its value-        -- when entered, but it won't update itself.  Wrapping the BCO-        -- in an AP_UPD thunk will take care of the update for us.-        ---        -- Furthermore:-        --   (a) An AP thunk *must* point directly to a BCO-        --   (b) A zero-arity BCO *must* be wrapped in an AP thunk-        --   (c) An AP is always fully saturated, so we *can't* wrap-        --       non-zero arity BCOs in an AP thunk.-        ---        -- See #17424.-        if (resolvedBCOArity bco > 0)-           -#if MIN_VERSION_ghc_prim(0, 7, 0)-           then return (HValue (unsafeCoerce linked_bco))-           else case mkApUpd0# linked_bco of { (# final_bco #) ->-#else-           then return (HValue (unsafeCoerce# bco#))-           else case mkApUpd0# bco# of { (# final_bco #) ->-#endif--                  return (HValue final_bco) }---toWordArray :: UArray Int Word64 -> UArray Int Word-toWordArray = amap fromIntegral--linkBCO' :: Array Int HValue -> ResolvedBCO -> IO BCO-linkBCO' arr ResolvedBCO{..} = do-  let-      ptrs   = ssElts resolvedBCOPtrs-      n_ptrs = sizeSS resolvedBCOPtrs--      !(I# arity#)  = resolvedBCOArity--      !(EmptyArr empty#) = emptyArr -- See Note [BCO empty array]--      barr a = case a of UArray _lo _hi n b -> if n == 0 then empty# else b-      insns_barr = barr resolvedBCOInstrs-      bitmap_barr = barr (toWordArray resolvedBCOBitmap)-      literals_barr = barr (toWordArray resolvedBCOLits)--  PtrsArr marr <- mkPtrsArray arr n_ptrs ptrs-  IO $ \s ->-    case unsafeFreezeArray# marr s of { (# s, arr #) ->-    case newBCO insns_barr literals_barr arr arity# bitmap_barr of { IO io ->-    io s-    }}----- we recursively link any sub-BCOs while making the ptrs array-mkPtrsArray :: Array Int HValue -> Word -> [ResolvedBCOPtr] -> IO PtrsArr-mkPtrsArray arr n_ptrs ptrs = do-  marr <- newPtrsArray (fromIntegral n_ptrs)-  let-    fill (ResolvedBCORef n) i =-      writePtrsArrayHValue i (arr ! n) marr  -- must be lazy!-    fill (ResolvedBCOPtr r) i = do-      hv <- localRef r-      writePtrsArrayHValue i hv marr-    fill (ResolvedBCOStaticPtr r) i = do-      writePtrsArrayPtr i (fromRemotePtr r)  marr-    fill (ResolvedBCOPtrBCO bco) i = do-      -#if MIN_VERSION_ghc_prim(0, 7, 0)-      bco <- linkBCO' arr bco-      writePtrsArrayBCO i bco marr-#else-      BCO bco# <- linkBCO' arr bco-      writePtrsArrayBCO i bco# marr-#endif--    fill (ResolvedBCOPtrBreakArray r) i = do-      BA mba <- localRef r-      writePtrsArrayMBA i mba marr-  zipWithM_ fill ptrs [0..]-  return marr--data PtrsArr = PtrsArr (MutableArray# RealWorld HValue)--newPtrsArray :: Int -> IO PtrsArr-newPtrsArray (I# i) = IO $ \s ->-  case newArray# i undefined s of (# s', arr #) -> (# s', PtrsArr arr #)--writePtrsArrayHValue :: Int -> HValue -> PtrsArr -> IO ()-writePtrsArrayHValue (I# i) hv (PtrsArr arr) = IO $ \s ->-  case writeArray# arr i hv s of s' -> (# s', () #)--writePtrsArrayPtr :: Int -> Ptr a -> PtrsArr -> IO ()-writePtrsArrayPtr (I# i) (Ptr a#) (PtrsArr arr) = IO $ \s ->-  case writeArrayAddr# arr i a# s of s' -> (# s', () #)---- This is rather delicate: convincing GHC to pass an Addr# as an Any but--- without making a thunk turns out to be surprisingly tricky.-{-# NOINLINE writeArrayAddr# #-}-writeArrayAddr# :: MutableArray# s a -> Int# -> Addr# -> State# s -> State# s-#if defined(javascript_HOST_ARCH)--- Addr# isn't coercible with Any with the JS backend.-writeArrayAddr# = error "writeArrayAddr#: currently unsupported with the JS backend"-#else-writeArrayAddr# marr i addr s = unsafeCoerce# writeArray# marr i addr s-#endif---#if MIN_VERSION_ghc_prim(0, 7, 0)-writePtrsArrayBCO :: Int -> BCO -> PtrsArr -> IO ()-#else-writePtrsArrayBCO :: Int -> BCO# -> PtrsArr -> IO ()-#endif--writePtrsArrayBCO (I# i) bco (PtrsArr arr) = IO $ \s ->-  case (unsafeCoerce# writeArray#) arr i bco s of s' -> (# s', () #)---#if MIN_VERSION_ghc_prim(0, 7, 0)-writePtrsArrayMBA :: Int -> MutableByteArray# s -> PtrsArr -> IO ()-#else-data BCO = BCO BCO#-writePtrsArrayMBA :: Int -> MutableByteArray# s -> PtrsArr -> IO ()-#endif--writePtrsArrayMBA (I# i) mba (PtrsArr arr) = IO $ \s ->-  case (unsafeCoerce# writeArray#) arr i mba s of s' -> (# s', () #)--newBCO :: ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> IO BCO-newBCO instrs lits ptrs arity bitmap = IO $ \s ->-  -#if MIN_VERSION_ghc_prim(0, 7, 0)-  newBCO# instrs lits ptrs arity bitmap s-#else-  case newBCO# instrs lits ptrs arity bitmap s of-    (# s1, bco #) -> (# s1, BCO bco #)-#endif---{- Note [BCO empty array]-   ~~~~~~~~~~~~~~~~~~~~~~-Lots of BCOs have empty ptrs or nptrs, but empty arrays are not free:-they are 2-word heap objects.  So let's make a single empty array and-share it between all BCOs.--}--data EmptyArr = EmptyArr ByteArray#--{-# NOINLINE emptyArr #-}-emptyArr :: EmptyArr-emptyArr = unsafeDupablePerformIO $ IO $ \s ->-  case newByteArray# 0# s of { (# s, arr #) ->-  case unsafeFreezeByteArray# arr s of { (# s, farr #) ->-  (# s, EmptyArr farr #)-  }}
− libraries/ghci/GHCi/InfoTable.hsc
@@ -1,419 +0,0 @@-{-# LANGUAGE CPP, MagicHash, ScopedTypeVariables #-}---- Get definitions for the structs, constants & config etc.-#include "Rts.h"---- |--- Run-time info table support.  This module provides support for--- creating and reading info tables /in the running program/.--- We use the RTS data structures directly via hsc2hs.----module GHCi.InfoTable-  (-    mkConInfoTable-  ) where--import Prelude hiding (fail) -- See note [Why do we import Prelude here?]--import Foreign-import Foreign.C-import GHC.Ptr-import GHC.Exts-import GHC.Exts.Heap-import Data.ByteString (ByteString)-import Control.Monad.Fail-import qualified Data.ByteString as BS-import GHC.Platform.Host (hostPlatformArch)-import GHC.Platform.ArchOS---- NOTE: Must return a pointer acceptable for use in the header of a closure.--- If tables_next_to_code is enabled, then it must point the 'code' field.--- Otherwise, it should point to the start of the StgInfoTable.-mkConInfoTable-   :: Bool    -- TABLES_NEXT_TO_CODE-   -> Int     -- ptr words-   -> Int     -- non-ptr words-   -> Int     -- constr tag-   -> Int     -- pointer tag-   -> ByteString  -- con desc-   -> IO (Ptr StgInfoTable)-      -- resulting info table is allocated with allocateExecPage(), and-      -- should be freed with freeExecPage().--mkConInfoTable tables_next_to_code ptr_words nonptr_words tag ptrtag con_desc = do-  let entry_addr = interpConstrEntry !! ptrtag-  code' <- if tables_next_to_code-    then Just <$> mkJumpToAddr entry_addr-    else pure Nothing-  let-     itbl  = StgInfoTable {-                 entry = if tables_next_to_code-                         then Nothing-                         else Just entry_addr,-                 ptrs  = fromIntegral ptr_words,-                 nptrs = fromIntegral nonptr_words,-                 tipe  = CONSTR,-                 srtlen = fromIntegral tag,-                 code  = code'-              }-  castFunPtrToPtr <$> newExecConItbl tables_next_to_code itbl con_desc----- -------------------------------------------------------------------------------- Building machine code fragments for a constructor's entry code--funPtrToInt :: FunPtr a -> Int-funPtrToInt (FunPtr a) = I## (addr2Int## a)--mkJumpToAddr :: MonadFail m => EntryFunPtr-> m ItblCodes-mkJumpToAddr a = case hostPlatformArch of-    ArchPPC -> pure $-        -- We'll use r12, for no particular reason.-        -- 0xDEADBEEF stands for the address:-        -- 3D80DEAD lis r12,0xDEAD-        -- 618CBEEF ori r12,r12,0xBEEF-        -- 7D8903A6 mtctr r12-        -- 4E800420 bctr--        let w32 = fromIntegral (funPtrToInt a)-            hi16 x = (x `shiftR` 16) .&. 0xFFFF-            lo16 x = x .&. 0xFFFF-        in Right [ 0x3D800000 .|. hi16 w32,-                   0x618C0000 .|. lo16 w32,-                   0x7D8903A6, 0x4E800420 ]--    ArchX86 -> pure $-        -- Let the address to jump to be 0xWWXXYYZZ.-        -- Generate   movl $0xWWXXYYZZ,%eax  ;  jmp *%eax-        -- which is-        -- B8 ZZ YY XX WW FF E0--        let w32 = fromIntegral (funPtrToInt a) :: Word32-            insnBytes :: [Word8]-            insnBytes-               = [0xB8, byte0 w32, byte1 w32,-                        byte2 w32, byte3 w32,-                  0xFF, 0xE0]-        in-            Left insnBytes--    ArchX86_64 -> pure $-        -- Generates:-        --      jmpq *.L1(%rip)-        --      .align 8-        -- .L1:-        --      .quad <addr>-        ---        -- which looks like:-        --     8:   ff 25 02 00 00 00     jmpq   *0x2(%rip)      # 10 <f+0x10>-        -- with addr at 10.-        ---        -- We need a full 64-bit pointer (we can't assume the info table is-        -- allocated in low memory).  Assuming the info pointer is aligned to-        -- an 8-byte boundary, the addr will also be aligned.--        let w64 = fromIntegral (funPtrToInt a) :: Word64-            insnBytes :: [Word8]-            insnBytes-               = [0xff, 0x25, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,-                  byte0 w64, byte1 w64, byte2 w64, byte3 w64,-                  byte4 w64, byte5 w64, byte6 w64, byte7 w64]-        in-            Left insnBytes--    ArchAlpha -> pure $-        let w64 = fromIntegral (funPtrToInt a) :: Word64-        in Right [ 0xc3800000      -- br   at, .+4-                 , 0xa79c000c      -- ldq  at, 12(at)-                 , 0x6bfc0000      -- jmp  (at)    # with zero hint -- oh well-                 , 0x47ff041f      -- nop-                 , fromIntegral (w64 .&. 0x0000FFFF)-                 , fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ]--    ArchARM {} -> pure $-        -- Generates Arm sequence,-        --      ldr r1, [pc, #0]-        --      bx r1-        ---        -- which looks like:-        --     00000000 <.addr-0x8>:-        --     0:       00109fe5    ldr    r1, [pc]      ; 8 <.addr>-        --     4:       11ff2fe1    bx     r1-        let w32 = fromIntegral (funPtrToInt a) :: Word32-        in Left [ 0x00, 0x10, 0x9f, 0xe5-                , 0x11, 0xff, 0x2f, 0xe1-                , byte0 w32, byte1 w32, byte2 w32, byte3 w32]--    ArchAArch64 {} -> pure $-        -- Generates:-        ---        --      ldr     x1, label-        --      br      x1-        -- label:-        --      .quad <addr>-        ---        -- which looks like:-        --     0:       58000041        ldr     x1, <label>-        --     4:       d61f0020        br      x1-       let w64 = fromIntegral (funPtrToInt a) :: Word64-       in Right [ 0x58000041-                , 0xd61f0020-                , fromIntegral w64-                , fromIntegral (w64 `shiftR` 32) ]--    ArchPPC_64 ELF_V1 -> pure $-        -- We use the compiler's register r12 to read the function-        -- descriptor and the linker's register r11 as a temporary-        -- register to hold the function entry point.-        -- In the medium code model the function descriptor-        -- is located in the first two gigabytes, i.e. the address-        -- of the function pointer is a non-negative 32 bit number.-        -- 0x0EADBEEF stands for the address of the function pointer:-        --    0:   3d 80 0e ad     lis     r12,0x0EAD-        --    4:   61 8c be ef     ori     r12,r12,0xBEEF-        --    8:   e9 6c 00 00     ld      r11,0(r12)-        --    c:   e8 4c 00 08     ld      r2,8(r12)-        --   10:   7d 69 03 a6     mtctr   r11-        --   14:   e9 6c 00 10     ld      r11,16(r12)-        --   18:   4e 80 04 20     bctr-       let  w32 = fromIntegral (funPtrToInt a)-            hi16 x = (x `shiftR` 16) .&. 0xFFFF-            lo16 x = x .&. 0xFFFF-       in Right [ 0x3D800000 .|. hi16 w32,-                  0x618C0000 .|. lo16 w32,-                  0xE96C0000,-                  0xE84C0008,-                  0x7D6903A6,-                  0xE96C0010,-                  0x4E800420]--    ArchPPC_64 ELF_V2 -> pure $-        -- The ABI requires r12 to point to the function's entry point.-        -- We use the medium code model where code resides in the first-        -- two gigabytes, so loading a non-negative32 bit address-        -- with lis followed by ori is fine.-        -- 0x0EADBEEF stands for the address:-        -- 3D800EAD lis r12,0x0EAD-        -- 618CBEEF ori r12,r12,0xBEEF-        -- 7D8903A6 mtctr r12-        -- 4E800420 bctr--        let w32 = fromIntegral (funPtrToInt a)-            hi16 x = (x `shiftR` 16) .&. 0xFFFF-            lo16 x = x .&. 0xFFFF-        in Right [ 0x3D800000 .|. hi16 w32,-                   0x618C0000 .|. lo16 w32,-                   0x7D8903A6, 0x4E800420 ]--    ArchS390X -> pure $-        -- Let 0xAABBCCDDEEFFGGHH be the address to jump to.-        -- The following code loads the address into scratch-        -- register r1 and jumps to it.-        ---        --    0:   C0 1E AA BB CC DD       llihf   %r1,0xAABBCCDD-        --    6:   C0 19 EE FF GG HH       iilf    %r1,0xEEFFGGHH-        --   12:   07 F1                   br      %r1--        let w64 = fromIntegral (funPtrToInt a) :: Word64-        in Left [ 0xC0, 0x1E, byte7 w64, byte6 w64, byte5 w64, byte4 w64,-                  0xC0, 0x19, byte3 w64, byte2 w64, byte1 w64, byte0 w64,-                  0x07, 0xF1 ]--    ArchRISCV64 -> pure $-        let w64 = fromIntegral (funPtrToInt a) :: Word64-        in Right [ 0x00000297          -- auipc t0,0-                 , 0x01053283          -- ld    t0,16(t0)-                 , 0x00028067          -- jr    t0-                 , 0x00000013          -- nop-                 , fromIntegral w64-                 , fromIntegral (w64 `shiftR` 32) ]--    arch ->-      -- The arch isn't supported. You either need to add your architecture as a-      -- distinct case, or use non-TABLES_NEXT_TO_CODE mode.-      fail $ "mkJumpToAddr: arch is not supported with TABLES_NEXT_TO_CODE ("-             ++ show arch ++ ")"--byte0 :: (Integral w) => w -> Word8-byte0 w = fromIntegral w--byte1, byte2, byte3, byte4, byte5, byte6, byte7-       :: (Integral w, Bits w) => w -> Word8-byte1 w = fromIntegral (w `shiftR` 8)-byte2 w = fromIntegral (w `shiftR` 16)-byte3 w = fromIntegral (w `shiftR` 24)-byte4 w = fromIntegral (w `shiftR` 32)-byte5 w = fromIntegral (w `shiftR` 40)-byte6 w = fromIntegral (w `shiftR` 48)-byte7 w = fromIntegral (w `shiftR` 56)----- -------------------------------------------------------------------------------- read & write intfo tables---- entry point for direct returns for created constr itbls-foreign import ccall "&stg_interp_constr1_entry" stg_interp_constr1_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr2_entry" stg_interp_constr2_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr3_entry" stg_interp_constr3_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr4_entry" stg_interp_constr4_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr5_entry" stg_interp_constr5_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr6_entry" stg_interp_constr6_entry :: EntryFunPtr-foreign import ccall "&stg_interp_constr7_entry" stg_interp_constr7_entry :: EntryFunPtr--interpConstrEntry :: [EntryFunPtr]-interpConstrEntry = [ error "pointer tag 0"-                    , stg_interp_constr1_entry-                    , stg_interp_constr2_entry-                    , stg_interp_constr3_entry-                    , stg_interp_constr4_entry-                    , stg_interp_constr5_entry-                    , stg_interp_constr6_entry-                    , stg_interp_constr7_entry ]--data StgConInfoTable = StgConInfoTable {-   conDesc   :: Ptr Word8,-   infoTable :: StgInfoTable-}---pokeConItbl-  :: Bool -> Ptr StgConInfoTable -> Ptr StgConInfoTable -> StgConInfoTable-  -> IO ()-pokeConItbl tables_next_to_code wr_ptr _ex_ptr itbl = do-  if tables_next_to_code-    then do-      -- Write the offset to the con_desc from the end of the standard InfoTable-      -- at the first byte.-      let con_desc_offset = conDesc itbl `minusPtr` (_ex_ptr `plusPtr` conInfoTableSizeB)-      (#poke StgConInfoTable, con_desc) wr_ptr con_desc_offset-    else do-      -- Write the con_desc address after the end of the info table.-      -- Use itblSize because CPP will not pick up PROFILING when calculating-      -- the offset.-      pokeByteOff wr_ptr itblSize (conDesc itbl)-  pokeItbl (wr_ptr `plusPtr` (#offset StgConInfoTable, i)) (infoTable itbl)--sizeOfEntryCode :: MonadFail m => Bool -> m Int-sizeOfEntryCode tables_next_to_code-  | not tables_next_to_code = pure 0-  | otherwise = do-     code' <- mkJumpToAddr undefined-     pure $ case code' of-       Left  (xs :: [Word8])  -> sizeOf (undefined :: Word8)  * length xs-       Right (xs :: [Word32]) -> sizeOf (undefined :: Word32) * length xs---- Note: Must return proper pointer for use in a closure-#if MIN_VERSION_rts(1,0,1)-newExecConItbl :: Bool -> StgInfoTable -> ByteString -> IO (FunPtr ())-newExecConItbl tables_next_to_code obj con_desc = do-    sz0 <- sizeOfEntryCode tables_next_to_code-    let lcon_desc = BS.length con_desc + 1{- null terminator -}-        -- SCARY-        -- This size represents the number of bytes in an StgConInfoTable.-        sz = fromIntegral $ conInfoTableSizeB + sz0-            -- Note: we need to allocate the conDesc string next to the info-            -- table, because on a 64-bit platform we reference this string-            -- with a 32-bit offset relative to the info table, so if we-            -- allocated the string separately it might be out of range.--    ex_ptr <- fillExecBuffer (sz + fromIntegral lcon_desc) $ \wr_ptr ex_ptr -> do-        let cinfo = StgConInfoTable { conDesc = ex_ptr `plusPtr` fromIntegral sz-                                    , infoTable = obj }-        pokeConItbl tables_next_to_code wr_ptr ex_ptr cinfo-        BS.useAsCStringLen con_desc $ \(src, len) ->-            copyBytes (castPtr wr_ptr `plusPtr` fromIntegral sz) src len-        let null_off = fromIntegral sz + fromIntegral (BS.length con_desc)-        poke (castPtr wr_ptr `plusPtr` null_off) (0 :: Word8)--    pure $ if tables_next_to_code-      then castPtrToFunPtr $ ex_ptr `plusPtr` conInfoTableSizeB-      else castPtrToFunPtr ex_ptr-#else-newExecConItbl :: Bool -> StgInfoTable -> ByteString -> IO (FunPtr ())-newExecConItbl tables_next_to_code obj con_desc-   = alloca $ \pcode -> do-        sz0 <- sizeOfEntryCode tables_next_to_code-        let lcon_desc = BS.length con_desc + 1{- null terminator -}-            -- SCARY-            -- This size represents the number of bytes in an StgConInfoTable.-            sz = fromIntegral $ conInfoTableSizeB + sz0-               -- Note: we need to allocate the conDesc string next to the info-               -- table, because on a 64-bit platform we reference this string-               -- with a 32-bit offset relative to the info table, so if we-               -- allocated the string separately it might be out of range.-        wr_ptr <- _allocateExec (sz + fromIntegral lcon_desc) pcode-        ex_ptr <- peek pcode-        let cinfo = StgConInfoTable { conDesc = ex_ptr `plusPtr` fromIntegral sz-                                    , infoTable = obj }-        pokeConItbl tables_next_to_code wr_ptr ex_ptr cinfo-        BS.useAsCStringLen con_desc $ \(src, len) ->-            copyBytes (castPtr wr_ptr `plusPtr` fromIntegral sz) src len-        let null_off = fromIntegral sz + fromIntegral (BS.length con_desc)-        poke (castPtr wr_ptr `plusPtr` null_off) (0 :: Word8)-        _flushExec sz ex_ptr -- Cache flush (if needed)-        pure $ if tables_next_to_code-          then castPtrToFunPtr $ ex_ptr `plusPtr` conInfoTableSizeB-          else castPtrToFunPtr ex_ptr-#endif---- | Allocate a buffer of a given size, use the given action to fill it with--- data, and mark it as executable. The action is given a writable pointer and--- the executable pointer. Returns a pointer to the executable code.-#if MIN_VERSION_rts(1,0,1)-fillExecBuffer :: CSize -> (Ptr a -> Ptr a -> IO ()) -> IO (Ptr a)-#endif--#if MIN_VERSION_rts(1,0,2)--data ExecPage--foreign import ccall unsafe "allocateExecPage"-  _allocateExecPage :: IO (Ptr ExecPage)--foreign import ccall unsafe "freezeExecPage"-  _freezeExecPage :: Ptr ExecPage -> IO ()--fillExecBuffer sz cont-    -- we can only allocate single pages. This assumes a 4k page size which-    -- isn't strictly correct but is a reasonable conservative lower bound.-  | sz > 4096 = fail "withExecBuffer: Too large"-  | otherwise = do-        pg <- _allocateExecPage-        cont (castPtr pg) (castPtr pg)-        _freezeExecPage pg-        return (castPtr pg)--#elif MIN_VERSION_rts(1,0,1)--foreign import ccall unsafe "allocateExec"-  _allocateExec :: CUInt -> Ptr (Ptr a) -> IO (Ptr a)--foreign import ccall unsafe "flushExec"-  _flushExec :: CUInt -> Ptr a -> IO ()--fillExecBuffer sz cont = alloca $ \pcode -> do-    wr_ptr <- _allocateExec (fromIntegral sz) pcode-    ex_ptr <- peek pcode-    cont wr_ptr ex_ptr-    _flushExec (fromIntegral sz) ex_ptr -- Cache flush (if needed)-    return (ex_ptr)--#else--foreign import ccall unsafe "allocateExec"-  _allocateExec :: CUInt -> Ptr (Ptr a) -> IO (Ptr a)--foreign import ccall unsafe "flushExec"-  _flushExec :: CUInt -> Ptr a -> IO ()---#endif---- -------------------------------------------------------------------------------- Constants and config--wORD_SIZE :: Int-wORD_SIZE = (#const SIZEOF_HSINT)--conInfoTableSizeB :: Int-conInfoTableSizeB = wORD_SIZE + itblSize
− libraries/ghci/GHCi/ObjLink.hs
@@ -1,195 +0,0 @@-{-# LANGUAGE CPP, UnboxedTuples, MagicHash #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}------  (c) The University of Glasgow 2002-2006------- ------------------------------------------------------------------------------      The dynamic linker for object code (.o .so .dll files)--- ------------------------------------------------------------------------------- | Primarily, this module consists of an interface to the C-land--- dynamic linker.-module GHCi.ObjLink-  ( initObjLinker, ShouldRetainCAFs(..)-  , loadDLL-  , loadArchive-  , loadObj-  , unloadObj-  , purgeObj-  , lookupSymbol-  , lookupClosure-  , resolveObjs-  , addLibrarySearchPath-  , removeLibrarySearchPath-  , findSystemLibrary-  )  where--import Prelude -- See note [Why do we import Prelude here?]-import GHCi.RemoteTypes-import Control.Exception (throwIO, ErrorCall(..))-import Control.Monad    ( when )-import Foreign.C-import Foreign.Marshal.Alloc ( free )-import Foreign          ( nullPtr )-import GHC.Exts-import System.Posix.Internals ( CFilePath, withFilePath, peekFilePath )-import System.FilePath  ( dropExtension, normalise )------- ------------------------------------------------------------------------------ RTS Linker Interface--- -----------------------------------------------------------------------------data ShouldRetainCAFs-  = RetainCAFs-    -- ^ Retain CAFs unconditionally in linked Haskell code.-    -- Note that this prevents any code from being unloaded.-    -- It should not be necessary unless you are GHCi or-    -- hs-plugins, which needs to be able call any function-    -- in the compiled code.-  | DontRetainCAFs-    -- ^ Do not retain CAFs.  Everything reachable from foreign-    -- exports will be retained, due to the StablePtrs-    -- created by the module initialisation code.  unloadObj-    -- frees these StablePtrs, which will allow the CAFs to-    -- be GC'd and the code to be removed.--initObjLinker :: ShouldRetainCAFs -> IO ()-initObjLinker RetainCAFs = c_initLinker_ 1-initObjLinker _ = c_initLinker_ 0--lookupSymbol :: String -> IO (Maybe (Ptr a))-lookupSymbol str_in = do-   let str = prefixUnderscore str_in-   withCAString str $ \c_str -> do-     addr <- c_lookupSymbol c_str-     if addr == nullPtr-        then return Nothing-        else return (Just addr)--lookupClosure :: String -> IO (Maybe HValueRef)-lookupClosure str = do-  m <- lookupSymbol str-  case m of-    Nothing -> return Nothing-    Just (Ptr addr) -> case addrToAny# addr of-      (# a #) -> Just <$> mkRemoteRef (HValue a)--prefixUnderscore :: String -> String-prefixUnderscore- | cLeadingUnderscore = ('_':)- | otherwise          = id---- | loadDLL loads a dynamic library using the OS's native linker--- (i.e. dlopen() on Unix, LoadLibrary() on Windows).  It takes either--- an absolute pathname to the file, or a relative filename--- (e.g. "libfoo.so" or "foo.dll").  In the latter case, loadDLL--- searches the standard locations for the appropriate library.----loadDLL :: String -> IO (Maybe String)--- Nothing      => success--- Just err_msg => failure-loadDLL str0 = do-  let-     -- On Windows, addDLL takes a filename without an extension, because-     -- it tries adding both .dll and .drv.  To keep things uniform in the-     -- layers above, loadDLL always takes a filename with an extension, and-     -- we drop it here on Windows only.-     str | isWindowsHost = dropExtension str0-         | otherwise     = str0-  ---  maybe_errmsg <- withFilePath (normalise str) $ \dll -> c_addDLL dll-  if maybe_errmsg == nullPtr-        then return Nothing-        else do str <- peekCString maybe_errmsg-                free maybe_errmsg-                return (Just str)--loadArchive :: String -> IO ()-loadArchive str = do-   withFilePath str $ \c_str -> do-     r <- c_loadArchive c_str-     when (r == 0) (throwIO (ErrorCall ("loadArchive " ++ show str ++ ": failed")))--loadObj :: String -> IO ()-loadObj str = do-   withFilePath str $ \c_str -> do-     r <- c_loadObj c_str-     when (r == 0) (throwIO (ErrorCall ("loadObj " ++ show str ++ ": failed")))---- | @unloadObj@ drops the given dynamic library from the symbol table--- as well as enables the library to be removed from memory during--- a future major GC.-unloadObj :: String -> IO ()-unloadObj str =-   withFilePath str $ \c_str -> do-     r <- c_unloadObj c_str-     when (r == 0) (throwIO (ErrorCall ("unloadObj " ++ show str ++ ": failed")))---- | @purgeObj@ drops the symbols for the dynamic library from the symbol--- table. Unlike 'unloadObj', the library will not be dropped memory during--- a future major GC.-purgeObj :: String -> IO ()-purgeObj str =-   withFilePath str $ \c_str -> do-     r <- c_purgeObj c_str-     when (r == 0) (throwIO (ErrorCall ("purgeObj " ++ show str ++ ": failed")))--addLibrarySearchPath :: String -> IO (Ptr ())-addLibrarySearchPath str =-   withFilePath str c_addLibrarySearchPath--removeLibrarySearchPath :: Ptr () -> IO Bool-removeLibrarySearchPath = c_removeLibrarySearchPath--findSystemLibrary :: String -> IO (Maybe String)-findSystemLibrary str = do-    result <- withFilePath str c_findSystemLibrary-    case result == nullPtr of-        True  -> return Nothing-        False -> do path <- peekFilePath result-                    free result-                    return $ Just path--resolveObjs :: IO Bool-resolveObjs = do-   r <- c_resolveObjs-   return (r /= 0)---- ------------------------------------------------------------------------------ Foreign declarations to RTS entry points which does the real work;--- -----------------------------------------------------------------------------foreign import ccall unsafe "addDLL"                  c_addDLL                  :: CFilePath -> IO CString-foreign import ccall unsafe "initLinker_"             c_initLinker_             :: CInt -> IO ()-foreign import ccall unsafe "lookupSymbol"            c_lookupSymbol            :: CString -> IO (Ptr a)-foreign import ccall unsafe "loadArchive"             c_loadArchive             :: CFilePath -> IO Int-foreign import ccall unsafe "loadObj"                 c_loadObj                 :: CFilePath -> IO Int-foreign import ccall unsafe "purgeObj"                c_purgeObj                :: CFilePath -> IO Int-foreign import ccall unsafe "unloadObj"               c_unloadObj               :: CFilePath -> IO Int-foreign import ccall unsafe "resolveObjs"             c_resolveObjs             :: IO Int-foreign import ccall unsafe "addLibrarySearchPath"    c_addLibrarySearchPath    :: CFilePath -> IO (Ptr ())-foreign import ccall unsafe "findSystemLibrary"       c_findSystemLibrary       :: CFilePath -> IO CFilePath-foreign import ccall unsafe "removeLibrarySearchPath" c_removeLibrarySearchPath :: Ptr() -> IO Bool---- -------------------------------------------------------------------------------- Configuration--#include "ghcautoconf.h"--cLeadingUnderscore :: Bool-#if defined(LEADING_UNDERSCORE)-cLeadingUnderscore = True-#else-cLeadingUnderscore = False-#endif--isWindowsHost :: Bool-#if defined(mingw32_HOST_OS)-isWindowsHost = True-#else-isWindowsHost = False-#endif
− libraries/ghci/GHCi/Run.hs
@@ -1,398 +0,0 @@-{-# LANGUAGE GADTs, RecordWildCards, MagicHash, ScopedTypeVariables, CPP,-    UnboxedTuples #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}---- |--- Execute GHCi messages.------ For details on Remote GHCi, see Note [Remote GHCi] in--- compiler/GHC/Runtime/Interpreter.hs.----module GHCi.Run-  ( run, redirectInterrupts-  ) where--import Prelude -- See note [Why do we import Prelude here?]-import GHCi.CreateBCO-import GHCi.InfoTable-import GHCi.FFI-import GHCi.Message-import GHCi.ObjLink-import GHCi.RemoteTypes-import GHCi.TH-import GHCi.BreakArray-import GHCi.StaticPtrTable--import Control.Concurrent-import Control.DeepSeq-import Control.Exception-import Control.Monad-import Data.Binary-import Data.Binary.Get-import Data.ByteString (ByteString)-import qualified Data.ByteString.Unsafe as B-import GHC.Exts-import qualified GHC.Exts.Heap as Heap-import GHC.Stack-import Foreign hiding (void)-import Foreign.C-import GHC.Conc.Sync-import GHC.IO hiding ( bracket )-import System.Mem.Weak  ( deRefWeak )-import Unsafe.Coerce---- -------------------------------------------------------------------------------- Implement messages--foreign import ccall "revertCAFs" rts_revertCAFs  :: IO ()-        -- Make it "safe", just in case--run :: Message a -> IO a-run m = case m of-  InitLinker -> initObjLinker RetainCAFs-  RtsRevertCAFs -> rts_revertCAFs-  LookupSymbol str -> fmap toRemotePtr <$> lookupSymbol str-  LookupClosure str -> lookupClosure str-  LoadDLL str -> loadDLL str-  LoadArchive str -> loadArchive str-  LoadObj str -> loadObj str-  UnloadObj str -> unloadObj str-  AddLibrarySearchPath str -> toRemotePtr <$> addLibrarySearchPath str-  RemoveLibrarySearchPath ptr -> removeLibrarySearchPath (fromRemotePtr ptr)-  ResolveObjs -> resolveObjs-  FindSystemLibrary str -> findSystemLibrary str-  CreateBCOs bcos -> createBCOs (concatMap (runGet get) bcos)-  FreeHValueRefs rs -> mapM_ freeRemoteRef rs-  AddSptEntry fpr r -> localRef r >>= sptAddEntry fpr-  EvalStmt opts r -> evalStmt opts r-  ResumeStmt opts r -> resumeStmt opts r-  AbandonStmt r -> abandonStmt r-  EvalString r -> evalString r-  EvalStringToString r s -> evalStringToString r s-  EvalIO r -> evalIO r-  MkCostCentres mod ccs -> mkCostCentres mod ccs-  CostCentreStackInfo ptr -> ccsToStrings (fromRemotePtr ptr)-  NewBreakArray sz -> mkRemoteRef =<< newBreakArray sz-  SetupBreakpoint ref ix cnt -> do-    arr <- localRef ref;-    _ <- setupBreakpoint arr ix cnt-    return ()-  BreakpointStatus ref ix -> do-    arr <- localRef ref; r <- getBreak arr ix-    case r of-      Nothing -> return False-      Just w -> return (w == 0)-  GetBreakpointVar ref ix -> do-    aps <- localRef ref-    mapM mkRemoteRef =<< getIdValFromApStack aps ix-  MallocData bs -> mkString bs-  MallocStrings bss -> mapM mkString0 bss-  PrepFFI conv args res -> toRemotePtr <$> prepForeignCall conv args res-  FreeFFI p -> freeForeignCallInfo (fromRemotePtr p)-  MkConInfoTable tc ptrs nptrs tag ptrtag desc ->-    toRemotePtr <$> mkConInfoTable tc ptrs nptrs tag ptrtag desc-  StartTH -> startTH-  GetClosure ref -> do-    clos <- Heap.getClosureData =<< localRef ref-    mapM (\(Heap.Box x) -> mkRemoteRef (HValue x)) clos-  Seq ref -> doSeq ref-  ResumeSeq ref -> resumeSeq ref-  _other -> error "GHCi.Run.run"--evalStmt :: EvalOpts -> EvalExpr HValueRef -> IO (EvalStatus [HValueRef])-evalStmt opts expr = do-  io <- mkIO expr-  sandboxIO opts $ do-    rs <- unsafeCoerce io :: IO [HValue]-    mapM mkRemoteRef rs- where-  mkIO (EvalThis href) = localRef href-  mkIO (EvalApp l r) = do-    l' <- mkIO l-    r' <- mkIO r-    return ((unsafeCoerce l' :: HValue -> HValue) r')--evalIO :: HValueRef -> IO (EvalResult ())-evalIO r = do-  io <- localRef r-  tryEval (unsafeCoerce io :: IO ())--evalString :: HValueRef -> IO (EvalResult String)-evalString r = do-  io <- localRef r-  tryEval $ do-    r <- unsafeCoerce io :: IO String-    evaluate (force r)--evalStringToString :: HValueRef -> String -> IO (EvalResult String)-evalStringToString r str = do-  io <- localRef r-  tryEval $ do-    r <- (unsafeCoerce io :: String -> IO String) str-    evaluate (force r)---- | Process the Seq message to force a value.                       #2950--- If during this processing a breakpoint is hit, return--- an EvalBreak value in the EvalStatus to the UI process,--- otherwise return an EvalComplete.--- The UI process has more and therefore also can show more--- information about the breakpoint than the current iserv--- process.-doSeq :: RemoteRef a -> IO (EvalStatus ())-doSeq ref = do-    sandboxIO evalOptsSeq $ do-      _ <- (void $ evaluate =<< localRef ref)-      return ()---- | Process a ResumeSeq message. Continue the :force processing     #2950--- after a breakpoint.-resumeSeq :: RemoteRef (ResumeContext ()) -> IO (EvalStatus ())-resumeSeq hvref = do-    ResumeContext{..} <- localRef hvref-    withBreakAction evalOptsSeq resumeBreakMVar resumeStatusMVar $-      mask_ $ do-        putMVar resumeBreakMVar () -- this awakens the stopped thread...-        redirectInterrupts resumeThreadId $ takeMVar resumeStatusMVar--evalOptsSeq :: EvalOpts-evalOptsSeq = EvalOpts-              { useSandboxThread = True-              , singleStep = False-              , breakOnException = False-              , breakOnError = False-              }---- When running a computation, we redirect ^C exceptions to the running--- thread.  ToDo: we might want a way to continue even if the target--- thread doesn't die when it receives the exception... "this thread--- is not responding".------ Careful here: there may be ^C exceptions flying around, so we start the new--- thread blocked (forkIO inherits mask from the parent, #1048), and unblock--- only while we execute the user's code.  We can't afford to lose the final--- putMVar, otherwise deadlock ensues. (#1583, #1922, #1946)--sandboxIO :: EvalOpts -> IO a -> IO (EvalStatus a)-sandboxIO opts io = do-  -- We are running in uninterruptibleMask-  breakMVar <- newEmptyMVar-  statusMVar <- newEmptyMVar-  withBreakAction opts breakMVar statusMVar $ do-    let runIt = measureAlloc $ tryEval $ rethrow opts $ clearCCS io-    if useSandboxThread opts-       then do-         tid <- forkIO $ do unsafeUnmask runIt >>= putMVar statusMVar-                                -- empty: can't block-         redirectInterrupts tid $ unsafeUnmask $ takeMVar statusMVar-       else-          -- GLUT on OS X needs to run on the main thread. If you-          -- try to use it from another thread then you just get a-          -- white rectangle rendered. For this, or anything else-          -- with such restrictions, you can turn the GHCi sandbox off-          -- and things will be run in the main thread.-          ---          -- BUT, note that the debugging features (breakpoints,-          -- tracing, etc.) need the expression to be running in a-          -- separate thread, so debugging is only enabled when-          -- using the sandbox.-         runIt---- We want to turn ^C into a break when -fbreak-on-exception is on,--- but it's an async exception and we only break for sync exceptions.--- Idea: if we catch and re-throw it, then the re-throw will trigger--- a break.  Great - but we don't want to re-throw all exceptions, because--- then we'll get a double break for ordinary sync exceptions (you'd have--- to :continue twice, which looks strange).  So if the exception is--- not "Interrupted", we unset the exception flag before throwing.----rethrow :: EvalOpts -> IO a -> IO a-rethrow EvalOpts{..} io =-  catch io $ \se -> do-    -- If -fbreak-on-error, we break unconditionally,-    --  but with care of not breaking twice-    if breakOnError && not breakOnException-       then poke exceptionFlag 1-       else case fromException se of-               -- If it is a "UserInterrupt" exception, we allow-               --  a possible break by way of -fbreak-on-exception-               Just UserInterrupt -> return ()-               -- In any other case, we don't want to break-               _ -> poke exceptionFlag 0-    throwIO se------- While we're waiting for the sandbox thread to return a result, if--- the current thread receives an asynchronous exception we re-throw--- it at the sandbox thread and continue to wait.------ This is for two reasons:------  * So that ^C interrupts runStmt (e.g. in GHCi), allowing the---    computation to run its exception handlers before returning the---    exception result to the caller of runStmt.------  * clients of the GHC API can terminate a runStmt in progress---    without knowing the ThreadId of the sandbox thread (#1381)------ NB. use a weak pointer to the thread, so that the thread can still--- be considered deadlocked by the RTS and sent a BlockedIndefinitely--- exception.  A symptom of getting this wrong is that conc033(ghci)--- will hang.----redirectInterrupts :: ThreadId -> IO a -> IO a-redirectInterrupts target wait = do-  wtid <- mkWeakThreadId target-  wait `catch` \e -> do-     m <- deRefWeak wtid-     case m of-       Nothing -> wait-       Just target -> do throwTo target (e :: SomeException); wait--measureAlloc :: IO (EvalResult a) -> IO (EvalStatus a)-measureAlloc io = do-  setAllocationCounter 0                                 -- #16012-  a <- io-  ctr <- getAllocationCounter-  let allocs = negate $ fromIntegral ctr-  return (EvalComplete allocs a)---- Exceptions can't be marshaled because they're dynamically typed, so--- everything becomes a String.-tryEval :: IO a -> IO (EvalResult a)-tryEval io = do-  e <- try io-  case e of-    Left ex -> return (EvalException (toSerializableException ex))-    Right a -> return (EvalSuccess a)---- This function sets up the interpreter for catching breakpoints, and--- resets everything when the computation has stopped running.  This--- is a not-very-good way to ensure that only the interactive--- evaluation should generate breakpoints.-withBreakAction :: EvalOpts -> MVar () -> MVar (EvalStatus b) -> IO a -> IO a-withBreakAction opts breakMVar statusMVar act- = bracket setBreakAction resetBreakAction (\_ -> act)- where-   setBreakAction = do-     stablePtr <- newStablePtr onBreak-     poke breakPointIOAction stablePtr-     when (breakOnException opts) $ poke exceptionFlag 1-     when (singleStep opts) $ setStepFlag-     return stablePtr-        -- Breaking on exceptions is not enabled by default, since it-        -- might be a bit surprising.  The exception flag is turned off-        -- as soon as it is hit, or in resetBreakAction below.--   onBreak :: BreakpointCallback-   onBreak ix# uniq# is_exception apStack = do-     tid <- myThreadId-     let resume = ResumeContext-           { resumeBreakMVar = breakMVar-           , resumeStatusMVar = statusMVar-           , resumeThreadId = tid }-     resume_r <- mkRemoteRef resume-     apStack_r <- mkRemoteRef apStack-     ccs <- toRemotePtr <$> getCCSOf apStack-     putMVar statusMVar $ EvalBreak is_exception apStack_r (I# ix#) (I# uniq#) resume_r ccs-     takeMVar breakMVar--   resetBreakAction stablePtr = do-     poke breakPointIOAction noBreakStablePtr-     poke exceptionFlag 0-     resetStepFlag-     freeStablePtr stablePtr--resumeStmt-  :: EvalOpts -> RemoteRef (ResumeContext [HValueRef])-  -> IO (EvalStatus [HValueRef])-resumeStmt opts hvref = do-  ResumeContext{..} <- localRef hvref-  withBreakAction opts resumeBreakMVar resumeStatusMVar $-    mask_ $ do-      putMVar resumeBreakMVar () -- this awakens the stopped thread...-      redirectInterrupts resumeThreadId $ takeMVar resumeStatusMVar---- when abandoning a computation we have to---      (a) kill the thread with an async exception, so that the---          computation itself is stopped, and---      (b) fill in the MVar.  This step is necessary because any---          thunks that were under evaluation will now be updated---          with the partial computation, which still ends in takeMVar,---          so any attempt to evaluate one of these thunks will block---          unless we fill in the MVar.---      (c) wait for the thread to terminate by taking its status MVar.  This---          step is necessary to prevent race conditions with---          -fbreak-on-exception (see #5975).---  See test break010.-abandonStmt :: RemoteRef (ResumeContext [HValueRef]) -> IO ()-abandonStmt hvref = do-  ResumeContext{..} <- localRef hvref-  killThread resumeThreadId-  putMVar resumeBreakMVar ()-  _ <- takeMVar resumeStatusMVar-  return ()--foreign import ccall "&rts_stop_next_breakpoint" stepFlag      :: Ptr CInt-foreign import ccall "&rts_stop_on_exception"    exceptionFlag :: Ptr CInt--setStepFlag :: IO ()-setStepFlag = poke stepFlag 1-resetStepFlag :: IO ()-resetStepFlag = poke stepFlag 0--type BreakpointCallback-     = Int#    -- the breakpoint index-    -> Int#    -- the module uniq-    -> Bool    -- exception?-    -> HValue  -- the AP_STACK, or exception-    -> IO ()--foreign import ccall "&rts_breakpoint_io_action"-   breakPointIOAction :: Ptr (StablePtr BreakpointCallback)--noBreakStablePtr :: StablePtr BreakpointCallback-noBreakStablePtr = unsafePerformIO $ newStablePtr noBreakAction--noBreakAction :: BreakpointCallback-noBreakAction _ _ False _ = putStrLn "*** Ignoring breakpoint"-noBreakAction _ _ True  _ = return () -- exception: just continue---- Malloc and copy the bytes.  We don't have any way to monitor the--- lifetime of this memory, so it just leaks.-mkString :: ByteString -> IO (RemotePtr ())-mkString bs = B.unsafeUseAsCStringLen bs $ \(cstr,len) -> do-  ptr <- mallocBytes len-  copyBytes ptr cstr len-  return (castRemotePtr (toRemotePtr ptr))--mkString0 :: ByteString -> IO (RemotePtr ())-mkString0 bs = B.unsafeUseAsCStringLen bs $ \(cstr,len) -> do-  ptr <- mallocBytes (len+1)-  copyBytes ptr cstr len-  pokeElemOff (ptr :: Ptr CChar) len 0-  return (castRemotePtr (toRemotePtr ptr))--mkCostCentres :: String -> [(String,String)] -> IO [RemotePtr CostCentre]-#if defined(PROFILING)-mkCostCentres mod ccs = do-  c_module <- newCString mod-  mapM (mk_one c_module) ccs- where-  mk_one c_module (decl_path,srcspan) = do-    c_name <- newCString decl_path-    c_srcspan <- newCString srcspan-    toRemotePtr <$> c_mkCostCentre c_name c_module c_srcspan--foreign import ccall unsafe "mkCostCentre"-  c_mkCostCentre :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO (Ptr CostCentre)-#else-mkCostCentres _ _ = return []-#endif--getIdValFromApStack :: HValue -> Int -> IO (Maybe HValue)-getIdValFromApStack apStack (I# stackDepth) = do-   case getApStackVal# apStack stackDepth of-        (# ok, result #) ->-            case ok of-              0# -> return Nothing -- AP_STACK not found-              _  -> return (Just (unsafeCoerce# result))
− libraries/ghci/GHCi/Signals.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE CPP #-}-module GHCi.Signals (installSignalHandlers) where--import Prelude -- See note [Why do we import Prelude here?]-import Control.Concurrent-import Control.Exception-import System.Mem.Weak  ( deRefWeak )--#if !defined(mingw32_HOST_OS)-import System.Posix.Signals-#endif--#if defined(mingw32_HOST_OS)-import GHC.ConsoleHandler-#endif---- | Install standard signal handlers for catching ^C, which just throw an---   exception in the target thread.  The current target thread is the---   thread at the head of the list in the MVar passed to---   installSignalHandlers.-installSignalHandlers :: IO ()-installSignalHandlers = do-  main_thread <- myThreadId-  wtid <- mkWeakThreadId main_thread--  let interrupt = do-        r <- deRefWeak wtid-        case r of-          Nothing -> return ()-          Just t  -> throwTo t UserInterrupt--#if !defined(mingw32_HOST_OS)-  _ <- installHandler sigQUIT  (Catch interrupt) Nothing-  _ <- installHandler sigINT   (Catch interrupt) Nothing-#else-  -- GHC 6.3+ has support for console events on Windows-  -- NOTE: running GHCi under a bash shell for some reason requires-  -- you to press Ctrl-Break rather than Ctrl-C to provoke-  -- an interrupt.  Ctrl-C is getting blocked somewhere, I don't know-  -- why --SDM 17/12/2004-  let sig_handler ControlC = interrupt-      sig_handler Break    = interrupt-      sig_handler _        = return ()--  _ <- installHandler (Catch sig_handler)-#endif-  return ()
− libraries/ghci/GHCi/StaticPtrTable.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ForeignFunctionInterface #-}--module GHCi.StaticPtrTable ( sptAddEntry ) where--import Prelude -- See note [Why do we import Prelude here?]-import Data.Word-import Foreign-import GHC.Fingerprint-import GHCi.RemoteTypes---- | Used by GHCi to add an SPT entry for a set of interactive bindings.-sptAddEntry :: Fingerprint -> HValue -> IO ()-sptAddEntry (Fingerprint a b) (HValue x) = do-    -- We own the memory holding the key (fingerprint) which gets inserted into-    -- the static pointer table and can't free it until the SPT entry is removed-    -- (which is currently never).-    fpr_ptr <- newArray [a,b]-    sptr <- newStablePtr x-    ent_ptr <- malloc-    poke ent_ptr (castStablePtrToPtr sptr)-    spt_insert_stableptr fpr_ptr ent_ptr--foreign import ccall "hs_spt_insert_stableptr"-    spt_insert_stableptr :: Ptr Word64 -> Ptr (Ptr ()) -> IO ()
− libraries/ghci/GHCi/TH.hs
@@ -1,273 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, DeriveGeneric,-    TupleSections, RecordWildCards, InstanceSigs, CPP #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}---- |--- Running TH splices----module GHCi.TH-  ( startTH-  , runModFinalizerRefs-  , runTH-  , GHCiQException(..)-  ) where--{- Note [Remote Template Haskell]-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Here is an overview of how TH works with -fexternal-interpreter.--Initialisation-~~~~~~~~~~~~~~--GHC sends a StartTH message to the server (see GHC.Tc.Gen.Splice.getTHState):--   StartTH :: Message (RemoteRef (IORef QState))--The server creates an initial QState object, makes an IORef to it, and-returns a RemoteRef to this to GHC. (see GHCi.TH.startTH below).--This happens once per module, the first time we need to run a TH-splice.  The reference that GHC gets back is kept in-tcg_th_remote_state in the TcGblEnv, and passed to each RunTH call-that follows.---For each splice-~~~~~~~~~~~~~~~--1. GHC compiles a splice to byte code, and sends it to the server: in-   a CreateBCOs message:--   CreateBCOs :: [LB.ByteString] -> Message [HValueRef]--2. The server creates the real byte-code objects in its heap, and-   returns HValueRefs to GHC.  HValueRef is the same as RemoteRef-   HValue.--3. GHC sends a RunTH message to the server:--  RunTH-   :: RemoteRef (IORef QState)-        -- The state returned by StartTH in step1-   -> HValueRef-        -- The HValueRef we got in step 4, points to the code for the splice-   -> THResultType-        -- Tells us what kind of splice this is (decl, expr, type, etc.)-   -> Maybe TH.Loc-        -- Source location-   -> Message (QResult ByteString)-        -- Eventually it will return a QResult back to GHC.  The-        -- ByteString here is the (encoded) result of the splice.--4. The server runs the splice code.--5. Each time the splice code calls a method of the Quasi class, such-   as qReify, a message is sent from the server to GHC.  These-   messages are defined by the THMessage type.  GHC responds with the-   result of the request, e.g. in the case of qReify it would be the-   TH.Info for the requested entity.--6. When the splice has been fully evaluated, the server sends-   RunTHDone back to GHC.  This tells GHC that the server has finished-   sending THMessages and will send the QResult next.--8. The server then sends a QResult back to GHC, which is notionally-   the response to the original RunTH message.  The QResult indicates-   whether the splice succeeded, failed, or threw an exception.---After typechecking-~~~~~~~~~~~~~~~~~~--GHC sends a FinishTH message to the server (see GHC.Tc.Gen.Splice.finishTH).-The server runs any finalizers that were added by addModuleFinalizer.---Other Notes on TH / Remote GHCi--  * Note [Remote GHCi] in compiler/GHC/Runtime/Interpreter.hs-  * Note [External GHCi pointers] in compiler/GHC/Runtime/Interpreter.hs-  * Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice--}--import Prelude -- See note [Why do we import Prelude here?]-import GHCi.Message-import GHCi.RemoteTypes-import GHC.Serialized--import Control.Exception-import Control.Monad.IO.Class (MonadIO (..))-import Data.Binary-import Data.Binary.Put-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as LB-import Data.Data-import Data.Dynamic-import Data.Either-import Data.IORef-import Data.Map (Map)-import qualified Data.Map as M-import Data.Maybe-import GHC.Desugar-import qualified Language.Haskell.TH        as TH-import qualified Language.Haskell.TH.Syntax as TH-import Unsafe.Coerce---- | Create a new instance of 'QState'-initQState :: Pipe -> QState-initQState p = QState M.empty Nothing p---- | The monad in which we run TH computations on the server-newtype GHCiQ a = GHCiQ { runGHCiQ :: QState -> IO (a, QState) }---- | The exception thrown by "fail" in the GHCiQ monad-data GHCiQException = GHCiQException QState String-  deriving Show--instance Exception GHCiQException--instance Functor GHCiQ where-  fmap f (GHCiQ s) = GHCiQ $ fmap (\(x,s') -> (f x,s')) . s--instance Applicative GHCiQ where-  f <*> a = GHCiQ $ \s ->-    do (f',s')  <- runGHCiQ f s-       (a',s'') <- runGHCiQ a s'-       return (f' a', s'')-  pure x = GHCiQ (\s -> return (x,s))--instance Monad GHCiQ where-  m >>= f = GHCiQ $ \s ->-    do (m', s')  <- runGHCiQ m s-       (a,  s'') <- runGHCiQ (f m') s'-       return (a, s'')--instance MonadFail GHCiQ where-  fail err  = GHCiQ $ \s -> throwIO (GHCiQException s err)--getState :: GHCiQ QState-getState = GHCiQ $ \s -> return (s,s)--noLoc :: TH.Loc-noLoc = TH.Loc "<no file>" "<no package>" "<no module>" (0,0) (0,0)---- | Send a 'THMessage' to GHC and return the result.-ghcCmd :: Binary a => THMessage (THResult a) -> GHCiQ a-ghcCmd m = GHCiQ $ \s -> do-  r <- remoteTHCall (qsPipe s) m-  case r of-    THException str -> throwIO (GHCiQException s str)-    THComplete res -> return (res, s)--instance MonadIO GHCiQ where-  liftIO m = GHCiQ $ \s -> fmap (,s) m--instance TH.Quasi GHCiQ where-  qNewName str = ghcCmd (NewName str)-  qReport isError msg = ghcCmd (Report isError msg)--  -- See Note [TH recover with -fexternal-interpreter] in GHC.Tc.Gen.Splice-  qRecover (GHCiQ h) a = GHCiQ $ \s -> mask $ \unmask -> do-    remoteTHCall (qsPipe s) StartRecover-    e <- try $ unmask $ runGHCiQ (a <* ghcCmd FailIfErrs) s-    remoteTHCall (qsPipe s) (EndRecover (isLeft e))-    case e of-      Left GHCiQException{} -> h s-      Right r -> return r-  qLookupName isType occ = ghcCmd (LookupName isType occ)-  qReify name = ghcCmd (Reify name)-  qReifyFixity name = ghcCmd (ReifyFixity name)-  qReifyType name = ghcCmd (ReifyType name)-  qReifyInstances name tys = ghcCmd (ReifyInstances name tys)-  qReifyRoles name = ghcCmd (ReifyRoles name)--  -- To reify annotations, we send GHC the AnnLookup and also the-  -- TypeRep of the thing we're looking for, to avoid needing to-  -- serialize irrelevant annotations.-  qReifyAnnotations :: forall a . Data a => TH.AnnLookup -> GHCiQ [a]-  qReifyAnnotations lookup =-    map (deserializeWithData . B.unpack) <$>-      ghcCmd (ReifyAnnotations lookup typerep)-    where typerep = typeOf (undefined :: a)--  qReifyModule m = ghcCmd (ReifyModule m)-  qReifyConStrictness name = ghcCmd (ReifyConStrictness name)-  qLocation = fromMaybe noLoc . qsLocation <$> getState-  qGetPackageRoot        = ghcCmd GetPackageRoot-  qAddDependentFile file = ghcCmd (AddDependentFile file)-  qAddTempFile suffix = ghcCmd (AddTempFile suffix)-  qAddTopDecls decls = ghcCmd (AddTopDecls decls)-  qAddForeignFilePath lang fp = ghcCmd (AddForeignFilePath lang fp)-  qAddModFinalizer fin = GHCiQ (\s -> mkRemoteRef fin >>= return . (, s)) >>=-                         ghcCmd . AddModFinalizer-  qAddCorePlugin str = ghcCmd (AddCorePlugin str)-  qGetQ = GHCiQ $ \s ->-    let lookup :: forall a. Typeable a => Map TypeRep Dynamic -> Maybe a-        lookup m = fromDynamic =<< M.lookup (typeOf (undefined::a)) m-    in return (lookup (qsMap s), s)-  qPutQ k = GHCiQ $ \s ->-    return ((), s { qsMap = M.insert (typeOf k) (toDyn k) (qsMap s) })-  qIsExtEnabled x = ghcCmd (IsExtEnabled x)-  qExtsEnabled = ghcCmd ExtsEnabled-  qPutDoc l s = ghcCmd (PutDoc l s)-  qGetDoc l = ghcCmd (GetDoc l)---- | The implementation of the 'StartTH' message: create--- a new IORef QState, and return a RemoteRef to it.-startTH :: IO (RemoteRef (IORef QState))-startTH = do-  r <- newIORef (initQState (error "startTH: no pipe"))-  mkRemoteRef r---- | Runs the mod finalizers.------ The references must be created on the caller process.-runModFinalizerRefs :: Pipe -> RemoteRef (IORef QState)-                    -> [RemoteRef (TH.Q ())]-                    -> IO ()-runModFinalizerRefs pipe rstate qrefs = do-  qs <- mapM localRef qrefs-  qstateref <- localRef rstate-  qstate <- readIORef qstateref-  _ <- runGHCiQ (TH.runQ $ sequence_ qs) qstate { qsPipe = pipe }-  return ()---- | The implementation of the 'RunTH' message-runTH-  :: Pipe-  -> RemoteRef (IORef QState)-      -- ^ The TH state, created by 'startTH'-  -> HValueRef-      -- ^ The splice to run-  -> THResultType-      -- ^ What kind of splice it is-  -> Maybe TH.Loc-      -- ^ The source location-  -> IO ByteString-      -- ^ Returns an (encoded) result that depends on the THResultType--runTH pipe rstate rhv ty mb_loc = do-  hv <- localRef rhv-  case ty of-    THExp -> runTHQ pipe rstate mb_loc (unsafeCoerce hv :: TH.Q TH.Exp)-    THPat -> runTHQ pipe rstate mb_loc (unsafeCoerce hv :: TH.Q TH.Pat)-    THType -> runTHQ pipe rstate mb_loc (unsafeCoerce hv :: TH.Q TH.Type)-    THDec -> runTHQ pipe rstate mb_loc (unsafeCoerce hv :: TH.Q [TH.Dec])-    THAnnWrapper -> do-      hv <- unsafeCoerce <$> localRef rhv-      case hv :: AnnotationWrapper of-        AnnotationWrapper thing -> return $!-          LB.toStrict (runPut (put (toSerialized serializeWithData thing)))---- | Run a Q computation.-runTHQ-  :: Binary a => Pipe -> RemoteRef (IORef QState) -> Maybe TH.Loc -> TH.Q a-  -> IO ByteString-runTHQ pipe rstate mb_loc ghciq = do-  qstateref <- localRef rstate-  qstate <- readIORef qstateref-  let st = qstate { qsLocation = mb_loc, qsPipe = pipe }-  (r,new_state) <- runGHCiQ (TH.runQ ghciq) st-  writeIORef qstateref new_state-  return $! LB.toStrict (runPut (put r))
− libraries/template-haskell/Language/Haskell/TH/CodeDo.hs
@@ -1,22 +0,0 @@--- | This module exists to work nicely with the QualifiedDo--- extension.------ @--- import qualified Language.Haskell.TH.CodeDo as Code------ myExample :: Monad m => Code m a -> Code m a -> Code m a--- myExample opt1 opt2 =---   Code.do---    x <- someSideEffect               -- This one is of type `M Bool`---    if x then opt1 else opt2--- @-module Language.Haskell.TH.CodeDo((>>=), (>>)) where--import Language.Haskell.TH.Syntax-import Prelude(Monad)---- | Module over monad operator for 'Code'-(>>=) :: Monad m => m a -> (a -> Code m b) -> Code m b-(>>=) = bindCode-(>>) :: Monad m => m a -> Code m b -> Code m b-(>>)  = bindCode_
− libraries/template-haskell/Language/Haskell/TH/Quote.hs
@@ -1,57 +0,0 @@-{-# LANGUAGE RankNTypes, ScopedTypeVariables, Safe #-}-{- |-Module : Language.Haskell.TH.Quote-Description : Quasi-quoting support for Template Haskell--Template Haskell supports quasiquoting, which permits users to construct-program fragments by directly writing concrete syntax.  A quasiquoter is-essentially a function with takes a string to a Template Haskell AST.-This module defines the 'QuasiQuoter' datatype, which specifies a-quasiquoter @q@ which can be invoked using the syntax-@[q| ... string to parse ... |]@ when the @QuasiQuotes@ language-extension is enabled, and some utility functions for manipulating-quasiquoters.  Nota bene: this package does not define any parsers,-that is up to you.--}-module Language.Haskell.TH.Quote(-        QuasiQuoter(..),-        quoteFile,-        -- * For backwards compatibility-        dataToQa, dataToExpQ, dataToPatQ-    ) where--import Language.Haskell.TH.Syntax-import Prelude---- | The 'QuasiQuoter' type, a value @q@ of this type can be used--- in the syntax @[q| ... string to parse ...|]@.  In fact, for--- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters--- to be used in different splice contexts; if you are only interested--- in defining a quasiquoter to be used for expressions, you would--- define a 'QuasiQuoter' with only 'quoteExp', and leave the other--- fields stubbed out with errors.-data QuasiQuoter = QuasiQuoter {-    -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@-    quoteExp  :: String -> Q Exp,-    -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@-    quotePat  :: String -> Q Pat,-    -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@-    quoteType :: String -> Q Type,-    -- | Quasi-quoter for declarations, invoked by top-level quotes-    quoteDec  :: String -> Q [Dec]-    }---- | 'quoteFile' takes a 'QuasiQuoter' and lifts it into one that read--- the data out of a file.  For example, suppose @asmq@ is an--- assembly-language quoter, so that you can write [asmq| ld r1, r2 |]--- as an expression. Then if you define @asmq_f = quoteFile asmq@, then--- the quote [asmq_f|foo.s|] will take input from file @"foo.s"@ instead--- of the inline text-quoteFile :: QuasiQuoter -> QuasiQuoter-quoteFile (QuasiQuoter { quoteExp = qe, quotePat = qp, quoteType = qt, quoteDec = qd }) -  = QuasiQuoter { quoteExp = get qe, quotePat = get qp, quoteType = get qt, quoteDec = get qd }-  where-   get :: (String -> Q a) -> String -> Q a-   get old_quoter file_name = do { file_cts <- runIO (readFile file_name) -                                 ; addDependentFile file_name-                                 ; old_quoter file_cts }