Hannes Siebenhandl pushed to branch wip/fendor/has-field-hie at Glasgow Haskell Compiler / GHC
Commits:
0c644375 by fendor at 2026-08-26T13:38:11+02:00
WIP
- - - - -
9 changed files:
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Utils.hs
- − testsuite/tests/hiefile/should_run/HasFieldQueries
- testsuite/tests/hiefile/should_run/HasFieldQueries.hs
- testsuite/tests/hiefile/should_run/HasFieldQueries.stdout
- testsuite/tests/hiefile/should_run/RecordDotTypes.stdout
- testsuite/tests/hiefile/should_run/T23492.hs
- testsuite/tests/hiefile/should_run/T23492.stdout
Changes:
=====================================
compiler/GHC/Iface/Ext/Ast.hs
=====================================
@@ -21,7 +21,6 @@ import GHC.Core.Class ( className, classSCSelIds )
import GHC.Core.Utils (exprType)
import GHC.Core.TyCo.Rep (Type(TyConApp))
import GHC.Core.TyCon (TyCon(..))
-import GHC.Builtin.Names (hasFieldClassName, getFieldName)
import GHC.Core.ConLike ( conLikeName )
import GHC.Core.DataCon ( dataConWrapperType )
import GHC.Core.Type ( Type, ForAllTyFlag(..) )
@@ -38,7 +37,7 @@ import GHC.Types.UnresolvedImport ( isGeneratedImport )
import GHC.Types.FieldLabel
import GHC.Types.Avail ( Avails )
import GHC.Types.Id ( isDataConId_maybe )
-import GHC.Types.Name ( Name, nameSrcSpan, nameUnique, wiredInNameTyThing_maybe, getName )
+import GHC.Types.Name ( Name, nameSrcSpan, nameUnique, wiredInNameTyThing_maybe, getName, hasKnownKey )
import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnv, lookupNameEnv )
import GHC.Types.Name.Reader ( RecFieldInfo(..), WithUserRdr(..) )
import GHC.Types.SrcLoc
@@ -50,6 +49,7 @@ import GHC.Tc.Types
import GHC.Tc.Types.ErrCtxt
import GHC.Tc.Types.Evidence
+import GHC.Builtin.KnownKeys (hasFieldClassKey)
import GHC.Builtin.Uniques
import GHC.Utils.Panic
@@ -688,21 +688,12 @@ hieEvIdsOfTerm :: EvTerm -> [EvId]
-- Returns only EvIds satisfying relevantEvId
hieEvIdsOfTerm = runFVSelectiveList isEvId . evTermFVs
-evFreeVarsOfTermList :: EvTerm -> [Var]
-evFreeVarsOfTermList (EvExpr e) = exprFreeVarsList e
-evFreeVarsOfTermList _ = []
-
-evDepsOfTermList :: EvTerm -> [EvId]
-evDepsOfTermList e
- | isHasFieldEvTerm e = evFreeVarsOfTermList e
- | otherwise = evVarsOfTermList e
-
instance ToHie (EvBindContext (LocatedA TcEvBinds)) where
toHie (EvBindContext sc sp (L span (EvBinds bs)))
= concatMapM go $ bagToList bs
where
go evbind = do
- let evDeps = evDepsOfTermList $ eb_rhs evbind
+ let evDeps = hieEvIdsOfTerm $ eb_rhs evbind
depNames = EvBindDeps $ map varName evDeps
concatM $
[ toHie (C (EvidenceVarBind (EvLetBind depNames) (combineScopes sc (mkScope span)) sp)
@@ -714,7 +705,7 @@ instance ToHie (EvBindContext (LocatedA TcEvBinds)) where
isHasFieldEvTerm :: EvTerm -> Bool
isHasFieldEvTerm (EvExpr expr)
| TyConApp tyCon _ <- exprType expr,
- tyConName tyCon == hasFieldClassName
+ tyConName tyCon `hasKnownKey` hasFieldClassKey
= True
isHasFieldEvTerm _ = False
@@ -732,7 +723,8 @@ instance ToHie (LocatedA HsWrapper) where
(WpEvApp a)
| isHasFieldEvTerm a ->
-- concatMapM (toHie . C EvidenceVarUse . L osp) $ hieEvIdsOfTerm a
- pprTrace "HasField" (ppr (a, osp)) $ concatMapM (toHie . C EvidenceVarUse . L osp) $ hieEvIdsOfTerm a
+ pprTrace "HasField" (ppr (a, osp)) $
+ concatMapM (toHie . C EvidenceVarUse . L osp) $ hieEvIdsOfTerm a
| otherwise ->
-- pprTrace "Not HasField" (ppr (a, osp)) $ concatMapM (toHie . C EvidenceVarUse . L osp) $ hieEvIdsOfTerm a
concatMapM (toHie . C EvidenceVarUse . L osp) $ hieEvIdsOfTerm a
=====================================
compiler/GHC/Rename/Expr.hs
=====================================
@@ -419,12 +419,11 @@ rnExpr (NegApp _ e _)
rnExpr (HsGetField _ e f)
= do { (getField, fv_getField) <- lookupSyntaxName getFieldClassOpOcc
; (e, fv_e) <- rnLExpr e
- ; let f' = rnDotFieldOcc f
- ; srcSpan <- getSrcSpanM
+ ; let f' = rnDotFieldOcc <$> f
; return ( mkExpandedExpr
(HsGetField noExtField e f')
- (mkGetField srcSpan getField e (fmap (unLoc . dfoLabel) f'))
- , fv_e `plusFV` fv_getField ) }
+ (mkGetField getField e (fmap (unLoc . dfoLabel) f'))
+ , fv_e `plusFN` fv_getField ) }
rnExpr (HsProjection _ fs)
= do { (getField, fv_getField) <- lookupSyntaxName getFieldClassOpOcc
@@ -2894,10 +2893,11 @@ rnHsIf p b1 b2
-- mkGetField arg field calculates a get_field @field arg expression.
-- e.g. z.x = mkGetField z x = get_field @x z
-mkGetField :: SrcSpan -> Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
-mkGetField srcSpan get_field arg (L _ (FieldLabelString field)) =
+mkGetField :: Name -> LHsExpr GhcRn -> LocatedAn NoEpAnns FieldLabelString -> HsExpr GhcRn
+mkGetField get_field arg (L ann (FieldLabelString field)) =
+ pprTrace "mkGetField" (ppr ann <+> ppr field)
-- See Note [Source locations for implicit function calls] in GHC.Iface.Ext.Ast
- genHsAppWith srcSpan (genAppTypeWith srcSpan (genHsVar get_field) (genHsTyLit field)) arg
+ genHsAppWith (getHasLoc ann) (genHsVar get_field `genAppType` genHsTyLit field) arg
-- mkSetField a field b calculates a set_field @field expression.
-- e.g mkSetSetField a field b = set_field @"field" a b (read as "set field 'field' to a on b").
=====================================
compiler/GHC/Rename/Utils.hs
=====================================
@@ -17,7 +17,7 @@ module GHC.Rename.Utils (
DeprecationWarnings(..), warnIfDeprecated,
checkUnusedRecordWildcard,
badQualBndrErr, typeAppErr, badFieldConErr,
- wrapGenSpan, wrapGenSpan', genHsVar, genHsVarWith, genLHsVar, genHsApp, genHsAppWith, genHsApps, genHsApps', genHsExpApps,
+ wrapGenSpan, wrapGenSpan', wrapNoSpan, genHsVar, genHsVarWith, genLHsVar, genHsApp, genHsAppWith, genHsApps, genHsApps', genHsExpApps,
genLHsApp, genAppType, genAppTypeWith,
genLHsLit, genHsIntegralLit, genHsTyLit, genSimpleConPat,
genVarPat, genWildPat,
@@ -740,7 +740,7 @@ genHsApp :: HsExpr GhcRn -> LHsExpr GhcRn -> HsExpr GhcRn
genHsApp fun arg = HsApp noExtField (wrapGenSpan fun) arg
genHsAppWith :: SrcSpan -> HsExpr GhcRn -> LHsExpr GhcRn -> HsExpr GhcRn
-genHsAppWith srcSpan fun arg = HsApp noExtField (wrapSrcSpan srcSpan fun) arg
+genHsAppWith srcSpan fun arg = HsApp noExtField (wrapGenSpan' srcSpan fun) arg
genLHsApp :: HsExpr GhcRn -> LHsExpr GhcRn -> LHsExpr GhcRn
genLHsApp fun arg = wrapGenSpan (genHsApp fun arg)
=====================================
testsuite/tests/hiefile/should_run/HasFieldQueries deleted
=====================================
Binary files a/testsuite/tests/hiefile/should_run/HasFieldQueries and /dev/null differ
=====================================
testsuite/tests/hiefile/should_run/HasFieldQueries.hs
=====================================
@@ -1,6 +1,4 @@
{-# LANGUAGE OverloadedRecordDot #-}
-{-# LANGUAGE TypeApplications #-}
-{-# LANGUAGE DataKinds #-}
module Main where
import TestUtils
@@ -8,46 +6,43 @@ import GHC.Records
import GHC.TypeLits
import Data.Tree
-class C a where
- f :: a -> Char
-
-instance C Char where
- f x = x
-
data Thing = Thing {field1 :: Char, field2 :: Bool}
deriving (Show, Eq)
foo :: Thing -> String
foo t = show t.field1 ++ show t.field2
- -- ^ this is the point
-point :: (Int,Int)
-point = (21,17)
-
-bar :: Show x => x -> String
-bar x = show [(1,x,A)]
--- ^ this is the point'
-point' :: (Int,Int)
-point' = (21,33)
-
-add :: Num a => a -> a -> a
-add x y = x + y
-
-testing (x :: Int) =
- add (add x x) x
-
+-- ^ this is the point
+
testing2 (x :: Thing) = x.field1
+-- ^ this is the point
+-- ^ this is the point
+
+data NestedThing = NestedThing { nested1 :: Thing }
-data A = A deriving Show
+nestedSig :: NestedThing -> Char
+nestedSig n = n.nested1.field1
+-- ^ this is the point
+-- ^ this is the point
-data Another = Another
+nestedNoSig n = n.nested1.field2 :: Bool
+-- ^ this is the point
+-- ^ this is the point
-testing3 = (natSing :: SNat 0)
+
+
+points =
+ [ (13,17)
+ , (16,25)
+ , (16,27)
+ , (23,17)
+ , (23,25)
+ , (27,20)
+ , (27,28)
+ ]
main = do
(df, hf) <- readTestHie "HasFieldQueries.hie"
let refmap = generateReferencesMap $ getAsts $ hie_asts hf
- explainEv df hf refmap point
-
- explainEv df hf refmap point'
+ traverse (explainEv df hf refmap) points
return ()
=====================================
testsuite/tests/hiefile/should_run/HasFieldQueries.stdout
=====================================
@@ -1,34 +1,109 @@
==========================
-At point (21,17), we found:
+At point (13,17), we found:
==========================
┌
│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
-│ is an evidence variable bound by a let, depending on: [field1]
+│ is an evidence variable bound by a let, depending on: [C:HasField]
│ with scope: ModuleScope
│
│ Defined at <no location info>
└
|
`- ┌
- │ field1 at HasFieldQueries.hs:1:1, of type: Thing -> Char
+ │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
│ is a usage of an external evidence variable
- │ Defined at HasFieldQueries.hs:17:21
+ │ Defined in `GHC.Internal.Records'
└
==========================
-At point (21,33), we found:
+At point (16,25), we found:
+==========================
+==========================
+At point (16,27), we found:
+==========================
+┌
+│ $dHasField at HasFieldQueries.hs:16:1-32, of type: HasField "field1" Thing Char
+│ is an evidence variable bound by a let, depending on: [C:HasField]
+│ with scope: LocalScope HasFieldQueries.hs:16:1-32
+│ bound at: HasFieldQueries.hs:16:1-32
+│ Defined at <no location info>
+└
+|
+`- ┌
+ │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
+ │ is a usage of an external evidence variable
+ │ Defined in `GHC.Internal.Records'
+ └
+
+==========================
+At point (23,17), we found:
==========================
┌
-│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field2" Thing Bool
-│ is an evidence variable bound by a let, depending on: [field2]
+│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "nested1" NestedThing Thing
+│ is an evidence variable bound by a let, depending on: [C:HasField]
│ with scope: ModuleScope
│
│ Defined at <no location info>
└
|
`- ┌
- │ field2 at HasFieldQueries.hs:1:1, of type: Thing -> Bool
+ │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
│ is a usage of an external evidence variable
- │ Defined at HasFieldQueries.hs:17:37
+ │ Defined in `GHC.Internal.Records'
+ └
+
+==========================
+At point (23,25), we found:
+==========================
+┌
+│ $dHasField at HasFieldQueries.hs:1:1, of type: HasField "field1" Thing Char
+│ is an evidence variable bound by a let, depending on: [C:HasField]
+│ with scope: ModuleScope
+│
+│ Defined at <no location info>
+└
+|
+`- ┌
+ │ C:HasField at HasFieldQueries.hs:1:1, of type: forall {k} (x :: k) r a. (r -> a) -> HasField x r a
+ │ is a usage of an external evidence variable
+ │ Defined in `GHC.Internal.Records'
+ └
+
+==========================
+At point (27,20), we found:
+==========================
+┌
+│ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "nested1" r r
+│ is an evidence variable bound by a let, depending on: [$dHasField]
+│ with scope: LocalScope HasFieldQueries.hs:27:1-40
+│ bound at: HasFieldQueries.hs:27:1-40
+│ Defined at <no location info>
+└
+|
+`- ┌
+ │ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "nested1" r r
+ │ is an evidence variable bound by a type signature
+ │ with scope: LocalScope HasFieldQueries.hs:27:1-40
+ │ bound at: HasFieldQueries.hs:27:1-40
+ │ Defined at <no location info>
+ └
+
+==========================
+At point (27,28), we found:
+==========================
+┌
+│ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "field2" r Bool
+│ is an evidence variable bound by a let, depending on: [$dHasField]
+│ with scope: LocalScope HasFieldQueries.hs:27:1-40
+│ bound at: HasFieldQueries.hs:27:1-40
+│ Defined at <no location info>
+└
+|
+`- ┌
+ │ $dHasField at HasFieldQueries.hs:27:1-40, of type: HasField "field2" r Bool
+ │ is an evidence variable bound by a type signature
+ │ with scope: LocalScope HasFieldQueries.hs:27:1-40
+ │ bound at: HasFieldQueries.hs:27:1-40
+ │ Defined at <no location info>
└
=====================================
testsuite/tests/hiefile/should_run/RecordDotTypes.stdout
=====================================
@@ -1,14 +1,5 @@
At (22,6), got type: MyRecord
-At (22,20), got type: Integer
-MyRecord -> Integer
-forall {k} (x :: k) r a. HasField x r a => r -> a
-forall (x :: Symbol) r a. HasField x r a => r -> a
+At (22,20), got type: MyRecord -> Integer
At (22,25), got type: MyRecord
-At (22,28), got type: String
-MyChild -> String
-forall {k} (x :: k) r a. HasField x r a => r -> a
-forall (x :: Symbol) r a. HasField x r a => r -> a
-At (22,29), got type: String
-MyChild -> String
-forall {k} (x :: k) r a. HasField x r a => r -> a
-forall (x :: Symbol) r a. HasField x r a => r -> a
+At (22,28), got type: MyChild -> String
+At (22,29), got type: MyChild -> String
=====================================
testsuite/tests/hiefile/should_run/T23492.hs
=====================================
@@ -24,12 +24,20 @@ g x = x.a
-- ^^^
-- 345
-p1, p2, p3, p4, p5 :: (Int,Int)
+h :: PartialFieldSelector -> Bool
+h x = (.a) x
+-- ^^ ^
+-- 67 8
+
+p1, p2, p3, p4, p5, p6, p7, p8 :: (Int,Int)
p1 = (13,20)
p2 = (18,7)
p3 = (23,7)
p4 = (23,8)
p5 = (23,9)
+p6 = (28,8)
+p7 = (28,9)
+p8 = (28,12)
selectPoint' :: HieFile -> (Int,Int) -> HieAST Int
selectPoint' hf loc =
@@ -37,7 +45,7 @@ selectPoint' hf loc =
main = do
(df, hf) <- readTestHie "T23492.hie"
- forM_ [p1,p2,p3,p4,p5] $ \point -> do
+ forM_ [p1,p2,p3,p4,p5,p6,p7,p8] $ \point -> do
putStr $ "At " ++ show point ++ ", got type: "
let types = concatMap nodeType $ getSourcedNodeInfo $ sourcedNodeInfo $ selectPoint' hf point
forM_ types $ \typ -> do
=====================================
testsuite/tests/hiefile/should_run/T23492.stdout
=====================================
@@ -4,4 +4,7 @@ PartialFieldSelector
At (18,7), got type: PartialFieldSelector -> Bool
At (23,7), got type: PartialFieldSelector
At (23,8), got type: PartialFieldSelector
-At (23,9), got type: Bool
+At (23,9), got type: PartialFieldSelector -> Bool
+At (28,8), got type: PartialFieldSelector -> Bool
+At (28,9), got type: PartialFieldSelector -> Bool
+At (28,12), got type: PartialFieldSelector
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0c64437518c798a293e4189acc0fd7d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0c64437518c798a293e4189acc0fd7d…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/jeltsch/improve-closure-property-check] Switch to unit identification via global unit keys
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
26 Aug '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/improve-closure-property-check at Glasgow Haskell Compiler / GHC
Commits:
ebd3f23d by Wolfgang Jeltsch at 2026-08-26T13:59:40+03:00
Switch to unit identification via global unit keys
- - - - -
2 changed files:
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Unit/External/Index.hs
Changes:
=====================================
compiler/GHC/Driver/Downsweep.hs
=====================================
@@ -55,7 +55,6 @@ import Language.Haskell.Syntax.ImpExp
import GHC.Types.UnresolvedImport
import GHC.Data.FastString
-import GHC.Data.ShortText (ShortText)
import GHC.Data.Maybe ( expectJust )
import qualified GHC.Data.Maybe as M
import GHC.Data.OsPath ( OsPath, unsafeEncodeUtf )
@@ -93,6 +92,7 @@ import GHC.Unit.Module.Graph
import GHC.Unit.Module.Deps
import qualified GHC.Unit.Home.Graph as HUG
import GHC.Unit.Module.Stage
+import GHC.Unit.External.Index (GlobalUnitKey, mkGlobalUnitKey)
import Data.Either ( partitionEithers, lefts )
import Data.Map (Map)
@@ -961,7 +961,7 @@ checkHomeUnitsClosed unit_env
Set.empty
where
- collect :: [UnitState] -> State (Set ShortText) [(UnitId, UnitId)]
+ collect :: [UnitState] -> State (Set GlobalUnitKey) [(UnitId, UnitId)]
collect []
= pure []
collect (current_unit_state : remaining_unit_states)
@@ -973,7 +973,7 @@ checkHomeUnitsClosed unit_env
collect_for_home_unit :: UnitInfoMap
-> [UnitId]
- -> State (Set ShortText) [(UnitId, UnitId)]
+ -> State (Set GlobalUnitKey) [(UnitId, UnitId)]
collect_for_home_unit _ []
= return []
collect_for_home_unit unit_info_map (current_unit : remaining_units) = do
@@ -988,14 +988,14 @@ checkHomeUnitsClosed unit_env
unit_not_found_msg :: String
unit_not_found_msg = "Unit not found during closure property check"
- abi_hash :: ShortText
- abi_hash = unitAbiHash unit_info
+ global_unit_key :: GlobalUnitKey
+ global_unit_key = mkGlobalUnitKey current_unit (unitAbiHash unit_info)
- has_been_processed <- gets (Set.member abi_hash)
+ has_been_processed <- gets (Set.member global_unit_key)
if has_been_processed
then collect_for_home_unit unit_info_map remaining_units
else do
- modify (Set.insert abi_hash)
+ modify (Set.insert global_unit_key)
let
needed_units :: [UnitId]
=====================================
compiler/GHC/Unit/External/Index.hs
=====================================
@@ -308,6 +308,7 @@ data GlobalUnitKey =
GlobalUnitKey
!UnitId -- ^ Unit Id of the 'UnitInfo'
!UnitAbiHash -- ^ ABI hash of the 'UnitInfo'
+ deriving (Eq, Ord)
globalUnitKeyFromUnitInfo :: UnitInfo -> GlobalUnitKey
globalUnitKeyFromUnitInfo ui = mkGlobalUnitKey (unitId ui) (unitAbiHash ui)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ebd3f23d37929fe81704bafb51069dd…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ebd3f23d37929fe81704bafb51069dd…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/jeltsch/improve-closure-property-check] Re-implement the home unit closure check
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
26 Aug '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/improve-closure-property-check at Glasgow Haskell Compiler / GHC
Commits:
755cf854 by Wolfgang Jeltsch at 2026-08-25T14:01:09+03:00
Re-implement the home unit closure check
Resolves #27051.
- - - - -
4 changed files:
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Unit/Env.hs
Changes:
=====================================
compiler/GHC/Driver/Downsweep.hs
=====================================
@@ -54,8 +54,8 @@ import GHC.Runtime.Context
import Language.Haskell.Syntax.ImpExp
import GHC.Types.UnresolvedImport
-import GHC.Data.Graph.Directed
import GHC.Data.FastString
+import GHC.Data.ShortText (ShortText)
import GHC.Data.Maybe ( expectJust )
import qualified GHC.Data.Maybe as M
import GHC.Data.OsPath ( OsPath, unsafeEncodeUtf )
@@ -71,12 +71,14 @@ import GHC.Utils.Logger
import GHC.Utils.Fingerprint
import GHC.Utils.TmpFs
import GHC.Utils.Constants
+import GHC.Utils.Monad.State.Strict
import GHC.Types.Error
import GHC.Types.Target
import GHC.Types.SourceFile
import GHC.Types.SourceError
import GHC.Types.SrcLoc
+import GHC.Types.Unique.Set
import GHC.Types.Unique.Map
import GHC.Types.PkgQual
import GHC.Types.Basic
@@ -93,7 +95,9 @@ import qualified GHC.Unit.Home.Graph as HUG
import GHC.Unit.Module.Stage
import Data.Either ( partitionEithers, lefts )
+import Data.Map (Map)
import qualified Data.Map as Map
+import Data.Set (Set)
import qualified Data.Set as Set
import Control.Concurrent.MVar
@@ -101,7 +105,7 @@ import Control.Monad
import Control.Monad.Trans.Except ( ExceptT(..), runExceptT, throwE )
import qualified Control.Monad.Catch as MC
import Data.Maybe
-import Data.List (partition)
+import Data.List (sort, partition)
import Data.Time
import Data.List (unfoldr)
import Data.Bifunctor (first, bimap)
@@ -933,52 +937,85 @@ rootSummariesParallel n_jobs hsc_env diag_wrapper msg get_summary = do
-- * Check/validate properties and error out
--------------------------------------------------------------------------------
--- | This function checks then important property that if both p and q are home units
--- then any dependency of p, which transitively depends on q is also a home unit.
---
--- See Note [Multiple Home Units], section 'Closure Property'.
-checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
-checkHomeUnitsClosed ue
- | Set.null bad_unit_ids = []
- | otherwise = [singleMessage $ mkPlainErrorMsgEnvelope rootLoc $ DriverHomePackagesNotClosed (Set.toList bad_unit_ids)]
+-- | Checks whether the given unit environment has the closure property. See
+-- the section “Closure Property” in @Note [Multiple Home Units]@.
+checkHomeUnitsClosed :: UnitEnv -> [DriverMessages]
+checkHomeUnitsClosed unit_env
+ | null offenders = []
+ | otherwise = [
+ singleMessage $
+ mkPlainErrorMsgEnvelope error_source_span $
+ DriverHomePackagesNotClosed (sort offenders)
+ ]
where
- home_id_set = HUG.allUnits $ ue_home_unit_graph ue
- bad_unit_ids = upwards_closure Set.\\ home_id_set {- Remove all home units reached, keep only bad nodes -}
- rootLoc = mkGeneralSrcSpan (fsLit "<command line>")
- downwards_closure :: Graph (Node UnitId UnitId)
- downwards_closure = graphFromEdgedVerticesUniq graphNodes
+ home_unit_data :: [(UnitId, HomeUnitEnv)]
+ home_unit_data = HUG.unitEnv_assocs (ue_home_unit_graph unit_env)
- inverse_closure = graphReachability $ transposeG downwards_closure
+ home_units :: UniqSet UnitId
+ home_units = mkUniqSet (map fst home_unit_data)
- upwards_closure = Set.fromList $ map node_key $ allReachableMany inverse_closure [DigraphNode uid uid [] | uid <- Set.toList home_id_set]
+ offenders :: [(UnitId, UnitId)]
+ offenders
+ = evalState (collect (map (homeUnitEnv_units . snd) home_unit_data)) $
+ Set.empty
+ where
- all_unit_direct_deps :: UniqMap UnitId (Set.Set UnitId)
- all_unit_direct_deps
- = HUG.unitEnv_foldWithKey go emptyUniqMap $ ue_home_unit_graph ue
+ collect :: [UnitState] -> State (Set ShortText) [(UnitId, UnitId)]
+ collect []
+ = pure []
+ collect (current_unit_state : remaining_unit_states)
+ = (++) <$> collect_for_home_unit
+ (unitInfoMap current_unit_state)
+ (map (toUnitId . fst) $ explicitUnits $ current_unit_state)
+ <*> collect remaining_unit_states
where
- go rest this this_uis =
- plusUniqMap_C Set.union
- (addToUniqMap_C Set.union external_depends this (Set.fromList $ this_deps))
- rest
- where
- external_depends = mapUniqMap (Set.fromList . unitDepends) (unitInfoMap this_units)
- this_units = homeUnitEnv_units this_uis
- this_deps = [ toUnitId unit | (unit,Just _) <- explicitUnits this_units]
-
- graphNodes :: [Node UnitId UnitId]
- graphNodes = go Set.empty home_id_set
- where
- go done todo
- = case Set.minView todo of
- Nothing -> []
- Just (uid, todo')
- | Set.member uid done -> go done todo'
- | otherwise -> case lookupUniqMap all_unit_direct_deps uid of
- Nothing -> pprPanic "uid not found" (ppr (uid, all_unit_direct_deps))
- Just depends ->
- let todo'' = (depends Set.\\ done) `Set.union` todo'
- in DigraphNode uid uid (Set.toList depends) : go (Set.insert uid done) todo''
+
+ collect_for_home_unit :: UnitInfoMap
+ -> [UnitId]
+ -> State (Set ShortText) [(UnitId, UnitId)]
+ collect_for_home_unit _ []
+ = return []
+ collect_for_home_unit unit_info_map (current_unit : remaining_units) = do
+ let
+
+ unit_info :: UnitInfo
+ unit_info
+ = fromMaybe (pprPanic unit_not_found_msg (ppr current_unit)) $
+ lookupUniqMap unit_info_map current_unit
+ where
+
+ unit_not_found_msg :: String
+ unit_not_found_msg = "Unit not found during closure property check"
+
+ abi_hash :: ShortText
+ abi_hash = unitAbiHash unit_info
+
+ has_been_processed <- gets (Set.member abi_hash)
+ if has_been_processed
+ then collect_for_home_unit unit_info_map remaining_units
+ else do
+ modify (Set.insert abi_hash)
+ let
+
+ needed_units :: [UnitId]
+ needed_units = unitDepends unit_info
+
+ current_offenders :: [(UnitId, UnitId)]
+ current_offenders
+ | current_unit `elementOfUniqSet` home_units
+ = []
+ | otherwise
+ = map ((,) current_unit) $
+ nonDetEltsUniqSet $
+ mkUniqSet needed_units `intersectUniqSets` home_units
+
+ remaining_offenders <- collect_for_home_unit unit_info_map $
+ needed_units ++ remaining_units
+ return $ current_offenders ++ remaining_offenders
+
+ error_source_span :: SrcSpan
+ error_source_span = mkGeneralSrcSpan (fsLit "<command line>")
--------------------------------------------------------------------------------
-- * Enable Code Gen for Template Haskell
@@ -1763,7 +1800,7 @@ data NodeRes v
--
-- See also Note [Downsweep Control Flow and Caching]
dfsBuild :: (Ord k, Monad m)
- => Maybe (Map.Map k (NodeRes v))
+ => Maybe (Map k (NodeRes v))
-- ^ Base map, existing results. We won't re-expand any of the nodes
-- already present in this map.
-> [n]
@@ -1773,7 +1810,7 @@ dfsBuild :: (Ord k, Monad m)
-> (n -> m (NodeRes (v,[n])))
-- ^ Expand this node into its payload result and into the list of
-- children nodes to visit next.
- -> m (Map.Map k (NodeRes v))
+ -> m (Map k (NodeRes v))
-- ^ The result accumulates the payload of expanding the root nodes
-- and all nodes transitively reachable from those roots.
dfsBuild base_map roots key expand = go roots (fromMaybe Map.empty base_map)
=====================================
compiler/GHC/Driver/Errors/Ppr.hs
=====================================
@@ -235,10 +235,17 @@ instance Diagnostic DriverMessage where
"but no output will be generated.") $$
(text "There is no module named" <+>
quotes (ppr mod_name) <> text "."))
- DriverHomePackagesNotClosed needed_unit_ids
- -> mkSimpleDecorated $ vcat ([text "Home units are not closed."
- , text "It is necessary to also load the following units:" ]
- ++ map (\uid -> text "-" <+> ppr uid) needed_unit_ids)
+ DriverHomePackagesNotClosed offending_dependencies
+ -> mkSimpleDecorated $
+ hang (text "Some units are not loaded but depend on loaded units.")
+ 4
+ (vcat (map pprDependency offending_dependencies))
+ where
+
+ pprDependency :: (UnitId, UnitId) -> SDoc
+ pprDependency (external_unit, home_unit)
+ = ppr external_unit <+> arrow <+> ppr home_unit
+
DriverInterfaceError reason -> diagnosticMessage (ifaceDiagnosticOpts opts) reason
DriverInconsistentDynFlags msg
=====================================
compiler/GHC/Driver/Errors/Types.hs
=====================================
@@ -369,7 +369,7 @@ data DriverMessage where
DriverRedirectedNoMain :: !ModuleName -> DriverMessage
- DriverHomePackagesNotClosed :: ![UnitId] -> DriverMessage
+ DriverHomePackagesNotClosed :: ![(UnitId, UnitId)] -> DriverMessage
DriverInterfaceError :: !IfaceMessage -> DriverMessage
=====================================
compiler/GHC/Unit/Env.hs
=====================================
@@ -443,13 +443,11 @@ The flow:
Closure Property
----------------
-You must perform a clean cut of the dependency graph.
-
-> Any dependency which is not a home unit must not (transitively) depend on a home unit.
-
-For example, if you have three packages p, q and r, then if p depends on q which
-depends on r then it is illegal to load both p and r as home units but not q,
-because q is a dependency of the home unit p which depends on another home unit r.
+A unit environment must have the closure property, which means that, whenever
+some units @h₁@ and @h₂@ have been loaded as home units, @h₁@ does not directly
+or indirectly depend on an external unit that directly or indirectly depends
+on @h₂@. 'GHC.Driver.Downsweep.checkHomeUnitsClosed' checks whether a given unit
+environment indeed has this property.
Offsetting Paths
----------------
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/755cf854150d85be469d6ad0d14cc6b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/755cf854150d85be469d6ad0d14cc6b…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc] Pushed new branch wip/jeltsch/improve-closure-property-check.global-unit-info-map
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
by Wolfgang Jeltsch (@jeltsch) 26 Aug '26
26 Aug '26
Wolfgang Jeltsch pushed new branch wip/jeltsch/improve-closure-property-check.global-unit-info-map at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/jeltsch/improve-closure-prope…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/fendor/has-field-hie] 54 commits: Cmm: print unreachable blocks under -dppr-debug (#27368)
by Hannes Siebenhandl (@fendor) 26 Aug '26
by Hannes Siebenhandl (@fendor) 26 Aug '26
26 Aug '26
Hannes Siebenhandl pushed to branch wip/fendor/has-field-hie at Glasgow Haskell Compiler / GHC
Commits:
0779e12c by Simon Jakobi at 2026-08-07T12:36:11-04:00
Cmm: print unreachable blocks under -dppr-debug (#27368)
Unreachable blocks linger in a CmmGraph's block map for most of the Cmm
pipeline, but pprCmmGraph only ever printed the blocks reachable from the
entry, so dumps looked consistent while the graph was not. Issues like
#27368 were hard to debug due to this.
pprCmmGraph now appends the stored-but-unreachable blocks under a
"// unreachable blocks:" heading when -dppr-debug is on.
See Note [unreachable blocks] in GHC.Cmm.Pipeline.
Assisted-by: Claude Opus 5
- - - - -
3a0f9a51 by Simon Peyton Jones at 2026-08-07T12:36:54-04:00
Fix three bugs related to required type args and INLINE pragmas
* `GHC.Core.Opt.Arity.mkEtaForAllMCo` got the visibility flags back to front,
leading to a Lint error (#27557)
* The arity in an InlineSaturation is the VisArity not the Arity; the
two can differ when we have "required" type arguments. This made the
INLINE pragma argument counting go wrong in `makeCorePair` (#27590).
* When a simple binding has a type signature, we take special path in `tcPolyCheck`,
leading to an outer `AbsBinds` that has no dictionaries, even when the binding
is in fact overloaded. That confused the inline-arity computation in
`makeCorePair` (#27589).
The latter two are fixed using the new function `GHC.HsToCore.Binds.findSatArity`.
That actually simplifies the API of `makeCorePair`, which is nice.
The first bug is fixed by swapping the visiblity flags in
`GHC.Core.Opt.Arity.mkEtaForAllMCo`
Getting the INLINE behaviour right led to some perf changes:
* Runtime /halved/ on T7954 due to better specialisation
* Compile time increased by 6% in T21839c because a bit more inlining
happened, as it always should have done.
* For some reason compile-time max-bytes-used dropped by 30% on
T27336, but only on one build configuration; and it increased
on LinkableUsage02 by 6% on another configuration
Geometric mean effect on our compile time benchmarks is +0.1%.
Metric Decrease:
T27336
T7954
Metric Increase:
LinkableUsage02
T21839c
- - - - -
4f985108 by Vladislav Zavialov at 2026-08-07T17:49:50-04:00
Discard type arguments in tcPatToExpr (#27440, #27583)
The builder expression of an implicitly bidirectional pattern synonym must not
mention types written in the RHS:
* Invisible type arguments led to a panic (#27440)
* Required type arguments failed with out-of-scope variables (#27583)
Both are now discarded, following the precedent established by pattern
signatures (#9867).
Discarding type arguments takes some care: a type pattern cannot be told from a
value pattern by syntax alone, as the `type` keyword may be omitted. Consider:
data T a b c where
MkT :: forall a. forall b c -> a -> T a b c
pattern P :: x -> T x y z
pattern P x = MkT @a (type b) c x
In P's right-hand side, `@a` and `type b` are clearly type arguments, but what
about `c` and `x`? We can only tell by matching the patterns against MkT's
type. So tcPatToExpr now runs in TcM and matches the arguments against the
constructor's TyVarBinders using zipPatsBndrs, which is made public for this
purpose. The resulting builder is $bP x = MkT _ _ x.
See Note [Discarding types in the builder expression].
Test cases: T27440a T27440b T27440c T27440d T27440e
T27583a T27583b T27583c T27583d T27583e T27583f T27583g
Metric Increase: LinkableUsage02
Metric Decrease: T27336
Assisted-by: Claude Opus 5
- - - - -
eb1dcd4d by sheaf at 2026-08-07T17:50:40-04:00
mkWpFun_FRR: fix ordering of coercion composition
When the subsumption machinery generates an eta-expansion, we must
perform a representation polymorphism check to ensure the lambda binder
it introduces has a fixed runtime representation.
This is done in GHC.Tc.Utils.mkWpFun_FRR.
This check involves composing quite a few coercions, arising from
representation-polymorphism checks on both the actual and expected
argument types. These coercions are then chained using HsWrapper
composition, <.>. The ordering of composition was incorrect, leading to
the Core Lint failure reported in #27639. This commit fixes that.
Fixes #27639
- - - - -
3a552476 by Simon Jakobi at 2026-08-09T15:20:06-04:00
Word64Map: add compareSize
compareSize m c compares the size of a map to an Int, but unlike
compare (size m) c it stops traversing the map once the outcome is
determined.
Based on https://github.com/haskell/containers/pull/1139
Assisted-by: Claude Opus 5
- - - - -
6e2c99d8 by Simon Jakobi at 2026-08-09T15:20:06-04:00
Use a pigeonhole sort for deterministic UniqDFM iteration
Deterministic UniqDFM iteration used a list mergesort, allocating O(n
log n) cons cells and contributing significantly to compiler allocations
(#27459).
Use a pigeonhole sort where appropriate, while retaining the mergesort
fallback. See Note [Sorting a UDFM] and Note [Cost of deterministic
iteration].
The peak_megabytes_allocated increase for LinkableUsage02 is probably
due to GC timing noise. See #27613.
-------------------------
Metric Decrease:
InstanceMatching
InstanceMatching1
ManyAlternatives
T12707
T13379
T13719
T24471
T27336
T5321FD
T5321Fun
T783
Metric Increase 'peak_megabytes_allocated':
LinkableUsage02
-------------------------
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
a938ab12 by sheaf at 2026-08-09T15:20:48-04:00
Testsuite: don't measure max residency for T27336
We really care more about total allocations for this test, so this commit
removes the maximum residency measurement.
- - - - -
7d94bb78 by Alan Zimmerman at 2026-08-09T15:21:29-04:00
EPA: Remove LocatedE, replace with LocatedA
This gets rid of one more LocatedXXX occurrence
- - - - -
9df24b7e by sheaf at 2026-08-10T14:28:30-04:00
hie.yaml: use a polyglot shell/batch script
This commit merges hie-bios and hie-bios.bat into a single polyglot
script. This avoids Windows users having to manually update hie.yaml
in order to be able to use HLS.
- - - - -
7f75c588 by Alan Zimmerman at 2026-08-10T14:29:11-04:00
EPA: Remove type parameter from AnnList
This is a step towards cutting AnnList down to its core for formatting
lists only
- - - - -
e8d1a0d6 by Bernhard M. Wiedemann at 2026-08-10T21:31:23-04:00
driver: Link object files in a deterministic order
The object files handed to the linker come from the HomePackageTable,
which is ordered by the order in which modules finished compiling. With
-j1 that is the build plan order, with -jN it is whatever the scheduler
produced, so the same sources can link to different (but equivalent)
binaries.
The order reaches the output: .text and .rodata contributions are
concatenated in link order, so e.g. building the hdav executable of the
DAV package twice, once with -j1 and once with -j4, yields two binaries
that differ in ~100kB of section contents.
Sort the home modules by module before collecting their linkables,
guarded under `Opt_ObjectDeterminism` .
Fixes #27612
Signed-off-by: Bernhard M. Wiedemann <bwiedemann(a)suse.de>
- - - - -
556db2f3 by sheaf at 2026-08-10T21:32:06-04:00
Reduce SpecConstr threshold in GHC.Tc.Solver.Rewrite
As remarked in #27628, this module currently sits on a knife's edge: if
the body of 'simplifyArgsWorker' is made even a tiny bit smaller, then
SpecConstr suddenly kicks in and causes disastrous reboxing of the
LiftingContext argument.
To make this less likely to happen, this commit lowers the SpecConstr
threshold.
- - - - -
c77d88fc by sheaf at 2026-08-13T10:15:22-04:00
Allow rewriting in RuntimeReps for newtype ConPats
This commit implements PHASE 2 of the FixedRuntimeRep plan described in
Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete for newtype
constructor patterns.
In short, GHC now accepts programs of the form
f (MkN x) = ...
in which the argument 'x' of the newtype constructor pattern 'MkN x'
has a representation that is not syntactically concrete, e.g. it can be
'Id IntRep' reducing to 'IntRep'. See T20363{,b,c} for examples.
There are two main parts to the implementation:
1. Typechecking, in GHC.Tc.Gen.Pat.tcDataConPat.
See Note [Typechecking newtype constructor patterns] in GHC.Tc.Gen.Pat.
2. Desugaring. We restructure the code for desugaring pattern matches
by allowing the scrutinised match variable to be casted. This allows
us to accumulate coercions and avoids creating binders at intermediate
types tha don't have a fixed RuntimeRep.
See the revamped Note [Match Ids] in GHC.HsToCore.Monad.
Fixes #20363
-------------------------
Metric Increase:
InstanceMatching
-------------------------
- - - - -
6ba9dd41 by Wolfgang Jeltsch at 2026-08-13T10:16:07-04:00
Improve the documentation of `--show-iface`
This change in particular gets rid of the claim that `--show-iface`
writes *the* contents of the interface file in question. It doesn’t do
that; it only writes those parts that are likely of interest to a human
reader.
- - - - -
4bd193fa by Sylvain Henry at 2026-08-13T10:17:00-04:00
RTS: fix LDV profiler's slop skipping (#27585)
processHeapForDead was the one heap scanner not updated for the slop
marker encoding introduced in #19048. It still assumed slop is zeroed:
while (p < bd->free && !*p) p++; // skip slop
so it stopped at the (StgWord)(-1) sentinel and passed it to
processHeapClosureForDead. IS_FORWARDING_PTR(-1) holds, hence a garbage
size was read out of LDVW and the scan ran off the block, tripping
ASSERT(p == bd->free) on a debug RTS and silently corrupting the census
otherwise.
The loop was hand-copied in four places, so factor it out into skipSlop
in ClosureMacros.h and use it in ProfHeap.c, Sanity.c, Printer.c and
LdvProfile.c.
Co-Authored-By: Claude Opus 5 (1M context) <noreply(a)anthropic.com>
- - - - -
1446bb03 by Zubin Duggal at 2026-08-13T10:17:48-04:00
hadrian: Fix links to remaining doc sites to not use the package hash for haddock links
In 07267f79d91169f474cacc8bcd38d76a6e97887d we changed hadrian to not include the package hash in the haddock
directory. This patch takes care of a few remaining links that were missed in that patch
Fixes #27671
- - - - -
257c3ed7 by Simon Jakobi at 2026-08-13T10:18:29-04:00
Testsuite: widen InstanceMatching acceptance window to 5% (#27673)
...in order to unblock CI.
Assisted-by: Claude Fable 5
- - - - -
e4cfaaa0 by Simon Peyton Jones at 2026-08-14T01:09:32+02:00
Major patch to re-engineer known-key names
This big patch implements the New Plan for known-key names,
described in #27013.
Read the big Note [Overview of known-key names] in GHC.Types.Name
Some things had to be reworked slightly to accomodate the new known-keys
design. A significant one was the generation of auxiliary KindRep
bindings, which was greatly simplified. Note [Grand plan for Typeable]
was updated accordingly. Another example: GHC.Internal.CString was
merged into GHC.Internal.Types.
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
The couple hundreds of hours spent here by Rodrigo were sponsored by Well-Typed
Metrics: compile_time/bytes allocated
-------------------------------------
Baseline
Test Metric value New value Change
------------------------------------------------------------------------------------------
MultiComponentModules100(normal) ghc/alloc 24,312,779,672 24,990,470,432 +2.8% BAD
MultiComponentModulesRecomp(normal) ghc/alloc 601,924,960 621,884,888 +3.3% BAD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,884,065,432 12,531,373,704 +5.4% BAD
MultiLayerModules(normal) ghc/alloc 3,861,537,072 3,706,919,512 -4.0% GOOD
T13701(normal) ghc/alloc 3,517,246,392 3,237,179,616 -8.0% GOOD
T13820(normal) ghc/alloc 28,961,056 29,663,208 +2.4% BAD
T14697(normal) ghc/alloc 472,044,184 443,550,048 -6.0% GOOD
T18140(normal) ghc/alloc 47,905,664 49,115,808 +2.5% BAD
T4801(normal) ghc/alloc 269,339,096 263,432,040 -2.2% GOOD
T783(normal) ghc/alloc 341,112,672 333,339,952 -2.3% GOOD
hard_hole_fits(normal) ghc/alloc 222,164,728 213,433,808 -3.9% GOOD
mhu-perf(normal) ghc/alloc 49,011,440 46,706,280 -4.7% GOOD
geo. mean +0.1%
minimum -8.0%
maximum +5.4%
All performance regressions were investigated in depth. The surviving
ones:
- MultiComponentModules100, MultiComponentModulesRecomp100,
MultiComponentModulesRecomp regresses because existing bugs that make
an additional implicit edge do too much redundant work: #27053 and #27461
- T13820, T18140, T10547, T13035 regress because we load an additional
interface and associated Names for GHC.Essentials.
-------------------------
Metric Decrease:
MultiLayerModules
T13379
T13701
T14697
T26989
T4801
T783
T9961
hard_hole_fits
mhu-perf
size_hello_artifact
size_hello_obj
size_hello_unicode
Metric Increase:
LinkableUsage01
LinkableUsage02
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
T10547
T13035
T13820
T18140
T18698a
T18698b
T20049
-------------------------
Bumps submodule binary
Closes #27013
- - - - -
61665e79 by sheaf at 2026-08-14T01:09:33+02:00
Allow GHC.Essentials to be hidden
This commit overhauls several aspects of the known entity handling,
in order to allow GHC.Essentials to be hidden without a proliferation
of special cases in the compiler.
The main contribution is to introduce the 'UnresolvedImport' datatype
which cleans up a lot of ad-hoc handling relating to 'ModSummary',
fixing #27603. This allows us to reduce duplication, e.g. by having
Backpack reuse 'mkUnresolvedImports' instead of replicating the
"add implicit imports" logic. It also makes it easier to avoid
undesirable edge cases (such as making sure that the Template Haskell
'reifyModule' function does not leak the implicit GHC.Essentials import).
In particular, the infamous 'findImportedModuleWithIsBoot' is now simply
'resolveImport', taking a single 'UnresolvedImport' and resolving it
to a 'FindResult' (usually a 'Module').
Other changes:
- Cache the result of looking up GHC.Essentials (in TcM and DsM
environments) to avoid redundant work.
This reduces allocations on LinkableUsage01 and hard_hole_fits.
- Properly look up known entities for StaticPointers like we do for
other known entities everywhere else. This allows e.g. modules in
ghc-internal to use -XStaticPointers.
- When using multiple home units, we are now careful to handle the
situation in which we may have multiple GHC.Essentials modules
around. See the new tests under 'driver/multipleHomeUnits'.
- - - - -
b19fcc1c by Vladislav Zavialov at 2026-08-14T06:26:11-04:00
Increase test coverage of diagnostics, batch 2
Add test cases for the previously untested diagnostics:
[GHC-26133] TcRnForeignImportPrimSafeAnn
[GHC-68444] SumAltArityExceeded
[GHC-63966] IllegalSumAlt
[GHC-23882] IllegalDeclaration
[GHC-60220] InvalidCCallImpent
[GHC-18816] RecGadtNoCons
[GHC-38140] GadtNoCons
[GHC-37056] InvalidTypeInstanceHeader
[GHC-78486] InvalidTyFamInstLHS
[GHC-39639] DefaultDataInstDecl
[GHC-78822] AssocDefaultNotAssoc
[GHC-43510] NotSimpleUnliftedType
[GHC-41843] IOResultExpected
[GHC-07641] AtLeastOneArgExpected
[GHC-52886] InvalidTopDecl
Remove unused error constructors:
[GHC-92057] ImportLookupAmbiguous
- - - - -
7b27f25a by Simon Jakobi at 2026-08-14T06:26:54-04:00
testsuite: Drop peak_megabytes_allocated from LinkableUsage tests
LinkableUsage01/02 collected all metrics with a 2% tolerance. For
peak_megabytes_allocated, whose granularity is 1 MB, that window is
under 0.7 MB at this test's ~34 MB peak, so any 1 MB step failed the
test (#27613, #27489). Drop that metric: max_bytes_used guards the
Linkable-retention property with byte granularity, at a tolerance
that still comfortably exceeds the noise observed in CI.
Assisted-by: Claude Fable 5
- - - - -
e5de423b by Simon Jakobi at 2026-08-14T06:26:54-04:00
testsuite: Don't truncate fractional baselines when computing bounds
RelativeMetricAcceptanceWindow.get_bounds truncated the baseline with
int() before applying the tolerance. Baselines can be fractional (they
are averaged over several measurements), so this skewed the acceptance
window downwards: in #27613, a baseline of 33.67 at 2% tolerance
yielded bounds (32, 34) instead of (32, 35), rejecting a measurement
that was within tolerance.
Assisted-by: Claude Fable 5
- - - - -
db959f83 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Expect length001 failure in nonmoving_thr_sanity
length001 relies on an optimization rule to avoid excessive stack use.
The nonmoving_thr_sanity way does not enable optimization, so classify
its stack overflow as an expected failure, as is already done for the
other unoptimized nonmoving ways.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
4f2b7d90 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Omit T22859 in nonmoving threaded ways
T22859 checks allocation-limit handlers with output that depends on
precise allocation behaviour. The nonmoving threaded ways change where
these limits are reached, just as the already-omitted LLVM ways do.
Omit these ways instead of treating their incidental output differences
as test failures.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
c4abddcb by Simon Jakobi at 2026-08-14T15:16:44-04:00
rts/js: Implement eq_thread, and test Eq/Ord ThreadId (#16761)
Since d1f3c63701, Eq ThreadId is implemented via the RTS function
eq_thread, but the JS RTS never provided it, so comparing ThreadIds
for equality on the JS backend crashed with
ReferenceError: h$eq_thread is not defined
Like the C implementation, h$eq_thread uses pointer equality: The JS
RTS has exactly one thread object per thread.
Since previously no test exercised eq_thread directly, this commit
adds a test covering equality, its stability across GC, and agreement
with Ord.
Assisted-by: Claude Fable 5
- - - - -
4a7defa1 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Make listThreads1 insensitive to the RTS's own threads
listThreads1 expected `listThreads` to return exactly [ThreadId 1]. That
holds only under a non-threaded RTS. Under a threaded RTS however there
are more threads present, so we change the test to simply check that
`myThreadId` is present in the list.
Assisted-by: Claude Opus 5
- - - - -
b757727a by Vladislav Zavialov at 2026-08-14T15:17:27-04:00
Fix tcLookupId panic with RequiredTypeArguments and PatternSynonyms (#27586)
The arguments declared on the left-hand side of a pattern synonym are looked up
as term variables bound by its right-hand side. Prior to this patch, that lookup
panicked with RequiredTypeArguments:
data T a where
MkT :: forall a -> T a
pattern P :: Int -> T Int
pattern P x = MkT x
On the RHS, `x` looks like a term argument, so the renamer binds it in the term
namespace. Only during type checking does it turn out to be a type variable, so
the lookup on the LHS finds an ATyVar rather than an ATcId. As the lookup was
done with tcLookupId, it resulted in a panic.
Now the arguments are looked up with tcLookupPatSynArg, which reports an illegal
term-level use of `x`, just as an ordinary function definition `f (MkT x) = x`
does.
Test cases: T27586a T27586b T27586c
Assisted-by: Claude Opus 5
- - - - -
c130188d by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
loopImports: Don't dup ms_uid in summary imports
We were writing the ms_unitid of the mod summary with every single
import of that module
That complicated the code (as though the UnitId in that list could ever
be something else) and also allocates unnecessarily per every mod
import. Very slight allocation decrease measured locally in a few tests:
(MultiComponentModulesRecomp: -0.06%; MultiComponentModulesRecomp100: -0.05%)
Purely a clean up.
- - - - -
c71166a8 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: make control flow simpler and cache correct
This refactor extracts the control flow of downsweep into a single
function `dfsBuild`, which takes care of iteratively expanding and
traversing all nodes of the in-construction module graph necessary to
build a full `ModuleGraph`.
There are three levels of caching going on, all of which are necessary
to make sure we don't do repeated work (notably, NEVER summarise the
same module twice).
1. `dfsBuild` accumulates the final module graph and never revisits the
same node of the module graph. Cache is keyed by the final
`ModuleGraph`s `NodeKey`s.
2. For Module A in home-unit u1, each import in the list of imports
needs to be *found* (call to `findImportedModuleWithIsBoot`): at this
point, we only have the `ModuleName` of the import, not the `Module`.
This *finding* is somewhat expensive, so we cache it as well
(`ImportsCache`). The cache key is the home-unit to which the module
belongs~[1], the import package qualifier, and the ModuleName.
[1] Different home-units will have different package flags, which means
potentially different `Module` resolution for the same `ModuleName`.
3. The most expensive operation we want to avoid is summarising a
`Module` into a `ModSummary`, which notably involves parsing the
module header from scratch.
The third cache, in essence, maps a `Module` to its `ModSummary`
(named `ModSummaryCache`). This cache upholds the invariant: we NEVER
summarise the same module twice. In practice, the cache key is the
Module's UnitId and the Source path; the reason is we need to
distinguish between `.hs` and `.hs-boot` files, as their summaries
will differ.
Note that (2) can't guarantee this alone: Two ModuleName imports in
separate units can (and likely do) map to the same `Module`.
Note that the previous implementation failed to achieve the
no-duplicate-work summarisation invariant, and we ended up doing a
quadratic amount of processing in scenarios like test
`MultiComponentModules100`.
See also Note [Downsweep Control Flow and Caching]
Fixes #27461
Perf changes:
MultiComponentModules(normal) ghc/alloc 2,097,389,264 1,992,186,736 -5.0% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,173,770 21,293,867,360 -12.4% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,761,394 498,543,984 -17.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,968,240 8,895,404,864 -25.2% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
ebc4047b by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
implicitRequirementsShallow can never reach HoleUnit
findImportedModule will never return `HoleUnit` for a `ModuleName`
(a `HoleUnit` can only be found as a signature instantiation, never as a
directly *imported* thing)
Therefore, we can drop `[ModuleName]` returned by
`implicitRequirementsShallow`, which makes many things dead code.
Namely, the call to `implicitRequirementsShallow` from
GHC.Driver.Downsweep which was a performance bottleneck (for doing lots
of duplicate work in findImportedModule) is now entirely gone.
Fixes #27053
In an MR with this patch and the downsweep refactor (previous commit), CI says:
MultiComponentModules(normal) ghc/alloc 2,097,396,728 1,943,662,304 -7.3% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,182,136 17,227,574,440 -29.1% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,769,518 449,973,656 -25.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,976,408 4,828,894,160 -59.4% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
85a6ab01 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: Cache negative results
When traversing a module graph structure, a uniquely identified node
should always expand to the same thing.
I don't see how visiting the same node which failed to be expanded a
first time would ever successfully expand the second time we try to
expand it (eg. when coming from a different edge to it -- it is still
the same node!). The node expansion is local, based just based on the
node itself, not on the path to get there.
Therefore, this patch removes the weird behavior and commentary of
`dfsBuild` wrt to `Nothing` not being cached and being potentially
expanded a second time around to something different, which was
misleading and, ultimately, incorrect.
Now, we have a `MGRes`, which is more explicit about a node being
Skipped just being a node that is ignored whenever it is found (and that
skip is cached) -- and we may want to do this due to failures or due to
just trying nodes which might not work on purpose, like hs-boots.
We uniformly cache positive and negative results and remove the
assumption that there might be an ordering in which the same node
visited at a later time might be expanded differently.
This makes it possible to traverse the module nodes in parallel without
a change in behavior, since there's no longer a hidden ordering
requirement.
- - - - -
56747c3f by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
Organize and clean-up GHC.Driver.Downsweep
Simply some cosmetic changes, moving definitions around to structure the
module better into its relevant sections
(In go (ns ++ ss), it's not a problem to use ++ because it's a good
producer and we won't have to append fully before processing the next
item in go)
- - - - -
12f64118 by Wolfgang Jeltsch at 2026-08-15T06:31:12-04:00
Add support for textual output of bytecode file content
- - - - -
a737df91 by Brandon Chinn at 2026-08-15T12:40:25-04:00
Add law in qualified strings doc
- - - - -
e3188581 by Zubin Duggal at 2026-08-15T12:41:06-04:00
DmdAnal: Fix maxDmdType
We need to eta expand the smaller DmdType using defaultArgDmd, like in lubDmdType.
Introduce zipDmdType as a common combinator to implement both maxDmdType and lubDmdType
uniformly.
fixes #27626
- - - - -
ca9b0b22 by mangoiv at 2026-08-15T12:41:47-04:00
hadrian: set the executable bit for hie-bios.bat
- - - - -
1aac7095 by sheaf at 2026-08-16T04:37:16-04:00
Avoid wasteful allocations in mkTyConAppCo
The idiom "traverse isReflCo_maybe" followed by "map fst" used in
'GHC.Core.Coercion.mkTyConAppCo' was allocating a lot of waste.
This commit uses 'GHC.Data.Unboxed.traverseMaybeUB' to avoid all these
unnecessary intermediate allocations.
In a quick microbenchmark for 'mkTyConAppCo', this change resulted in:
- refl case (all argument coercions are reflexive):
- -60% runtime
- -80% allocations
- non-refl case:
- from 0% to -12% runtime (depending on which argument is non-refl)
- from 0% to -70% allocations ( -- '' -- )
Fixes #27648
-------------------------
Metric Decrease:
FamAppCachePerf
SimplCastPerf
T12425
T15703
T26426
T3064
T9872a
T9872b
T9872b_defer
T9872c
T9872d
T5321Fun
T9020
T9630
TcPlugin_RewritePerf
Metric Increase:
LinkableUsage02
-------------------------
- - - - -
3915e982 by Alan Zimmerman at 2026-08-16T04:37:58-04:00
EPA: Remove al_trailing from AnnList
It was not being used
- - - - -
fed942ac by Andreas Klebinger at 2026-08-17T12:11:57-04:00
testsuite: Use sigkill in process009.
SIGHUB might have been blocked by a (grand)*parent of the test.
In such cases the test would fail as the python process would simply
exist gracefully instead of committing to a premature end.
By using SIGKILL we can rely on the signal not being blocked, fixing #27578
in the process.
- - - - -
574c875f by Andreas Klebinger at 2026-08-17T12:12:39-04:00
Simplify comparison in DFM.hs
Fixes #27669
- - - - -
d8f1a2a3 by Alan Zimmerman at 2026-08-17T12:13:18-04:00
TTG: Add extension points to BooleanFormula
They are currently unused, but will be used for exact print
annotations next, allowing us to get rid of LocatedBF / SrcSpanAnnBF
- - - - -
93a2b20f by Andreas Klebinger at 2026-08-18T04:31:04-04:00
Fix a number of incorrect module references:
Fix module reference in Note [DataCon wrappers are conlike].
Fix module reference in Note [Detailed InertCans Invariants].
Fix module reference in Note [GHC's data format representations].
Fix module reference in Note [Grand plan for static forms].
Fix module reference in Note [How tuples work].
Fix module reference in Note [Solved dictionaries].
Fix module reference in Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)].
Fix module reference in Note [The VarBndr type and its uses].
Found the incorrect references with a llm.
- - - - -
eb0dfb01 by Simon Jakobi at 2026-08-18T04:31:44-04:00
ci: Run stack-hadrian-build only in full-ci pipelines
The job exists to catch changes that break hadrian/build-stack (#18726),
but nothing in the pipeline depends on it, and it can only break when
hadrian's dependencies change. Restricting it to full-ci (like
hadrian-multi) still covers marge-bot merge batches, so such breakage
cannot reach master unnoticed, while ordinary validate pipelines skip
the job.
Assisted-by: Claude Fable 5
- - - - -
b9160962 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Show baseline sample count and range in perf failures
A perf baseline is the mean of all samples recorded for a commit, and
it prints as a single number, hiding how far the samples spread. When
the spread is wide, this can indicate an unstable metric that isn't
actually useful as a signal for the perf tests.
For example, in #27602, T27336's peak_megabytes_allocated baseline
showed as 757 when the underlying samples were 605 and 909.
When the baseline is averaged from more than one sample, say so in the
failure output: the one-line stat-failure reason shows the sample
range, and the detail block lists the raw samples. Single-sample
baselines print exactly as before.
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
a4979877 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Fold Baseline into CommitMetric
A Baseline was just a CommitMetric plus the commit it came from, built
by copying fields across. Since get_commit_metric already knows that
commit, record it on CommitMetric itself and drop Baseline. This also
collapses both branches of find_baseline into plain returns.
Assisted-by: Claude Fable 5
- - - - -
99fb8d68 by Simon Jakobi at 2026-08-20T14:57:52-04:00
ci: Clarify comment on pushing perf notes after failures
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
2ca87972 by Alan Zimmerman at 2026-08-20T14:58:36-04:00
EPA: Remove LocatedBC / SrcSpanBF
The custom annotations are now in the BooleanFormula TTG extension
points, so LBooleanFormula can now use the standard LocatedA.
- - - - -
d2bc32aa by Simon Peyton Jones at 2026-08-21T12:59:26-04:00
Better handling of serialisation of wired-in names
Fixes #27501
- - - - -
d2795ffc by Alan Zimmerman at 2026-08-21T13:00:05-04:00
EPA: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead
Also introduce helper functions noEpTok and noEpUniTok to serve
as simple replacements in code inserting an token annotation without
location information.
- - - - -
b5d29ab8 by Brandon Chinn at 2026-08-25T18:42:08-04:00
Add Data.RealFloat and Infinity/NegInfinity/NaN pattern synonyms (#26961)
- - - - -
e60eb3bc by Andreas Klebinger at 2026-08-25T18:42:59-04:00
rts linker: Fix pointer arithmetic issue in flushInstructionCacheRISCV64
We accidentally operated over `uint64_t*` when we should use `uint8_t`.
Fixes #27569
- - - - -
735c2c7c by brian at 2026-08-26T12:46:07+02:00
add HasField info in hie file
- - - - -
91546e99 by brian at 2026-08-26T12:46:07+02:00
update tests
- - - - -
f70a72f4 by fendor at 2026-08-26T12:46:08+02:00
WIP
- - - - -
1017 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- + changelog.d/27626
- + changelog.d/T20363
- + changelog.d/T27368-ppr-unreachable-cmm-blocks.md
- + changelog.d/T27440
- + changelog.d/T27557
- + changelog.d/T27583
- + changelog.d/T27586
- + changelog.d/T27589
- + changelog.d/T27639
- + changelog.d/downsweep-refactor
- changelog.d/fix-heap-census-large-arrays-19048
- + changelog.d/link-deterministic-order
- + changelog.d/refactor-known-names
- + changelog.d/show-byte-code
- compiler/GHC.hs
- + compiler/GHC/Builtin.hs
- + compiler/GHC/Builtin/KnownKeys.hs
- + compiler/GHC/Builtin/KnownOccs.hs
- + compiler/GHC/Builtin/Modules.hs
- − compiler/GHC/Builtin/Names.hs
- − compiler/GHC/Builtin/Names/TH.hs
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/Builtin/PrimOps/Casts.hs
- compiler/GHC/Builtin/PrimOps/Ids.hs
- + compiler/GHC/Builtin/TH.hs
- compiler/GHC/Builtin/Uniques.hs
- compiler/GHC/Builtin/Uniques.hs-boot
- − compiler/GHC/Builtin/Utils.hs
- + compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/Types/Prim.hs → compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/Types/Literals.hs → compiler/GHC/Builtin/WiredIn/TypeLits.hs
- compiler/GHC/Builtin/Types.hs → compiler/GHC/Builtin/WiredIn/Types.hs
- compiler/GHC/Builtin/Types.hs-boot → compiler/GHC/Builtin/WiredIn/Types.hs-boot
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Serialize.hs
- + compiler/GHC/ByteCode/Show.hs
- compiler/GHC/Cmm.hs
- compiler/GHC/Cmm/Pipeline.hs
- compiler/GHC/CmmToAsm/Format.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Class.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Multiplicity.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/CprAnal.hs
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Core/Opt/LiberateCase.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Unfold.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Data/BooleanFormula.hs
- compiler/GHC/Data/Unboxed.hs
- compiler/GHC/Data/Word64Map/Internal.hs
- compiler/GHC/Data/Word64Map/Lazy.hs
- compiler/GHC/Data/Word64Map/Strict.hs
- compiler/GHC/Data/Word64Map/Strict/Internal.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Tidy.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/KnotVars.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/GenerateCgIPEStub.hs
- compiler/GHC/Driver/Main/Hsc.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Plugins.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Arrows.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/HsToCore/Foreign/Call.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Foreign/Utils.hs
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- compiler/GHC/HsToCore/ListComp.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match.hs-boot
- compiler/GHC/HsToCore/Match/Constructor.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc/Check.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Ppr.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/HsToCore/Utils.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Env.hs
- − compiler/GHC/Iface/Env.hs-boot
- compiler/GHC/Iface/Errors/Ppr.hs
- compiler/GHC/Iface/Errors/Types.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Plugins.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Context.hs
- compiler/GHC/Runtime/Debugger.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/Unarise.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Bind.hs
- compiler/GHC/StgToCmm/DataCon.hs
- compiler/GHC/StgToCmm/Env.hs
- compiler/GHC/StgToCmm/Foreign.hs
- compiler/GHC/StgToCmm/Lit.hs
- compiler/GHC/StgToCmm/Ticky.hs
- compiler/GHC/StgToJS/Apply.hs
- compiler/GHC/StgToJS/Arg.hs
- compiler/GHC/StgToJS/Expr.hs
- compiler/GHC/StgToJS/FFI.hs
- compiler/GHC/StgToJS/Linker/Utils.hs
- compiler/GHC/StgToJS/Utils.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Deriv/Functor.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Deriv/Infer.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Default.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Foreign.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Instance/Typeable.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Build.hs
- compiler/GHC/Tc/TyCl/Class.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Arity.hs
- compiler/GHC/Types/DefaultEnv.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/InlinePragma.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Types/Name.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Name/Ppr.hs
- compiler/GHC/Types/Name/Reader.hs
- compiler/GHC/Types/RepType.hs
- compiler/GHC/Types/TyThing.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/DFM.hs
- compiler/GHC/Types/Unique/FM.hs
- + compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Unit.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/External.hs
- compiler/GHC/Unit/External/Index.hs
- compiler/GHC/Unit/External/ModuleOrigin.hs
- compiler/GHC/Unit/External/Providers.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- compiler/GHC/Utils/Binary.hs
- − compiler/GHC/Utils/Binary/Typeable.hs
- compiler/Language/Haskell/Syntax/BooleanFormula.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/ghc.cabal.in
- docs/index.html.in
- docs/users_guide/debugging.rst
- docs/users_guide/exts/qualified_strings.rst
- docs/users_guide/ghc_config.py.in
- docs/users_guide/separate_compilation.rst
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Monad.hs
- ghc/Main.hs
- − hadrian/hie-bios
- hadrian/hie-bios.bat
- hadrian/src/Rules/Generate.hs
- hie.yaml
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Control/Applicative.hs
- libraries/base/src/Control/Concurrent.hs
- libraries/base/src/Control/Concurrent/Chan.hs
- libraries/base/src/Control/Concurrent/QSem.hs
- libraries/base/src/Control/Concurrent/QSemN.hs
- libraries/base/src/Data/Array/Byte.hs
- libraries/base/src/Data/Bifoldable.hs
- libraries/base/src/Data/Bifoldable1.hs
- libraries/base/src/Data/Bifunctor.hs
- libraries/base/src/Data/Bitraversable.hs
- libraries/base/src/Data/Bool.hs
- libraries/base/src/Data/Complex.hs
- libraries/base/src/Data/Data.hs
- libraries/base/src/Data/Enum.hs
- libraries/base/src/Data/Fixed.hs
- libraries/base/src/Data/Foldable1.hs
- libraries/base/src/Data/Functor/Classes.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Data/Functor/Contravariant.hs
- libraries/base/src/Data/Functor/Product.hs
- libraries/base/src/Data/Functor/Sum.hs
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- libraries/base/src/Data/List/NubOrdSet.hs
- + libraries/base/src/Data/RealFloat.hs
- libraries/base/src/Data/Semigroup.hs
- libraries/base/src/Data/Version.hs
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/ByteOrder.hs
- + libraries/base/src/GHC/Essentials.hs
- libraries/base/src/GHC/Exts.hs
- libraries/base/src/GHC/Fingerprint.hs
- libraries/base/src/GHC/RTS/Flags.hs
- libraries/base/src/GHC/ResponseFile.hs
- libraries/base/src/GHC/Stats.hs
- libraries/base/src/GHC/Weak/Finalize.hs
- libraries/base/src/Numeric.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/System/CPUTime/Posix/ClockGetTime.hsc
- libraries/base/src/System/CPUTime/Posix/RUsage.hsc
- libraries/base/src/System/CPUTime/Posix/Times.hsc
- libraries/base/src/System/CPUTime/Unsupported.hs
- libraries/base/src/System/Console/GetOpt.hs
- libraries/base/src/System/Exit.hs
- libraries/base/src/System/IO.hs
- libraries/base/src/System/IO/OS.hs
- libraries/base/src/System/IO/Unsafe.hs
- libraries/base/src/System/Info.hs
- libraries/base/src/System/Timeout.hs
- libraries/base/src/Text/Printf.hs
- libraries/base/src/Text/Read.hs
- libraries/base/src/Text/Show/Functions.hs
- libraries/base/tests/all.T
- libraries/base/tests/listThreads1.hs
- libraries/base/tests/listThreads1.stdout
- libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr
- libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr
- libraries/binary
- libraries/ghc-experimental/src/Data/Sum/Experimental.hs
- libraries/ghc-experimental/src/Data/Tuple/Experimental.hs
- libraries/ghc-experimental/src/GHC/Profiling/Eras.hs
- libraries/ghc-experimental/src/Prelude/Experimental.hs
- libraries/ghc-internal/codepages/MakeTable.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/include/RtsIfaceSymbols.h
- libraries/ghc-internal/src/GHC/Internal/AllocationLimitHandler.hs
- libraries/ghc-internal/src/GHC/Internal/Arr.hs
- libraries/ghc-internal/src/GHC/Internal/ArrayArray.hs
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/GMP.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Primitives.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/WordArray.hs
- libraries/ghc-internal/src/GHC/Internal/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs
- libraries/ghc-internal/src/GHC/Internal/CString.hs
- libraries/ghc-internal/src/GHC/Internal/Char.hs
- libraries/ghc-internal/src/GHC/Internal/Classes.hs
- libraries/ghc-internal/src/GHC/Internal/Classes/IP.hs
- libraries/ghc-internal/src/GHC/Internal/Clock.hsc
- libraries/ghc-internal/src/GHC/Internal/ClosureTypes.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Bound.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/POSIX.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/POSIX/Const.hsc
- libraries/ghc-internal/src/GHC/Internal/Conc/Signal.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs
- libraries/ghc-internal/src/GHC/Internal/ConsoleHandler.hsc
- libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Category.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Concurrent/MVar.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fail.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fix.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/IO/Class.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Zip.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Coerce.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Data.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Dynamic.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Either.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Function.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Const.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Utils.hs
- libraries/ghc-internal/src/GHC/Internal/Data/IORef.hs
- libraries/ghc-internal/src/GHC/Internal/Data/List.hs
- libraries/ghc-internal/src/GHC/Internal/Data/List/NonEmpty.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Maybe.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Monoid.hs
- libraries/ghc-internal/src/GHC/Internal/Data/NonEmpty.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Ord.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Proxy.hs
- libraries/ghc-internal/src/GHC/Internal/Data/STRef.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Semigroup/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/String.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Traversable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Tuple.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Bool.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Coercion.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Equality.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Ord.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Typeable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Typeable/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Unique.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Void.hs
- libraries/ghc-internal/src/GHC/Internal/Debug/Trace.hs
- libraries/ghc-internal/src/GHC/Internal/Desugar.hs
- libraries/ghc-internal/src/GHC/Internal/Encoding/UTF8.hs
- libraries/ghc-internal/src/GHC/Internal/Enum.hs
- libraries/ghc-internal/src/GHC/Internal/Enum.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Environment.hs
- libraries/ghc-internal/src/GHC/Internal/Err.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Arr.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Array.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Event/EPoll.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/IntTable.hs
- libraries/ghc-internal/src/GHC/Internal/Event/IntVar.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Internal/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Event/KQueue.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/PSQ.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Poll.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimeOut.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Unique.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Clock.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/ConsoleEvent.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/FFI.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/ManagedThreadPool.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs-boot
- libraries/ghc-internal/src/GHC/Internal/ExecutionStack.hs
- libraries/ghc-internal/src/GHC/Internal/ExecutionStack/Internal.hsc
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- libraries/ghc-internal/src/GHC/Internal/Fingerprint.hs
- libraries/ghc-internal/src/GHC/Internal/Fingerprint/Type.hs
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- libraries/ghc-internal/src/GHC/Internal/Float/ConversionUtils.hs
- libraries/ghc-internal/src/GHC/Internal/Float/RealFracMethods.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/ConstPtr.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/Error.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/String.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/String/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/ForeignPtr/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Alloc.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Array.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Error.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Pool.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Utils.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Ptr.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Storable.hs
- libraries/ghc-internal/src/GHC/Internal/ForeignPtr.hs
- libraries/ghc-internal/src/GHC/Internal/ForeignSrcLang.hs
- libraries/ghc-internal/src/GHC/Internal/Functor/ZipList.hs
- libraries/ghc-internal/src/GHC/Internal/GHCi.hs
- libraries/ghc-internal/src/GHC/Internal/GHCi/Helpers.hs
- libraries/ghc-internal/src/GHC/Internal/Generics.hs
- libraries/ghc-internal/src/GHC/Internal/Heap/Closures.hs
- libraries/ghc-internal/src/GHC/Internal/Heap/Constants.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable/Types.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTableProf.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/ProfInfo/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO.hs
- libraries/ghc-internal/src/GHC/Internal/IO.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/Buffer.hs
- libraries/ghc-internal/src/GHC/Internal/IO/BufferedIO.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Device.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/API.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/Table.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Failure.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Iconv.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Latin1.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF16.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF32.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF8.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/FD.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/FD.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Common.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Flock.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/LinuxOFD.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/NoOp.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Windows.hs
- libraries/ghc-internal/src/GHC/Internal/IO/IOMode.hs
- libraries/ghc-internal/src/GHC/Internal/IO/SubSystem.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Unsafe.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Windows/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Windows/Handle.hsc
- libraries/ghc-internal/src/GHC/Internal/IOArray.hs
- libraries/ghc-internal/src/GHC/Internal/IORef.hs
- libraries/ghc-internal/src/GHC/Internal/InfoProv.hs
- libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
- libraries/ghc-internal/src/GHC/Internal/Int.hs
- libraries/ghc-internal/src/GHC/Internal/IsList.hs
- libraries/ghc-internal/src/GHC/Internal/Ix.hs
- libraries/ghc-internal/src/GHC/Internal/JS/Foreign/Callback.hs
- libraries/ghc-internal/src/GHC/Internal/JS/Prim.hs
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- libraries/ghc-internal/src/GHC/Internal/Lexeme.hs
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghc-internal/src/GHC/Internal/MVar.hs
- libraries/ghc-internal/src/GHC/Internal/Magic.hs
- libraries/ghc-internal/src/GHC/Internal/Magic/Dict.hs
- libraries/ghc-internal/src/GHC/Internal/Maybe.hs
- libraries/ghc-internal/src/GHC/Internal/Num.hs
- libraries/ghc-internal/src/GHC/Internal/Num.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Numeric.hs
- libraries/ghc-internal/src/GHC/Internal/OverloadedLabels.hs
- libraries/ghc-internal/src/GHC/Internal/Pack.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Ext.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Panic.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/PtrEq.hs
- libraries/ghc-internal/src/GHC/Internal/Profiling.hs
- libraries/ghc-internal/src/GHC/Internal/Ptr.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags/Test.hsc
- libraries/ghc-internal/src/GHC/Internal/Read.hs
- libraries/ghc-internal/src/GHC/Internal/Real.hs
- libraries/ghc-internal/src/GHC/Internal/Real.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Records.hs
- libraries/ghc-internal/src/GHC/Internal/ST.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- libraries/ghc-internal/src/GHC/Internal/STRef.hs
- libraries/ghc-internal/src/GHC/Internal/Show.hs
- libraries/ghc-internal/src/GHC/Internal/Stable.hs
- libraries/ghc-internal/src/GHC/Internal/StableName.hs
- libraries/ghc-internal/src/GHC/Internal/Stack.hs
- libraries/ghc-internal/src/GHC/Internal/Stack.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/CCS.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Constants.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/ConstantsProf.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Types.hs
- libraries/ghc-internal/src/GHC/Internal/StaticPtr.hs
- libraries/ghc-internal/src/GHC/Internal/StaticPtr/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Stats.hsc
- libraries/ghc-internal/src/GHC/Internal/Storable.hs
- libraries/ghc-internal/src/GHC/Internal/System/Environment.hs
- libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc
- libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc
- libraries/ghc-internal/src/GHC/Internal/System/IO/Error.hs
- libraries/ghc-internal/src/GHC/Internal/System/Mem.hs
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Types.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs
- libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadP.hs
- libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadPrec.hs
- libraries/ghc-internal/src/GHC/Internal/Text/Read/Lex.hs
- libraries/ghc-internal/src/GHC/Internal/TopHandler.hs
- libraries/ghc-internal/src/GHC/Internal/Tuple.hs
- libraries/ghc-internal/src/GHC/Internal/Type/Reflection.hs
- libraries/ghc-internal/src/GHC/Internal/Type/Reflection/Unsafe.hs
- libraries/ghc-internal/src/GHC/Internal/TypeError.hs
- libraries/ghc-internal/src/GHC/Internal/TypeLits.hs
- libraries/ghc-internal/src/GHC/Internal/TypeLits/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/TypeNats.hs
- libraries/ghc-internal/src/GHC/Internal/TypeNats/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/DerivedCoreProperties.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/GeneralCategory.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleLowerCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleTitleCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleUpperCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Unsafe/Coerce.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Exports.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Imports.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Weak.hs
- libraries/ghc-internal/src/GHC/Internal/Weak/Finalize.hs
- libraries/ghc-internal/src/GHC/Internal/Windows.hs
- libraries/ghc-internal/src/GHC/Internal/Word.hs
- libraries/ghc-internal/tools/ucd2haskell/exe/UCD2Haskell/ModuleGenerators.hs
- libraries/ghc-prim/Dummy.hs
- libraries/ghc-prim/ghc-prim.cabal
- libraries/template-haskell/Language/Haskell/TH/Lib.hs
- linters/lint-codes/LintCodes/Static.hs
- rts/LdvProfile.c
- rts/PrimOps.cmm
- rts/Printer.c
- rts/ProfHeap.c
- rts/include/rts/RtsToHsIface.h
- rts/include/rts/storage/ClosureMacros.h
- rts/js/thread.js
- rts/linker/elf_reloc_riscv64.c
- rts/sm/Sanity.c
- rts/sm/Storage.c
- testsuite/driver/perf_notes.py
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- testsuite/tests/ado/T13242a.stderr
- testsuite/tests/annotations/should_fail/annfail10.stderr
- testsuite/tests/backpack/cabal/bkpcabal07/Makefile
- testsuite/tests/backpack/should_compile/T20396.stderr
- testsuite/tests/backpack/should_fail/bkpfail17.stderr
- testsuite/tests/bytecode/TLinkable/all.T
- testsuite/tests/cabal/T12485/Makefile
- + testsuite/tests/cabal/T27013a/Makefile
- + testsuite/tests/cabal/T27013a/Setup.hs
- + testsuite/tests/cabal/T27013a/all.T
- + testsuite/tests/cabal/T27013a/composition.cabal
- + testsuite/tests/cabal/T27013a/src/Data/Composition.hs
- + testsuite/tests/cabal/T27013d/Composition.hs
- + testsuite/tests/cabal/T27013d/Makefile
- + testsuite/tests/cabal/T27013d/T27013d.stdout
- + testsuite/tests/cabal/T27013d/all.T
- testsuite/tests/callarity/unittest/CallArity1.hs
- testsuite/tests/cmm/should_compile/Makefile
- + testsuite/tests/cmm/should_compile/T27368-ppr-debug.cmm
- + testsuite/tests/cmm/should_compile/T27368-ppr-debug.stdout
- testsuite/tests/cmm/should_compile/all.T
- + testsuite/tests/concurrent/should_run/T16761.hs
- + testsuite/tests/concurrent/should_run/T16761.stdout
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/corelint/LintEtaExpand.hs
- testsuite/tests/corelint/T21115b.stderr
- testsuite/tests/corelint/T27374.hs
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/deSugar/should_compile/T13208.stdout
- testsuite/tests/deSugar/should_compile/T16615.stderr
- testsuite/tests/deSugar/should_compile/T2431.stderr
- testsuite/tests/default/DefaultImportFail01.stderr
- testsuite/tests/default/DefaultImportFail02.stderr
- testsuite/tests/default/DefaultImportFail03.stderr
- testsuite/tests/default/DefaultImportFail04.stderr
- testsuite/tests/default/DefaultImportFail05.stderr
- testsuite/tests/default/DefaultImportFail07.stderr
- testsuite/tests/default/T25775.stderr
- testsuite/tests/deriving/should_compile/T14682.stderr
- testsuite/tests/deriving/should_compile/T20496.stderr
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/dmdanal/should_compile/T23398.stderr
- + testsuite/tests/dmdanal/should_run/M2.hs
- + testsuite/tests/dmdanal/should_run/T27626.hs
- + testsuite/tests/dmdanal/should_run/T27626.stdout
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/driver/T27013b/Makefile
- + testsuite/tests/driver/T27013b/T27013b.stdout
- + testsuite/tests/driver/T27013b/X.hs
- + testsuite/tests/driver/T27013b/all.T
- + testsuite/tests/driver/T27013c/Makefile
- + testsuite/tests/driver/T27013c/T27013c.stdout
- + testsuite/tests/driver/T27013c/X.hs
- + testsuite/tests/driver/T27013c/all.T
- + testsuite/tests/driver/T27013e/T27013e.hs
- + testsuite/tests/driver/T27013e/T27013e.stderr
- + testsuite/tests/driver/T27013e/all.T
- + testsuite/tests/driver/T27013f/T27013f.hs
- + testsuite/tests/driver/T27013f/T27013f.stderr
- + testsuite/tests/driver/T27013f/all.T
- + testsuite/tests/driver/T27013g/T27013g.hs
- + testsuite/tests/driver/T27013g/all.T
- + testsuite/tests/driver/T27013h/GHC/Essentials.hs
- + testsuite/tests/driver/T27013h/T27013h.stderr
- + testsuite/tests/driver/T27013h/all.T
- + testsuite/tests/driver/T27013h/unitT27013h
- + testsuite/tests/driver/T27013i/T27013i.hs
- + testsuite/tests/driver/T27013i/T27013i.stderr
- + testsuite/tests/driver/T27013i/all.T
- + testsuite/tests/driver/T27461/Main1.hs
- + testsuite/tests/driver/T27461/Main2.hs
- + testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461a.stderr
- + testsuite/tests/driver/T27461/T27461b.script
- + testsuite/tests/driver/T27461/T27461b.stderr
- + testsuite/tests/driver/T27461/T27461b.stdout
- + testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Bar.hs
- testsuite/tests/driver/T3007/A/Internal.hs
- testsuite/tests/driver/T3007/Makefile
- testsuite/tests/driver/make-prim/Makefile
- testsuite/tests/driver/multipleHomeUnits/Makefile
- testsuite/tests/driver/multipleHomeUnits/all.T
- + testsuite/tests/driver/multipleHomeUnits/essentials-home/GHC/Essentials.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-order-base/B.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-order-user/U.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-user/M.hs
- testsuite/tests/driver/multipleHomeUnits/multipleHomeUnitsModuleVisibility.stderr
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials.stdout
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_order.stderr
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_recomp.stdout
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHome
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHomeHidden
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderBase
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderUser
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUser
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUserHidden
- testsuite/tests/driver/recomp24656/Makefile
- testsuite/tests/driver/recomp24656/recomp24656.stdout
- testsuite/tests/ffi/should_fail/all.T
- + testsuite/tests/ffi/should_fail/ccfail006.hs
- + testsuite/tests/ffi/should_fail/ccfail006.stderr
- + testsuite/tests/ffi/should_fail/ccfail007.hs
- + testsuite/tests/ffi/should_fail/ccfail007.stderr
- + testsuite/tests/ffi/should_fail/ccfail008.hs
- + testsuite/tests/ffi/should_fail/ccfail008.stderr
- + testsuite/tests/ffi/should_fail/ccfail009.hs
- + testsuite/tests/ffi/should_fail/ccfail009.stderr
- + testsuite/tests/ghc-api/EssentialsCoverage.hs
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/ghc-api/T8628.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/Test20239.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghci.debugger/scripts/break006.stderr
- testsuite/tests/ghci.debugger/scripts/print019.stderr
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T4175.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/ghci/scripts/ghci064.stdout
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- + testsuite/tests/hiefile/should_run/HasFieldQueries.hs
- + testsuite/tests/hiefile/should_run/HasFieldQueries.stdout
- testsuite/tests/hiefile/should_run/RecordDotTypes.stdout
- testsuite/tests/hiefile/should_run/T23120.stdout
- testsuite/tests/hiefile/should_run/T23492.hs
- testsuite/tests/hiefile/should_run/T23492.stdout
- testsuite/tests/hiefile/should_run/all.T
- testsuite/tests/iface/IfaceSharingIfaceType.hs
- testsuite/tests/iface/IfaceSharingName.hs
- testsuite/tests/indexed-types/should_fail/T12522a.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/javascript/Makefile
- testsuite/tests/javascript/T24495.hs
- testsuite/tests/module/mod185.stderr
- testsuite/tests/numeric/should_compile/T14170.stdout
- testsuite/tests/numeric/should_compile/T14465.stdout
- testsuite/tests/numeric/should_compile/T23907.stderr
- testsuite/tests/numeric/should_compile/T7116.stdout
- testsuite/tests/overloadedlists/should_fail/overloadedlistsfail01.stderr
- testsuite/tests/package/all.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20718b.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail11.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.stderr
- testsuite/tests/parser/should_fail/T16270h.hs
- testsuite/tests/partial-sigs/should_fail/NamedWildcardsNotInMonotype.stderr
- + testsuite/tests/patsyn/should_compile/T27440a.hs
- + testsuite/tests/patsyn/should_compile/T27440b.hs
- + testsuite/tests/patsyn/should_compile/T27440c.hs
- testsuite/tests/patsyn/should_compile/all.T
- testsuite/tests/patsyn/should_fail/T26465.stderr
- + testsuite/tests/patsyn/should_fail/T27440d.hs
- + testsuite/tests/patsyn/should_fail/T27440d.stderr
- testsuite/tests/patsyn/should_fail/all.T
- testsuite/tests/perf/compiler/all.T
- testsuite/tests/perf/should_run/ByteCodeAsm.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/plugins09.stdout
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/plugins/plugins11.stdout
- testsuite/tests/plugins/simple-plugin/Simple/ReplacePlugin.hs
- testsuite/tests/plugins/static-plugins.stdout
- testsuite/tests/printer/AnnotationNoListTuplePuns.stdout
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/process/process009.hs
- testsuite/tests/process/process009.stdout
- testsuite/tests/profiling/should_run/callstack001.stdout
- testsuite/tests/profiling/should_run/callstack002.stderr
- testsuite/tests/profiling/should_run/callstack002.stdout
- testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs
- testsuite/tests/rename/should_compile/T3103/GHC/Base.lhs
- testsuite/tests/rename/should_compile/T3103/GHC/Word.hs
- testsuite/tests/rename/should_compile/T3103/test.T
- testsuite/tests/rep-poly/RepPolyRecordPattern.hs
- testsuite/tests/rep-poly/RepPolyRecordPattern.stderr
- testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr
- testsuite/tests/rep-poly/T20113.stderr
- − testsuite/tests/rep-poly/T20363.stderr
- − testsuite/tests/rep-poly/T20363_show_co.hs
- − testsuite/tests/rep-poly/T20363_show_co.stderr
- − testsuite/tests/rep-poly/T20363b.stderr
- + testsuite/tests/rep-poly/T20363c.hs
- + testsuite/tests/rep-poly/T27639.hs
- testsuite/tests/rep-poly/all.T
- testsuite/tests/roles/should_compile/Roles1.stderr
- testsuite/tests/roles/should_compile/Roles13.stderr
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles2.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- + testsuite/tests/rts/T27585.hs
- + testsuite/tests/rts/T27585.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/show-bytecode/Example.hs
- + testsuite/tests/show-bytecode/Makefile
- + testsuite/tests/show-bytecode/all.T
- + testsuite/tests/show-bytecode/normalize
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout-javascript-unknown-ghcjs
- + testsuite/tests/show-bytecode/show-bytecode-hpc.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout-javascript-unknown-ghcjs
- testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr
- testsuite/tests/simplCore/should_compile/T13543.stderr
- testsuite/tests/simplCore/should_compile/T16038/T16038.stdout
- testsuite/tests/simplCore/should_compile/T24229a.stderr
- testsuite/tests/simplCore/should_compile/T24229b.stderr
- + testsuite/tests/simplCore/should_compile/T27589.hs
- + testsuite/tests/simplCore/should_compile/T27589.stderr
- + testsuite/tests/simplCore/should_compile/T27590.hs
- + testsuite/tests/simplCore/should_compile/T27590.stderr
- testsuite/tests/simplCore/should_compile/T3717.stderr
- testsuite/tests/simplCore/should_compile/T3772.stdout
- testsuite/tests/simplCore/should_compile/T4081.stderr
- testsuite/tests/simplCore/should_compile/T4908.stderr
- testsuite/tests/simplCore/should_compile/T4930.stderr
- testsuite/tests/simplCore/should_compile/T7360.stderr
- testsuite/tests/simplCore/should_compile/T8274.stdout
- testsuite/tests/simplCore/should_compile/T9400.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/noinline01.stderr
- testsuite/tests/simplCore/should_compile/par01.stderr
- testsuite/tests/simplCore/should_compile/rule2.stderr
- testsuite/tests/simplCore/should_compile/str-rules.hs
- testsuite/tests/splice-imports/SI35.hs
- testsuite/tests/tcplugins/ArgsPlugin.hs
- testsuite/tests/tcplugins/EmitWantedPlugin.hs
- testsuite/tests/tcplugins/RewritePlugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- testsuite/tests/tcplugins/TyFamPlugin.hs
- + testsuite/tests/th/AssocDefaultNotAssoc.hs
- + testsuite/tests/th/AssocDefaultNotAssoc.stderr
- testsuite/tests/th/T14741.hs
- testsuite/tests/th/T21547.stderr
- testsuite/tests/th/T26568.stderr
- + testsuite/tests/th/T27013th.hs
- + testsuite/tests/th/TH_InvalidTopDecl.hs
- + testsuite/tests/th/TH_InvalidTopDecl.stderr
- testsuite/tests/th/TH_Roles2.stderr
- + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.hs
- + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.stderr
- + testsuite/tests/th/TH_cvt_GadtNoCons.hs
- + testsuite/tests/th/TH_cvt_GadtNoCons.stderr
- + testsuite/tests/th/TH_cvt_IllegalDeclaration.hs
- + testsuite/tests/th/TH_cvt_IllegalDeclaration.stderr
- + testsuite/tests/th/TH_cvt_IllegalSumAlt.hs
- + testsuite/tests/th/TH_cvt_IllegalSumAlt.stderr
- + testsuite/tests/th/TH_cvt_InvalidCCallImpent.hs
- + testsuite/tests/th/TH_cvt_InvalidCCallImpent.stderr
- + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.hs
- + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.stderr
- + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.hs
- + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.stderr
- + testsuite/tests/th/TH_cvt_RecGadtNoCons.hs
- + testsuite/tests/th/TH_cvt_RecGadtNoCons.stderr
- + testsuite/tests/th/TH_cvt_SumAltArityExceeded.hs
- + testsuite/tests/th/TH_cvt_SumAltArityExceeded.stderr
- + testsuite/tests/th/TH_pragmaSpecOld.hs
- + testsuite/tests/th/TH_pragmaSpecOld.stderr
- testsuite/tests/th/all.T
- testsuite/tests/typecheck/should_compile/T13032.stderr
- testsuite/tests/typecheck/should_compile/T14273.stderr
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- + testsuite/tests/typecheck/should_compile/T27557.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_compile/holes.stderr
- testsuite/tests/typecheck/should_compile/holes2.stderr
- testsuite/tests/typecheck/should_compile/holes3.stderr
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/T12921.stderr
- testsuite/tests/typecheck/should_fail/T14884.stderr
- testsuite/tests/typecheck/should_fail/T15883b.stderr
- testsuite/tests/typecheck/should_fail/T15883c.stderr
- testsuite/tests/typecheck/should_fail/T15883d.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
- testsuite/tests/typecheck/should_fail/T3323.stderr
- testsuite/tests/typecheck/should_fail/T5095.stderr
- testsuite/tests/typecheck/should_fail/T7279.stderr
- testsuite/tests/typecheck/should_fail/TcStaticPointersFail02.stderr
- testsuite/tests/typecheck/should_fail/TyAppPat_PatternBindingExistential.stderr
- testsuite/tests/typecheck/should_fail/tcfail072.stderr
- testsuite/tests/typecheck/should_fail/tcfail097.stderr
- testsuite/tests/typecheck/should_fail/tcfail133.stderr
- testsuite/tests/typecheck/should_run/T22510.stdout
- testsuite/tests/unboxedsums/UbxSumLevPoly.hs
- testsuite/tests/unboxedsums/unboxedsums_unit_tests.hs
- + testsuite/tests/vdq-rta/should_compile/T27583a.hs
- + testsuite/tests/vdq-rta/should_compile/T27583b.hs
- + testsuite/tests/vdq-rta/should_compile/T27583c.hs
- + testsuite/tests/vdq-rta/should_compile/T27583d.hs
- + testsuite/tests/vdq-rta/should_compile/T27583e.hs
- + testsuite/tests/vdq-rta/should_compile/T27583g.hs
- testsuite/tests/vdq-rta/should_compile/all.T
- + testsuite/tests/vdq-rta/should_fail/T27440e.hs
- + testsuite/tests/vdq-rta/should_fail/T27440e.stderr
- + testsuite/tests/vdq-rta/should_fail/T27583f.hs
- + testsuite/tests/vdq-rta/should_fail/T27583f.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586a.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586b.hs
- + testsuite/tests/vdq-rta/should_fail/T27586b.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586c.hs
- + testsuite/tests/vdq-rta/should_fail/T27586c.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- testsuite/tests/warnings/should_compile/DerivingTypeable.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/genprimopcode/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/f453b12681a5846712b8b9ed85eb2c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/f453b12681a5846712b8b9ed85eb2c…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/fendor/homeunit-is-just] 44 commits: hie.yaml: use a polyglot shell/batch script
by Hannes Siebenhandl (@fendor) 26 Aug '26
by Hannes Siebenhandl (@fendor) 26 Aug '26
26 Aug '26
Hannes Siebenhandl pushed to branch wip/fendor/homeunit-is-just at Glasgow Haskell Compiler / GHC
Commits:
9df24b7e by sheaf at 2026-08-10T14:28:30-04:00
hie.yaml: use a polyglot shell/batch script
This commit merges hie-bios and hie-bios.bat into a single polyglot
script. This avoids Windows users having to manually update hie.yaml
in order to be able to use HLS.
- - - - -
7f75c588 by Alan Zimmerman at 2026-08-10T14:29:11-04:00
EPA: Remove type parameter from AnnList
This is a step towards cutting AnnList down to its core for formatting
lists only
- - - - -
e8d1a0d6 by Bernhard M. Wiedemann at 2026-08-10T21:31:23-04:00
driver: Link object files in a deterministic order
The object files handed to the linker come from the HomePackageTable,
which is ordered by the order in which modules finished compiling. With
-j1 that is the build plan order, with -jN it is whatever the scheduler
produced, so the same sources can link to different (but equivalent)
binaries.
The order reaches the output: .text and .rodata contributions are
concatenated in link order, so e.g. building the hdav executable of the
DAV package twice, once with -j1 and once with -j4, yields two binaries
that differ in ~100kB of section contents.
Sort the home modules by module before collecting their linkables,
guarded under `Opt_ObjectDeterminism` .
Fixes #27612
Signed-off-by: Bernhard M. Wiedemann <bwiedemann(a)suse.de>
- - - - -
556db2f3 by sheaf at 2026-08-10T21:32:06-04:00
Reduce SpecConstr threshold in GHC.Tc.Solver.Rewrite
As remarked in #27628, this module currently sits on a knife's edge: if
the body of 'simplifyArgsWorker' is made even a tiny bit smaller, then
SpecConstr suddenly kicks in and causes disastrous reboxing of the
LiftingContext argument.
To make this less likely to happen, this commit lowers the SpecConstr
threshold.
- - - - -
c77d88fc by sheaf at 2026-08-13T10:15:22-04:00
Allow rewriting in RuntimeReps for newtype ConPats
This commit implements PHASE 2 of the FixedRuntimeRep plan described in
Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete for newtype
constructor patterns.
In short, GHC now accepts programs of the form
f (MkN x) = ...
in which the argument 'x' of the newtype constructor pattern 'MkN x'
has a representation that is not syntactically concrete, e.g. it can be
'Id IntRep' reducing to 'IntRep'. See T20363{,b,c} for examples.
There are two main parts to the implementation:
1. Typechecking, in GHC.Tc.Gen.Pat.tcDataConPat.
See Note [Typechecking newtype constructor patterns] in GHC.Tc.Gen.Pat.
2. Desugaring. We restructure the code for desugaring pattern matches
by allowing the scrutinised match variable to be casted. This allows
us to accumulate coercions and avoids creating binders at intermediate
types tha don't have a fixed RuntimeRep.
See the revamped Note [Match Ids] in GHC.HsToCore.Monad.
Fixes #20363
-------------------------
Metric Increase:
InstanceMatching
-------------------------
- - - - -
6ba9dd41 by Wolfgang Jeltsch at 2026-08-13T10:16:07-04:00
Improve the documentation of `--show-iface`
This change in particular gets rid of the claim that `--show-iface`
writes *the* contents of the interface file in question. It doesn’t do
that; it only writes those parts that are likely of interest to a human
reader.
- - - - -
4bd193fa by Sylvain Henry at 2026-08-13T10:17:00-04:00
RTS: fix LDV profiler's slop skipping (#27585)
processHeapForDead was the one heap scanner not updated for the slop
marker encoding introduced in #19048. It still assumed slop is zeroed:
while (p < bd->free && !*p) p++; // skip slop
so it stopped at the (StgWord)(-1) sentinel and passed it to
processHeapClosureForDead. IS_FORWARDING_PTR(-1) holds, hence a garbage
size was read out of LDVW and the scan ran off the block, tripping
ASSERT(p == bd->free) on a debug RTS and silently corrupting the census
otherwise.
The loop was hand-copied in four places, so factor it out into skipSlop
in ClosureMacros.h and use it in ProfHeap.c, Sanity.c, Printer.c and
LdvProfile.c.
Co-Authored-By: Claude Opus 5 (1M context) <noreply(a)anthropic.com>
- - - - -
1446bb03 by Zubin Duggal at 2026-08-13T10:17:48-04:00
hadrian: Fix links to remaining doc sites to not use the package hash for haddock links
In 07267f79d91169f474cacc8bcd38d76a6e97887d we changed hadrian to not include the package hash in the haddock
directory. This patch takes care of a few remaining links that were missed in that patch
Fixes #27671
- - - - -
257c3ed7 by Simon Jakobi at 2026-08-13T10:18:29-04:00
Testsuite: widen InstanceMatching acceptance window to 5% (#27673)
...in order to unblock CI.
Assisted-by: Claude Fable 5
- - - - -
e4cfaaa0 by Simon Peyton Jones at 2026-08-14T01:09:32+02:00
Major patch to re-engineer known-key names
This big patch implements the New Plan for known-key names,
described in #27013.
Read the big Note [Overview of known-key names] in GHC.Types.Name
Some things had to be reworked slightly to accomodate the new known-keys
design. A significant one was the generation of auxiliary KindRep
bindings, which was greatly simplified. Note [Grand plan for Typeable]
was updated accordingly. Another example: GHC.Internal.CString was
merged into GHC.Internal.Types.
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
The couple hundreds of hours spent here by Rodrigo were sponsored by Well-Typed
Metrics: compile_time/bytes allocated
-------------------------------------
Baseline
Test Metric value New value Change
------------------------------------------------------------------------------------------
MultiComponentModules100(normal) ghc/alloc 24,312,779,672 24,990,470,432 +2.8% BAD
MultiComponentModulesRecomp(normal) ghc/alloc 601,924,960 621,884,888 +3.3% BAD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,884,065,432 12,531,373,704 +5.4% BAD
MultiLayerModules(normal) ghc/alloc 3,861,537,072 3,706,919,512 -4.0% GOOD
T13701(normal) ghc/alloc 3,517,246,392 3,237,179,616 -8.0% GOOD
T13820(normal) ghc/alloc 28,961,056 29,663,208 +2.4% BAD
T14697(normal) ghc/alloc 472,044,184 443,550,048 -6.0% GOOD
T18140(normal) ghc/alloc 47,905,664 49,115,808 +2.5% BAD
T4801(normal) ghc/alloc 269,339,096 263,432,040 -2.2% GOOD
T783(normal) ghc/alloc 341,112,672 333,339,952 -2.3% GOOD
hard_hole_fits(normal) ghc/alloc 222,164,728 213,433,808 -3.9% GOOD
mhu-perf(normal) ghc/alloc 49,011,440 46,706,280 -4.7% GOOD
geo. mean +0.1%
minimum -8.0%
maximum +5.4%
All performance regressions were investigated in depth. The surviving
ones:
- MultiComponentModules100, MultiComponentModulesRecomp100,
MultiComponentModulesRecomp regresses because existing bugs that make
an additional implicit edge do too much redundant work: #27053 and #27461
- T13820, T18140, T10547, T13035 regress because we load an additional
interface and associated Names for GHC.Essentials.
-------------------------
Metric Decrease:
MultiLayerModules
T13379
T13701
T14697
T26989
T4801
T783
T9961
hard_hole_fits
mhu-perf
size_hello_artifact
size_hello_obj
size_hello_unicode
Metric Increase:
LinkableUsage01
LinkableUsage02
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
T10547
T13035
T13820
T18140
T18698a
T18698b
T20049
-------------------------
Bumps submodule binary
Closes #27013
- - - - -
61665e79 by sheaf at 2026-08-14T01:09:33+02:00
Allow GHC.Essentials to be hidden
This commit overhauls several aspects of the known entity handling,
in order to allow GHC.Essentials to be hidden without a proliferation
of special cases in the compiler.
The main contribution is to introduce the 'UnresolvedImport' datatype
which cleans up a lot of ad-hoc handling relating to 'ModSummary',
fixing #27603. This allows us to reduce duplication, e.g. by having
Backpack reuse 'mkUnresolvedImports' instead of replicating the
"add implicit imports" logic. It also makes it easier to avoid
undesirable edge cases (such as making sure that the Template Haskell
'reifyModule' function does not leak the implicit GHC.Essentials import).
In particular, the infamous 'findImportedModuleWithIsBoot' is now simply
'resolveImport', taking a single 'UnresolvedImport' and resolving it
to a 'FindResult' (usually a 'Module').
Other changes:
- Cache the result of looking up GHC.Essentials (in TcM and DsM
environments) to avoid redundant work.
This reduces allocations on LinkableUsage01 and hard_hole_fits.
- Properly look up known entities for StaticPointers like we do for
other known entities everywhere else. This allows e.g. modules in
ghc-internal to use -XStaticPointers.
- When using multiple home units, we are now careful to handle the
situation in which we may have multiple GHC.Essentials modules
around. See the new tests under 'driver/multipleHomeUnits'.
- - - - -
b19fcc1c by Vladislav Zavialov at 2026-08-14T06:26:11-04:00
Increase test coverage of diagnostics, batch 2
Add test cases for the previously untested diagnostics:
[GHC-26133] TcRnForeignImportPrimSafeAnn
[GHC-68444] SumAltArityExceeded
[GHC-63966] IllegalSumAlt
[GHC-23882] IllegalDeclaration
[GHC-60220] InvalidCCallImpent
[GHC-18816] RecGadtNoCons
[GHC-38140] GadtNoCons
[GHC-37056] InvalidTypeInstanceHeader
[GHC-78486] InvalidTyFamInstLHS
[GHC-39639] DefaultDataInstDecl
[GHC-78822] AssocDefaultNotAssoc
[GHC-43510] NotSimpleUnliftedType
[GHC-41843] IOResultExpected
[GHC-07641] AtLeastOneArgExpected
[GHC-52886] InvalidTopDecl
Remove unused error constructors:
[GHC-92057] ImportLookupAmbiguous
- - - - -
7b27f25a by Simon Jakobi at 2026-08-14T06:26:54-04:00
testsuite: Drop peak_megabytes_allocated from LinkableUsage tests
LinkableUsage01/02 collected all metrics with a 2% tolerance. For
peak_megabytes_allocated, whose granularity is 1 MB, that window is
under 0.7 MB at this test's ~34 MB peak, so any 1 MB step failed the
test (#27613, #27489). Drop that metric: max_bytes_used guards the
Linkable-retention property with byte granularity, at a tolerance
that still comfortably exceeds the noise observed in CI.
Assisted-by: Claude Fable 5
- - - - -
e5de423b by Simon Jakobi at 2026-08-14T06:26:54-04:00
testsuite: Don't truncate fractional baselines when computing bounds
RelativeMetricAcceptanceWindow.get_bounds truncated the baseline with
int() before applying the tolerance. Baselines can be fractional (they
are averaged over several measurements), so this skewed the acceptance
window downwards: in #27613, a baseline of 33.67 at 2% tolerance
yielded bounds (32, 34) instead of (32, 35), rejecting a measurement
that was within tolerance.
Assisted-by: Claude Fable 5
- - - - -
db959f83 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Expect length001 failure in nonmoving_thr_sanity
length001 relies on an optimization rule to avoid excessive stack use.
The nonmoving_thr_sanity way does not enable optimization, so classify
its stack overflow as an expected failure, as is already done for the
other unoptimized nonmoving ways.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
4f2b7d90 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Omit T22859 in nonmoving threaded ways
T22859 checks allocation-limit handlers with output that depends on
precise allocation behaviour. The nonmoving threaded ways change where
these limits are reached, just as the already-omitted LLVM ways do.
Omit these ways instead of treating their incidental output differences
as test failures.
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
c4abddcb by Simon Jakobi at 2026-08-14T15:16:44-04:00
rts/js: Implement eq_thread, and test Eq/Ord ThreadId (#16761)
Since d1f3c63701, Eq ThreadId is implemented via the RTS function
eq_thread, but the JS RTS never provided it, so comparing ThreadIds
for equality on the JS backend crashed with
ReferenceError: h$eq_thread is not defined
Like the C implementation, h$eq_thread uses pointer equality: The JS
RTS has exactly one thread object per thread.
Since previously no test exercised eq_thread directly, this commit
adds a test covering equality, its stability across GC, and agreement
with Ord.
Assisted-by: Claude Fable 5
- - - - -
4a7defa1 by Simon Jakobi at 2026-08-14T15:16:44-04:00
testsuite: Make listThreads1 insensitive to the RTS's own threads
listThreads1 expected `listThreads` to return exactly [ThreadId 1]. That
holds only under a non-threaded RTS. Under a threaded RTS however there
are more threads present, so we change the test to simply check that
`myThreadId` is present in the list.
Assisted-by: Claude Opus 5
- - - - -
b757727a by Vladislav Zavialov at 2026-08-14T15:17:27-04:00
Fix tcLookupId panic with RequiredTypeArguments and PatternSynonyms (#27586)
The arguments declared on the left-hand side of a pattern synonym are looked up
as term variables bound by its right-hand side. Prior to this patch, that lookup
panicked with RequiredTypeArguments:
data T a where
MkT :: forall a -> T a
pattern P :: Int -> T Int
pattern P x = MkT x
On the RHS, `x` looks like a term argument, so the renamer binds it in the term
namespace. Only during type checking does it turn out to be a type variable, so
the lookup on the LHS finds an ATyVar rather than an ATcId. As the lookup was
done with tcLookupId, it resulted in a panic.
Now the arguments are looked up with tcLookupPatSynArg, which reports an illegal
term-level use of `x`, just as an ordinary function definition `f (MkT x) = x`
does.
Test cases: T27586a T27586b T27586c
Assisted-by: Claude Opus 5
- - - - -
c130188d by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
loopImports: Don't dup ms_uid in summary imports
We were writing the ms_unitid of the mod summary with every single
import of that module
That complicated the code (as though the UnitId in that list could ever
be something else) and also allocates unnecessarily per every mod
import. Very slight allocation decrease measured locally in a few tests:
(MultiComponentModulesRecomp: -0.06%; MultiComponentModulesRecomp100: -0.05%)
Purely a clean up.
- - - - -
c71166a8 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: make control flow simpler and cache correct
This refactor extracts the control flow of downsweep into a single
function `dfsBuild`, which takes care of iteratively expanding and
traversing all nodes of the in-construction module graph necessary to
build a full `ModuleGraph`.
There are three levels of caching going on, all of which are necessary
to make sure we don't do repeated work (notably, NEVER summarise the
same module twice).
1. `dfsBuild` accumulates the final module graph and never revisits the
same node of the module graph. Cache is keyed by the final
`ModuleGraph`s `NodeKey`s.
2. For Module A in home-unit u1, each import in the list of imports
needs to be *found* (call to `findImportedModuleWithIsBoot`): at this
point, we only have the `ModuleName` of the import, not the `Module`.
This *finding* is somewhat expensive, so we cache it as well
(`ImportsCache`). The cache key is the home-unit to which the module
belongs~[1], the import package qualifier, and the ModuleName.
[1] Different home-units will have different package flags, which means
potentially different `Module` resolution for the same `ModuleName`.
3. The most expensive operation we want to avoid is summarising a
`Module` into a `ModSummary`, which notably involves parsing the
module header from scratch.
The third cache, in essence, maps a `Module` to its `ModSummary`
(named `ModSummaryCache`). This cache upholds the invariant: we NEVER
summarise the same module twice. In practice, the cache key is the
Module's UnitId and the Source path; the reason is we need to
distinguish between `.hs` and `.hs-boot` files, as their summaries
will differ.
Note that (2) can't guarantee this alone: Two ModuleName imports in
separate units can (and likely do) map to the same `Module`.
Note that the previous implementation failed to achieve the
no-duplicate-work summarisation invariant, and we ended up doing a
quadratic amount of processing in scenarios like test
`MultiComponentModules100`.
See also Note [Downsweep Control Flow and Caching]
Fixes #27461
Perf changes:
MultiComponentModules(normal) ghc/alloc 2,097,389,264 1,992,186,736 -5.0% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,173,770 21,293,867,360 -12.4% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,761,394 498,543,984 -17.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,968,240 8,895,404,864 -25.2% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
ebc4047b by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
implicitRequirementsShallow can never reach HoleUnit
findImportedModule will never return `HoleUnit` for a `ModuleName`
(a `HoleUnit` can only be found as a signature instantiation, never as a
directly *imported* thing)
Therefore, we can drop `[ModuleName]` returned by
`implicitRequirementsShallow`, which makes many things dead code.
Namely, the call to `implicitRequirementsShallow` from
GHC.Driver.Downsweep which was a performance bottleneck (for doing lots
of duplicate work in findImportedModule) is now entirely gone.
Fixes #27053
In an MR with this patch and the downsweep refactor (previous commit), CI says:
MultiComponentModules(normal) ghc/alloc 2,097,396,728 1,943,662,304 -7.3% GOOD
MultiComponentModules100(normal) ghc/alloc 24,310,182,136 17,227,574,440 -29.1% GOOD
MultiComponentModulesRecomp(normal) ghc/alloc 602,769,518 449,973,656 -25.3% GOOD
MultiComponentModulesRecomp100(normal) ghc/alloc 11,885,976,408 4,828,894,160 -59.4% GOOD
-------------------------
Metric Decrease:
MultiComponentModules
MultiComponentModules100
MultiComponentModulesRecomp
MultiComponentModulesRecomp100
-------------------------
- - - - -
85a6ab01 by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
downsweep: Cache negative results
When traversing a module graph structure, a uniquely identified node
should always expand to the same thing.
I don't see how visiting the same node which failed to be expanded a
first time would ever successfully expand the second time we try to
expand it (eg. when coming from a different edge to it -- it is still
the same node!). The node expansion is local, based just based on the
node itself, not on the path to get there.
Therefore, this patch removes the weird behavior and commentary of
`dfsBuild` wrt to `Nothing` not being cached and being potentially
expanded a second time around to something different, which was
misleading and, ultimately, incorrect.
Now, we have a `MGRes`, which is more explicit about a node being
Skipped just being a node that is ignored whenever it is found (and that
skip is cached) -- and we may want to do this due to failures or due to
just trying nodes which might not work on purpose, like hs-boots.
We uniformly cache positive and negative results and remove the
assumption that there might be an ordering in which the same node
visited at a later time might be expanded differently.
This makes it possible to traverse the module nodes in parallel without
a change in behavior, since there's no longer a hidden ordering
requirement.
- - - - -
56747c3f by Rodrigo Mesquita at 2026-08-15T06:29:53-04:00
Organize and clean-up GHC.Driver.Downsweep
Simply some cosmetic changes, moving definitions around to structure the
module better into its relevant sections
(In go (ns ++ ss), it's not a problem to use ++ because it's a good
producer and we won't have to append fully before processing the next
item in go)
- - - - -
12f64118 by Wolfgang Jeltsch at 2026-08-15T06:31:12-04:00
Add support for textual output of bytecode file content
- - - - -
a737df91 by Brandon Chinn at 2026-08-15T12:40:25-04:00
Add law in qualified strings doc
- - - - -
e3188581 by Zubin Duggal at 2026-08-15T12:41:06-04:00
DmdAnal: Fix maxDmdType
We need to eta expand the smaller DmdType using defaultArgDmd, like in lubDmdType.
Introduce zipDmdType as a common combinator to implement both maxDmdType and lubDmdType
uniformly.
fixes #27626
- - - - -
ca9b0b22 by mangoiv at 2026-08-15T12:41:47-04:00
hadrian: set the executable bit for hie-bios.bat
- - - - -
1aac7095 by sheaf at 2026-08-16T04:37:16-04:00
Avoid wasteful allocations in mkTyConAppCo
The idiom "traverse isReflCo_maybe" followed by "map fst" used in
'GHC.Core.Coercion.mkTyConAppCo' was allocating a lot of waste.
This commit uses 'GHC.Data.Unboxed.traverseMaybeUB' to avoid all these
unnecessary intermediate allocations.
In a quick microbenchmark for 'mkTyConAppCo', this change resulted in:
- refl case (all argument coercions are reflexive):
- -60% runtime
- -80% allocations
- non-refl case:
- from 0% to -12% runtime (depending on which argument is non-refl)
- from 0% to -70% allocations ( -- '' -- )
Fixes #27648
-------------------------
Metric Decrease:
FamAppCachePerf
SimplCastPerf
T12425
T15703
T26426
T3064
T9872a
T9872b
T9872b_defer
T9872c
T9872d
T5321Fun
T9020
T9630
TcPlugin_RewritePerf
Metric Increase:
LinkableUsage02
-------------------------
- - - - -
3915e982 by Alan Zimmerman at 2026-08-16T04:37:58-04:00
EPA: Remove al_trailing from AnnList
It was not being used
- - - - -
fed942ac by Andreas Klebinger at 2026-08-17T12:11:57-04:00
testsuite: Use sigkill in process009.
SIGHUB might have been blocked by a (grand)*parent of the test.
In such cases the test would fail as the python process would simply
exist gracefully instead of committing to a premature end.
By using SIGKILL we can rely on the signal not being blocked, fixing #27578
in the process.
- - - - -
574c875f by Andreas Klebinger at 2026-08-17T12:12:39-04:00
Simplify comparison in DFM.hs
Fixes #27669
- - - - -
d8f1a2a3 by Alan Zimmerman at 2026-08-17T12:13:18-04:00
TTG: Add extension points to BooleanFormula
They are currently unused, but will be used for exact print
annotations next, allowing us to get rid of LocatedBF / SrcSpanAnnBF
- - - - -
93a2b20f by Andreas Klebinger at 2026-08-18T04:31:04-04:00
Fix a number of incorrect module references:
Fix module reference in Note [DataCon wrappers are conlike].
Fix module reference in Note [Detailed InertCans Invariants].
Fix module reference in Note [GHC's data format representations].
Fix module reference in Note [Grand plan for static forms].
Fix module reference in Note [How tuples work].
Fix module reference in Note [Solved dictionaries].
Fix module reference in Note [Stacktraces from Info Table Provenance Entries (IPE based stack unwinding)].
Fix module reference in Note [The VarBndr type and its uses].
Found the incorrect references with a llm.
- - - - -
eb0dfb01 by Simon Jakobi at 2026-08-18T04:31:44-04:00
ci: Run stack-hadrian-build only in full-ci pipelines
The job exists to catch changes that break hadrian/build-stack (#18726),
but nothing in the pipeline depends on it, and it can only break when
hadrian's dependencies change. Restricting it to full-ci (like
hadrian-multi) still covers marge-bot merge batches, so such breakage
cannot reach master unnoticed, while ordinary validate pipelines skip
the job.
Assisted-by: Claude Fable 5
- - - - -
b9160962 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Show baseline sample count and range in perf failures
A perf baseline is the mean of all samples recorded for a commit, and
it prints as a single number, hiding how far the samples spread. When
the spread is wide, this can indicate an unstable metric that isn't
actually useful as a signal for the perf tests.
For example, in #27602, T27336's peak_megabytes_allocated baseline
showed as 757 when the underlying samples were 605 and 909.
When the baseline is averaged from more than one sample, say so in the
failure output: the one-line stat-failure reason shows the sample
range, and the detail block lists the raw samples. Single-sample
baselines print exactly as before.
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
a4979877 by Simon Jakobi at 2026-08-20T14:57:52-04:00
testsuite: Fold Baseline into CommitMetric
A Baseline was just a CommitMetric plus the commit it came from, built
by copying fields across. Since get_commit_metric already knows that
commit, record it on CommitMetric itself and drop Baseline. This also
collapses both branches of find_baseline into plain returns.
Assisted-by: Claude Fable 5
- - - - -
99fb8d68 by Simon Jakobi at 2026-08-20T14:57:52-04:00
ci: Clarify comment on pushing perf notes after failures
Context: #27602
Assisted-by: Claude Fable 5
- - - - -
2ca87972 by Alan Zimmerman at 2026-08-20T14:58:36-04:00
EPA: Remove LocatedBC / SrcSpanBF
The custom annotations are now in the BooleanFormula TTG extension
points, so LBooleanFormula can now use the standard LocatedA.
- - - - -
d2bc32aa by Simon Peyton Jones at 2026-08-21T12:59:26-04:00
Better handling of serialisation of wired-in names
Fixes #27501
- - - - -
d2795ffc by Alan Zimmerman at 2026-08-21T13:00:05-04:00
EPA: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead
Also introduce helper functions noEpTok and noEpUniTok to serve
as simple replacements in code inserting an token annotation without
location information.
- - - - -
b5d29ab8 by Brandon Chinn at 2026-08-25T18:42:08-04:00
Add Data.RealFloat and Infinity/NegInfinity/NaN pattern synonyms (#26961)
- - - - -
e60eb3bc by Andreas Klebinger at 2026-08-25T18:42:59-04:00
rts linker: Fix pointer arithmetic issue in flushInstructionCacheRISCV64
We accidentally operated over `uint64_t*` when we should use `uint8_t`.
Fixes #27569
- - - - -
45f37ba4 by fendor at 2026-08-26T12:27:30+02:00
`HomeUnitEnv` should always have a concrete `HomeUnit`
The `HomeUnit` describes what kind of home unit a particular
`HomeUnitEnv` is and its `UnitId`.
To get a `HomeUnit`, we need to initialise the `UnitState` via `initUnits` otherwise,
we can't tell whether the `HomeUnit` is a definite one, or an indefinite
one, for example a backpack signature file.
That's why previously we maintained a `Maybe HomeUnit`.
However, a `HomeUnitEnv` always has at least a `UnitId` (accessible via
`DynFlags`).
We can fake a `HomeUnit` until we have actually initialised the
home unit and assume it is not a backpack unit.
This avoids many partial functions that should have never been partial
in the first case.
- - - - -
971 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- + changelog.d/27626
- + changelog.d/T20363
- + changelog.d/T27586
- + changelog.d/downsweep-refactor
- changelog.d/fix-heap-census-large-arrays-19048
- + changelog.d/link-deterministic-order
- + changelog.d/refactor-known-names
- + changelog.d/show-byte-code
- compiler/GHC.hs
- + compiler/GHC/Builtin.hs
- + compiler/GHC/Builtin/KnownKeys.hs
- + compiler/GHC/Builtin/KnownOccs.hs
- + compiler/GHC/Builtin/Modules.hs
- − compiler/GHC/Builtin/Names.hs
- − compiler/GHC/Builtin/Names/TH.hs
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/Builtin/PrimOps/Casts.hs
- compiler/GHC/Builtin/PrimOps/Ids.hs
- + compiler/GHC/Builtin/TH.hs
- compiler/GHC/Builtin/Uniques.hs
- compiler/GHC/Builtin/Uniques.hs-boot
- − compiler/GHC/Builtin/Utils.hs
- + compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/Types/Prim.hs → compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/Types/Literals.hs → compiler/GHC/Builtin/WiredIn/TypeLits.hs
- compiler/GHC/Builtin/Types.hs → compiler/GHC/Builtin/WiredIn/Types.hs
- compiler/GHC/Builtin/Types.hs-boot → compiler/GHC/Builtin/WiredIn/Types.hs-boot
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Serialize.hs
- + compiler/GHC/ByteCode/Show.hs
- compiler/GHC/CmmToAsm/Format.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Class.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Multiplicity.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/CprAnal.hs
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Core/Opt/LiberateCase.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Unfold.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Data/BooleanFormula.hs
- compiler/GHC/Data/Unboxed.hs
- compiler/GHC/Data/Word64Map/Internal.hs
- compiler/GHC/Data/Word64Map/Lazy.hs
- compiler/GHC/Data/Word64Map/Strict.hs
- compiler/GHC/Data/Word64Map/Strict/Internal.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Tidy.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/KnotVars.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/GenerateCgIPEStub.hs
- compiler/GHC/Driver/Main/Hsc.hs
- compiler/GHC/Driver/Main/Passes.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Plugins.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Arrows.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/HsToCore/Foreign/Call.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Foreign/Utils.hs
- compiler/GHC/HsToCore/Foreign/Wasm.hs
- compiler/GHC/HsToCore/ListComp.hs
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Match.hs-boot
- compiler/GHC/HsToCore/Match/Constructor.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc/Check.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Ppr.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/HsToCore/Utils.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Env.hs
- − compiler/GHC/Iface/Env.hs-boot
- compiler/GHC/Iface/Errors.hs
- compiler/GHC/Iface/Errors/Ppr.hs
- compiler/GHC/Iface/Errors/Types.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Plugins.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Context.hs
- compiler/GHC/Runtime/Debugger.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/Unarise.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Bind.hs
- compiler/GHC/StgToCmm/DataCon.hs
- compiler/GHC/StgToCmm/Env.hs
- compiler/GHC/StgToCmm/Foreign.hs
- compiler/GHC/StgToCmm/Lit.hs
- compiler/GHC/StgToCmm/Ticky.hs
- compiler/GHC/StgToJS/Apply.hs
- compiler/GHC/StgToJS/Arg.hs
- compiler/GHC/StgToJS/Expr.hs
- compiler/GHC/StgToJS/FFI.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/StgToJS/Linker/Utils.hs
- compiler/GHC/StgToJS/Utils.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Deriv/Functor.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Deriv/Infer.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Default.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Foreign.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Instance/Typeable.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Build.hs
- compiler/GHC/Tc/TyCl/Class.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/DefaultEnv.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Literal.hs
- compiler/GHC/Types/Name.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Name/Ppr.hs
- compiler/GHC/Types/Name/Reader.hs
- compiler/GHC/Types/RepType.hs
- compiler/GHC/Types/TyThing.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/DFM.hs
- compiler/GHC/Types/Unique/FM.hs
- + compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Unit.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/External.hs
- compiler/GHC/Unit/External/Index.hs
- compiler/GHC/Unit/External/ModuleOrigin.hs
- compiler/GHC/Unit/External/Providers.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Home.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- compiler/GHC/Utils/Binary.hs
- − compiler/GHC/Utils/Binary/Typeable.hs
- compiler/Language/Haskell/Syntax/BooleanFormula.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/ghc.cabal.in
- docs/index.html.in
- docs/users_guide/exts/qualified_strings.rst
- docs/users_guide/ghc_config.py.in
- docs/users_guide/separate_compilation.rst
- docs/users_guide/using.rst
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Monad.hs
- ghc/Main.hs
- − hadrian/hie-bios
- hadrian/hie-bios.bat
- hadrian/src/Rules/Generate.hs
- hie.yaml
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Control/Applicative.hs
- libraries/base/src/Control/Concurrent.hs
- libraries/base/src/Control/Concurrent/Chan.hs
- libraries/base/src/Control/Concurrent/QSem.hs
- libraries/base/src/Control/Concurrent/QSemN.hs
- libraries/base/src/Data/Array/Byte.hs
- libraries/base/src/Data/Bifoldable.hs
- libraries/base/src/Data/Bifoldable1.hs
- libraries/base/src/Data/Bifunctor.hs
- libraries/base/src/Data/Bitraversable.hs
- libraries/base/src/Data/Bool.hs
- libraries/base/src/Data/Complex.hs
- libraries/base/src/Data/Data.hs
- libraries/base/src/Data/Enum.hs
- libraries/base/src/Data/Fixed.hs
- libraries/base/src/Data/Foldable1.hs
- libraries/base/src/Data/Functor/Classes.hs
- libraries/base/src/Data/Functor/Compose.hs
- libraries/base/src/Data/Functor/Contravariant.hs
- libraries/base/src/Data/Functor/Product.hs
- libraries/base/src/Data/Functor/Sum.hs
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- libraries/base/src/Data/List/NubOrdSet.hs
- + libraries/base/src/Data/RealFloat.hs
- libraries/base/src/Data/Semigroup.hs
- libraries/base/src/Data/Version.hs
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/ByteOrder.hs
- + libraries/base/src/GHC/Essentials.hs
- libraries/base/src/GHC/Exts.hs
- libraries/base/src/GHC/Fingerprint.hs
- libraries/base/src/GHC/RTS/Flags.hs
- libraries/base/src/GHC/ResponseFile.hs
- libraries/base/src/GHC/Stats.hs
- libraries/base/src/GHC/Weak/Finalize.hs
- libraries/base/src/Numeric.hs
- libraries/base/src/Prelude.hs
- libraries/base/src/System/CPUTime/Posix/ClockGetTime.hsc
- libraries/base/src/System/CPUTime/Posix/RUsage.hsc
- libraries/base/src/System/CPUTime/Posix/Times.hsc
- libraries/base/src/System/CPUTime/Unsupported.hs
- libraries/base/src/System/Console/GetOpt.hs
- libraries/base/src/System/Exit.hs
- libraries/base/src/System/IO.hs
- libraries/base/src/System/IO/OS.hs
- libraries/base/src/System/IO/Unsafe.hs
- libraries/base/src/System/Info.hs
- libraries/base/src/System/Timeout.hs
- libraries/base/src/Text/Printf.hs
- libraries/base/src/Text/Read.hs
- libraries/base/src/Text/Show/Functions.hs
- libraries/base/tests/all.T
- libraries/base/tests/listThreads1.hs
- libraries/base/tests/listThreads1.stdout
- libraries/binary
- libraries/ghc-experimental/src/Data/Sum/Experimental.hs
- libraries/ghc-experimental/src/Data/Tuple/Experimental.hs
- libraries/ghc-experimental/src/GHC/Profiling/Eras.hs
- libraries/ghc-experimental/src/Prelude/Experimental.hs
- libraries/ghc-internal/codepages/MakeTable.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/include/RtsIfaceSymbols.h
- libraries/ghc-internal/src/GHC/Internal/AllocationLimitHandler.hs
- libraries/ghc-internal/src/GHC/Internal/Arr.hs
- libraries/ghc-internal/src/GHC/Internal/ArrayArray.hs
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/GMP.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Backend/Native.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/BigNat.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Integer.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Bignum/Primitives.hs
- libraries/ghc-internal/src/GHC/Internal/Bignum/WordArray.hs
- libraries/ghc-internal/src/GHC/Internal/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs
- libraries/ghc-internal/src/GHC/Internal/CString.hs
- libraries/ghc-internal/src/GHC/Internal/Char.hs
- libraries/ghc-internal/src/GHC/Internal/Classes.hs
- libraries/ghc-internal/src/GHC/Internal/Classes/IP.hs
- libraries/ghc-internal/src/GHC/Internal/Clock.hsc
- libraries/ghc-internal/src/GHC/Internal/ClosureTypes.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Bound.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/POSIX.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/POSIX/Const.hsc
- libraries/ghc-internal/src/GHC/Internal/Conc/Signal.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs
- libraries/ghc-internal/src/GHC/Internal/ConsoleHandler.hsc
- libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Category.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Concurrent/MVar.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fail.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fix.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/IO/Class.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Zip.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Coerce.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Data.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Dynamic.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Either.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Function.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Const.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Utils.hs
- libraries/ghc-internal/src/GHC/Internal/Data/IORef.hs
- libraries/ghc-internal/src/GHC/Internal/Data/List.hs
- libraries/ghc-internal/src/GHC/Internal/Data/List/NonEmpty.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Maybe.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Monoid.hs
- libraries/ghc-internal/src/GHC/Internal/Data/NonEmpty.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Ord.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Proxy.hs
- libraries/ghc-internal/src/GHC/Internal/Data/STRef.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Semigroup/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/String.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Traversable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Tuple.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Bool.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Coercion.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Equality.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Ord.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Typeable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Typeable/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Unique.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Void.hs
- libraries/ghc-internal/src/GHC/Internal/Debug/Trace.hs
- libraries/ghc-internal/src/GHC/Internal/Desugar.hs
- libraries/ghc-internal/src/GHC/Internal/Encoding/UTF8.hs
- libraries/ghc-internal/src/GHC/Internal/Enum.hs
- libraries/ghc-internal/src/GHC/Internal/Enum.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Environment.hs
- libraries/ghc-internal/src/GHC/Internal/Err.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Arr.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Array.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Event/EPoll.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/IntTable.hs
- libraries/ghc-internal/src/GHC/Internal/Event/IntVar.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Internal/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Event/KQueue.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/PSQ.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Poll.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimeOut.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Unique.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Clock.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/ConsoleEvent.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/FFI.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/ManagedThreadPool.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs-boot
- libraries/ghc-internal/src/GHC/Internal/ExecutionStack.hs
- libraries/ghc-internal/src/GHC/Internal/ExecutionStack/Internal.hsc
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- libraries/ghc-internal/src/GHC/Internal/Fingerprint.hs
- libraries/ghc-internal/src/GHC/Internal/Fingerprint/Type.hs
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- libraries/ghc-internal/src/GHC/Internal/Float/ConversionUtils.hs
- libraries/ghc-internal/src/GHC/Internal/Float/RealFracMethods.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/ConstPtr.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/Error.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/String.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/String/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/C/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/ForeignPtr/Imp.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Alloc.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Array.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Error.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Pool.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Marshal/Utils.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Ptr.hs
- libraries/ghc-internal/src/GHC/Internal/Foreign/Storable.hs
- libraries/ghc-internal/src/GHC/Internal/ForeignPtr.hs
- libraries/ghc-internal/src/GHC/Internal/ForeignSrcLang.hs
- libraries/ghc-internal/src/GHC/Internal/Functor/ZipList.hs
- libraries/ghc-internal/src/GHC/Internal/GHCi.hs
- libraries/ghc-internal/src/GHC/Internal/GHCi/Helpers.hs
- libraries/ghc-internal/src/GHC/Internal/Generics.hs
- libraries/ghc-internal/src/GHC/Internal/Heap/Closures.hs
- libraries/ghc-internal/src/GHC/Internal/Heap/Constants.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable/Types.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/InfoTableProf.hsc
- libraries/ghc-internal/src/GHC/Internal/Heap/ProfInfo/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO.hs
- libraries/ghc-internal/src/GHC/Internal/IO.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/Buffer.hs
- libraries/ghc-internal/src/GHC/Internal/IO/BufferedIO.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Device.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/API.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/CodePage/Table.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Failure.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Iconv.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Latin1.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF16.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF32.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Encoding/UTF8.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/FD.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/FD.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Common.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Flock.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/LinuxOFD.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/NoOp.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs-boot
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Windows.hs
- libraries/ghc-internal/src/GHC/Internal/IO/IOMode.hs
- libraries/ghc-internal/src/GHC/Internal/IO/SubSystem.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Unsafe.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Windows/Encoding.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Windows/Handle.hsc
- libraries/ghc-internal/src/GHC/Internal/IOArray.hs
- libraries/ghc-internal/src/GHC/Internal/IORef.hs
- libraries/ghc-internal/src/GHC/Internal/InfoProv.hs
- libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
- libraries/ghc-internal/src/GHC/Internal/Int.hs
- libraries/ghc-internal/src/GHC/Internal/IsList.hs
- libraries/ghc-internal/src/GHC/Internal/Ix.hs
- libraries/ghc-internal/src/GHC/Internal/JS/Foreign/Callback.hs
- libraries/ghc-internal/src/GHC/Internal/JS/Prim.hs
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- libraries/ghc-internal/src/GHC/Internal/Lexeme.hs
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghc-internal/src/GHC/Internal/MVar.hs
- libraries/ghc-internal/src/GHC/Internal/Magic.hs
- libraries/ghc-internal/src/GHC/Internal/Magic/Dict.hs
- libraries/ghc-internal/src/GHC/Internal/Maybe.hs
- libraries/ghc-internal/src/GHC/Internal/Num.hs
- libraries/ghc-internal/src/GHC/Internal/Num.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Numeric.hs
- libraries/ghc-internal/src/GHC/Internal/OverloadedLabels.hs
- libraries/ghc-internal/src/GHC/Internal/Pack.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Ext.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/Panic.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/PtrEq.hs
- libraries/ghc-internal/src/GHC/Internal/Profiling.hs
- libraries/ghc-internal/src/GHC/Internal/Ptr.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags/Test.hsc
- libraries/ghc-internal/src/GHC/Internal/Read.hs
- libraries/ghc-internal/src/GHC/Internal/Real.hs
- libraries/ghc-internal/src/GHC/Internal/Real.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Records.hs
- libraries/ghc-internal/src/GHC/Internal/ST.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- libraries/ghc-internal/src/GHC/Internal/STRef.hs
- libraries/ghc-internal/src/GHC/Internal/Show.hs
- libraries/ghc-internal/src/GHC/Internal/Stable.hs
- libraries/ghc-internal/src/GHC/Internal/StableName.hs
- libraries/ghc-internal/src/GHC/Internal/Stack.hs
- libraries/ghc-internal/src/GHC/Internal/Stack.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/CCS.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Constants.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/ConstantsProf.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Types.hs
- libraries/ghc-internal/src/GHC/Internal/StaticPtr.hs
- libraries/ghc-internal/src/GHC/Internal/StaticPtr/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Stats.hsc
- libraries/ghc-internal/src/GHC/Internal/Storable.hs
- libraries/ghc-internal/src/GHC/Internal/System/Environment.hs
- libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc
- libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc
- libraries/ghc-internal/src/GHC/Internal/System/IO/Error.hs
- libraries/ghc-internal/src/GHC/Internal/System/Mem.hs
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Types.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs
- libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadP.hs
- libraries/ghc-internal/src/GHC/Internal/Text/ParserCombinators/ReadPrec.hs
- libraries/ghc-internal/src/GHC/Internal/Text/Read/Lex.hs
- libraries/ghc-internal/src/GHC/Internal/TopHandler.hs
- libraries/ghc-internal/src/GHC/Internal/Tuple.hs
- libraries/ghc-internal/src/GHC/Internal/Type/Reflection.hs
- libraries/ghc-internal/src/GHC/Internal/Type/Reflection/Unsafe.hs
- libraries/ghc-internal/src/GHC/Internal/TypeError.hs
- libraries/ghc-internal/src/GHC/Internal/TypeLits.hs
- libraries/ghc-internal/src/GHC/Internal/TypeLits/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/TypeNats.hs
- libraries/ghc-internal/src/GHC/Internal/TypeNats/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Bits.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/DerivedCoreProperties.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/GeneralCategory.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleLowerCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleTitleCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Char/UnicodeData/SimpleUpperCaseMapping.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Unsafe/Coerce.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Conc/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Exports.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Imports.hs
- libraries/ghc-internal/src/GHC/Internal/Wasm/Prim/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Weak.hs
- libraries/ghc-internal/src/GHC/Internal/Weak/Finalize.hs
- libraries/ghc-internal/src/GHC/Internal/Windows.hs
- libraries/ghc-internal/src/GHC/Internal/Word.hs
- libraries/ghc-internal/tools/ucd2haskell/exe/UCD2Haskell/ModuleGenerators.hs
- libraries/ghc-prim/Dummy.hs
- libraries/ghc-prim/ghc-prim.cabal
- libraries/template-haskell/Language/Haskell/TH/Lib.hs
- linters/lint-codes/LintCodes/Static.hs
- rts/LdvProfile.c
- rts/PrimOps.cmm
- rts/Printer.c
- rts/ProfHeap.c
- rts/include/rts/RtsToHsIface.h
- rts/include/rts/storage/ClosureMacros.h
- rts/js/thread.js
- rts/linker/elf_reloc_riscv64.c
- rts/sm/Sanity.c
- rts/sm/Storage.c
- testsuite/driver/perf_notes.py
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/driver/testutil.py
- testsuite/tests/ado/T13242a.stderr
- testsuite/tests/annotations/should_fail/annfail10.stderr
- testsuite/tests/backpack/cabal/bkpcabal07/Makefile
- testsuite/tests/backpack/should_compile/T20396.stderr
- testsuite/tests/backpack/should_fail/bkpfail17.stderr
- testsuite/tests/bytecode/TLinkable/all.T
- testsuite/tests/cabal/T12485/Makefile
- + testsuite/tests/cabal/T27013a/Makefile
- + testsuite/tests/cabal/T27013a/Setup.hs
- + testsuite/tests/cabal/T27013a/all.T
- + testsuite/tests/cabal/T27013a/composition.cabal
- + testsuite/tests/cabal/T27013a/src/Data/Composition.hs
- + testsuite/tests/cabal/T27013d/Composition.hs
- + testsuite/tests/cabal/T27013d/Makefile
- + testsuite/tests/cabal/T27013d/T27013d.stdout
- + testsuite/tests/cabal/T27013d/all.T
- testsuite/tests/callarity/unittest/CallArity1.hs
- + testsuite/tests/concurrent/should_run/T16761.hs
- + testsuite/tests/concurrent/should_run/T16761.stdout
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/corelint/LintEtaExpand.hs
- testsuite/tests/corelint/T21115b.stderr
- testsuite/tests/corelint/T27374.hs
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/deSugar/should_compile/T13208.stdout
- testsuite/tests/deSugar/should_compile/T16615.stderr
- testsuite/tests/deSugar/should_compile/T2431.stderr
- testsuite/tests/default/DefaultImportFail01.stderr
- testsuite/tests/default/DefaultImportFail02.stderr
- testsuite/tests/default/DefaultImportFail03.stderr
- testsuite/tests/default/DefaultImportFail04.stderr
- testsuite/tests/default/DefaultImportFail05.stderr
- testsuite/tests/default/DefaultImportFail07.stderr
- testsuite/tests/default/T25775.stderr
- testsuite/tests/deriving/should_compile/T14682.stderr
- testsuite/tests/deriving/should_compile/T20496.stderr
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/dmdanal/should_compile/T23398.stderr
- + testsuite/tests/dmdanal/should_run/M2.hs
- + testsuite/tests/dmdanal/should_run/T27626.hs
- + testsuite/tests/dmdanal/should_run/T27626.stdout
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/driver/T27013b/Makefile
- + testsuite/tests/driver/T27013b/T27013b.stdout
- + testsuite/tests/driver/T27013b/X.hs
- + testsuite/tests/driver/T27013b/all.T
- + testsuite/tests/driver/T27013c/Makefile
- + testsuite/tests/driver/T27013c/T27013c.stdout
- + testsuite/tests/driver/T27013c/X.hs
- + testsuite/tests/driver/T27013c/all.T
- + testsuite/tests/driver/T27013e/T27013e.hs
- + testsuite/tests/driver/T27013e/T27013e.stderr
- + testsuite/tests/driver/T27013e/all.T
- + testsuite/tests/driver/T27013f/T27013f.hs
- + testsuite/tests/driver/T27013f/T27013f.stderr
- + testsuite/tests/driver/T27013f/all.T
- + testsuite/tests/driver/T27013g/T27013g.hs
- + testsuite/tests/driver/T27013g/all.T
- + testsuite/tests/driver/T27013h/GHC/Essentials.hs
- + testsuite/tests/driver/T27013h/T27013h.stderr
- + testsuite/tests/driver/T27013h/all.T
- + testsuite/tests/driver/T27013h/unitT27013h
- + testsuite/tests/driver/T27013i/T27013i.hs
- + testsuite/tests/driver/T27013i/T27013i.stderr
- + testsuite/tests/driver/T27013i/all.T
- + testsuite/tests/driver/T27461/Main1.hs
- + testsuite/tests/driver/T27461/Main2.hs
- + testsuite/tests/driver/T27461/Makefile
- + testsuite/tests/driver/T27461/T27461a.stderr
- + testsuite/tests/driver/T27461/T27461b.script
- + testsuite/tests/driver/T27461/T27461b.stderr
- + testsuite/tests/driver/T27461/T27461b.stdout
- + testsuite/tests/driver/T27461/all.T
- + testsuite/tests/driver/T27461/src/Bar.hs
- testsuite/tests/driver/T3007/A/Internal.hs
- testsuite/tests/driver/T3007/Makefile
- testsuite/tests/driver/make-prim/Makefile
- testsuite/tests/driver/multipleHomeUnits/Makefile
- testsuite/tests/driver/multipleHomeUnits/all.T
- + testsuite/tests/driver/multipleHomeUnits/essentials-home/GHC/Essentials.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-order-base/B.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-order-user/U.hs
- + testsuite/tests/driver/multipleHomeUnits/essentials-user/M.hs
- testsuite/tests/driver/multipleHomeUnits/multipleHomeUnitsModuleVisibility.stderr
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials.stdout
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_order.stderr
- + testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_essentials_recomp.stdout
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHome
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsHomeHidden
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderBase
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsOrderUser
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUser
- + testsuite/tests/driver/multipleHomeUnits/unitEssentialsUserHidden
- testsuite/tests/driver/recomp24656/Makefile
- testsuite/tests/driver/recomp24656/recomp24656.stdout
- testsuite/tests/ffi/should_fail/all.T
- + testsuite/tests/ffi/should_fail/ccfail006.hs
- + testsuite/tests/ffi/should_fail/ccfail006.stderr
- + testsuite/tests/ffi/should_fail/ccfail007.hs
- + testsuite/tests/ffi/should_fail/ccfail007.stderr
- + testsuite/tests/ffi/should_fail/ccfail008.hs
- + testsuite/tests/ffi/should_fail/ccfail008.stderr
- + testsuite/tests/ffi/should_fail/ccfail009.hs
- + testsuite/tests/ffi/should_fail/ccfail009.stderr
- + testsuite/tests/ghc-api/EssentialsCoverage.hs
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/ghc-api/T8628.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/downsweep/PartialDownsweep.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/Test20239.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghci.debugger/scripts/break006.stderr
- testsuite/tests/ghci.debugger/scripts/print019.stderr
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T4175.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/ghci/scripts/ghci064.stdout
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- testsuite/tests/hiefile/should_run/T23120.stdout
- testsuite/tests/iface/IfaceSharingIfaceType.hs
- testsuite/tests/iface/IfaceSharingName.hs
- testsuite/tests/indexed-types/should_fail/T12522a.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/javascript/Makefile
- testsuite/tests/javascript/T24495.hs
- testsuite/tests/module/mod185.stderr
- testsuite/tests/numeric/should_compile/T14170.stdout
- testsuite/tests/numeric/should_compile/T14465.stdout
- testsuite/tests/numeric/should_compile/T23907.stderr
- testsuite/tests/numeric/should_compile/T7116.stdout
- testsuite/tests/overloadedlists/should_fail/overloadedlistsfail01.stderr
- testsuite/tests/package/all.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20718b.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail11.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail8.stderr
- testsuite/tests/parser/should_fail/T16270h.hs
- testsuite/tests/partial-sigs/should_fail/NamedWildcardsNotInMonotype.stderr
- testsuite/tests/patsyn/should_fail/T26465.stderr
- testsuite/tests/perf/compiler/all.T
- testsuite/tests/perf/should_run/ByteCodeAsm.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/plugins09.stdout
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/plugins/plugins11.stdout
- testsuite/tests/plugins/simple-plugin/Simple/ReplacePlugin.hs
- testsuite/tests/plugins/static-plugins.stdout
- testsuite/tests/printer/AnnotationNoListTuplePuns.stdout
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/process/process009.hs
- testsuite/tests/process/process009.stdout
- testsuite/tests/profiling/should_run/callstack001.stdout
- testsuite/tests/profiling/should_run/callstack002.stderr
- testsuite/tests/profiling/should_run/callstack002.stdout
- testsuite/tests/rename/should_compile/T3103/Foreign/Ptr.hs
- testsuite/tests/rename/should_compile/T3103/GHC/Base.lhs
- testsuite/tests/rename/should_compile/T3103/GHC/Word.hs
- testsuite/tests/rename/should_compile/T3103/test.T
- testsuite/tests/rep-poly/RepPolyRecordPattern.hs
- testsuite/tests/rep-poly/RepPolyRecordPattern.stderr
- testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr
- testsuite/tests/rep-poly/T20113.stderr
- − testsuite/tests/rep-poly/T20363.stderr
- − testsuite/tests/rep-poly/T20363_show_co.hs
- − testsuite/tests/rep-poly/T20363_show_co.stderr
- − testsuite/tests/rep-poly/T20363b.stderr
- + testsuite/tests/rep-poly/T20363c.hs
- testsuite/tests/rep-poly/all.T
- testsuite/tests/roles/should_compile/Roles1.stderr
- testsuite/tests/roles/should_compile/Roles13.stderr
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles2.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- + testsuite/tests/rts/T27585.hs
- + testsuite/tests/rts/T27585.stdout
- testsuite/tests/rts/all.T
- + testsuite/tests/show-bytecode/Example.hs
- + testsuite/tests/show-bytecode/Makefile
- + testsuite/tests/show-bytecode/all.T
- + testsuite/tests/show-bytecode/normalize
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout
- + testsuite/tests/show-bytecode/show-bytecode-breakpoints.stdout-javascript-unknown-ghcjs
- + testsuite/tests/show-bytecode/show-bytecode-hpc.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout
- + testsuite/tests/show-bytecode/show-bytecode-vanilla.stdout-javascript-unknown-ghcjs
- testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr
- testsuite/tests/simplCore/should_compile/T13543.stderr
- testsuite/tests/simplCore/should_compile/T16038/T16038.stdout
- testsuite/tests/simplCore/should_compile/T24229a.stderr
- testsuite/tests/simplCore/should_compile/T24229b.stderr
- testsuite/tests/simplCore/should_compile/T3717.stderr
- testsuite/tests/simplCore/should_compile/T3772.stdout
- testsuite/tests/simplCore/should_compile/T4081.stderr
- testsuite/tests/simplCore/should_compile/T4908.stderr
- testsuite/tests/simplCore/should_compile/T4930.stderr
- testsuite/tests/simplCore/should_compile/T7360.stderr
- testsuite/tests/simplCore/should_compile/T8274.stdout
- testsuite/tests/simplCore/should_compile/T9400.stderr
- testsuite/tests/simplCore/should_compile/noinline01.stderr
- testsuite/tests/simplCore/should_compile/par01.stderr
- testsuite/tests/simplCore/should_compile/rule2.stderr
- testsuite/tests/simplCore/should_compile/str-rules.hs
- testsuite/tests/splice-imports/SI35.hs
- testsuite/tests/tcplugins/ArgsPlugin.hs
- testsuite/tests/tcplugins/EmitWantedPlugin.hs
- testsuite/tests/tcplugins/RewritePlugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- testsuite/tests/tcplugins/TyFamPlugin.hs
- + testsuite/tests/th/AssocDefaultNotAssoc.hs
- + testsuite/tests/th/AssocDefaultNotAssoc.stderr
- testsuite/tests/th/T14741.hs
- testsuite/tests/th/T21547.stderr
- testsuite/tests/th/T26568.stderr
- + testsuite/tests/th/T27013th.hs
- + testsuite/tests/th/TH_InvalidTopDecl.hs
- + testsuite/tests/th/TH_InvalidTopDecl.stderr
- testsuite/tests/th/TH_Roles2.stderr
- + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.hs
- + testsuite/tests/th/TH_cvt_DefaultDataInstDecl.stderr
- + testsuite/tests/th/TH_cvt_GadtNoCons.hs
- + testsuite/tests/th/TH_cvt_GadtNoCons.stderr
- + testsuite/tests/th/TH_cvt_IllegalDeclaration.hs
- + testsuite/tests/th/TH_cvt_IllegalDeclaration.stderr
- + testsuite/tests/th/TH_cvt_IllegalSumAlt.hs
- + testsuite/tests/th/TH_cvt_IllegalSumAlt.stderr
- + testsuite/tests/th/TH_cvt_InvalidCCallImpent.hs
- + testsuite/tests/th/TH_cvt_InvalidCCallImpent.stderr
- + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.hs
- + testsuite/tests/th/TH_cvt_InvalidTyFamInstLHS.stderr
- + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.hs
- + testsuite/tests/th/TH_cvt_InvalidTypeInstanceHeader.stderr
- + testsuite/tests/th/TH_cvt_RecGadtNoCons.hs
- + testsuite/tests/th/TH_cvt_RecGadtNoCons.stderr
- + testsuite/tests/th/TH_cvt_SumAltArityExceeded.hs
- + testsuite/tests/th/TH_cvt_SumAltArityExceeded.stderr
- + testsuite/tests/th/TH_pragmaSpecOld.hs
- + testsuite/tests/th/TH_pragmaSpecOld.stderr
- testsuite/tests/th/all.T
- testsuite/tests/typecheck/should_compile/T13032.stderr
- testsuite/tests/typecheck/should_compile/T14273.stderr
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- testsuite/tests/typecheck/should_compile/holes.stderr
- testsuite/tests/typecheck/should_compile/holes2.stderr
- testsuite/tests/typecheck/should_compile/holes3.stderr
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/T12921.stderr
- testsuite/tests/typecheck/should_fail/T14884.stderr
- testsuite/tests/typecheck/should_fail/T15883b.stderr
- testsuite/tests/typecheck/should_fail/T15883c.stderr
- testsuite/tests/typecheck/should_fail/T15883d.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
- testsuite/tests/typecheck/should_fail/T3323.stderr
- testsuite/tests/typecheck/should_fail/T5095.stderr
- testsuite/tests/typecheck/should_fail/T7279.stderr
- testsuite/tests/typecheck/should_fail/TcStaticPointersFail02.stderr
- testsuite/tests/typecheck/should_fail/TyAppPat_PatternBindingExistential.stderr
- testsuite/tests/typecheck/should_fail/tcfail072.stderr
- testsuite/tests/typecheck/should_fail/tcfail097.stderr
- testsuite/tests/typecheck/should_fail/tcfail133.stderr
- testsuite/tests/typecheck/should_run/T22510.stdout
- testsuite/tests/unboxedsums/UbxSumLevPoly.hs
- testsuite/tests/unboxedsums/unboxedsums_unit_tests.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.hs
- + testsuite/tests/vdq-rta/should_fail/T27586a.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586b.hs
- + testsuite/tests/vdq-rta/should_fail/T27586b.stderr
- + testsuite/tests/vdq-rta/should_fail/T27586c.hs
- + testsuite/tests/vdq-rta/should_fail/T27586c.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- testsuite/tests/warnings/should_compile/DerivingTypeable.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/genprimopcode/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/92a5637068785265c4e9c709f55030…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/92a5637068785265c4e9c709f55030…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/dcoutts/io-manager-uring] Hacking on io_uring I/O manager
by Duncan Coutts (@dcoutts) 26 Aug '26
by Duncan Coutts (@dcoutts) 26 Aug '26
26 Aug '26
Duncan Coutts pushed to branch wip/dcoutts/io-manager-uring at Glasgow Haskell Compiler / GHC
Commits:
102b80f6 by Duncan Coutts at 2026-08-26T11:16:05+01:00
Hacking on io_uring I/O manager
- - - - -
16 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/StgToCmm/Prim.hs
- hadrian/src/Oracles/Flag.hs
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/PrimOps.cmm
- rts/configure.ac
- rts/include/rts/Constants.h
- rts/include/rts/Flags.h
- rts/include/rts/storage/Closures.h
- rts/posix/Poll.c
- + rts/posix/URing.c
- + rts/posix/URing.h
- + rts/posix/URing.svg
- rts/rts.cabal
Changes:
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3185,6 +3185,128 @@ primop WaitWriteOp "waitWrite#" GenPrimOp
effect = ReadWriteEffect
out_of_line = True
+------------------------------------------------------------------------
+section "synchronous I/O operations"
+ {These primops read up to n bytes from an open file into memory, or write up
+ to n bytes from memory to an open file.
+
+ There are I\/O primops for all combinations of:
+
+ * read or write to open files
+ * pinned byte array or raw pointer for the memory buffer
+ * I/O at the current file pointer or at a given file offset
+
+ All of these operations are synchronous with respect to the calling
+ thread. It is implementation defined whether these operations block just
+ the calling thread or block all other Haskell threads running on the same
+ capability. In practice this depends on the I\/O manager being used.
+
+ The result is the number of bytes transferred (if non-negative), or an
+ error code if negative. The error code is a system error code which,
+ depending on the platform, is either a C/Posix style errno, or a Win32 error
+ code.
+
+ Note that partial\/short reads\/writes are possible. These are common with
+ sockets and character devices, and rare with disk block devices, but they
+ can happen and Posix and Win32 APIs say they can happen, so they must be
+ handled.
+
+ The source\/destination buffer is either specified by a pointer, or by a
+ (mutable, pinned) byte array and an offset within the array. This area is
+ required to be at least n bytes large. This cannot be checked for the
+ pointer variants but it is checked for the byte array variants. For the
+ byte array variants, the array must be pinned (so that the location of the
+ buffer is stable for the duration of the I/O operation) and this is
+ checked.
+
+ The buffer must remain live for the duration of the I/O operation (until
+ the I/O completes or the I/O is cancelled by an asynchronous exception).
+ For the primop variants that use byte array buffers this is done
+ automatically: the byte array is kept live for the duration of the
+ operation. For the pointer primop variants it is the caller's
+ responsibility to keep the buffer live for the duration of the I/O
+ operation. For these synchronous primops, callers can rely on the guarantee
+ that the I/O operation is complete or cancelled by the time the I/O primop
+ returns.
+
+ For the primop variants that do I/O at the current file pointer, the
+ current file pointer constitutes shared mutable state and should be treated
+ appropriately. Concurrent reads or writes are possible, and will happen in
+ some sequentially consistent order, but the order is not deterministic.
+
+ For the primop variants that do I/O at given offsets, note that this is
+ only supported on seekable files, which in practice means disk files. There
+ is no mutation to a shared file pointer in this case so it is safer to
+ use concurrent reads and writes. Callers are however responsible for
+ avoiding concurrent write operations to overlapping ranges (either
+ write\/write or read\/write), as these would have unspecified results.
+ }
+------------------------------------------------------------------------
+
+primop SyncIOReadAddrOp "syncIOReadAddr#" GenPrimOp
+ Int# -> Addr# -> Word# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, byte count}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOReadByteArrayOp "syncIOReadByteArray#" GenPrimOp
+ Int# -> MutableByteArray# RealWorld -> Word# -> Word# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, buf offset, byte count}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOReadAddrAtOp "syncIOReadAddrAt#" GenPrimOp
+ Int# -> Addr# -> Word# -> Int64# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, byte count, file offset}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOReadByteArrayAtOp "syncIOReadByteArrayAt#" GenPrimOp
+ Int# -> MutableByteArray# RealWorld -> Word# -> Word# -> Int64# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, buf offset, byte count, file offset}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOWriteAddrOp "syncIOWriteAddr#" GenPrimOp
+ Int# -> Addr# -> Word# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, byte count}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOWriteByteArrayOp "syncIOWriteByteArray#" GenPrimOp
+ Int# -> ByteArray# -> Word# -> Word# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, buf offset, byte count}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOWriteAddrAtOp "syncIOWriteAddrAt#" GenPrimOp
+ Int# -> Addr# -> Word# -> Int64# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, byte count, file offset}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
+primop SyncIOWriteByteArrayAtOp "syncIOWriteByteArrayAt#" GenPrimOp
+ Int# -> ByteArray# -> Word# -> Word# -> Int64# ->
+ State# RealWorld -> (# State# RealWorld, Int# #)
+ {Args: fd, buf, buf offset, byte count, file offset}
+ with
+ effect = ReadWriteEffect
+ out_of_line = True
+
------------------------------------------------------------------------
section "Concurrency primitives"
------------------------------------------------------------------------
=====================================
compiler/GHC/StgToCmm/Prim.hs
=====================================
@@ -1714,6 +1714,14 @@ emitPrimOp cfg primop =
DelayOp -> alwaysExternal
WaitReadOp -> alwaysExternal
WaitWriteOp -> alwaysExternal
+ SyncIOReadAddrOp -> alwaysExternal
+ SyncIOReadByteArrayOp -> alwaysExternal
+ SyncIOReadAddrAtOp -> alwaysExternal
+ SyncIOReadByteArrayAtOp -> alwaysExternal
+ SyncIOWriteAddrOp -> alwaysExternal
+ SyncIOWriteByteArrayOp -> alwaysExternal
+ SyncIOWriteAddrAtOp -> alwaysExternal
+ SyncIOWriteByteArrayAtOp -> alwaysExternal
ForkOp -> alwaysExternal
ForkOnOp -> alwaysExternal
KillThreadOp -> alwaysExternal
=====================================
hadrian/src/Oracles/Flag.hs
=====================================
@@ -37,6 +37,7 @@ data Flag = CrossCompiling
| UseLibdl
| UseLibbfd
| UseLibpthread
+ | UseLiburing
| NeedLibatomic
| UseGhcToolchain
@@ -61,6 +62,7 @@ flag f = do
UseLibdl -> "use-lib-dl"
UseLibbfd -> "use-lib-bfd"
UseLibpthread -> "use-lib-pthread"
+ UseLiburing -> "use-lib-uring"
NeedLibatomic -> "need-libatomic"
UseGhcToolchain -> "use-ghc-toolchain"
value <- lookupSystemConfig key
=====================================
rts/IOManager.c
=====================================
@@ -38,6 +38,11 @@
#include "posix/Timeout.h"
#endif
+#if defined(IOMGR_ENABLED_URING)
+#include "posix/URing.h"
+#include "posix/Timeout.h"
+#endif
+
#if defined(IOMGR_ENABLED_MIO_POSIX)
#include "posix/Signals.h"
#include "Prelude.h"
@@ -114,6 +119,14 @@ parseIOManagerFlag(const char *iomgrstr, IO_MANAGER_FLAG *flag)
return IOManagerAvailable;
#else
return IOManagerUnavailable;
+#endif
+ }
+ else if (strcmp("uring", iomgrstr) == 0) {
+#if defined(IOMGR_ENABLED_URING)
+ *flag = IO_MNGR_FLAG_URING;
+ return IOManagerAvailable;
+#else
+ return IOManagerUnavailable;
#endif
}
else if (strcmp("mio", iomgrstr) == 0) {
@@ -218,6 +231,8 @@ void selectIOManager(void)
iomgr_type = IO_MANAGER_SELECT;
#elif defined(IOMGR_DEFAULT_NON_THREADED_POLL)
iomgr_type = IO_MANAGER_POLL;
+#elif defined(IOMGR_DEFAULT_NON_THREADED_URING)
+ iomgr_type = IO_MANAGER_URING;
#elif defined(IOMGR_DEFAULT_NON_THREADED_WINIO)
iomgr_type = IO_MANAGER_WINIO;
#elif defined(IOMGR_DEFAULT_NON_THREADED_WIN32_LEGACY)
@@ -240,6 +255,12 @@ void selectIOManager(void)
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MNGR_FLAG_URING:
+ iomgr_type = IO_MANAGER_URING;
+ break;
+#endif
+
#if defined(IOMGR_ENABLED_MIO_POSIX)
case IO_MNGR_FLAG_MIO:
iomgr_type = IO_MANAGER_MIO_POSIX;
@@ -282,6 +303,10 @@ char * showIOManager(void)
case IO_MANAGER_POLL:
return "poll";
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ return "uring";
+#endif
#if defined(IOMGR_ENABLED_MIO_POSIX)
case IO_MANAGER_MIO_POSIX:
return "mio";
@@ -335,6 +360,12 @@ void initCapabilityIOManager(Capability *cap)
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ initCapabilityIOManagerURing(cap, iomgr);
+ break;
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
iomgr->blocked_queue_hd = END_TSO_QUEUE;
@@ -378,6 +409,11 @@ void initIOManager(void)
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ break;
+#endif
+
#if defined(IOMGR_ENABLED_MIO_POSIX)
case IO_MANAGER_MIO_POSIX:
/* Posix implementation in posix/Signals.c
@@ -441,6 +477,18 @@ initIOManagerAfterFork(Capability **pcap)
*/
ioManagerStartCap(pcap);
break;
+#endif
+#if defined(IOMGR_ENABLED_URING)
+ //TODO: So currently there's no per-cap re-initialisation
+ // except for cap0.
+ case IO_MANAGER_URING:
+ barf("IOManager.c:initIOManagerAfterFork:URing:TODO");
+ {
+ for (unsigned int i = 0; i < getNumCapabilities(); i++) {
+ Capability *cap = getCapability(i);
+ initCapabilityIOManagerAfterForkURing(cap, cap->iomgr);
+ }
+ }
#endif
/* The IO_MANAGER_SELECT needs no initialisation */
/* The IO_MANAGER_POLL needs no initialisation */
@@ -452,7 +500,13 @@ initIOManagerAfterFork(Capability **pcap)
}
-/* Called from setNumCapabilities.
+/* Called from setNumCapabilities, after all other per-capability changes have
+ * been made. When the scheduler increases the number of capabilities, it
+ * (indirectly) calls initCapabilityIOManager, for each new capability. So this
+ * notification is only needed by I/O managers that need a global hook (not
+ * per-cap), and/or need to be notified of there being fewer (as well as more)
+ * capabilities. There is no per-capability notification for disabling a
+ * capability (which occurs when the number of capabilities is reduced).
*/
void notifyIOManagerCapabilitiesChanged(Capability **pcap)
{
@@ -583,6 +637,18 @@ void markCapabilityIOManager(evac_fn evac, void *user, Capability *cap)
}
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ {
+ CapIOManager *iomgr = cap->iomgr;
+ markClosureTable(evac, user, &iomgr->aiop_table);
+ evac(user, (StgClosure **)(void *)&iomgr->overflow_tso_q_hd);
+ evac(user, (StgClosure **)(void *)&iomgr->overflow_tso_q_tl);
+ evac(user, (StgClosure **)(void *)&iomgr->timeout_queue);
+ break;
+ }
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
{
@@ -608,8 +674,15 @@ void scavengeTSOIOManager(StgTSO *tso)
* both of these are not GC pointers, so there is nothing to do.
*/
+#if defined(IOMGR_ENABLED_POLL) \
+ || defined(IOMGR_ENABLED_URING)
+
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
+#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+#endif
/* BlockedOn{Read,Write} uses block_info.aiop
* BlockedOnDelay uses block_info.timeout
* both of these are heap allocated, so we can do the same in all
@@ -669,6 +742,12 @@ bool anyPendingTimeoutsOrIO(Capability *cap)
return anyPendingTimeoutsOrIOPoll(cap->iomgr);
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ return anyPendingTimeoutsOrIOURing(cap->iomgr);
+ //TODO: do we want to share code with poll here?
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
{
@@ -732,6 +811,12 @@ void pollCompletedTimeoutsOrIO(Capability *cap)
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ pollCompletedTimeoutsOrIOURing(cap);
+ break;
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY) || \
(defined(IOMGR_ENABLED_WINIO) && !defined(THREADED_RTS))
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
@@ -765,6 +850,12 @@ void awaitCompletedTimeoutsOrIO(Capability *cap)
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ awaitCompletedTimeoutsOrIOURing(cap);
+ break;
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY) || \
(defined(IOMGR_ENABLED_WINIO) && !defined(THREADED_RTS))
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
@@ -805,8 +896,11 @@ int syncIOWaitReady(Capability *cap,
#endif
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
- ASSERT(tso->why_blocked == NotBlocked);
return syncIOWaitReadyPoll(cap, tso, rw, fd);
+#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ return syncIOWaitReadyURing(cap, tso, rw, fd);
#endif
default:
barf("waitRead# / waitWrite# not available for current I/O manager");
@@ -814,6 +908,91 @@ int syncIOWaitReady(Capability *cap,
}
+int syncIOReadWrite(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len)
+{
+ debugTrace(DEBUG_iomanager,
+ "thread %ld %s fd %d", (long) tso->id,
+ rw == IORead ? "reading from" : "writing to", (int) fd);
+ ASSERT(tso->why_blocked == NotBlocked);
+ switch (iomgr_type) {
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ return syncIOReadWriteURing(cap, tso, rw, (int)fd, live, buf,
+ (size_t)len, (off_t)(-1));
+ /* off_t = -1 means use and update the file pointer. */
+#endif
+/*
+#if defined(IOMGR_ENABLED_SELECT) \
+ || defined(IOMGR_ENABLED_POLL)
+#if defined(IOMGR_ENABLED_SELECT)
+ case IO_MANAGER_SELECT:
+#endif
+#if defined(IOMGR_ENABLED_POLL)
+ case IO_MANAGER_POLL:
+#endif
+ {
+ if (rw == IORead) {
+ read((int) fd, buf, (size_t) len);
+ } else {
+ write((int) fd, buf, (size_t) len);
+ }
+ //TODO: Ugg! We need to tell the primop to return synchonrously!
+ //Need to change the return type. Should use an out arg for the
+ //GC alloc retry.
+ }
+#endif
+*/
+ default:
+ barf("syncIORead/Write# not available for current I/O manager");
+ }
+}
+
+int syncIOReadWriteAt(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len, HsInt64 off)
+{
+ debugTrace(DEBUG_iomanager,
+ "thread %ld %s fd %d", (long) tso->id,
+ rw == IORead ? "reading from" : "writing to", (int) fd);
+ ASSERT(tso->why_blocked == NotBlocked);
+ switch (iomgr_type) {
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ return syncIOReadWriteURing(cap, tso, rw,
+ (int)fd, live, buf,
+ (size_t)len, (off_t)off);
+#endif
+/*
+#if defined(IOMGR_ENABLED_SELECT) \
+ || defined(IOMGR_ENABLED_POLL)
+#if defined(IOMGR_ENABLED_SELECT)
+ case IO_MANAGER_SELECT:
+#endif
+#if defined(IOMGR_ENABLED_POLL)
+ case IO_MANAGER_POLL:
+#endif
+ {
+ if (rw == IORead) {
+ pread((int)fd, buf, (size_t)len, (off_t)off);
+ } else {
+ pwrite((int)fd, buf, (size_t)len, (off_t)off);
+ }
+ //TODO: Ugg! We need to tell the primop to return synchonrously!
+ //Need to change the return type. Should use an out arg for the
+ //GC alloc retry.
+ }
+#endif
+*/
+ default:
+ barf("syncIORead/Write# not available for current I/O manager");
+ }
+}
+
+
void syncIOCancel(Capability *cap, StgTSO *tso)
{
debugTrace(DEBUG_iomanager, "cancelling I/O for thread %ld", (long) tso->id);
@@ -829,6 +1008,11 @@ void syncIOCancel(Capability *cap, StgTSO *tso)
syncIOCancelPoll(cap, tso);
break;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+ syncIOCancelURing(cap, tso);
+ break;
+#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
case IO_MANAGER_WIN32_LEGACY:
removeThreadFromDeQueue(cap, &cap->iomgr->blocked_queue_hd,
@@ -862,8 +1046,15 @@ int syncDelay(Capability *cap, StgTSO *tso, HsInt us_delay)
return 0;
}
#endif
+#if defined(IOMGR_ENABLED_POLL) \
+ || defined(IOMGR_ENABLED_URING)
+
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
+#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+#endif
return syncDelayTimeout(cap, tso, us_delay);
#endif
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
@@ -903,8 +1094,15 @@ void syncDelayCancel(Capability *cap, StgTSO *tso)
removeThreadFromQueue(cap, &cap->iomgr->sleeping_queue, tso);
break;
#endif
+#if defined(IOMGR_ENABLED_POLL) \
+ || defined(IOMGR_ENABLED_URING)
+
#if defined(IOMGR_ENABLED_POLL)
case IO_MANAGER_POLL:
+#endif
+#if defined(IOMGR_ENABLED_URING)
+ case IO_MANAGER_URING:
+#endif
syncDelayCancelTimeout(cap, tso);
break;
#endif
=====================================
rts/IOManager.h
=====================================
@@ -46,6 +46,9 @@
#if defined(IOMGR_BUILD_POLL) && !defined(THREADED_RTS)
#define IOMGR_ENABLED_POLL
#endif
+#if defined(IOMGR_BUILD_URING) && !defined(THREADED_RTS)
+ #define IOMGR_ENABLED_URING
+#endif
#if defined(IOMGR_BUILD_MIO) && defined(THREADED_RTS)
/* For MIO, it is really two separate I/O manager implementations: one for
* Windows and one for non-Windows. This is clear from both the C code on the
@@ -110,6 +113,11 @@
#else
#define IOMGR_ENABLED_STR_POLL ""
#endif
+#if defined(IOMGR_ENABLED_URING)
+ #define IOMGR_ENABLED_STR_URING " uring"
+#else
+ #define IOMGR_ENABLED_STR_URING ""
+#endif
#if defined(IOMGR_ENABLED_MIO_POSIX) || defined(IOMGR_ENABLED_MIO_WIN32)
#define IOMGR_ENABLED_STR_MIO " mio"
#else
@@ -128,6 +136,7 @@
#define IOMGRS_ENABLED_STR \
IOMGR_ENABLED_STR_SELECT \
IOMGR_ENABLED_STR_POLL \
+ IOMGR_ENABLED_STR_URING \
IOMGR_ENABLED_STR_MIO \
IOMGR_ENABLED_STR_WINIO \
IOMGR_ENABLED_STR_WIN32_LEGACY
@@ -143,6 +152,9 @@ typedef enum {
#if defined(IOMGR_ENABLED_POLL)
IO_MANAGER_POLL,
#endif
+#if defined(IOMGR_ENABLED_URING)
+ IO_MANAGER_URING,
+#endif
#if defined(IOMGR_ENABLED_MIO_POSIX)
IO_MANAGER_MIO_POSIX,
#endif
@@ -298,7 +310,7 @@ void scavengeTSOIOManager(StgTSO *tso);
/* Several code paths are almost identical between read and write paths. In
* such cases we use a shared code path with an enum to say which we're doing.
*/
-typedef enum { IORead, IOWrite } IOReadOrWrite;
+typedef enum { IORead = 0, IOWrite = 1 } IOReadOrWrite;
/* Synchronous operations: I/O and delays. As synchronous operations they
* necessarily operate on threads. The thread is suspended until the operation
@@ -310,7 +322,18 @@ typedef enum { IORead, IOWrite } IOReadOrWrite;
* GC to free up at least n words and then retry the operation.
*/
-int syncIOWaitReady(Capability *cap, StgTSO *tso, IOReadOrWrite rw, HsInt fd);
+int syncIOWaitReady(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd);
+
+int syncIOReadWrite(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len);
+
+int syncIOReadWriteAt(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len, HsInt64 off);
void syncIOCancel(Capability *cap, StgTSO *tso);
=====================================
rts/IOManagerInternals.h
=====================================
@@ -42,7 +42,8 @@ struct _CapIOManager {
StgTSO *sleeping_queue;
#endif
-#if defined(IOMGR_ENABLED_POLL)
+#if defined(IOMGR_ENABLED_POLL) \
+ || defined(IOMGR_ENABLED_URING)
/* AIOP and timeout collections shared by several I/O manager impls */
ClosureTable aiop_table;
StgTimeoutQueue *timeout_queue;
@@ -53,6 +54,54 @@ struct _CapIOManager {
struct pollfd *aiop_poll_table;
#endif
+#if defined(IOMGR_ENABLED_URING)
+ /* io_uring library structure */
+ struct io_uring *uring;
+
+ /* The number of operations submitted (by Haskell threads to the I/O
+ manager) and not yet notified of completion. */
+ int n_submitted_b; /* for blocking operations */
+ int n_submitted_nb; /* for non-blocking operations */
+
+ /* The number of operations pending in the submission queue, but not yet
+ submitted to the kernel (so not in-flight). */
+ int n_prepared_b; /* for blocking operations */
+ int n_prepared_nb; /* for non-blocking operations */
+
+ /* The number of operations submitted to the kernel but where the
+ corresponding completion has not yet been processed. */
+ int n_inflight_b; /* for blocking operations */
+ int n_inflight_nb; /* for non-blocking operations */
+
+ /* The limit on the number of operations we allow to be in-flight */
+ int limit_inflight_b; /* for blocking operations */
+ int limit_inflight_nb; /* for non-blocking operations */
+
+ /* The number of operations pending in the overflow queue (so not in the
+ submission queue or in flight) */
+ /* no overflow for blocking operations */
+ int n_overflow_nb; /* for non-blocking operations */
+
+ /* Invariants:
+ n_submitted_b = n_prepared_b + n_inflight_b
+ n_submitted_nb = n_prepared_nb + n_inflight_nb + n_overflow_nb
+ n_prepared_b + n_prepared_nb <= size of submission queue
+ */
+
+ /* A queue of threads blocked on I/O submission and a parallel queue of
+ * their corresponding SQEs. This is only used when there are more pending
+ * (non-blocking) I/O operations than the inflight limit.
+ */
+ StgTSO *overflow_tso_q_hd, *overflow_tso_q_tl;
+ struct overflow_sqe_q_t {
+ struct io_uring_sqe *sqe;
+ struct overflow_sqe_q_t *next;
+#if defined(DEBUG)
+ StgThreadID tid;
+#endif
+ } *overflow_sqe_q_hd, *overflow_sqe_q_tl;
+#endif
+
#if defined(IOMGR_ENABLED_WIN32_LEGACY)
/* Thread queue for threads blocked on I/O completion. */
StgTSO *blocked_queue_hd;
=====================================
rts/PrimOps.cmm
=====================================
@@ -2602,6 +2602,108 @@ stg_delayzh ( W_ us_delay )
}
}
+/*
+int syncIOReadWrite(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len);
+
+int syncIOReadWriteAt(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, HsInt fd,
+ StgClosure *live, void *buf,
+ HsWord len, HsInt64 off);
+*/
+
+#define SYNCIO_BLOCK_OR_GC(fail) \
+ if (fail == 0) (likely: True) { \
+ jump stg_block_noregs(); \
+ } else { \
+ /* TODO: should invoke GC, requesting 'fail' words, then retry \
+ see: https://gitlab.haskell.org/ghc/ghc/-/issues/24105 */ \
+ jump stg_raisezh(ghczminternal_GHCziInternalziIOziException_heapOverflow_closure); \
+ }
+ //TODO: need to handle returning synchonrously, for non-uring I/O managers.
+ //or if uring optimises the read case.
+
+stg_syncIOReadAddrzh ( W_ fd, W_ buf, W_ len )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 0::I32 /* IORead */, fd,
+ stg_ASYNCIO_LIVE0_closure, buf,
+ len);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOReadByteArrayzh ( W_ fd, P_ buf, W_ boff, W_ len )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 0::I32 /* IORead */, fd,
+ buf, buf + SIZEOF_StgArrBytes + boff,
+ len);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOReadAddrAtzh ( W_ fd, W_ buf, W_ len, I64 foff )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWriteAt(MyCapability() "ptr", CurrentTSO "ptr",
+ 0::I32 /* IORead */, fd,
+ stg_ASYNCIO_LIVE0_closure, buf,
+ len, foff);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOReadByteArrayAtzh ( W_ fd, P_ buf, W_ boff, W_ len, I64 foff )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 0::I32 /* IORead */, fd,
+ buf, buf + SIZEOF_StgArrBytes + boff,
+ len, foff);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOWriteAddrzh ( W_ fd, W_ buf, W_ len )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 1::I32 /* IOWrite */, fd,
+ stg_ASYNCIO_LIVE0_closure, buf,
+ len);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOWriteByteArrayzh ( W_ fd, P_ buf, W_ boff, W_ len )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 1::I32 /* IOWrite */, fd,
+ buf, buf + SIZEOF_StgArrBytes + boff,
+ len);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOWriteAddrAtzh ( W_ fd, W_ buf, W_ len, I64 foff )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWriteAt(MyCapability() "ptr", CurrentTSO "ptr",
+ 1::I32 /* IOWrite */, fd,
+ stg_ASYNCIO_LIVE0_closure, buf,
+ len, foff);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
+
+stg_syncIOWriteByteArrayAtzh ( W_ fd, P_ buf, W_ boff, W_ len, I64 foff )
+{
+ W_ fail; /* Request this many words on heap alloc failure. */
+ (fail) = ccall syncIOReadWrite(MyCapability() "ptr", CurrentTSO "ptr",
+ 1::I32 /* IOWrite */, fd,
+ buf, buf + SIZEOF_StgArrBytes + boff,
+ len, foff);
+ SYNCIO_BLOCK_OR_GC(fail);
+}
#if defined(mingw32_HOST_OS)
stg_asyncReadzh ( W_ fd, W_ is_sock, W_ len, W_ buf )
=====================================
rts/configure.ac
=====================================
@@ -397,6 +397,23 @@ GHC_IOMANAGER_ENABLE([poll], [EnableIOManagerPoll], [IOMGR_BUILD_POLL],
#include <poll.h>])
fi])
+GHC_IOMANAGER_ENABLE([uring], [EnableIOManagerURing], [IOMGR_BUILD_URING],
+ [if test "$HostOS" = "linux"; then
+ AC_CHECK_HEADER([liburing.h], [HaveLiburingH=YES],
+ [AC_MSG_WARN([liburing.h is required by the uring I/O manager])],[])
+ AC_CHECK_LIB([uring], [io_uring_check_version], [HaveLiburing=YES],
+ [AC_MSG_WARN([liburing is required by the uring I/O manager])], [])
+ if test "$HaveLiburingH" = "YES" && test "$HaveLiburing" = YES; then
+ EnableIOManagerURing=YES
+ LinkLiburing=uring
+ else
+ EnableIOManagerURing=NO
+ fi
+ else
+ EnableIOManagerURing=NO
+ fi])
+AC_SUBST(LinkLiburing)
+
GHC_IOMANAGER_ENABLE([mio], [EnableIOManagerMIO], [IOMGR_BUILD_MIO],
[EnableIOManagerMIO=YES])
@@ -415,6 +432,7 @@ if test "$HostOS" = "mingw32"; then
GHC_IOMANAGER_DEFAULT_SELECT([IOManagerThreadedDefault], [winio], [EnableIOManagerWinIO])
GHC_IOMANAGER_DEFAULT_SELECT([IOManagerThreadedDefault], [mio], [EnableIOManagerMIO])
else
+ GHC_IOMANAGER_DEFAULT_SELECT([IOManagerNonThreadedDefault], [uring], [EnableIOManagerURing])
GHC_IOMANAGER_DEFAULT_SELECT([IOManagerNonThreadedDefault], [select], [EnableIOManagerSelect])
GHC_IOMANAGER_DEFAULT_SELECT([IOManagerNonThreadedDefault], [poll], [EnableIOManagerPoll])
GHC_IOMANAGER_DEFAULT_SELECT([IOManagerThreadedDefault], [mio], [EnableIOManagerMIO])
@@ -432,6 +450,9 @@ GHC_IOMANAGER_DEFAULT_AC_DEFINE([IOManagerNonThreadedDefault], [non-threaded],
GHC_IOMANAGER_DEFAULT_AC_DEFINE([IOManagerNonThreadedDefault], [non-threaded],
[poll], [IOMGR_DEFAULT_NON_THREADED_POLL])
+GHC_IOMANAGER_DEFAULT_AC_DEFINE([IOManagerNonThreadedDefault], [non-threaded],
+ [uring], [IOMGR_DEFAULT_NON_THREADED_URING])
+
GHC_IOMANAGER_DEFAULT_AC_DEFINE([IOManagerNonThreadedDefault], [non-threaded],
[winio], [IOMGR_DEFAULT_NON_THREADED_WINIO])
=====================================
rts/include/rts/Constants.h
=====================================
@@ -271,7 +271,9 @@
by tryWakeupThread() */
#define ThreadMigrating 13
-/* Next number is 15. */
+#define BlockedOnIOSubmission 15
+
+/* Next number is 16. */
/*
* These constants are returned to the scheduler by a thread that has
=====================================
rts/include/rts/Flags.h
=====================================
@@ -247,6 +247,7 @@ typedef enum _IO_MANAGER_FLAG {
/* All other choices pick only the requested one, with no fallback. */
IO_MNGR_FLAG_SELECT, /* Unix only, non-threaded RTS only */
IO_MNGR_FLAG_POLL, /* Unix only, non-threaded RTS only */
+ IO_MNGR_FLAG_URING, /* Linux only, non-threaded RTS only */
IO_MNGR_FLAG_MIO, /* cross-platform, threaded RTS only */
IO_MNGR_FLAG_WINIO, /* Windows only */
IO_MNGR_FLAG_WIN32_LEGACY, /* Windows only, non-threaded RTS only */
@@ -272,6 +273,8 @@ typedef struct _MISC_FLAGS {
* for the linker, NULL ==> off */
IO_MANAGER_FLAG ioManager; /* The I/O manager to use. */
uint32_t numIoWorkerThreads; /* Number of I/O worker threads to use. */
+ uint32_t io_uring_sq_entries; /* io_uring submission queue size */
+ uint32_t io_uring_cq_entries; /* io_uring completion queue size */
} MISC_FLAGS;
/* See Note [Synchronization of flags and base APIs] */
=====================================
rts/include/rts/storage/Closures.h
=====================================
@@ -713,7 +713,13 @@ union NotifyCompletion {
enum NotifyCompletionType {
NotifyTSO = 0,
NotifyMVar = 1,
- NotifyTVar = 2
+ NotifyTVar = 2,
+ NotifyNone = 3
+ /* If a TSO receives an async exception while it's waiting on I/O then
+ * the TSO stops waiting but the I/O may still be outstanding, and we
+ * need the corresponding StgAsyncIOOp until the I/O completes. We use
+ * NotifyNone in this case to avoid disturbing the original TSO.
+ */
};
/* A node in the leftist heap. */
@@ -786,9 +792,9 @@ typedef struct {
// to know which capability an aiop is on.
uint16_t capno;
- // Tells us which thing the notify union above contains.
- // This is a value from enum IONotify but we don't use the enum type
- // here due to portability concerns for this size C enum bitfield.
+ // Tells us which thing the notify union above contains. This is a value
+ // from enum NotifyCompletionType but we don't use the enum type here
+ // due to portability concerns for this size C enum bitfield.
uint16_t notify_type: 2;
// The outcome:
@@ -816,3 +822,15 @@ typedef struct {
// We handle this in the INFO_TABLE_CONSTR decl for stg_ASYNCIOOP using
// Either32Or64Bit(4,2) for the non-pointer words.
} StgAsyncIOOp;
+
+struct io_uring_sqe;
+typedef struct {
+ StgHeader header;
+
+ // Any heap object to keep alive for the duration of the I/O operation,
+ // for example I/O buffers.
+ StgClosure *live;
+
+ struct io_uring_sqe *sqe;
+} StgAsyncURingSQE;
+
=====================================
rts/posix/Poll.c
=====================================
@@ -347,7 +347,7 @@ void pollCompletedTimeoutsOrIOPoll(Capability *cap)
#if defined(HAVE_DECL_PPOLL) && HAVE_DECL_PPOLL == 1
/* We could use poll here, since we use no timeout, but for
consistency we use the same syscall as at the other call site. */
- struct timespec tv = (struct timespec) { .tv_sec = 0, .tv_nsec = 0 };
+ struct timespec tv = { .tv_sec = 0, .tv_nsec = 0 };
int res = ppoll(iomgr->aiop_poll_table, nfds, &tv, NULL);
debugTrace(DEBUG_iomanager,
=====================================
rts/posix/URing.c
=====================================
@@ -0,0 +1,1259 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team 2021-2023
+ *
+ * An I/O manager based on the Linux io_uring API.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "rts/PosixSource.h"
+#include "Rts.h"
+
+#include "IOManager.h" // defines IOMGR_ENABLED_URING
+
+#if defined(IOMGR_ENABLED_URING)
+
+#include "Capability.h"
+#include "Threads.h"
+#include "Schedule.h"
+#include "Prelude.h"
+#include "RtsUtils.h"
+#include "rts/Time.h"
+#include "RaiseAsync.h"
+
+#include "URing.h"
+#include "Signals.h"
+
+#include <liburing.h>
+#include <poll.h> // for poll() flags POLLIN POLLOUT
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "IOManagerInternals.h"
+#include "Timeout.h"
+
+/******************************************************************************
+
+This I/O manager is based on the Linux io_uring API. We rely on the liburing
+library, rather than using the system calls directly.
+
+Introduction
+============
+
+The io_uring API is an _almost_ generic mechanism for performing Linux syscalls
+asynchronously. It supports a range of I/O related operations, including
+ordinary file read and write, and waiting for I/O readiness. It works using a
+queue to submit I/O operations, and another queue to receive I/O completions.
+The io_uring documentation calls these the "submission queue", abbreviated SQ,
+and "completion queue", abbreviated CQ. The corresponding queue entries are
+abbreviated as SQEs and CQEs.
+
+There is a single system call to both submit operations and/or wait for I/O
+completion (or a timeout). It is also possible to poll for new entries in the
+completion queue without using a system call at all. This fits the RTS
+scheduler design quite well. Every time round the scheduler loop we have to
+do a non-blocking check for I/O completion, and it is only when there are no
+runnable threads that we want to block and wait for I/O (or timers). So in busy
+applications there are a lot more non-blocking than blocking checks for I/O
+completion. So being able to do the non-blocking poll without needing a system
+call should save significantly on system calls, compared to other APIs.
+
+We use the liburing C library, rather than the system calls directly. This
+provides a degree of convenience and portability across kernel versions.
+
+Synchronous I/O
+---------------
+
+Classically, asynchronous I/O APIs are slower than ordinary synchronous I/O
+APIs for the case of buffered I/O reads where the requested data is already in
+the OS page cache (if they support buffered I/O at all). This requires
+applications that use asynchronous I/O (and thus care about performance) to use
+it only in some cases, and use synchronous I/O when that is expected to be
+faster. This is complex, and thus relatively few applications use asynchronous
+I/O. Furthermore, knowing whether data is in the page cache is something that
+only the kernel knows reliably. User space can only make educated guesses.
+
+A major selling point of io_uring is that it (mostly) solves this problem. It
+is designed work for buffered I/O (as well as direct I/O). Operations are
+submitted by putting entries (SQEs) into the submission queue (SQ) and then
+entering the kernel (io_uring_enter). The kernel starts work on all the
+operations. If any of them can complete synchronously then the kernel can place
+the completion entries (CQEs) into the completion queue (CQ). Thus the
+synchronous operations complete synchronously. Furthermore, the decision about
+whether it can complete synchronously is made dynamically by the kernel (e.g.
+based on whether the data is available in the page cache). The result is that a
+simple file read where the data is available in the page cache can be as quick
+as a normal synchronous file read system call.
+
+Overall, this allows the same API to be used for all I/O, without having to
+guess about synchronous vs asynchronous completions. Furthermore, io_uring
+supports both disk I/O and sockets I/O, whereas older APIs only supported one
+or the other (see e.g. epoll for sockets and Linux/Posix AIO for disk files).
+Overall this allows a less complex solution, by using the same relatively
+uniform API for everything (even through the API itself is somewhat more
+complex than other APIs).
+
+General strategy
+----------------
+
+Our I/O strategy with io_uring is to prepare but not submit I/O operations in
+the I/O primops, and then submit the operations in the scheduler. That is, in
+the I/O primops we put the I/O operations (SQEs) into the submission queue (SQ),
+but we don't yet call into the kernel to inform it of the new operations.
+Instead we do that in the scheduler. At this point in the scheduler, we can
+both submit any pending I/O operations and handle any completions. This lets us
+submit and collect I/O with a single system call. Handling I/O completions
+typically results in waking up threads, which the scheduler can then deal with.
+
+Consider the important example of simple disk reads that complete synchronously.
+In this case the completion is available immediately after io_uring_enter
+returns and the scheduler can reschedule the thread that submitted the I/O. So
+the end result _should_ be as fast as a normal synchronous blocking read()
+system call (but benchmarks are needed to verify this).
+
+Important fast-path cases
+-------------------------
+
+There are a few important special fast-path cases to keep in mind:
+
+1. Common case: as above, a Haskell thread has pending I/O, so we submit
+ it. This requires a system call. Afterwards we also process any
+ completions. This means any I/O operations that complete synchronously
+ get handled immediately and with a single system call. This is crucial
+ for performance of ordinary buffered I/O in the common case that the data
+ is available in the page cache.
+
+2. Common case: no pending I/O to submit, but there is outstanding I/O
+ that we need to see if it has completed. This does not require a
+ system call. We just need to look at the completion ring.
+
+3. Rare case: we have pending I/O to submit but the kernel refuses to
+ accept more I/O because the completion queue is full. In this case
+ we process the completion queue first, and then retry. This ends up
+ using two system calls.
+
+I/O submission overload
+-----------------------
+
+Asynchronous I/O APIs enable I/O to be submitted without waiting and thus they
+must deal with the problem of having too much I/O in flight at once for the
+resources available.
+
+For example, epoll_ctl will return ENOMEM or ENOSPC if it cannot allocate the
+necessary memory or hits a resource limit. The epoll backend for MIO turns
+these failures into Haskell exceptions. This works ok in practice for epoll
+because epoll only supports one kind of async I/O operation: waiting for I/O
+readiness. This has relatively low resource use and so systems generally hit
+other resource limits first, e.g. file descriptors.
+
+On the other hand io_uring supports a variety of I/O operations with different
+behaviour and resource use. They can roughly be divided into two categories:
+1. cheap blocking operations; and
+2. expensive non-blocking operations.
+
+The cheap blocking operations include waiting for I/O readiness on pipes and
+sockets, as with epoll, but it also includes blocking reads/write/send/recv on
+pipes and sockets. These operations tend to have very low resource use and
+correspondingly the kernel can support very many outstanding operations. This
+is needed for some large scale networking use cases where there can be very
+many sockets in use at once.
+
+The comparatively expensive non-blocking operations include read and write on
+disk files and various file and file system operations. These operations tend
+to have higher resource use and so the kernel cannot support too many of them
+in progress at once. Furthermore, for non-blocking operations there isn't much
+need to have huge numbers in progress at once: the performance benefit is
+limited by the hardware concurrency (CPUs, SSD queue depth etc).
+
+Unfortunately, the limits on the number of concurrent operations of each kind
+is not known, or at least not reported by the kernel in advance. When trying
+to submit new operations, the kernel can report EAGAIN if it is out of
+resources. This reporting mechanism is awkward because of the two classes of
+operations. The way we would like to respond to hitting a limit is also
+different for blocking vs non-blocking operations.
+
+For non-blocking operations, we can simply wait for some operations to complete
+and then submit more. This works because non-blocking operations will
+eventually complete, and indeed typically complete fairly promptly.
+
+For blocking operations on the other hand, there's not a lot we can do if we
+hit a resource limit. Waiting may not help. Blocking operations can block
+indefinitely. It is also possible to deadlock if not all I/O readiness
+notifications are active simultaneously. So if we hit a resource limit for
+these operations then we can't do much better than throw exceptions to the
+Haskell threads submitting the operations. This is of course what the MIO epoll
+backend does.
+
+We will make the assumption that the kernel does _not_ have separate limits for
+these two classes of operations, but assume that it is a common limit based on
+the common resource of kernel memory. As noted above, there is no great benefit
+to having excessive concurrency of non-blocking operations. We can limit the
+concurrency (using a queue) with no change in semantics of the application. On
+the other hand an application that wants to wait on zillions of blocking
+operations cannot have that concurrency reduced without it having a semantic
+effect on the application. We either have to support it or (hopefully
+gracefully) fail as resources run out.
+
+So we take the approach of trying to limit the concurrency and thus resource
+use of the non-blocking operations so that the remaining kernel memory can
+maximise the number of blocking operations we can support. We do that by
+imposing a "reasonable" limit on the number of concurrent non-blocking
+operations. We also impose a separate larger limit on the number of concurrent
+blocking operations. The high level idea is that we treat the non-blocking
+limit like a semaphore (with that concurrency limit) on the threads submitting
+non-blocking I/O operations. This means we can handle overload transparently.
+On the other hand the limit on blocking operations is a hard limit and if we
+hit that then we have to throw exceptions (to the threads submitting the I/O).
+
+In the typical application use cases this strategy should avoid encountering
+EAGAIN in the first place, however it can still happen and we must handle it
+somehow.
+
+Before considering EAGAIN, consider a more normal scenario with lots of
+concurrent I/O -- both blocking and non-blocking operations -- where we do hit
+the limit on non-blocking operations. We track the number of blocking and
+non-blocking operations that are currently "in flight" using the counters
+iomgr->uring_inflight_{non}blocking_aiops. These are incremented by the number
+of prepared operations when the submission queue is successfully flushed, and
+decremented for each completion processed. Hitting the limit means that when a
+thread submits a new non-blocking operation we find the count of inflight
+non-blocking operations is already at the limit, and thus a new operation would
+be over the limit.
+
+Normally when a thread uses a primop to submit an I/O operation we would grab
+an existing SQE from the submission queue (SQ) and fill in the SQE. If however
+we would go over the inflight limit, then instead we allocate a fresh SQE (on
+the C heap using malloc) and then fill in the SQE as normal. Then we put the
+SQE and the TSO for the thread that submitted it onto (the end of) a pair of
+overflow queues: one for the SQEs and one for the corresponding threads. We use
+a pair of queues rather than a queue of pairs because the TSOs are allocated on
+the GC heap but the SQEs are on the C heap and there is existing infrastructure
+for handling TSO queues, including tracing them for GC. In the scheduler, when
+we process the completion of a blocking operation, if there are entries on the
+overflow queues then we can dequeue an SQE and corresponding TSO and copy the
+SQE into the SQ and reschedule the TSO. This means the SQE is ready to go and
+the TSO is unblocked. If we are in this overflow situation and the completions
+for several non-blocking operations are processed in one go then will will add
+several SQEs to be added to the SQ in one batch. This should naturally lead to
+batching in the overflow situation and amortise the syscall overheads.
+
+While all of this is going on, other threads submitting _blocking_ operations
+can proceed as normal, preparing their operations into the submission queue.
+
+Now if we do encounter EAGAIN, we assume that it's the blocking operations
+that are at fault.
+
+Approaches to batching
+----------------------
+
+We currently do no batching, but this section discusses plausible approaches.
+
+With this design we have the opportunity to try to accumulate multiple pending
+I/O operations and then submit them in one batch, which could improve
+performance in I/O intensive applications by reducing the number of system
+calls. Ordinary synchronous I/O primops like threadWaitRead# block the Haskell
+thread and return to the scheduler, which means we only accumulate a single
+pending I/O operation. There are a couple ways we could achieve batching.
+
+One approach is to allow individual Haskell threads to prepare multiple I/O
+operations by providing asynchronous I/O primops. This could be quite effective
+at generating a lot of I/O, but it would likely see relatively little use
+because it requires changing application designs.
+
+Another approach is by having the scheduler not always submit pending I/O, but
+instead let it run other threads in the hope that they will produce more
+pending I/O. It would wait until either a time limit or a pending count limit
+before submitting the I/O. Such an approach would increase I/O latency:
+consider the scheduler running a thread that creates a pending I/O operation,
+followed by running a CPU-bound thread for a whole 20 millisecond timeslice,
+after which the scheduler submits the I/O. Thus this approach could only be
+used for low priority I/O, which itself would require introducing a notion of
+I/O priority.
+
+One can imagine variations on this design such as a more sophisticated
+scheduler predicting if the next thread to run is likely to be I/O or CPU bound
+and using that to decide whether to flush pending I/O or to speculate on
+accumulating more. Or the scheduler could set a timer to interrupt CPU bound
+threads sooner if it's speculating on gathering more I/O. This could reduce
+the cost on average, and bound latency, but there would still be a latency vs
+throughput tradeoff, which would almost certainly require some notion of I/O
+priority.
+
+
+io_uring features we use
+------------------------
+
+IORING_FEAT_NODROP
+
+io_uring features we could use but don't (yet)
+----------------------------------------------
+
+io_uring features we cannot use
+-------------------------------
+
+NOTES: cannot use registered ring fd, due to multiple worker threads, even
+though it's protected by the lock. Same for registered/direct fds.
+
+
+Tracking counters
+-----------------
+
+We track the number of operations submitted (by Haskell threads to the I/O
+manager) and not yet notified of completion:
+
+> int n_submitted_b;
+> int n_submitted_nb;
+
+These are incremented when the primop submits I/O to the I/O manager, and are
+decremented when the I/O completion is processed. We track blocking and
+non-blocking operations separately.
+
+We track the number of operations that are prepared in the submission queue,
+but not yet submitted to the kernel.
+
+> int n_prepared_b;
+> int n_prepared_nb;
+
+These are incremented when an operation is prepared in the submission queue
+and decremented when operations are submitted to the kernel.
+
+We track the number of operations submitted to the kernel and where the
+completion has not yet been processed. We call these "in-flight" operations.
+
+> int n_inflight_b;
+> int n_inflight_nb;
+
+These are incremented when operations are submitted to the kernel, and
+decremented when I/O completions are processed.
+
+We track the limit on the number of operations the I/O manager will allow to be
+in-flight with the kernel.
+
+> int limit_inflight_b;
+> int limit_inflight_nb;
+
+These are typically set on RTS startup and then rarely changed. The
+limit_inflight_b can be reduced dynamically if the I/O manager encounters
+EAGAIN when submitting operations.
+
+We track the number of non-blocking operations that are in the overflow queue.
+These are operations that have been submitted, and could not be put into the
+submission queue (because it would exceed the limit_inflight_nb), and so go
+into the overflow queue instead.
+
+> int n_overflow_nb;
+
+This is incremented (instead of n_prepared_nb) if the number of n_inflight_nb
+plus n_prepared_nb is at or above the limit_inflight_nb, in which case the
+operation (and submitting thread) is put into the overflow queue. It is
+decremented when there is space available within the limit_inflight_nb and the
+operation can be put into the submission queue (and thus also incrementing the
+n_prepared_nb).
+
+We maintain two invariants:
+
+1. n_submitted_b = n_prepared_b + n_inflight_b
+2. n_submitted_nb = n_prepared_nb + n_overflow_nb + n_inflight_nb
+
+The implication is that set of prepared, overflow and inflight operations are
+distinct from each other and their union is equal to the submitted set. Another
+way to look at it is that there distinct states for submitted operations:
+prepared, overflow (for non-blocking) and inflight.
+
+******************************************************************************/
+
+/* Forward declarations */
+static int enlargeTables(Capability *cap, CapIOManager *iomgr);
+static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop);
+static void enqueueOverflowQueue(Capability *cap, CapIOManager *iomgr,
+ StgTSO *tso, struct io_uring_sqe *sqe);
+static void dequeueOverflowQueue(CapIOManager *iomgr,
+ StgTSO **ptso, struct io_uring_sqe **psqe);
+
+/* Constants */
+
+/* A couple tags we add to the sqe->user_data to tell us about this operation
+ * when we process the completion. Currently we distinguish:
+ * 1. non-blocking vs blocking operations, just so we can update our counters
+ * which count these separately.
+ * 2. cancellation operations
+ */
+const uint64_t AIOP_TAG_CANCEL = 0x80lu << 56; /* bit 63 */
+const uint64_t AIOP_TAG_OP_NB = 0x40lu << 56; /* bit 62 */
+const uint64_t AIOP_TAG_MASK = 0xc0lu << 56; /* bit 62 | 63 */
+
+
+void initCapabilityIOManagerURing(Capability *cap, CapIOManager *iomgr)
+{
+ initClosureTable(&iomgr->aiop_table, ClosureTableCompact);
+ iomgr->timeout_queue = emptyTimeoutQueue();
+
+ int sq_entries = RtsFlags.MiscFlags.io_uring_sq_entries;
+
+ iomgr->n_submitted_b = 0;
+ iomgr->n_submitted_nb = 0;
+ iomgr->n_prepared_b = 0;
+ iomgr->n_prepared_nb = 0;
+ iomgr->n_inflight_b = 0;
+ iomgr->n_inflight_nb = 0;
+ iomgr->limit_inflight_b = INT_MAX;
+ iomgr->limit_inflight_nb = 4 * sq_entries;
+ iomgr->n_overflow_nb = 0;
+ iomgr->overflow_tso_q_hd = END_TSO_QUEUE;
+ iomgr->overflow_tso_q_tl = END_TSO_QUEUE;
+ iomgr->overflow_sqe_q_hd = NULL;
+ iomgr->overflow_sqe_q_tl = NULL;
+
+ /* Set the uring params: we want to use independent sizes of submission
+ * and completion queues. We typically want a bigger completion queue than
+ * a submission queue.
+ */
+ struct io_uring_params params = {
+ .flags = IORING_SETUP_CQSIZE
+ | IORING_SETUP_CLAMP
+ | IORING_SETUP_SUBMIT_ALL,
+ .cq_entries = RtsFlags.MiscFlags.io_uring_cq_entries
+ };
+ //TODO: what happens if we use flags that are not recognised by the kernel
+ // version, e.g. IORING_SETUP_SUBMIT_ALL prior to 5.18?
+
+ /* TODO: see if we want to support IORING_SETUP_SQPOLL. With
+ IORING_FEAT_NATIVE_WORKERS, it doesn't need any priviledges. */
+
+ /* Share the same kernel work-queue between the urings for each capability.
+ * Do this by using the IORING_SETUP_ATTACH_WQ flag for capabilities > 0,
+ * and pass the uring fd for cap 0 (the main capability).
+ */
+ if (cap->no > 0) {
+ params.flags |= IORING_SETUP_ATTACH_WQ;
+ params.wq_fd = MainCapability.iomgr->uring->ring_fd;
+ }
+
+ /* Try to initialise the uring */
+ struct io_uring *uring = stgMallocBytes(sizeof (struct io_uring),
+ "initCapabilityIOManagerUring");
+ int res = io_uring_queue_init_params(sq_entries, uring, ¶ms);
+ if (res < 0) goto fail;
+
+ /* Check for features we require. */
+ unsigned required =
+ /* Needed for simple handling of ring sizes and limits.
+ * TODO: we might be able to support kernels without this
+ * by setting the limits to be the same as the ring sizes. */
+ IORING_FEAT_NODROP
+
+ /* TODO: explain why */
+ | IORING_FEAT_SUBMIT_STABLE
+
+ /* Needed for read/write that updates the file pos. */
+ | IORING_FEAT_RW_CUR_POS
+
+ /* Needed for corner cases like reading from /proc/self,
+ * or signalfd */
+ | IORING_FEAT_NATIVE_WORKERS;
+
+ if ((uring->features & required) != required) goto fail;
+
+ /* Arrange for the uring (fd and mmap'ed queues) not to be inherited. */
+ res = fcntl(uring->ring_fd, F_SETFD, FD_CLOEXEC);
+ if (res < 0) goto fail;
+ res = io_uring_ring_dontfork(uring);
+ if (res < 0) goto fail;
+
+ /* Success. Save what we need. */
+ iomgr->uring = uring;
+ return;
+
+ /* Failure. Clean up. */
+fail:
+ stgFree(uring);
+ barf("uring iomgr: initialisation failed");
+ //TODO: we should add support to fail and use a fallback I/O manager
+}
+
+
+void initCapabilityIOManagerAfterForkURing(Capability *cap STG_UNUSED,
+ CapIOManager *iomgr STG_UNUSED)
+{
+ //TODO: ugg, do we need to shutdown all the other caps? Or does that
+ // happen automagically? Need to look into forkProcess and shutting
+ // down the I/O managers.
+}
+
+/******************************************************************************
+ * Common prologues and epilogues for primops for I/O operations.
+ *
+ * There are different common prologues/epilogues depending on:
+ * - synchronous or asynchronous primops
+ * - blocking or non-blocking I/O operations
+ */
+
+
+/* The common prologue for for all synchronous primops for both blocking and
+ * non-blocking I/O operations.
+ */
+static int prologueSyncIOOp(Capability *cap, StgTSO *tso,
+ int why_blocked, StgAsyncIOOp **paiop)
+{
+ StgAsyncIOOp *aiop;
+ aiop = (StgAsyncIOOp *)allocateMightFail(cap, sizeofW(StgAsyncIOOp));
+ if (RTS_UNLIKELY(aiop == NULL)) { return (sizeof(StgAsyncIOOp)); }
+ SET_HDR(aiop, &stg_ASYNCIOOP_info, CCS_SYSTEM); //TODO: get CCCS
+ aiop->notify_type = NotifyTSO;
+ aiop->notify.tso = tso;
+ tso->why_blocked = why_blocked;
+ tso->block_info.aiop = aiop;
+ *paiop = aiop;
+ return 0;
+}
+
+
+/* The common prologue for all non-blocking I/O operations.
+ *
+ * Allocate a table index
+ * Fill in some of the aiop fields
+ * Allocate an SQE, either on the ring or on the heap if we're in overflow.
+ */
+static int prologueNonBlockingIOOp(Capability *cap,
+ StgTSO *tso, StgAsyncIOOp *aiop,
+ struct io_uring_sqe **psqe,
+ bool *tso_block)
+{
+ CapIOManager *iomgr = cap->iomgr;
+ if (RTS_UNLIKELY(isFullClosureTable(&iomgr->aiop_table))) {
+ int fail = enlargeTables(cap, iomgr);
+ if (RTS_UNLIKELY(fail)) return fail;
+ }
+
+ int index = insertClosureTable(cap, &iomgr->aiop_table, aiop);
+
+ aiop->capno = cap->no;
+ aiop->index = index;
+
+ struct io_uring_sqe *sqe;
+
+ if (iomgr->n_inflight_nb + iomgr->n_prepared_nb
+ < iomgr->limit_inflight_nb) {
+ /* The typical case. Allocate an SQE from the ring */
+ sqe = io_uring_get_sqe(iomgr->uring);
+ ASSERT(sqe); /* Otherwise we counted wrong */
+ iomgr->n_submitted_nb++;
+ iomgr->n_prepared_nb++;
+ *tso_block = false;
+ } else {
+ /* We're going to have to block the submitting thread.
+ * Allocate an SQE on the heap and suspend the calling TSO.
+ */
+ sqe = stgMallocBytes(sizeof (struct io_uring_sqe), "uring iomgr");
+ enqueueOverflowQueue(cap, iomgr, tso, sqe);
+ iomgr->n_submitted_nb++;
+ iomgr->n_overflow_nb++;
+ *tso_block = true;
+ }
+ io_uring_sqe_set_data64(sqe, index);
+ *psqe = sqe;
+ return 0;
+}
+
+
+/* The common prologue for all blocking I/O operations.
+ *
+ * Allocate a table index
+ * Fill in some of the aiop fields
+ * Allocate an SQE, or return failure if we're at the limit.
+ */
+static int prologueBlockingIOOp(Capability *cap,
+ StgTSO *tso, StgAsyncIOOp *aiop,
+ struct io_uring_sqe **psqe)
+{
+ CapIOManager *iomgr = cap->iomgr;
+
+ if (iomgr->n_inflight_b + iomgr->n_prepared_b >= iomgr->limit_inflight_b) {
+ /* If we reach the limit we fail and throw an exception */
+ raiseAsync(cap, tso, (StgClosure *)blockedOnBadFD_closure
+ /*TODO: use ioopResourcesExhausted_closure */,
+ false, NULL);
+ return -1;
+ //TODO: review this
+ //TODO: current return value is for memory alloc failure, not for
+ // other failures. Need error result separate from alloc.
+ }
+
+ if (RTS_UNLIKELY(isFullClosureTable(&iomgr->aiop_table))) {
+ int fail = enlargeTables(cap, iomgr);
+ if (RTS_UNLIKELY(fail)) return fail;
+ }
+
+ int index = insertClosureTable(cap, &iomgr->aiop_table, aiop);
+
+ aiop->capno = cap->no;
+ aiop->index = index;
+
+ /* Allocate an SQE on the ring */
+ struct io_uring_sqe *sqe = io_uring_get_sqe(iomgr->uring);
+ ASSERT(sqe); /* Otherwise we counted wrong */
+ iomgr->n_submitted_b++;
+ iomgr->n_prepared_b++;
+ io_uring_sqe_set_data64(sqe, index);
+ *psqe = sqe;
+ return 0;
+}
+
+
+/* The common epilogue for all async non-blocking I/O operations.
+ */
+static int epilogueAsyncNonBlockingIOOp(CapIOManager *iomgr,
+ StgTSO *tso, StgAsyncIOOp *aiop,
+ bool tso_block)
+{
+ if (tso_block) {
+ tso->why_blocked = BlockedOnIOSubmission;
+ tso->block_info.aiop = aiop;
+ return -1;
+ } else if (io_uring_sq_space_left(iomgr->uring) == 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/* Common epilogue for all async blocking I/O operations.
+ */
+static int epilogueAsyncBlockingIOOp(CapIOManager *iomgr)
+{
+ return io_uring_sq_space_left(iomgr->uring) == 0 ? -1 : 0;
+}
+
+
+/******************************************************************************
+ * Non-blocking I/O operations. This includes read/write on files (not sockets).
+ *
+ * The code is organised as common I/O preparation functions and then individual
+ * primops (sync and async). They also rely on the common prologue and epilogue
+ * functions above.
+ */
+
+static int prepareIOReadWrite(Capability *cap, StgTSO *tso, bool *tso_block,
+ StgAsyncIOOp *aiop,
+ IOReadOrWrite rw, int fd,
+ StgClosure *live, void *buf,
+ size_t len, off_t off) {
+ struct io_uring_sqe *sqe;
+ int fail = prologueNonBlockingIOOp(cap, tso, aiop, &sqe, tso_block);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ aiop->live = live;
+ if (rw == IORead) {
+ io_uring_prep_read(sqe, fd, buf, len, off);
+ } else {
+ io_uring_prep_write(sqe, fd, buf, len, off);
+ }
+ return 0;
+}
+
+
+int asyncIOReadWriteURing(Capability *cap, StgTSO *tso, StgAsyncIOOp *aiop,
+ IOReadOrWrite rw, int fd,
+ StgClosure *live, void *buf,
+ size_t len, off_t off)
+{
+ bool tso_block;
+ int fail = prepareIOReadWrite(cap, tso, &tso_block, aiop,
+ rw, fd, live, buf, len, off);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ return epilogueAsyncNonBlockingIOOp(cap->iomgr, tso, aiop, tso_block);
+}
+
+
+int syncIOReadWriteURing(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, int fd,
+ StgClosure *live, void *buf,
+ size_t len, off_t off)
+{
+ StgAsyncIOOp *aiop;
+ int why_blocked = rw == IORead ? BlockedOnRead : BlockedOnWrite;
+ int fail = prologueSyncIOOp(cap, tso, why_blocked, &aiop);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ bool unused;
+ fail = prepareIOReadWrite(cap, tso, &unused, aiop,
+ rw, fd, live, buf, len, off);
+ if (RTS_UNLIKELY(fail)) return fail;
+ return 0;
+}
+
+
+/******************************************************************************
+ * Blocking I/O operations. This includes waiting for I/O readiness on sockets,
+ * pipes etc.
+ *
+ * The code is organised as common I/O preparation functions and then individual
+ * primops (sync and async). They also rely on the common prologue and epilogue
+ * functions above.
+ */
+
+
+static void prepareIOWaitReady(StgAsyncIOOp *aiop, struct io_uring_sqe *sqe,
+ IOReadOrWrite rw, int fd) {
+ aiop->live = &stg_ASYNCIO_LIVE0_closure;
+ io_uring_prep_poll_add(sqe, fd, rw == IORead ? POLLIN : POLLOUT);
+}
+
+
+int asyncIOWaitReadyURing(Capability *cap, StgTSO *tso, StgAsyncIOOp *aiop,
+ IOReadOrWrite rw, int fd)
+{
+ struct io_uring_sqe *sqe;
+ int fail = prologueBlockingIOOp(cap, tso, aiop, &sqe);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ prepareIOWaitReady(aiop,sqe, rw, fd);
+
+ return epilogueAsyncBlockingIOOp(cap->iomgr);
+}
+
+
+int syncIOWaitReadyURing(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, int fd)
+{
+ StgAsyncIOOp *aiop;
+ int why_blocked = rw == IORead ? BlockedOnRead : BlockedOnWrite;
+ int fail = prologueSyncIOOp(cap, tso, why_blocked, &aiop);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ struct io_uring_sqe *sqe;
+ fail = prologueBlockingIOOp(cap, tso, aiop, &sqe);
+ if (RTS_UNLIKELY(fail)) return fail;
+
+ prepareIOWaitReady(aiop, sqe, rw, fd);
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * Actions to cancel outstanding I/O operations. Also support cancelling any
+ * outstanding I/O on an fd prior to it being closed.
+ *
+ * This covers both synchronous and asynchronous operations.
+ */
+
+
+static void ioCancel(Capability *cap, StgAsyncIOOp *aiop);
+
+
+void syncIOCancelURing(Capability *cap, StgTSO *tso)
+{
+ StgAsyncIOOp *aiop = tso->block_info.aiop;
+ ASSERT(aiop->notify_type == NotifyTSO);
+ ASSERT(indexClosureTable(&cap->iomgr->aiop_table, aiop->index) == aiop);
+ ioCancel(cap, aiop);
+ /* We cannot use the normal notifyIOCompletion here. We are in the context
+ * of throwTo, interrupting a thread blocked on IO via an async exception.
+ * We don't put the TSO back on the run queue or change the why_blocked
+ * status, as that is done by removeFromQueues (in the throwTo* functions).
+ */
+ tso->block_info.closure = (StgClosure *)END_TSO_QUEUE;
+
+ //TODO: Synchronous cancellation from throwTo seems to be pretty keen for
+ // the thread to be unblocked immediately so it can start unwinding the
+ // stack. Perhaps it is ok to continue the cancellation in the background.
+ // But if so then we will need to adjust the notify type to be none /
+ // cancelled!
+ /* Cancelling thread-synchronous I/O happens from throwTo, which is very
+ * keen for the thread to be unblocked immediately so it can unwind the
+ * stack and schedule the thread to run an exception handler. This demand
+ * to be synchronous is a bit tricky to arrange because cancelling the I/O
+ * operation the thread is blocked on is potentially asynchronous.
+ */
+ aiop->notify_type = NotifyNone;
+ aiop->notify.tso = END_TSO_QUEUE;
+}
+
+
+void asyncIOCancelURing(Capability *cap, StgAsyncIOOp *aiop)
+{
+ /* We can reliably determine if the aiop is still in progress by checking
+ * if the aiop_table still points to this aiop object. This is reliable
+ * because each aiop is GC heap allocated, so cannot be recycled until it
+ * is no longer retained by the application.
+ */
+ ASSERT(aiop->notify_type != NotifyTSO);
+ if (indexClosureTable(&cap->iomgr->aiop_table, aiop->index) == aiop) {
+ ioCancel(cap, aiop);
+ notifyIOCompletion(cap, aiop);
+ }
+}
+
+
+static void ioCancel(Capability *cap, StgAsyncIOOp *aiop)
+{
+ barf("URing.c:ioCancel:TODO");
+
+ CapIOManager *iomgr = cap->iomgr;
+
+ int ix = aiop->index;
+ struct io_uring_sqe *sqe = io_uring_get_sqe(iomgr->uring);
+ //TODO: return status to indicate if we need to return to the scheduler
+ // to flush a full submission queue
+
+ /* io_uring lets us include one word into submission queue entries (SQEs),
+ * which come back in the corresponding completion queue entry (CQE). We
+ * use this feature to identify the aiop so that we will be able to
+ * process the completion properly, e.g. waking up the right thread.
+ * We can't use a direct pointer to the aiop because the aiops are heap
+ * allocated and GC pointers are not stable. We use the index in the
+ * ClosureTable, because this is stable. Indeed the raison d'être of the
+ * ClosureTable is to provide stable pointers for thus purpose.
+ //TODO: the above is a helpful comment but it belongs elsewhere, e.g.
+ //in the intro.
+ */
+ uint64_t sqe_data = ix;
+
+ /* Although IORING_OP_POLL_ADD has a special separate cancellation using
+ * IORING_OP_POLL_REMOVE, apparently it can also be cancelled using the
+ * generic IORING_OP_ASYNC_CANCEL, which is good so we don't need to
+ * distinguish.
+ */
+ io_uring_prep_cancel64(sqe, sqe_data, 0 /*flags*/);
+ //TODO: if we use other tags in the sqe_data we'll need to reconstruct
+ // them here so we can find the right item. e.g. if we use AIOP_TAG_OP_NB
+ // we'd need to distinguish in the aiop->flags for example.
+
+ /* Cancelling is itself a new uring I/O operation which will have a
+ * corresponding completion. Set a high bit to mark this as a cancel
+ * operation, but still knowing the index of the original operation.
+ */
+ io_uring_sqe_set_data64(sqe, sqe_data | AIOP_TAG_CANCEL);
+
+ //TODO: verify for IORING_OP_POLL_ADD, if we do a successful
+ // IORING_OP_POLL_REMOVE then which completions do we get?
+ // Do we get a completion for the IORING_OP_POLL_ADD, and if so with
+ // what result? Or does a successful IORING_OP_POLL_REMOVE mean we
+ // only get a completion for the remove and not the add?
+
+ //TODO: verify similar for normal I/O cancel, e.g. a read on a pipe.
+ // Which completions do we get if we
+
+ //TODO: is it ok cancel I/O asynchronously here? Do we need to submit the
+ // cancel op? The cancel op will complete synchronously but the cancellation
+ // may only complete later. This might confuse resource cleanup, e.g. because
+ // a file will not get closed until the cancel finishes.
+
+ /* This is an CQE for a cancellation. After posting a
+ * cancellation SQE then we expect to get _both_
+ * a cancellation CQE and a CQE for the original operation that
+ * was the target of cancellation. This means that (provided
+ * it's not an error) we can ignore the cancellation SQE and
+ * just process the normal SQE for the target operation.
+ *
+ * The target operation will either be cancelled successfully
+ * immediately (in which case the cancellation cqe_data->res == 0) or if the target operation
+ * is in progress and cannot be cancelled, then we'll get
+ * cqe_data->res == -EALREADY for the cancellation
+ * the
+ * result of the operation (which may still be an interrupted
+ * outcome. If the cancellation fails, we
+ */
+ if (cqe_data->res != 0 && cqe_data->res != -EALREADY)
+ sysErrorBelch("uring:processIOCompletions");
+ }
+
+}
+
+
+
+
+/* TODO: need to add support for closing properly.
+ * Unfortunately, uring's behaviour for closing a fd when there are outstanding
+ * poll (or other async I/O) operations on that fd is unhelpful. The poll
+ * operation itself keeps a reference to the file open. Thus the close will
+ * not in fact interrupt and cancel the poll.
+ * So the I/O manager needs to be notified of fd close, so that we can do
+ * something. Fortunately we can use io_uring_prep_cancel_fd to cancel all
+ * operations on an fd.
+ *
+ * I think cancelled ops _do_ generate CQEs. So we should be able to do the
+ * appropriate notifications by waiting for the original CQEs. We should
+ * probably issue the cancellation
+ *
+ */
+
+
+/******************************************************************************
+ * The functions called from the scheduler to poll or wait for pending I/O,
+ * and process any I/O completions.
+ */
+
+
+bool anyPendingTimeoutsOrIOURing(CapIOManager *iomgr)
+{
+ return !isEmptyTimeoutQueue(iomgr->timeout_queue)
+ || !isEmptyClosureTable(&iomgr->aiop_table);
+}
+
+
+static void notifyIOCompletion(Capability *cap, StgAsyncIOOp *aiop)
+{
+ switch (aiop->notify_type) {
+ case NotifyTSO:
+ {
+ if (aiop->outcome == IOOpOutcomeFailed && aiop->error == EBADF) {
+ /* The fd is invalid: raise an IOError exception in the blocked
+ * thread. (See bug #4934 for what happens without this.)
+ */
+ StgTSO *tso = aiop->notify.tso;
+ debugTrace(DEBUG_iomanager,
+ "Raising exception in thread %" FMT_StgThreadID
+ " blocked on an invalid fd", tso->id);
+ raiseAsync(cap, tso, (StgClosure *)blockedOnBadFD_closure,
+ false, NULL);
+ break;
+ } else {
+ /* We should be guaranteed that the tso is still on the same
+ * cap because the tso was not on the run queue of any cap and
+ * so is not subject to thread migration.
+ */
+ StgTSO *tso = aiop->notify.tso;
+ tso->why_blocked = NotBlocked;
+ tso->_link = END_TSO_QUEUE;
+ pushOnRunQueue(cap, tso);
+ }
+ break;
+ }
+ case NotifyMVar:
+ performTryPutMVar(cap, aiop->notify.mvar, Unit_closure);
+ break;
+
+ case NotifyTVar:
+ barf("uring iomgr: TVar notification not yet supported");
+ break;
+ }
+}
+
+
+/* Process all the I/O completions that are currently available without
+ * blocking.
+ *
+ * This will correctly deal with completion queue overflow: if the completions
+ * queue is empty but has the overflow bit set then io_uring_peek_batch_cqe
+ * will do another non-blocking uring enter to refill the completion queue.
+ */
+static void processIOCompletions(Capability *cap, CapIOManager *iomgr)
+{
+ struct io_uring *uring = iomgr->uring;
+ while (1) {
+ unsigned head, count = 0;
+ struct io_uring_cqe *cqe;
+ io_uring_for_each_cqe(uring, head, cqe) {
+ uint64_t cqe_data = io_uring_cqe_get_data64(cqe);
+ if (RTS_UNLIKELY(cqe_data & AIOP_TAG_CANCEL)) {
+
+ } else {
+ int ix = cqe_data;
+ StgAsyncIOOp *aiop = indexClosureTable(&iomgr->aiop_table, ix);
+ removeClosureTable(cap, &iomgr->aiop_table, ix);
+ aiop->result = cqe->res;
+ //TODO: if we use these tags in the sqe_data we'll need to reconstruct
+ // them for cancel so we can find the right item. e.g. if we use AIOP_TAG_OP_NB
+ // we'd need to distinguish in the aiop->flags for example.
+ if (cqe_data & AIOP_TAG_OP_NB) {
+ iomgr->n_inflight_nb--;
+ iomgr->n_submitted_nb--;
+ } else {
+ iomgr->n_inflight_b--;
+ iomgr->n_submitted_b--;
+ }
+ notifyIOCompletion(cap, aiop);
+ }
+ count++;
+ }
+ io_uring_cq_advance(uring, count);
+ if (RTS_UNLIKELY(io_uring_cq_has_overflow(uring))) {
+ if (io_uring_get_events(uring) < 0) {
+ sysErrorBelch("io_uring_enter");
+ stg_exit(EXIT_FAILURE);
+ }
+ continue;
+ } else {
+ break;
+ }
+ }
+}
+
+
+/* Check invariants that must hold on entry to and exit from the scheduler.
+ * Used before/after {poll,await}CompletedTimeoutsOrIOURing which are called
+ * from the scheduler.
+ */
+static void assertURingSchedulerInvariants(CapIOManager *iomgr)
+{
+ struct io_uring *uring = iomgr->uring;
+
+ // That our tracking counters are consistent.
+ ASSERT(iomgr->n_submitted_b == iomgr->n_prepared_b
+ + iomgr->n_inflight_b);
+ ASSERT(iomgr->n_submitted_nb == iomgr->n_prepared_nb
+ + iomgr->n_overflow_nb
+ + iomgr->n_inflight_nb);
+
+ // That we are within limits
+ ASSERT(iomgr->n_inflight_b <= iomgr->limit_inflight_b);
+ ASSERT(iomgr->n_inflight_nb <= iomgr->limit_inflight_nb);
+
+ // That we correctly track the submission queue size.
+ ASSERT((int)io_uring_sq_ready(uring) == iomgr->n_prepared_b
+ + iomgr->n_prepared_nb);
+
+ // That our overflow queue is consistent with the overflow counter.
+ ASSERT(iomgr->n_overflow_nb > 0
+ ? iomgr->overflow_sqe_q_hd == NULL &&
+ iomgr->overflow_sqe_q_tl == NULL &&
+ iomgr->overflow_tso_q_hd == END_TSO_QUEUE &&
+ iomgr->overflow_tso_q_tl == END_TSO_QUEUE
+ : iomgr->n_overflow_nb == 0 &&
+ iomgr->overflow_sqe_q_hd != NULL &&
+ iomgr->overflow_sqe_q_tl != NULL &&
+ iomgr->overflow_tso_q_hd != END_TSO_QUEUE &&
+ iomgr->overflow_tso_q_tl != END_TSO_QUEUE);
+}
+
+/* If there are any completed I/O operations or expired timers, process the
+ * completions as appropriate. If there are none, return without waiting.
+ *
+ * This is the non-blocking variant. See awaitCompletedTimeoutsOrIOURing
+ * for the potentially-blocking variant.
+ */
+void pollCompletedTimeoutsOrIOURing(Capability *cap)
+{
+ CapIOManager *iomgr = cap->iomgr;
+ struct io_uring *uring = iomgr->uring;
+
+ assertURingSchedulerInvariants(iomgr);
+
+ /* Process timeouts, if any, but don't immediately return to the scheduler,
+ * since we should submit I/O and reap any completions too.
+ */
+ if (!isEmptyTimeoutQueue(iomgr->timeout_queue)) {
+ Time now = getProcessElapsedTime();
+ processTimeoutCompletions(cap, now);
+ }
+
+ /* Submit I/O if needed */
+ if (io_uring_sq_ready(uring)) {
+ int res = io_uring_submit_and_get_events(uring);
+
+ if (RTS_UNLIKELY(res < 0)) {
+ if (res == -EBUSY) {
+ /* This is an odd one. According to the doc:
+ * If the IORING_FEAT_NODROP feature flag is set, then EBUSY
+ * will be returned if there were overflow entries,
+ * IORING_ENTER_GETEVENTS flag is set and not all of the
+ * overflow entries were able to be flushed to the CQ ring.
+ *
+ * So it's not really an error at all. It just means we will
+ * have to do multiple iterations in processIOCompletions()
+ * to collect all the completions.
+ *
+ * Thus EBUSY should imply that there are entries in the CQ.
+ */
+ ASSERT(io_uring_cq_ready(uring) > 0);
+ }
+ } else {
+ ASSERT(res == iomgr->n_prepared_b + iomgr->n_prepared_nb);
+ /* We're using IORING_SETUP_SUBMIT_ALL so we should expect to have
+ * all of them submitted, or an error.
+ * https://github.com/axboe/liburing/issues/186
+ * Alternatively, we could loop and submit the remainder.
+ */
+ iomgr->n_inflight_b += iomgr->n_prepared_b;
+ iomgr->n_inflight_nb += iomgr->n_prepared_nb;
+ iomgr->n_prepared_b = 0;
+ iomgr->n_prepared_nb = 0;
+ }
+ }
+
+ if (io_uring_cq_ready(uring)) {
+ processIOCompletions(cap, iomgr);
+ }
+ //TODO: now we need to check if we have any items in our overflow queue
+ //and if so, we need to copy some of those into the SQ and submit them.
+ //copy in up to either the SQ limit or in-flight limit.
+
+ assertURingSchedulerInvariants(iomgr);
+}
+
+
+/* If there are any completed I/O operations or expired timers, process the
+ * completions as appropriate. If there are none, wait until I/O or a timer
+ * does complete (or we get a signal with a handler) and process the
+ * completions as appropriate.
+ *
+ * This is the potentially-blocking variant. See pollCompletedTimeoutsOrIOURing
+ * for the non-blocking variant.
+ */
+void awaitCompletedTimeoutsOrIOURing(Capability *cap)
+{
+ CapIOManager *iomgr = cap->iomgr;
+ struct io_uring *uring = iomgr->uring;
+
+ assertURingSchedulerInvariants(iomgr);
+
+ do {
+
+ /* We're being asked (by the scheduler) to block if there's no
+ * immediate timer or I/O completions. So there had better be
+ * some pending I/O or pending timers, or we'd deadlock.
+ */
+ ASSERT(!isEmptyTimeoutQueue(iomgr->timeout_queue) ||
+ !isEmptyClosureTable(&iomgr->aiop_table));
+
+ Time now = getProcessElapsedTime();
+ processTimeoutCompletions(cap, now);
+
+ /* If we didn't wake any threads due to expiring timeouts, then we need
+ * to wait on I/O. Or to put it another way, even if we did wake some
+ * threads, we'll still poll (but not wait) for I/O. This is to ensure
+ * we avoid starving threads blocked on I/O.
+ */
+ bool wait = emptyRunQueue(cap);
+
+ /* There are four possible cases:
+ * 1. non-blocking check for I/O completion with I/O submission
+ * 2. non-blocking check for I/O completion with no I/O submission
+ * 3. blocking wait for I/O completion with a timeout
+ * 4. blocking wait for I/O completion without a timeout
+ *
+ * If we woke any threads due to timeouts we're in the first or second
+ * case.
+ *
+ * Otherwise we're in one of the blocking cases. We will use a timeout
+ * if the timeout queue is non-empty.
+ */
+
+ int res;
+ if (!wait && io_uring_sq_ready(uring)) {
+ /* Case 1 (as above) */
+ res = io_uring_submit_and_get_events(uring);
+ } else if (!wait) {
+ /* Case 2 (as above) */
+ res = io_uring_get_events(uring);
+ } else {
+ struct timespec tv;
+ if (timeoutInNanoseconds(iomgr, true, now, &tv)) {
+ /* Case 3 (as above) */
+ /* struct timespec and struct __kernel_timespec are compatible
+ * but not exactly the same. Sigh. */
+ struct __kernel_timespec ts = { .tv_sec = tv.tv_sec,
+ .tv_nsec = tv.tv_nsec };
+ struct io_uring_cqe *cqe_unused;
+ res = io_uring_submit_and_wait_timeout(uring, &cqe_unused,
+ 1, &ts, NULL);
+ } else {
+ /* Case 4 (as above) */
+ res = io_uring_submit_and_wait(uring, 1);
+ }
+ }
+
+ if (res >= 0) {
+ processIOCompletions(cap, iomgr);
+ } else if (errno == EINTR) {
+
+ } else if (errno == EBUSY || errno == EAGAIN) {
+
+ } else {
+ sysErrorBelch("io_uring_enter");
+ stg_exit(EXIT_FAILURE);
+ }
+ } while (emptyRunQueue(cap)
+ && (!isEmptyClosureTable(&iomgr->aiop_table) ||
+ !isEmptyTimeoutQueue(iomgr->timeout_queue))
+ && getSchedState() == SCHED_RUNNING);
+
+ assertURingSchedulerInvariants(iomgr);
+}
+
+
+/******************************************************************************
+ * Local helper utilities
+ */
+
+static int enlargeTables(Capability *cap, CapIOManager *iomgr)
+{
+ int oldcapacity = capacityClosureTable(&iomgr->aiop_table);
+ int newcapacity = (oldcapacity == 0) ? 1 : (oldcapacity * 2);
+
+ int fail = enlargeClosureTable(cap, &iomgr->aiop_table, newcapacity);
+ if (RTS_UNLIKELY(fail)) return fail;
+ return 0;
+}
+
+
+/*
+ */
+static void enqueueOverflowQueue(Capability *cap, CapIOManager *iomgr,
+ StgTSO *tso, struct io_uring_sqe *sqe)
+{
+ /* Append the TSO to the tail of the overflow queue of TSOs. */
+ ASSERT(tso->_link == END_TSO_QUEUE);
+ if (iomgr->overflow_tso_q_hd == END_TSO_QUEUE) {
+ iomgr->overflow_tso_q_hd = tso;
+ } else {
+ setTSOLink(cap, iomgr->overflow_tso_q_tl, tso);
+ }
+ iomgr->overflow_tso_q_tl = tso;
+
+ /* And append the SQE to the tail of the overflow queue of SQEs. */
+ struct overflow_sqe_q_t *entry;
+ entry = stgMallocBytes(sizeof(struct overflow_sqe_q_t), "uring iomgr");
+ *entry = (struct overflow_sqe_q_t) {
+ .sqe = sqe,
+ .next = NULL,
+#if defined(DEBUG)
+ .tid = tso->id
+#endif
+ };
+ if (iomgr->overflow_sqe_q_hd == NULL) {
+ iomgr->overflow_sqe_q_hd = entry;
+ } else {
+ iomgr->overflow_sqe_q_tl->next = entry;
+ }
+ iomgr->overflow_sqe_q_tl = entry;
+}
+
+
+static void dequeueOverflowQueue(CapIOManager *iomgr,
+ StgTSO **ptso, struct io_uring_sqe **psqe)
+{
+ /* Remove the TSO and SQE from the head of their respective queues */
+ StgTSO *tso = iomgr->overflow_tso_q_hd;
+ struct overflow_sqe_q_t *entry = iomgr->overflow_sqe_q_hd;
+
+ if (tso == END_TSO_QUEUE) {
+ //TODO: decide if we need this or if we should assume the queue is
+ // non-empty
+ ASSERT(entry == NULL);
+ *ptso = END_TSO_QUEUE;
+ *psqe = NULL;
+ } else {
+ iomgr->overflow_tso_q_hd = tso->_link;
+ RELAXED_STORE(&tso->_link, END_TSO_QUEUE);
+ if (iomgr->overflow_tso_q_hd == END_TSO_QUEUE) {
+ iomgr->overflow_tso_q_tl = END_TSO_QUEUE;
+ }
+
+ iomgr->overflow_sqe_q_hd = entry->next;
+ if (iomgr->overflow_sqe_q_hd == NULL) {
+ iomgr->overflow_sqe_q_tl = NULL;
+ }
+
+ *ptso = tso;
+ *psqe = entry->sqe;
+ }
+}
+
+#endif /* IOMGR_ENABLED_URING */
+
=====================================
rts/posix/URing.h
=====================================
@@ -0,0 +1,52 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team 2021-2023
+ *
+ * An I/O manager based on the Linux io_uring API.
+ *
+ * Prototypes for functions in URing.c
+ *
+ * -------------------------------------------------------------------------*/
+
+#pragma once
+
+#include "IOManager.h"
+
+#include "BeginPrivate.h"
+
+#if defined(IOMGR_ENABLED_URING)
+
+void initCapabilityIOManagerURing(Capability *cap, CapIOManager *iomgr);
+void initCapabilityIOManagerAfterForkURing(Capability *cap, CapIOManager *iomgr);
+
+/* Synchronous I/O and timer operations */
+int syncIOWaitReadyURing(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, int fd);
+
+int syncIOReadWriteURing(Capability *cap, StgTSO *tso,
+ IOReadOrWrite rw, int fd,
+ StgClosure *live, void *buf,
+ size_t len, off_t off);
+
+void syncIOCancelURing(Capability *cap, StgTSO *tso);
+
+/* Asynchronous operations */
+int asyncIOWaitReadyURing(Capability *cap, StgTSO *tso, StgAsyncIOOp *aiop,
+ IOReadOrWrite rw, int fd);
+
+int asyncIOReadWriteURing(Capability *cap, StgTSO *tso, StgAsyncIOOp *aiop,
+ IOReadOrWrite rw, int fd,
+ StgClosure *live, void *buf,
+ size_t len, off_t off);
+
+void asyncIOCancelURing(Capability *cap, StgAsyncIOOp *aiop);
+
+/* Scheduler operations */
+bool anyPendingTimeoutsOrIOURing(CapIOManager *iomgr);
+void pollCompletedTimeoutsOrIOURing(Capability *cap);
+void awaitCompletedTimeoutsOrIOURing(Capability *cap);
+
+#endif /* IOMGR_ENABLED_URING */
+
+#include "EndPrivate.h"
+
=====================================
rts/posix/URing.svg
=====================================
@@ -0,0 +1,691 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
+<svg width="116cm" height="39cm" viewBox="-281 18 2304 768" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g>
+ <rect style="fill: #ffffff" x="-200" y="20" width="158.525" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-200" y="20" width="158.525" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120.738" y="42.8812">
+ <tspan x="-120.738" y="42.8812">Primop: async</tspan>
+ <tspan x="-120.738" y="58.8812">non-blocking I/O</tspan>
+ <tspan x="-120.738" y="74.8812">submission</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120.738" y="55">
+ <tspan x="-120.738" y="55"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-120.738" y1="90" x2="-120.224" y2="112.267"/>
+ <polygon style="fill: #000000" points="-120.052,119.765 -125.281,109.882 -120.224,112.267 -115.283,109.652 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-120.052,119.765 -125.281,109.882 -120.224,112.267 -115.283,109.652 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="-200" y="122" width="160" height="54"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-200" y="122" width="160" height="54"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="144.881">
+ <tspan x="-120" y="144.881">Allocate AIOP</tspan>
+ <tspan x="-120" y="160.881">Allocate table index</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="-280" y1="105" x2="180" y2="105"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-280" y="98.6222">
+ <tspan x="-280" y="98.6222">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-280" y="121.539">
+ <tspan x="-280" y="121.539">RTS C</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="0" y="25" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="0" y="25" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="58.8813">
+ <tspan x="80" y="58.8813">Primop: GC and retry</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="55">
+ <tspan x="80" y="55"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="0" y1="55" x2="-31.7389" y2="55"/>
+ <polygon style="fill: #000000" points="-39.2389,55 -29.2389,50 -31.7389,55 -29.2389,60 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-39.2389,55 -29.2389,50 -31.7389,55 -29.2389,60 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="149">
+ <tspan x="-120" y="149"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="156.981">
+ <tspan x="-20" y="156.981">mem alloc failure?</tspan>
+ </text>
+ <g>
+ <polygon style="fill: #ffffff" points="-120,262 -40,322.81 -120,383.619 -200,322.81 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-120,262 -40,322.81 -120,383.619 -200,322.81 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="310.691">
+ <tspan x="-120" y="310.691">inflight</tspan>
+ <tspan x="-120" y="326.691">within</tspan>
+ <tspan x="-120" y="342.691">limit?</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="-200" y="402" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-200" y="402" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="427.881">
+ <tspan x="-120" y="427.881">Allocate SQE on ring</tspan>
+ <tspan x="-120" y="443.881">Inc prep counter</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-80" y="386.431">
+ <tspan x="-80" y="386.431">Yes</tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="346.431">
+ <tspan x="-20" y="346.431">No</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="-12.825" y="395" width="185.65" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-12.825" y="395" width="185.65" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="417.881">
+ <tspan x="80" y="417.881">Allocate SQE on heap</tspan>
+ <tspan x="80" y="433.881">Inc overflow counter</tspan>
+ <tspan x="80" y="449.881">TSO & SQE on overflow Q</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="-201.625" y="202" width="163.25" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-201.625" y="202" width="163.25" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="225.881">
+ <tspan x="-120" y="225.881">Inc submitted counter</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-120" y1="384.619" x2="-120" y2="392.264"/>
+ <polygon style="fill: #000000" points="-120,399.764 -125,389.764 -120,392.264 -115,389.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-120,399.764 -125,389.764 -120,392.264 -115,389.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-120" y1="176" x2="-120" y2="192.264"/>
+ <polygon style="fill: #000000" points="-120,199.764 -125,189.764 -120,192.264 -115,189.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-120,199.764 -125,189.764 -120,192.264 -115,189.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-120" y1="242" x2="-120" y2="252.264"/>
+ <polygon style="fill: #000000" points="-120,259.764 -125,249.764 -120,252.264 -115,249.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-120,259.764 -125,249.764 -120,252.264 -115,249.764 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-40,149 80,125 80,94.7361 "/>
+ <polygon style="fill: #000000" points="80,87.2361 85,97.2361 80,94.7361 75,97.2361 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="80,87.2361 85,97.2361 80,94.7361 75,97.2361 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="430">
+ <tspan x="80" y="430"></tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="-100" y="482" width="160" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-100" y="482" width="160" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="505.881">
+ <tspan x="-20" y="505.881">Fill in SQE</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-120" y1="462" x2="-106.884" y2="475.116"/>
+ <polygon style="fill: #000000" points="-101.581,480.419 -112.188,476.883 -106.884,475.116 -105.117,469.812 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-101.581,480.419 -112.188,476.883 -106.884,475.116 -105.117,469.812 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="80" y1="465" x2="67.4183" y2="475.694"/>
+ <polygon style="fill: #000000" points="61.7037,480.552 66.0849,470.266 67.4183,475.694 72.5614,477.885 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="61.7037,480.552 66.0849,470.266 67.4183,475.694 72.5614,477.885 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="-195.75" y="677" width="157.15" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-195.75" y="677" width="157.15" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-117.175" y="699.881">
+ <tspan x="-117.175" y="699.881">Primop:</tspan>
+ <tspan x="-117.175" y="715.881">result is AIOP</tspan>
+ <tspan x="-117.175" y="731.881">control to caller</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="0" y="677" width="160" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="0" y="677" width="160" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="699.881">
+ <tspan x="80" y="699.881">Primop:</tspan>
+ <tspan x="80" y="715.881">result is AIOP</tspan>
+ <tspan x="80" y="731.881">control to scheduler</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="-280" y1="662" x2="180" y2="662"/>
+ <g>
+ <polygon style="fill: #ffffff" points="-20,542 120,592 -20,642 -160,592 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-20,542 120,592 -20,642 -160,592 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="587.881">
+ <tspan x="-20" y="587.881">inflight within limit</tspan>
+ <tspan x="-20" y="603.881">And SQ ring not full</tspan>
+ </text>
+ </g>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-280" y="682">
+ <tspan x="-280" y="682">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-280" y="655.622">
+ <tspan x="-280" y="655.622">RTS C</tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-20" y1="522.977" x2="-20" y2="532.264"/>
+ <polygon style="fill: #000000" points="-20,539.764 -25,529.764 -20,532.264 -15,529.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-20,539.764 -25,529.764 -20,532.264 -15,529.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-55" y1="629.5" x2="-73.6614" y2="668.229"/>
+ <polygon style="fill: #000000" points="-76.917,674.986 -77.0805,663.806 -73.6614,668.229 -68.0718,668.147 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-76.917,674.986 -77.0805,663.806 -73.6614,668.229 -68.0718,668.147 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="15" y1="629.5" x2="35.4655" y2="668.384"/>
+ <polygon style="fill: #000000" points="38.9586,675.021 29.8765,668.501 35.4655,668.384 38.7257,663.843 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="38.9586,675.021 29.8765,668.501 35.4655,668.384 38.7257,663.843 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-100" y="646.431">
+ <tspan x="-100" y="646.431">Yes</tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="40" y="646.431">
+ <tspan x="40" y="646.431">No</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1019.34" y="25" width="163.85" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1019.34" y="25" width="163.85" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1101.26" y="47.8812">
+ <tspan x="1101.26" y="47.8812">Primop: async</tspan>
+ <tspan x="1101.26" y="63.8812">blocking I/O</tspan>
+ <tspan x="1101.26" y="79.8812">submission</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1101.26" y="60">
+ <tspan x="1101.26" y="60"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1101.26" y1="95" x2="1101.76" y2="115.267"/>
+ <polygon style="fill: #000000" points="1101.95,122.765 1096.7,112.89 1101.76,115.267 1106.7,112.645 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1101.95,122.765 1096.7,112.89 1101.76,115.267 1106.7,112.645 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1022" y="125" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1022" y="125" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="150.881">
+ <tspan x="1102" y="150.881">Allocate AIOP</tspan>
+ <tspan x="1102" y="166.881">Allocate table index</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="942" y1="110" x2="1402" y2="110"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="942" y="103.622">
+ <tspan x="942" y="103.622">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="942" y="126.539">
+ <tspan x="942" y="126.539">RTS C</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1222" y="30" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1222" y="30" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1302" y="63.8813">
+ <tspan x="1302" y="63.8813">Primop: GC and retry</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1302" y="60">
+ <tspan x="1302" y="60"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1222" y1="60" x2="1192.92" y2="60"/>
+ <polygon style="fill: #000000" points="1185.42,60 1195.42,55 1192.92,60 1195.42,65 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1185.42,60 1195.42,55 1192.92,60 1195.42,65 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="155">
+ <tspan x="1102" y="155"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1222" y="161.981">
+ <tspan x="1222" y="161.981">mem alloc failure?</tspan>
+ </text>
+ <g>
+ <polygon style="fill: #ffffff" points="1102,285 1182,345.81 1102,406.619 1022,345.81 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1102,285 1182,345.81 1102,406.619 1022,345.81 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="333.691">
+ <tspan x="1102" y="333.691">inflight</tspan>
+ <tspan x="1102" y="349.691">within</tspan>
+ <tspan x="1102" y="365.691">limit?</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1022" y="440" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1022" y="440" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="465.881">
+ <tspan x="1102" y="465.881">Allocate SQE on ring</tspan>
+ <tspan x="1102" y="481.881">Inc ring prep counter</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1042" y="409.431">
+ <tspan x="1042" y="409.431">Yes</tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1142" y="409.431">
+ <tspan x="1142" y="409.431">No</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1020.37" y="205" width="163.25" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1020.37" y="205" width="163.25" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="228.881">
+ <tspan x="1102" y="228.881">Inc submitted counter</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1102" y1="406.62" x2="1102" y2="430.264"/>
+ <polygon style="fill: #000000" points="1102,437.764 1097,427.764 1102,430.264 1107,427.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1102,437.764 1097,427.764 1102,430.264 1107,427.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1102" y1="185" x2="1102" y2="195.264"/>
+ <polygon style="fill: #000000" points="1102,202.764 1097,192.764 1102,195.264 1107,192.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1102,202.764 1097,192.764 1102,195.264 1107,192.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1102" y1="245" x2="1102" y2="275.264"/>
+ <polygon style="fill: #000000" points="1102,282.764 1097,272.764 1102,275.264 1107,272.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1102,282.764 1097,272.764 1102,275.264 1107,272.764 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1182,155 1302,130 1302,99.7361 "/>
+ <polygon style="fill: #000000" points="1302,92.2361 1307,102.236 1302,99.7361 1297,102.236 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1302,92.2361 1307,102.236 1302,99.7361 1297,102.236 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1202" y="455">
+ <tspan x="1202" y="455"></tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1022" y="525" width="160" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1022" y="525" width="160" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="548.881">
+ <tspan x="1102" y="548.881">Fill in SQE</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1102" y1="500" x2="1102" y2="515.264"/>
+ <polygon style="fill: #000000" points="1102,522.764 1097,512.764 1102,515.264 1107,512.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1102,522.764 1097,512.764 1102,515.264 1107,512.764 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1022" y="716" width="160" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1022" y="716" width="160" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="738.881">
+ <tspan x="1102" y="738.881">Primop:</tspan>
+ <tspan x="1102" y="754.881">result is AIOP</tspan>
+ <tspan x="1102" y="770.881">control to caller</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1222" y="717" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1222" y="717" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1302" y="742.881">
+ <tspan x="1302" y="742.881">Primop:</tspan>
+ <tspan x="1302" y="758.881">throw exception</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="942" y1="697" x2="1402" y2="697"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="942" y="717">
+ <tspan x="942" y="717">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="942" y="690.622">
+ <tspan x="942" y="690.622">RTS C</tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1102.53" y1="565.994" x2="1102.86" y2="579.104"/>
+ <polygon style="fill: #000000" points="1103.05,586.601 1097.8,576.73 1102.86,579.104 1107.79,576.479 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1103.05,586.601 1097.8,576.73 1102.86,579.104 1107.79,576.479 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1182,345.81 1182,345 1302,345 1302,707.264 "/>
+ <polygon style="fill: #000000" points="1302,714.764 1297,704.764 1302,707.264 1307,704.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1302,714.764 1297,704.764 1302,707.264 1307,704.764 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-40,322.81 -40,322 80,322 80,385.264 "/>
+ <polygon style="fill: #000000" points="80,392.764 75,382.764 80,385.264 85,382.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="80,392.764 75,382.764 80,385.264 85,382.764 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="403" y="22" width="158.525" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="403" y="22" width="158.525" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="482.262" y="44.8813">
+ <tspan x="482.262" y="44.8813">Primop: sync</tspan>
+ <tspan x="482.262" y="60.8812">non-blocking I/O</tspan>
+ <tspan x="482.262" y="76.8812">submission</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="482.262" y="57">
+ <tspan x="482.262" y="57"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="482.262" y1="92" x2="482.795" y2="117.266"/>
+ <polygon style="fill: #000000" points="482.953,124.764 477.743,114.872 482.795,117.266 487.741,114.661 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="482.953,124.764 477.743,114.872 482.795,117.266 487.741,114.661 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="403" y="127" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="403" y="127" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="152.881">
+ <tspan x="483" y="152.881">Allocate AIOP</tspan>
+ <tspan x="483" y="168.881">Allocate table index</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="323" y1="107" x2="783" y2="107"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="323" y="100.622">
+ <tspan x="323" y="100.622">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="323" y="123.539">
+ <tspan x="323" y="123.539">RTS C</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="603" y="27" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="603" y="27" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="683" y="60.8812">
+ <tspan x="683" y="60.8812">Primop: GC and retry</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="683" y="57">
+ <tspan x="683" y="57"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="603" y1="57" x2="571.262" y2="57"/>
+ <polygon style="fill: #000000" points="563.762,57 573.762,52 571.262,57 573.762,62 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="563.762,57 573.762,52 571.262,57 573.762,62 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="157">
+ <tspan x="483" y="157"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="583" y="163.981">
+ <tspan x="583" y="163.981">mem alloc failure?</tspan>
+ </text>
+ <g>
+ <polygon style="fill: #ffffff" points="483,262 563,322.81 483,383.619 403,322.81 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="483,262 563,322.81 483,383.619 403,322.81 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="310.691">
+ <tspan x="483" y="310.691">inflight</tspan>
+ <tspan x="483" y="326.691">within</tspan>
+ <tspan x="483" y="342.691">limit?</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="403" y="402" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="403" y="402" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="427.881">
+ <tspan x="483" y="427.881">Allocate SQE on ring</tspan>
+ <tspan x="483" y="443.881">Inc ring prep counter</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="523" y="386.431">
+ <tspan x="523" y="386.431">Yes</tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="583" y="346.431">
+ <tspan x="583" y="346.431">No</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="603" y="402" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="603" y="402" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="683" y="427.881">
+ <tspan x="683" y="427.881">Allocate SQE on heap</tspan>
+ <tspan x="683" y="443.881">TSO on overflow Q</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="401.375" y="207" width="163.25" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="401.375" y="207" width="163.25" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="230.881">
+ <tspan x="483" y="230.881">Inc submitted counter</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="483" y1="384.619" x2="483" y2="392.264"/>
+ <polygon style="fill: #000000" points="483,399.764 478,389.764 483,392.264 488,389.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="483,399.764 478,389.764 483,392.264 488,389.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="483" y1="187" x2="483" y2="197.264"/>
+ <polygon style="fill: #000000" points="483,204.764 478,194.764 483,197.264 488,194.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="483,204.764 478,194.764 483,197.264 488,194.764 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="483" y1="247" x2="483" y2="252.264"/>
+ <polygon style="fill: #000000" points="483,259.764 478,249.764 483,252.264 488,249.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="483,259.764 478,249.764 483,252.264 488,249.764 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="563,157 683,127 683,96.7361 "/>
+ <polygon style="fill: #000000" points="683,89.2361 688,99.2361 683,96.7361 678,99.2361 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="683,89.2361 688,99.2361 683,96.7361 678,99.2361 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="683" y="432">
+ <tspan x="683" y="432"></tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="503" y="482" width="160" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="503" y="482" width="160" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="583" y="505.881">
+ <tspan x="583" y="505.881">Fill in SQE</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="483" y1="462" x2="496.116" y2="475.116"/>
+ <polygon style="fill: #000000" points="501.419,480.419 490.812,476.883 496.116,475.116 497.883,469.812 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="501.419,480.419 490.812,476.883 496.116,475.116 497.883,469.812 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="683" y1="462" x2="669.884" y2="475.116"/>
+ <polygon style="fill: #000000" points="664.581,480.419 668.117,469.812 669.884,475.116 675.188,476.883 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="664.581,480.419 668.117,469.812 669.884,475.116 675.188,476.883 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="503" y="562" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="503" y="562" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="583" y="587.881">
+ <tspan x="583" y="587.881">Primop:</tspan>
+ <tspan x="583" y="603.881">control to scheduler</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="323" y1="542" x2="783" y2="542"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="323" y="562">
+ <tspan x="323" y="562">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="323" y="535.622">
+ <tspan x="323" y="535.622">RTS C</tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="583" y1="522.991" x2="583" y2="552.264"/>
+ <polygon style="fill: #000000" points="583,559.764 578,549.764 583,552.264 588,549.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="583,559.764 578,549.764 583,552.264 588,549.764 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="563,322.81 563,322 683,322 683,392.264 "/>
+ <polygon style="fill: #000000" points="683,399.764 678,389.764 683,392.264 688,389.764 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="683,399.764 678,389.764 683,392.264 688,389.764 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1638.85" y="38.6" width="163.85" height="70"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1638.85" y="38.6" width="163.85" height="70"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1720.77" y="61.4813">
+ <tspan x="1720.77" y="61.4813">Primop: sync</tspan>
+ <tspan x="1720.77" y="77.4813">blocking I/O</tspan>
+ <tspan x="1720.77" y="93.4812">submission</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1720.77" y="73.6">
+ <tspan x="1720.77" y="73.6"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1720.77" y1="108.6" x2="1721.27" y2="128.867"/>
+ <polygon style="fill: #000000" points="1721.46,136.365 1716.21,126.491 1721.27,128.867 1726.21,126.245 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.46,136.365 1716.21,126.491 1721.27,128.867 1726.21,126.245 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1641.51" y="138.6" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1641.51" y="138.6" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="164.481">
+ <tspan x="1721.51" y="164.481">Allocate AIOP</tspan>
+ <tspan x="1721.51" y="180.481">Allocate table index</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="1561.51" y1="123.6" x2="2021.52" y2="123.6"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1561.51" y="117.222">
+ <tspan x="1561.51" y="117.222">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1561.51" y="140.139">
+ <tspan x="1561.51" y="140.139">RTS C</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1841.51" y="43.6" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1841.51" y="43.6" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1921.51" y="77.4813">
+ <tspan x="1921.51" y="77.4813">Primop: GC and retry</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1921.51" y="73.6">
+ <tspan x="1921.51" y="73.6"></tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1841.51" y1="73.6" x2="1812.44" y2="73.6"/>
+ <polygon style="fill: #000000" points="1804.94,73.6 1814.94,68.6 1812.44,73.6 1814.94,78.6 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1804.94,73.6 1814.94,68.6 1812.44,73.6 1814.94,78.6 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="168.6">
+ <tspan x="1721.51" y="168.6"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1841.51" y="175.581">
+ <tspan x="1841.51" y="175.581">mem alloc failure?</tspan>
+ </text>
+ <g>
+ <polygon style="fill: #ffffff" points="1721.51,298.6 1801.51,359.41 1721.51,420.219 1641.51,359.41 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,298.6 1801.51,359.41 1721.51,420.219 1641.51,359.41 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="347.291">
+ <tspan x="1721.51" y="347.291">inflight</tspan>
+ <tspan x="1721.51" y="363.291">within</tspan>
+ <tspan x="1721.51" y="379.291">limit?</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1641.51" y="453.6" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1641.51" y="453.6" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="479.481">
+ <tspan x="1721.51" y="479.481">Allocate SQE on ring</tspan>
+ <tspan x="1721.51" y="495.481">Inc ring prep counter</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1661.51" y="423.031">
+ <tspan x="1661.51" y="423.031">Yes</tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1761.51" y="423.031">
+ <tspan x="1761.51" y="423.031">No</tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1639.89" y="218.6" width="163.25" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1639.89" y="218.6" width="163.25" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="242.481">
+ <tspan x="1721.51" y="242.481">Inc submitted counter</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1721.51" y1="420.22" x2="1721.51" y2="443.864"/>
+ <polygon style="fill: #000000" points="1721.51,451.364 1716.51,441.364 1721.51,443.864 1726.51,441.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,451.364 1716.51,441.364 1721.51,443.864 1726.51,441.364 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1721.51" y1="198.6" x2="1721.51" y2="208.864"/>
+ <polygon style="fill: #000000" points="1721.51,216.364 1716.51,206.364 1721.51,208.864 1726.51,206.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,216.364 1716.51,206.364 1721.51,208.864 1726.51,206.364 "/>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1721.51" y1="258.6" x2="1721.51" y2="288.864"/>
+ <polygon style="fill: #000000" points="1721.51,296.364 1716.51,286.364 1721.51,288.864 1726.51,286.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,296.364 1716.51,286.364 1721.51,288.864 1726.51,286.364 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1801.51,168.6 1921.51,143.6 1921.51,113.336 "/>
+ <polygon style="fill: #000000" points="1921.51,105.836 1926.51,115.836 1921.51,113.336 1916.51,115.836 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1921.51,105.836 1926.51,115.836 1921.51,113.336 1916.51,115.836 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1821.51" y="468.6">
+ <tspan x="1821.51" y="468.6"></tspan>
+ </text>
+ <g>
+ <rect style="fill: #ffffff" x="1641.51" y="538.6" width="160" height="40"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1641.51" y="538.6" width="160" height="40"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="562.481">
+ <tspan x="1721.51" y="562.481">Fill in SQE</tspan>
+ </text>
+ </g>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1721.51" y1="513.6" x2="1721.51" y2="528.864"/>
+ <polygon style="fill: #000000" points="1721.51,536.364 1716.51,526.364 1721.51,528.864 1726.51,526.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,536.364 1716.51,526.364 1721.51,528.864 1726.51,526.364 "/>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1641.51" y="618.6" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1641.51" y="618.6" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1721.51" y="644.481">
+ <tspan x="1721.51" y="644.481">Primop:</tspan>
+ <tspan x="1721.51" y="660.481">return to scheduler</tspan>
+ </text>
+ </g>
+ <g>
+ <rect style="fill: #ffffff" x="1841.51" y="618.6" width="160" height="60"/>
+ <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="1841.51" y="618.6" width="160" height="60"/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1921.51" y="644.481">
+ <tspan x="1921.51" y="644.481">Primop:</tspan>
+ <tspan x="1921.51" y="660.481">throw exception</tspan>
+ </text>
+ </g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #000000" x1="1561.51" y1="598.6" x2="2021.52" y2="598.6"/>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1561.51" y="618.6">
+ <tspan x="1561.51" y="618.6">RTS CMM</tspan>
+ </text>
+ <text font-size="14.6756" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1561.51" y="592.222">
+ <tspan x="1561.51" y="592.222">RTS C</tspan>
+ </text>
+ <g>
+ <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="1721.51" y1="579.591" x2="1721.51" y2="608.864"/>
+ <polygon style="fill: #000000" points="1721.51,616.364 1716.51,606.364 1721.51,608.864 1726.51,606.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1721.51,616.364 1716.51,606.364 1721.51,608.864 1726.51,606.364 "/>
+ </g>
+ <g>
+ <polyline style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1801.51,359.41 1801.51,358.6 1921.51,358.6 1921.51,608.864 "/>
+ <polygon style="fill: #000000" points="1921.51,616.364 1916.51,606.364 1921.51,608.864 1926.51,606.364 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1921.51,616.364 1916.51,606.364 1921.51,608.864 1926.51,606.364 "/>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120.738" y="55">
+ <tspan x="-120.738" y="55"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-120" y="149">
+ <tspan x="-120" y="149"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-117.175" y="712">
+ <tspan x="-117.175" y="712"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="-117.175" y="712">
+ <tspan x="-117.175" y="712"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="583" y="592">
+ <tspan x="583" y="592"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="80" y="712">
+ <tspan x="80" y="712"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1102" y="751">
+ <tspan x="1102" y="751"></tspan>
+ </text>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1720.77" y="73.6">
+ <tspan x="1720.77" y="73.6"></tspan>
+ </text>
+ <g>
+ <polygon style="fill: #ffffff" points="1104,589.546 1208.51,624.256 1104,658.967 999.486,624.256 "/>
+ <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="1104,589.546 1208.51,624.256 1104,658.967 999.486,624.256 "/>
+ <text font-size="12.8" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="1104" y="628.138">
+ <tspan x="1104" y="628.138">SQ ring not full</tspan>
+ </text>
+ </g>
+ <text font-size="12.8" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="1104" y="624.256">
+ <tspan x="1104" y="624.256"></tspan>
+ </text>
+ <text font-size="12.7998" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="483" y="227">
+ <tspan x="483" y="227"></tspan>
+ </text>
+</svg>
=====================================
rts/rts.cabal
=====================================
@@ -48,6 +48,8 @@ flag libdw
default: False
flag libnuma
default: False
+flag liburing
+ default: True
flag libzstd
default: False
flag static-libzstd
@@ -231,6 +233,8 @@ library
extra-libraries: elf dw
if flag(libnuma)
extra-libraries: numa
+ if flag(liburing)
+ extra-libraries: uring
if flag(libzstd)
if flag(static-libzstd)
if os(darwin)
@@ -536,6 +540,7 @@ library
posix/Signals.c
posix/Timeout.c
posix/TTY.c
+ posix/URing.c
-- ticker/*.c
-- We don't want to compile posix/ticker/*.c, these will be #included
-- from Ticker.c
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/102b80f6e461541aa174a473f68cab1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/102b80f6e461541aa174a473f68cab1…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc] Pushed new branch wip/dcoutts/io-manager-uring
by Duncan Coutts (@dcoutts) 26 Aug '26
by Duncan Coutts (@dcoutts) 26 Aug '26
26 Aug '26
Duncan Coutts pushed new branch wip/dcoutts/io-manager-uring at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/dcoutts/io-manager-uring
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/fendor/ghc-ghci-mhu-27640] GHCi: Fix order of `PackageDBFlag`s for interactive home unit
by Hannes Siebenhandl (@fendor) 26 Aug '26
by Hannes Siebenhandl (@fendor) 26 Aug '26
26 Aug '26
Hannes Siebenhandl pushed to branch wip/fendor/ghc-ghci-mhu-27640 at Glasgow Haskell Compiler / GHC
Commits:
b304c203 by fendor at 2026-08-26T10:30:05+02:00
GHCi: Fix order of `PackageDBFlag`s for interactive home unit
`PackageDBFlag`s are stored in reverse order of cli specification.
When sorting the `PackageDBFlag`s by longest common prefix, we need thus
to reverse the package db stacks before calculating the prefix.
We make sure to reverse the package db stack for the interactive home
unit to uphold that later specified package dbs overwrite earlier ones.
Resolved and adds regression test for #27640
- - - - -
14 changed files:
- changelog.d/T27202
- ghc/GHCi/UI.hs
- + testsuite/tests/ghci/prog-mhu007/Makefile
- + testsuite/tests/ghci/prog-mhu007/a/A.hs
- + testsuite/tests/ghci/prog-mhu007/all.T
- + testsuite/tests/ghci/prog-mhu007/b/B.hs
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
- + testsuite/tests/ghci/prog-mhu007/unitA
- + testsuite/tests/ghci/prog-mhu007/unitB
Changes:
=====================================
changelog.d/T27202
=====================================
@@ -1,7 +1,7 @@
section: ghci
synopsis: Fix regression to honour module targets in nested directories into GHCi after startup.
-issues: #27202
-mrs: !15980
+issues: #27202 #27640
+mrs: !15980 !16591
description: {
Fix a regression that made it impossible to import modules using `:load <Mod>` and `:add <Mod>` after GHCi startup.
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -763,7 +763,7 @@ installInteractiveHomeUnits dflags = do
-- However, in the case of multiple home units, initialised via @ghci -unit ... -unit ...@, there
-- are not @-package-db@ arguments in the base 'DynFlags'...
-- To fix this, we look at the home units and merge their package dbs stacks.
- -- We assume, that many package db stacks look almost identical, and only differ in view elements.
+ -- We assume, that many package db stacks look almost identical, and only differ in few unit databases.
-- Thus, we try to extract a common package db stack (i.e., longest common prefix), and then concat
-- the rest of the package db stacks. At last, we add the two result package db stacks.
-- This should work reliably with cabal and stack, but it is hacky.
@@ -864,8 +864,14 @@ installInteractiveHomeUnits dflags = do
pure (HUG.mkHomeUnitEnv unit_state dflags hpt (Just home_unit))
concatPackageDbStacksUsingLongestCommonPrefix :: [[PackageDBFlag]] -> [PackageDBFlag]
- concatPackageDbStacksUsingLongestCommonPrefix stacks =
+ concatPackageDbStacksUsingLongestCommonPrefix stacks' =
let
+ -- Package DB stacks are accumulated from the cli right to left.
+ -- E.g., @-clear-package-db -global-package-db@ is stored as
+ -- @[PackageDB GlobalPkgDb, ClearPackageDBs]@.
+ -- Hence, we reverse the stacks, before computing the longest common prefix,
+ -- otherwise the prefix won't match at all.
+ stacks = map List.reverse stacks'
-- O (m * n)
-- m ... Number of PackageDBFlag stacks
-- n ... Size of the stacks
@@ -873,8 +879,21 @@ installInteractiveHomeUnits dflags = do
map List.head . List.takeWhile ((List.all . (==) . List.head) <*> List.tail) . List.transpose
prefix =
longestCommonPrefix stacks
+
+ -- We reverse each individual stack segment to maintain the relative order within in a package
+ -- db stack.
+ -- There should be no 'ClearPackageDBs' in here, otherwise we are going to overwrite
+ -- the longest common prefix stacks.
+ --
+ -- @nubOrd@ can silently change precedence of package db stack merging.
+ -- This is not trivially avoidable right now, since multiple home units could simply
+ -- have package db stacks that cannot be unified.
+ unmergeableStack =
+ nubOrd (concatMap (List.reverse . List.drop (length prefix)) stacks)
in
- prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks)
+ -- We reverse the final common package db stack again to match the expectation of 'packageDBFlags' that they are
+ -- stord in reverse order.
+ unmergeableStack ++ reverse prefix
reportError :: GhciMonad m => GhciCommandMessage -> m ()
reportError err = do
=====================================
testsuite/tests/ghci/prog-mhu007/Makefile
=====================================
@@ -0,0 +1,33 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+PKGCONF_FOO=local-foo.package.conf
+PKGCONF_BAR=local-bar.package.conf
+LOCAL_GHC_PKG_FOO = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_FOO)
+LOCAL_GHC_PKG_BAR = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_BAR)
+
+# Finds both packages in different unit databases
+.PHONY: prog-mhu007
+prog-mhu007:
+ cd testpkg-foo && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-foo-0.1.0.0 -this-unit-id testpkg-foo-0.1.0.0-XXX \
+ -i. Foo
+ cd testpkg-bar && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-bar-0.1.0.0 -this-unit-id testpkg-bar-0.1.0.0-XXX \
+ -i. Bar
+
+ $(LOCAL_GHC_PKG_FOO) init $(PKGCONF_FOO) 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) register --force testpkg-foo/testpkg-foo.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) hide testpkg-foo
+ $(LOCAL_GHC_PKG_FOO) list
+
+ $(LOCAL_GHC_PKG_BAR) init $(PKGCONF_BAR) 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) register --force testpkg-bar/testpkg-bar.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) hide testpkg-bar
+ $(LOCAL_GHC_PKG_BAR) list
+
+ '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) $(WAY_FLAGS) $(ghciWayFlags) \
+ -no-user-package-db -fno-code -unit @unitA -unit @unitB < prog-mhu007.script
=====================================
testsuite/tests/ghci/prog-mhu007/a/A.hs
=====================================
@@ -0,0 +1,3 @@
+module A where
+
+import Bar
=====================================
testsuite/tests/ghci/prog-mhu007/all.T
=====================================
@@ -0,0 +1,8 @@
+
+proj_files = extra_files(['a/', 'b/', 'unitA', 'unitB', 'testpkg-bar/', 'testpkg-foo/'])
+
+test('prog-mhu007',
+ [proj_files,
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ makefile_test, ['prog-mhu007'])
=====================================
testsuite/tests/ghci/prog-mhu007/b/B.hs
=====================================
@@ -0,0 +1,3 @@
+module B where
+
+import Foo
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
=====================================
@@ -0,0 +1,5 @@
+:m + A B
+"Loaded A and B"
+import Foo
+import Bar
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
=====================================
@@ -0,0 +1,10 @@
+Reading package info from "testpkg-foo/testpkg-foo.pkg" ... done.
+local-foo.package.conf
+ (testpkg-foo-0.1.0.0)
+
+Reading package info from "testpkg-bar/testpkg-bar.pkg" ... done.
+local-bar.package.conf
+ (testpkg-bar-0.1.0.0)
+
+"Loaded A and B"
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
=====================================
@@ -0,0 +1 @@
+module Bar where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-bar
+version: 0.1.0.0
+id: testpkg-bar-0.1.0.0-XXX
+key: testpkg-bar-0.1.0.0-XXX
+exposed: True
+exposed-modules: Bar
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-bar/dist-testpkg-bar-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
=====================================
@@ -0,0 +1 @@
+module Foo where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-foo
+version: 0.1.0.0
+id: testpkg-foo-0.1.0.0-XXX
+key: testpkg-foo-0.1.0.0-XXX
+exposed: True
+exposed-modules: Foo
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-foo/dist-testpkg-foo-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/unitA
=====================================
@@ -0,0 +1,11 @@
+-i
+-ia/
+A
+-this-unit-id a-0.0.0
+-this-package-name a
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-bar.package.conf
+-package base
+-package-id testpkg-bar-0.1.0.0-XXX
=====================================
testsuite/tests/ghci/prog-mhu007/unitB
=====================================
@@ -0,0 +1,11 @@
+-i
+-ib/
+B
+-this-unit-id b-0.0.0
+-this-package-name b
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-foo.package.conf
+-package base
+-package-id testpkg-foo-0.1.0.0-XXX
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b304c203d3f30dc9c8c9fa381a12685…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b304c203d3f30dc9c8c9fa381a12685…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/fendor/ghc-ghci-mhu-27640] GHCi: Fix order of `PackageDBFlag`s for interactive home unit
by Hannes Siebenhandl (@fendor) 26 Aug '26
by Hannes Siebenhandl (@fendor) 26 Aug '26
26 Aug '26
Hannes Siebenhandl pushed to branch wip/fendor/ghc-ghci-mhu-27640 at Glasgow Haskell Compiler / GHC
Commits:
e2c011e7 by fendor at 2026-08-26T09:38:05+02:00
GHCi: Fix order of `PackageDBFlag`s for interactive home unit
`PackageDBFlag`s are stored in reverse order of cli specification.
When sorting the `PackageDBFlag`s by longest common prefix, we need thus
to reverse the package db stacks before calculating the prefix.
We make sure to reverse the package db stack for the interactive home
unit to uphold that later specified package dbs overwrite earlier ones.
Resolved and adds regression test for #27640
- - - - -
14 changed files:
- changelog.d/T27202
- ghc/GHCi/UI.hs
- + testsuite/tests/ghci/prog-mhu007/Makefile
- + testsuite/tests/ghci/prog-mhu007/a/A.hs
- + testsuite/tests/ghci/prog-mhu007/all.T
- + testsuite/tests/ghci/prog-mhu007/b/B.hs
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
- + testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
- + testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
- + testsuite/tests/ghci/prog-mhu007/unitA
- + testsuite/tests/ghci/prog-mhu007/unitB
Changes:
=====================================
changelog.d/T27202
=====================================
@@ -1,7 +1,7 @@
section: ghci
synopsis: Fix regression to honour module targets in nested directories into GHCi after startup.
issues: #27202
-mrs: !15980
+mrs: !15980 !16591
description: {
Fix a regression that made it impossible to import modules using `:load <Mod>` and `:add <Mod>` after GHCi startup.
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -864,8 +864,14 @@ installInteractiveHomeUnits dflags = do
pure (HUG.mkHomeUnitEnv unit_state dflags hpt (Just home_unit))
concatPackageDbStacksUsingLongestCommonPrefix :: [[PackageDBFlag]] -> [PackageDBFlag]
- concatPackageDbStacksUsingLongestCommonPrefix stacks =
+ concatPackageDbStacksUsingLongestCommonPrefix stacks' =
let
+ -- Package DB stacks are accumulated from the cli right to left.
+ -- E.g., @-clear-package-db -global-package-db@ is stored as
+ -- @[GlobalPackageDb, ClearPackageDb]@.
+ -- Hence, we reverse the stacks, before computing the longest common prefix,
+ -- otherwise the prefix won't match at all.
+ stacks = map List.reverse stacks'
-- O (m * n)
-- m ... Number of PackageDBFlag stacks
-- n ... Size of the stacks
@@ -873,8 +879,22 @@ installInteractiveHomeUnits dflags = do
map List.head . List.takeWhile ((List.all . (==) . List.head) <*> List.tail) . List.transpose
prefix =
longestCommonPrefix stacks
+
+ -- We reverse each individual stack segment to maintain the relative order.
+ -- There should be no 'ClearPackageDb' in here, otherwise we are going to overwrite
+ -- the longest common prefix stacks.
+ unmergableStack =
+ nubOrd (concatMap (List.reverse . List.drop (length prefix)) stacks)
in
- prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks)
+ -- We reverse the final common package db stack again to match the expectation of 'packageDBFlags' that they are
+ -- stord in reverse order.
+ unmergableStack ++ reverse prefix
+
+-- [[d, b, a], [c, b, a]]
+-- [[a, b, d], [a, b, c]]
+-- [a, b], [[d], [c]]
+-- [d, c,]
+-- [d, c, b, a]
reportError :: GhciMonad m => GhciCommandMessage -> m ()
reportError err = do
=====================================
testsuite/tests/ghci/prog-mhu007/Makefile
=====================================
@@ -0,0 +1,33 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+PKGCONF_FOO=local-foo.package.conf
+PKGCONF_BAR=local-bar.package.conf
+LOCAL_GHC_PKG_FOO = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_FOO)
+LOCAL_GHC_PKG_BAR = '$(GHC_PKG)' --no-user-package-db -f $(PKGCONF_BAR)
+
+# Finds both packages in different unit databases
+.PHONY: prog-mhu007
+prog-mhu007:
+ cd testpkg-foo && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-foo-0.1.0.0 -this-unit-id testpkg-foo-0.1.0.0-XXX \
+ -i. Foo
+ cd testpkg-bar && \
+ '$(TEST_HC)' $(TEST_HC_OPTS) $(WAY_FLAGS) -hisuf=$(ghciWayExt) $(ghciWayFlags) \
+ -v0 -fno-code -fwrite-interface -hidir dist-testpkg-bar-0.1.0.0 -this-unit-id testpkg-bar-0.1.0.0-XXX \
+ -i. Bar
+
+ $(LOCAL_GHC_PKG_FOO) init $(PKGCONF_FOO) 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) register --force testpkg-foo/testpkg-foo.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_FOO) hide testpkg-foo
+ $(LOCAL_GHC_PKG_FOO) list
+
+ $(LOCAL_GHC_PKG_BAR) init $(PKGCONF_BAR) 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) register --force testpkg-bar/testpkg-bar.pkg 2>/dev/null
+ $(LOCAL_GHC_PKG_BAR) hide testpkg-bar
+ $(LOCAL_GHC_PKG_BAR) list
+
+ '$(TEST_HC)' $(TEST_HC_OPTS_INTERACTIVE) $(WAY_FLAGS) $(ghciWayFlags) \
+ -no-user-package-db -fno-code -unit @unitA -unit @unitB < prog-mhu007.script
=====================================
testsuite/tests/ghci/prog-mhu007/a/A.hs
=====================================
@@ -0,0 +1,3 @@
+module A where
+
+import Bar
=====================================
testsuite/tests/ghci/prog-mhu007/all.T
=====================================
@@ -0,0 +1,8 @@
+
+proj_files = extra_files(['a/', 'b/', 'unitA', 'unitB', 'testpkg-bar/', 'testpkg-foo/'])
+
+test('prog-mhu007',
+ [proj_files,
+ cmd_prefix('ghciWayFlags=' + config.ghci_way_flags),
+ req_interp],
+ makefile_test, ['prog-mhu007'])
=====================================
testsuite/tests/ghci/prog-mhu007/b/B.hs
=====================================
@@ -0,0 +1,3 @@
+module B where
+
+import Foo
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.script
=====================================
@@ -0,0 +1,5 @@
+:m + A B
+"Loaded A and B"
+import Foo
+import Bar
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/prog-mhu007.stdout
=====================================
@@ -0,0 +1,10 @@
+Reading package info from "testpkg-foo/testpkg-foo.pkg" ... done.
+local-foo.package.conf
+ (testpkg-foo-0.1.0.0)
+
+Reading package info from "testpkg-bar/testpkg-bar.pkg" ... done.
+local-bar.package.conf
+ (testpkg-bar-0.1.0.0)
+
+"Loaded A and B"
+"Loaded dependencies Foo and Bar"
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/Bar.hs
=====================================
@@ -0,0 +1 @@
+module Bar where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-bar/testpkg-bar.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-bar
+version: 0.1.0.0
+id: testpkg-bar-0.1.0.0-XXX
+key: testpkg-bar-0.1.0.0-XXX
+exposed: True
+exposed-modules: Bar
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-bar/dist-testpkg-bar-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/Foo.hs
=====================================
@@ -0,0 +1 @@
+module Foo where
=====================================
testsuite/tests/ghci/prog-mhu007/testpkg-foo/testpkg-foo.pkg
=====================================
@@ -0,0 +1,11 @@
+name: testpkg-foo
+version: 0.1.0.0
+id: testpkg-foo-0.1.0.0-XXX
+key: testpkg-foo-0.1.0.0-XXX
+exposed: True
+exposed-modules: Foo
+hidden-modules:
+import-dirs: ${pkgroot}/testpkg-foo/dist-testpkg-foo-0.1.0.0
+library-dirs:
+include-dirs:
+hs-libraries:
=====================================
testsuite/tests/ghci/prog-mhu007/unitA
=====================================
@@ -0,0 +1,11 @@
+-i
+-ia/
+A
+-this-unit-id a-0.0.0
+-this-package-name a
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-bar.package.conf
+-package base
+-package-id testpkg-bar-0.1.0.0-XXX
=====================================
testsuite/tests/ghci/prog-mhu007/unitB
=====================================
@@ -0,0 +1,11 @@
+-i
+-ib/
+B
+-this-unit-id b-0.0.0
+-this-package-name b
+-clear-package-db
+-global-package-db
+-no-user-package-db
+-package-db local-foo.package.conf
+-package base
+-package-id testpkg-foo-0.1.0.0-XXX
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2c011e7a9287f420eb88262b3480ab…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e2c011e7a9287f420eb88262b3480ab…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0